package game 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) BULLET_SPEED : f32 = 30.5 BULLET_RADIUS: f32 = 2 WEAPON_ROF: f32 = 0.08 ANGULAR_SPEED: f32 = 0.045 THRUST_SPEED: f32 = 2.3 Player :: struct { pos: Vec2, angle: f32, vel: Vec2 } Bullet :: struct { pos: Vec2, vel: Vec2, } GameState :: struct { dt: f32, keymap: map[string]Key, player: Player, bullets: [dynamic]Bullet, weapon: f32, } 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, player = Player { pos = Vec2{BW / 2, BH / 2}, }, } 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(.D) { horizontal = 1 } if rl.IsKeyDown(.A) { horizontal = -1 } if rl.IsKeyDown(.W) { vertical = -1 } if rl.IsKeyDown(.S) { vertical = 1 } speed :f32 = 600 player.vel += rl.Vector2Normalize(Vec2{horizontal, vertical}) * (speed * dt) if rl.IsMouseButtonDown(rl.MouseButton.LEFT) && weapon >= WEAPON_ROF { angle := player.angle - get_rand_angle(0, 10) + (5 * rl.DEG2RAD) b_vel := Vec2{ math.cos(angle) , math.sin(angle) } * BULLET_SPEED append(&s.bullets, Bullet{player.pos, b_vel}) weapon = 0 } } update :: proc(using s: ^GameState) { player.vel *= 0.9 player.pos += player.vel * (THRUST_SPEED * s.dt) m_pos, p_pos := rl.GetMousePosition(), player.pos player.angle = math.atan2(m_pos.y - p_pos.y, m_pos.x - p_pos.x) for i := len(s.bullets) - 1; i >= 0; i -= 1 { if ( s.bullets[i].pos.x < 0 || s.bullets[i].pos.x > BW || s.bullets[i].pos.y < 0 || s.bullets[i].pos.y > BH) { unordered_remove(&s.bullets, i) continue } s.bullets[i].pos += s.bullets[i].vel } weapon += dt } draw :: proc(using s: ^GameState) { rl.DrawCircleV(player.pos, 10, rl.BLACK) rect := Rect{player.pos.x, player.pos.y, 15, 5} rl.DrawRectanglePro(rect, Vec2{0,2.5}, player.angle * rl.RAD2DEG, rl.BLACK) m_pos := rl.GetMousePosition() reticle_size :f32 = 50 reticle_rect := Rect{m_pos.x - reticle_size / 2, m_pos.y- reticle_size / 2, reticle_size, reticle_size} color := Color{255, 0, 0, 172} rl.DrawRectangleRoundedLines(reticle_rect, 0.2, 5, 5, color) rl.DrawCircleV(m_pos, 3, color) // Draw Bullets for i := 0; i < len(s.bullets); i += 1 { rl.DrawLineV(s.bullets[i].pos, s.bullets[i].pos - s.bullets[i].vel, rl.BLACK) } } main :: proc() { rl.SetTraceLogLevel(.ERROR) rl.InitWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "F&M") rl.SetTargetFPS(60) rl.DisableCursor() 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() }