summaryrefslogtreecommitdiff
path: root/dungeon
diff options
context:
space:
mode:
authorFreya Murphy <freya@freyacat.org>2025-11-20 10:07:41 -0500
committerFreya Murphy <freya@freyacat.org>2025-11-20 10:07:41 -0500
commit65b69d06200d7757bb7f9f9ae3645a7366d08826 (patch)
treeeb5897af68d7a3a103a5b318b01c2c1d56da44c4 /dungeon
parentdungeon: inventory usage (diff)
downloadDungeonCrawl-65b69d06200d7757bb7f9f9ae3645a7366d08826.tar.gz
DungeonCrawl-65b69d06200d7757bb7f9f9ae3645a7366d08826.tar.bz2
DungeonCrawl-65b69d06200d7757bb7f9f9ae3645a7366d08826.zip
dungeon: entity death
Diffstat (limited to 'dungeon')
-rw-r--r--dungeon/src/entity.rs31
-rw-r--r--dungeon/src/lib.rs73
2 files changed, 94 insertions, 10 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) {