package boids import rl "vendor:raylib" import "core:math" import "core:math/rand" import "core:fmt" Vec2 :: [2]f32 Rect :: rl.Rectangle Img :: rl.Image Tex :: rl.Texture Key :: rl.KeyboardKey Color :: rl.Color SCREEN_WIDTH : i32 = 1600 SCREEN_HEIGHT : i32 = 1000 BW := f32(SCREEN_WIDTH) BH := f32(SCREEN_HEIGHT) Boid :: struct { pos: Vec2, angle: f32, accel: Vec2, vel: Vec2 } GameState :: struct { dt: f32, keymap: map[string]Key, follow_point: Maybe(Vec2), boids: [dynamic]Boid, } init_state :: proc() -> ^GameState { keymap := make(map[string]Key) keymap["Left"] = .A keymap["Right"] = .D keymap["Up"] = .W keymap["Down"] = .S state := GameState { keymap = keymap, } boid := Boid { pos = {100, 100}, } append(&state.boids, boid) cloned := new_clone(state) return cloned } get_rand_angle :: proc(min: i32, max: i32) -> f32 { return f32(rl.GetRandomValue(min, max)) * rl.DEG2RAD } player_input :: proc(using s: ^GameState) { horizontal: f32 vertical: f32 if rl.IsKeyDown(s.keymap["Right"]) { horizontal = 1 } if rl.IsKeyDown(s.keymap["Left"]) { horizontal = -1 } if rl.IsKeyDown(s.keymap["Up"]) { vertical = -1 } if rl.IsKeyDown(s.keymap["Down"]) { vertical = 1 } if rl.IsMouseButtonPressed(rl.MouseButton.LEFT) { follow_point = rl.GetMousePosition() } } update :: proc(using s: ^GameState) { if fpoint, ok := follow_point.?; ok { for &boid in boids { desired := fpoint - boid.pos desired = rl.Vector2ClampValue(desired, 10, 10) steer := desired - boid.vel steer = rl.Vector2ClampValue(steer, 0, 0.3) boid.vel += steer boid.pos += boid.vel } } } draw :: proc(using s: ^GameState) { for boid in boids { rl.DrawCircleV(boid.pos, 15, rl.RED) } } main :: proc() { rl.SetTraceLogLevel(.ERROR) rl.InitWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Boids") rl.SetTargetFPS(60) // rl.DisableCursor() state := init_state() defer { delete(state.boids) free(state) } for !rl.WindowShouldClose() { state.dt = rl.GetFrameTime() player_input(state) update(state) rl.BeginDrawing() rl.ClearBackground(rl.WHITE) draw(state) rl.EndDrawing() } rl.CloseWindow() }