diff --git a/examples/survivor_game/src/game.rs b/examples/survivor_game/src/game.rs index 0c2f98f..c9efda8 100644 --- a/examples/survivor_game/src/game.rs +++ b/examples/survivor_game/src/game.rs @@ -5,6 +5,12 @@ use crate::projectile::Projectile; use crate::enemy::Enemy; use crate::wave::WaveSystem; +pub struct FrameEvents { + pub shot_fired: bool, + pub enemies_killed: u32, + pub player_hit: bool, +} + pub struct GameState { pub player: Player, pub projectiles: Vec, @@ -26,18 +32,28 @@ impl GameState { } } - pub fn try_shoot(&mut self, aim_dir: Vec3) { + pub fn try_shoot(&mut self, aim_dir: Vec3) -> bool { if self.player.fire_cooldown <= 0.0 { let origin = self.player.position + Vec3::new(0.0, 0.5, 0.0); self.projectiles.push(Projectile::new(origin, aim_dir, 20.0)); self.player.fire_cooldown = 0.2; + true + } else { + false } } - pub fn update(&mut self, input: &InputState, dt: f32) { + pub fn update(&mut self, input: &InputState, dt: f32) -> FrameEvents { + let mut events = FrameEvents { + shot_fired: false, + enemies_killed: 0, + player_hit: false, + }; + if self.game_over { - return; + return events; } + self.player.update(input, dt); self.player.fire_cooldown = (self.player.fire_cooldown - dt).max(0.0); @@ -64,5 +80,56 @@ impl GameState { // Remove dead enemies self.enemies.retain(|e| e.alive); + + // Collision: projectile vs enemy + let mut killed_enemies = Vec::new(); + let mut killed_projectiles = Vec::new(); + + for (pi, proj) in self.projectiles.iter().enumerate() { + for (ei, enemy) in self.enemies.iter().enumerate() { + let dist = (proj.position - enemy.position).length(); + if dist < 0.55 { + // projectile radius 0.15 + enemy radius 0.4 + killed_enemies.push(ei); + killed_projectiles.push(pi); + self.score += 100; + events.enemies_killed += 1; + } + } + } + + // Remove killed (reverse order to preserve indices) + killed_enemies.sort(); + killed_enemies.dedup(); + for &i in killed_enemies.iter().rev() { + self.enemies.remove(i); + } + killed_projectiles.sort(); + killed_projectiles.dedup(); + for &i in killed_projectiles.iter().rev() { + self.projectiles.remove(i); + } + + // Collision: enemy vs player + if self.player.invincible_timer <= 0.0 { + for enemy in self.enemies.iter() { + let dist = (enemy.position - self.player.position).length(); + if dist < 0.9 { + // player radius 0.5 + enemy radius 0.4 + self.player.hp -= 1; + self.player.invincible_timer = 1.0; + events.player_hit = true; + if self.player.hp <= 0 { + self.game_over = true; + } + break; + } + } + } + + // Update invincible timer + self.player.invincible_timer = (self.player.invincible_timer - dt).max(0.0); + + events } }