player.zig (3711B)
1 const raylib = @import("raylib"); 2 const raymath = @import("raymath"); 3 4 const bullet = @import("./bullet.zig"); 5 const constants = @import("./constants.zig"); 6 const Timer = @import("./timer.zig"); 7 8 pub const Player = @This(); 9 10 pub const bullet_spawn_cooldown: f32 = 0.4; 11 const acceleration: f32 = 10000.0; 12 const friction: f32 = 10000.0; 13 const max_delta: f32 = 1.0 / 30.0; 14 const starting_max_health: u8 = 255; 15 16 movement_speed: f32 = 140.0, 17 bullet_speed: f32 = 300.0, 18 health_regen_amount: f32 = 50, 19 size: raylib.Vector2 = .{ .x = 50, .y = 50 }, 20 position: raylib.Vector2 = .{}, 21 velocity: raylib.Vector2 = .{}, 22 max_health: f32 = starting_max_health, 23 health: f32 = starting_max_health, 24 25 health_regen_timer: Timer = .{ 26 .duration = 5.0, 27 }, 28 29 bullet_pool: bullet.Pool, 30 31 pub fn render(self: *Player) void { 32 raylib.DrawRectangleV( 33 self.position, 34 self.size, 35 raylib.BLUE, 36 ); 37 38 self.bullet_pool.render(.{ 39 .x = @floatFromInt(raylib.GetScreenWidth()), 40 .y = @floatFromInt(raylib.GetScreenHeight()), 41 }); 42 } 43 44 pub fn tick(self: *Player) void { 45 if (self.health_regen_timer.tick(raylib.GetFrameTime())) { 46 self.health = @min(self.health + self.health_regen_amount, self.max_health); 47 } 48 } 49 50 pub fn handleDamage(self: *Player, damage: f32) void { 51 self.health -= damage; 52 } 53 54 pub fn handleMovement(self: *Player) void { 55 const delta: f32 = @min(raylib.GetFrameTime(), max_delta); 56 57 var input: raymath.Vector2 = .{}; 58 if (raylib.IsKeyDown(raylib.KEY_D)) input.x += 1; 59 if (raylib.IsKeyDown(raylib.KEY_A)) input.x -= 1; 60 if (raylib.IsKeyDown(raylib.KEY_W)) input.y -= 1; 61 if (raylib.IsKeyDown(raylib.KEY_S)) input.y += 1; 62 63 const is_moving = input.x != 0 or input.y != 0; 64 65 if (is_moving) { 66 const target = raymath.Vector2Normalize(input); 67 68 const desired: raymath.Vector2 = .{ 69 .x = target.x * self.movement_speed, 70 .y = target.y * self.movement_speed, 71 }; 72 const t = @min(1.0, acceleration * delta / self.movement_speed); 73 self.velocity.x += (desired.x - self.velocity.x) * t; 74 self.velocity.y += (desired.y - self.velocity.y) * t; 75 } else { 76 const speed = raymath.Vector2Length(@bitCast(self.velocity)); 77 if (speed > 0) { 78 const new_speed = @max(0, speed - friction * delta); 79 const norm = raymath.Vector2Normalize(@bitCast(self.velocity)); 80 self.velocity = .{ 81 .x = norm.x * new_speed, 82 .y = norm.y * new_speed, 83 }; 84 } 85 } 86 87 self.position.x += self.velocity.x * delta; 88 self.position.y += self.velocity.y * delta; 89 90 const max_x: f32 = @as(f32, @floatFromInt(raylib.GetScreenWidth())) - self.size.x; 91 const max_y: f32 = @as(f32, @floatFromInt(raylib.GetScreenHeight())) - self.size.y; 92 self.position.x = @max(0, @min(max_x, self.position.x)); 93 self.position.y = @max(0, @min(max_y, self.position.y)); 94 95 self.shoot(); 96 } 97 98 pub fn shoot(self: *Player) void { 99 if (self.bullet_pool.tick()) { 100 const mouse_pos = raylib.GetMousePosition(); 101 const center: raylib.Vector2 = .{ 102 .x = self.position.x + (self.size.x / 2), 103 .y = self.position.y + (self.size.y / 2), 104 }; 105 const dir = raymath.Vector2Normalize(.{ 106 .x = mouse_pos.x - center.x, 107 .y = mouse_pos.y - center.y, 108 }); 109 const bullet_vel: raylib.Vector2 = .{ 110 .x = dir.x * self.bullet_speed, 111 .y = dir.y * self.bullet_speed, 112 }; 113 self.bullet_pool.spawn( 114 center, 115 bullet_vel, 116 raylib.BLUE, 117 constants.player_bullet_damage, 118 ); 119 } 120 }