package main import rl "vendor:raylib" import "core:math" import "core:fmt" Player :: struct { pos: vec3, vel: vec3, dir: f32, radius: f32, thrust: f32, max_speed: f32, is_dodging: bool, can_dodge: bool, can_shoot: bool, is_invulnerable: bool, is_dead: bool } player_spawn :: proc(position: vec3) -> Player { return Player{ pos = position, radius = 1, max_speed = 40, dir = 0, vel = {-40, 0, 0}, can_dodge = true, can_shoot = true } } player_update :: proc(player: ^Player, game: ^Game, delta: f32) { using player pos += vel * delta mouse_ray := rl.GetMouseRay(rl.GetMousePosition(), game.camera) mouse_pos : vec3 hit := rl.GetRayCollisionQuad(mouse_ray, {-1000, -1000, 0}, {-1000, 1000, 0}, {1000, 1000, 0}, {1000, -1000, 0} ) if hit.hit { mouse_pos = hit.point } mouse_diff := mouse_pos - pos mouse_angle := math.atan2(-mouse_diff.y, mouse_diff.x) if !is_dead { if !is_dodging { dir = angle_rotate(dir, mouse_angle, math.PI * 2 * delta) dir_vector := get_vec_from_angle(dir) thrust = 0 if rl.IsKeyDown(rl.KeyboardKey.W) { thrust = 70 } if thrust > 0 { vel = rl.Vector3MoveTowards(vel, dir_vector * max_speed, thrust * delta) } } if thrust == 0 { vel = rl.Vector3MoveTowards(vel, {0, -30, 0}, 20 * delta) } if rl.IsMouseButtonPressed(rl.MouseButton.RIGHT) && can_dodge { is_dodging = true can_dodge = false timer_start(0.45, player, proc(data: rawptr) { player := transmute(^Player)data player.is_dodging = false }) timer_start(0.55, player, proc(data: rawptr) { player := transmute(^Player)data player.can_dodge = true }) } if rl.IsMouseButtonDown(rl.MouseButton.LEFT) && can_shoot { b := bullet_spawn(pos, dir) append(&game.bullets, b) can_shoot = false timer_start(0.1, player, proc(data: rawptr) { player := transmute(^Player)data player.can_shoot = true }) } } got_hit := false if !is_invulnerable && !is_dodging && !is_dead { for segment in Segments { if rl.Vector3DistanceSqrt(pos, segment.pos) < math.pow(radius + segment.radius, 2) { got_hit = true break } } } if got_hit { game.health -= 10 is_invulnerable = true timer_start(1, player, proc(data: rawptr) { plr := transmute(^Player)data plr.is_invulnerable = false }) if game.health <= 0 && !is_dead { is_dead = true } } } player_draw :: proc(player: ^Player) { using player dir_vector := get_vec_from_angle(dir) color := rl.GREEN if is_dodging { color = rl.GRAY } if is_invulnerable { color = rl.YELLOW } rl.DrawCircle3D(pos, radius, vec3up, 0, color) rl.DrawLine3D(pos, pos + dir_vector * radius, rl.BLACK) rl.DrawLine3D(pos, pos + vel, rl.RED) }