package main import ( "fmt" "math" "math/rand" rl "github.com/gen2brain/raylib-go/raylib" ) const ( WIDTH = 1100 HEIGHT = 700 buildingSpacing = 2.5 buildingSize = 1.2 maxColumns = 5 enemyAcc = 0.01 maxSpeed = 0.1 ) type enemy struct { pos rl.Vector3 speed float32 } type remainingFrames int type animationFunc func()remainingFrames type building struct { pos rl.Vector3 size rl.Vector3 color rl.Color life int boundingBox rl.BoundingBox animate animationFunc } func draw_plane() { rl.DrawPlane( rl.NewVector3(16, 0.0, 16), rl.NewVector2(128.0, 128.0), rl.NewColor(50, 50, 50, 255), ) } func newBuilding(x, z float32) *building { color := rl.NewColor( uint8(rl.GetRandomValue(0, 180)), uint8(rl.GetRandomValue(0, 180)), uint8(rl.GetRandomValue(0, 180)), 255, ) pos := rl.NewVector3(x * buildingSpacing, 0, z * buildingSpacing) size := rl.NewVector3( buildingSize, float32(rl.GetRandomValue(1, 7)), buildingSize, ) min := rl.NewVector3( pos.X - buildingSize/2, 0, pos.Z - buildingSize/2, ) max := rl.NewVector3( pos.X + buildingSize/2, size.Y/2, pos.Z + buildingSize/2, ) return &building{ color: color, life: 100, pos: pos, size: size, boundingBox: rl.NewBoundingBox(min, max), } } func drawWireframe(building building) { increasedSize := rl.Vector3Scale(building.size, 1.05) invertedColor := building.color invertedColor.R += 127 invertedColor.G += 127 invertedColor.B += 127 rl.DrawCubeWiresV( building.pos, increasedSize, invertedColor, ) } func shakeBuilding(b building) animationFunc { var frame remainingFrames = 60 * 0.7 return func() remainingFrames { building := b if frame % 4 == 0 { building.color = rl.RayWhite } drawWireframe(building) shake := rl.NewVector3( rand.Float32() * .2 - .1, rand.Float32() * .1 - .05, rand.Float32() * .2 - .1, ) // shake = rl.Vector3Scale(shake, float32(math.Sin(rl.GetTime()) + 1)/3) rl.DrawCubeV( rl.Vector3Add(building.pos, shake), building.size, building.color, ) frame -= 1 return frame } } func draw_buildings(buildings []*building, selected *building) { for _, building := range buildings { hasAnimation := building.animate != nil hit := building == selected && !hasAnimation if !hit { building.animate = shakeBuilding(*building) } if hasAnimation { remainingFrames := building.animate() if remainingFrames == 0 { building.animate = nil } continue } drawWireframe(*building) rl.DrawCubeV(building.pos, building.size, building.color) } } func demage_building(camera rl.Camera, buildings []*building) *building { if !rl.IsMouseButtonPressed(rl.MouseLeftButton) { return nil } ray := rl.Ray{ Position: camera.Position, Direction: rl.Vector3Subtract(camera.Target, camera.Position), } // var collision rl.RayCollision closestDistance := math.Inf(1) var closest *building for _, building := range buildings { playerDistance := rl.Vector3Distance(camera.Position, building.pos) if playerDistance < float32(closestDistance) { collision := rl.GetRayCollisionBox(ray, building.boundingBox) if collision.Hit { closestDistance = float64(playerDistance) closest = building } } } return closest } func main() { fmt.Println("hello world") rl.SetConfigFlags(rl.FlagMsaa4xHint) rl.InitWindow(WIDTH, HEIGHT, "raylib [core] example - 3d camera first person") rl.SetTargetFPS(60) rl.HideCursor() rl.DisableCursor() rl.SetMousePosition(WIDTH/2, HEIGHT/2) var enemies []*enemy for i := 0; i < 10; i++ { pos := rl.NewVector3( float32(rl.GetRandomValue(-10, 10)), 2, float32(rl.GetRandomValue(-10, 10)), ) enemies = append(enemies, &enemy{ pos: pos }) } camera := rl.Camera3D{} camera.Position = rl.NewVector3(4.0, 2.0, 4.0) camera.Target = rl.NewVector3(0.0, 1.8, 0.0) camera.Up = rl.NewVector3(0.0, 1.0, 0.0) camera.Fovy = 80.0 camera.Projection = rl.CameraPerspective var buildings []*building for i := 0; i < 32; i++ { for j := 0; j < 32; j++ { buildings = append(buildings, newBuilding(float32(i), float32(j))) } } for !rl.WindowShouldClose() { // shake := rl.NewVector3( // rand.Float32() * .4 - .2, // rand.Float32() * .4 - .2, // rand.Float32() * .4 - .2, // ) // shake = rl.Vector3Scale(shake, float32(math.Sin(rl.GetTime()) + 1)/3) // camera.Target = rl.Vector3Add(camera.Target, shake) rl.UpdateCamera(&camera, rl.CameraFirstPerson) rl.BeginDrawing() rl.ClearBackground(rl.LightGray) rl.BeginMode3D(camera) { selected := demage_building(camera, buildings) draw_plane() draw_buildings(buildings, selected) } rl.EndMode3D() rl.DrawLineV( rl.NewVector2(WIDTH/2-5, HEIGHT/2-5), rl.NewVector2(WIDTH/2+5, HEIGHT/2+5), rl.Red, ) rl.DrawLineV( rl.NewVector2(WIDTH/2-5, HEIGHT/2+5), rl.NewVector2(WIDTH/2+5, HEIGHT/2-5), rl.Red, ) rl.DrawFPS(10, 10) rl.EndDrawing() } rl.CloseWindow() } // for _, e := range enemies { // // if dist := rl.Vector3Distance(camera.Position, e.pos); dist > 8 { // rl.DrawSphere(e.pos, 1, rl.Blue) // e.speed = 0 // continue // } // rl.DrawSphere(e.pos, 1, rl.Red) // // direction := rl.Vector3Normalize(rl.Vector3Subtract(camera.Position, e.pos)) // e.speed += enemyAcc // e.speed = float32(math.Mod(float64(e.speed), maxSpeed)) // direction.Y = 0 // direction = rl.Vector3Scale(direction, e.speed) // e.pos = rl.Vector3Add(e.pos, direction) // } // fmt.Println( // rl.Vector3Subtract(camera.Target, camera.Position), // ) // ray = rl.GetMouseRay(rl.GetMousePosition(), camera) // rl.GetRayCollisionBox(ray // )