package balls 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) BALL_R :f32 = 15 Ball :: struct { pos: Vec2, accel: Vec2, vel: Vec2 } GameState :: struct { dt: f32, keymap: map[string]Key, balls: [dynamic]Ball, } init_state :: proc() -> ^GameState { keymap := make(map[string]Key) keymap["Left"] = .LEFT keymap["Right"] = .RIGHT keymap["Up"] = .UP keymap["Down"] = .DOWN state := GameState { keymap = keymap, } for i in 0..<30 { append(&state.balls, Ball { pos = { f32(rl.GetRandomValue(i32(BALL_R), i32(BW - BALL_R))), f32(rl.GetRandomValue(i32(BALL_R), i32(BH - BALL_R))) } }) } 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) { if rl.IsKeyDown(s.keymap["Right"]) { for &ball in balls { ball.vel.x += 0.3 } } if rl.IsKeyDown(s.keymap["Left"]) { for &ball in balls { ball.vel.x -= 0.3 } } if rl.IsKeyPressed(.SPACE) { for &ball in balls { ball.vel.y -= f32(rl.GetRandomValue(8, 12)) } } } gravity := Vec2 {0,0.3} damping :f32 = 0.7 update :: proc(using s: ^GameState) { for &ball in balls { if rl.Vector2LengthSqr(ball.vel) < 1 && ball.pos.y == BH - BALL_R { ball.vel *= 0 continue } // Forces ball.accel += gravity ball.vel += ball.accel ball.accel *= 0 ball.pos += ball.vel if ball.pos.y > BH - BALL_R { ball.vel.y *= -damping ball.pos.y = BH - BALL_R } if ball.pos.y < BALL_R { ball.vel.y *= -damping ball.pos.y = BALL_R } if ball.pos.x > BW - BALL_R { ball.vel.x *= -damping ball.pos.x = BW - BALL_R } if ball.pos.x < BALL_R { ball.vel.x *= -damping ball.pos.x = BALL_R } } } draw :: proc(using s: ^GameState) { for ball in balls { rl.DrawCircleLinesV(ball.pos, BALL_R, rl.BLACK) } } main :: proc() { rl.SetTraceLogLevel(.ERROR) rl.InitWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Boids") rl.SetTargetFPS(60) state := init_state() defer { 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() }