diff options
| author | Freya Murphy <freya@freyacat.org> | 2025-11-20 10:07:41 -0500 |
|---|---|---|
| committer | Freya Murphy <freya@freyacat.org> | 2025-11-20 10:07:41 -0500 |
| commit | 65b69d06200d7757bb7f9f9ae3645a7366d08826 (patch) | |
| tree | eb5897af68d7a3a103a5b318b01c2c1d56da44c4 | |
| parent | dungeon: inventory usage (diff) | |
| download | DungeonCrawl-65b69d06200d7757bb7f9f9ae3645a7366d08826.tar.gz DungeonCrawl-65b69d06200d7757bb7f9f9ae3645a7366d08826.tar.bz2 DungeonCrawl-65b69d06200d7757bb7f9f9ae3645a7366d08826.zip | |
dungeon: entity death
| -rw-r--r-- | dungeon/src/entity.rs | 31 | ||||
| -rw-r--r-- | dungeon/src/lib.rs | 73 | ||||
| -rw-r--r-- | game/src/lib.rs | 12 |
3 files changed, 102 insertions, 14 deletions
diff --git a/dungeon/src/entity.rs b/dungeon/src/entity.rs index 9af27bd..da807c2 100644 --- a/dungeon/src/entity.rs +++ b/dungeon/src/entity.rs @@ -67,6 +67,18 @@ impl Item { } } } + + /// Returns if this item is a bomb + #[must_use] + pub const fn is_bomb(self) -> bool { + matches!(self, Self::Bomb | Self::LargeBomb) + } + + /// Returns if this item is a potion + #[must_use] + pub const fn is_potion(self) -> bool { + matches!(self, Self::HealthPotion | Self::SpeedPotion) + } } /// Different speed entities can move @@ -308,6 +320,16 @@ impl Entity { _ => None, } } + + /// Returns if this entity is dead + pub const fn is_dead(&self) -> bool { + self.health == 0 && self.kind.initial_health() > 0 + } + + /// Returns if the entity is alive (or does not have/use health) + pub const fn is_alive(&self) -> bool { + !self.is_dead() + } } /// The current "weapon" level we have @@ -520,8 +542,13 @@ impl Dungeon { }; updater.update_entity(&mut self.player.entity); - for enemy in &mut self.entities { - updater.update_entity(enemy); + + for entity in &mut self.entities { + updater.update_entity(entity); + if entity.is_dead() { + // TODO: on entity death + } } + self.entities.retain(Entity::is_alive); } } diff --git a/dungeon/src/lib.rs b/dungeon/src/lib.rs index 0076f26..0fd3e0d 100644 --- a/dungeon/src/lib.rs +++ b/dungeon/src/lib.rs @@ -23,18 +23,40 @@ use crate::{ rng::DungeonRng, }; +/// Lets the caller know what actions +/// exactly the player has done +#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct PlayerAction { + // The player picked up an item + pub pickup_item: bool, + // The player dropped an item + pub drop_item: bool, + // The player moved + pub walk: bool, + // The player attacked + pub attack: bool, + // The player used a bomb + pub bomb: bool, + // The player used a potion + pub potion: bool, +} + /// Lets the caller know what has /// changed in the game state this /// tick -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum UpdateResult { - /// Default, entities have moved - EntityMovement, + /// Default, entities have moved, player done stuff + Default(PlayerAction), /// We have moved to the next floor NextFloor, /// Message on screen updated. /// Contains if a char was added. MessageUpdated(bool), + /// Game over :( + GameOver, + /// We have done nothing! + Nothing, } /// The `Dungeon` type represents the game state of the @@ -48,6 +70,7 @@ pub struct Dungeon { seed: u64, level_rng: DungeonRng, game_rng: DungeonRng, + game_over: bool, } impl Dungeon { /// Creates a new `Dungeon` with a provided seed. @@ -68,6 +91,7 @@ impl Dungeon { let player = Player::new(floor.player_start()); let entities = vec![]; let msg = Message::empty(); + let game_over = false; let mut dungeon = Self { floor, player, @@ -76,6 +100,7 @@ impl Dungeon { seed, level_rng, game_rng, + game_over, }; dungeon.spawn_enimies(); @@ -116,12 +141,32 @@ impl Dungeon { } pub fn update(&mut self, player_input: PlayerInput, delta_time: f32) -> UpdateResult { - if self.msg.visible() { + if self.game_over { + UpdateResult::Nothing + } else if self.msg.visible() { let changed = self.msg.update(player_input); UpdateResult::MessageUpdated(changed) } else { + let mut action = self.update_player(player_input); + + let curr_player_pos = self.player.entity.fpos; self.update_entities(player_input, delta_time); - self.update_player(player_input); + if self + .player + .entity + .fpos + .abs_diff(curr_player_pos) + .magnitude() > 0.0 + { + // player has moved + action.walk = true; + } + + if self.player.entity.health < 1 { + // player has died :( + self.game_over = true; + return UpdateResult::GameOver; + } if self.floor.get(self.player.entity.pos) == Tile::Stairs { // we are moving to a new floor @@ -132,11 +177,13 @@ impl Dungeon { return UpdateResult::NextFloor; } - UpdateResult::EntityMovement + UpdateResult::Default(action) } } - fn update_player(&mut self, player_input: PlayerInput) { + fn update_player(&mut self, player_input: PlayerInput) -> PlayerAction { + let mut action = PlayerAction::default(); + // update potion timer if let Some(timer) = self.player.potion_timer && Instant::now() > timer @@ -150,10 +197,15 @@ impl Dungeon { && self.player.active_inv_slot < self.player.inventory.len() { let item = self.player.inventory.remove(self.player.active_inv_slot); + action.potion = item.is_potion(); + action.bomb = item.is_bomb(); item.consume(self); } - // TODO: attack + if player_input.attack { + // TODO: attack + action.attack = true; + } // check for drop input if player_input.drop && self.player.active_inv_slot < self.player.inventory.len() { @@ -167,14 +219,19 @@ impl Dungeon { .player .active_inv_slot .max(self.player.inventory.len().saturating_sub(1)); + action.drop_item = true; } + // TODO: pickup items + // check for inv slot request if let Some(slot) = player_input.inv_slot && slot < PLAYER_INVENTORY_SIZE_USIZE { self.player.active_inv_slot = slot; } + + action } fn spawn_enimies(&mut self) { diff --git a/game/src/lib.rs b/game/src/lib.rs index f123326..b6d2fa4 100644 --- a/game/src/lib.rs +++ b/game/src/lib.rs @@ -88,9 +88,7 @@ impl Game { self.window.toggle_debug(); } if self.window.is_key_pressed(Key::F4) { - self.dungeon - .msg - .set_message("Lorem ipsum dolor sit amet consectetur adipiscing elit"); + self.dungeon.player.entity.health = 0; } // Update game state @@ -99,7 +97,9 @@ impl Game { .dungeon .update(inputs, self.window.delta_time().as_secs_f32()); match result { - UpdateResult::EntityMovement => {} + UpdateResult::Default(_action) => { + // TODO: make noises for player actions + } UpdateResult::NextFloor => { // TODO: stairs audio } @@ -108,6 +108,10 @@ impl Game { self.window.audio().speak.play(); } } + UpdateResult::GameOver => { + // TODO: player game over music, very sad + } + UpdateResult::Nothing => {} } // Draw a single frame |