diff options
| author | Freya Murphy <freya@freyacat.org> | 2025-11-14 23:30:05 -0500 |
|---|---|---|
| committer | Freya Murphy <freya@freyacat.org> | 2025-11-14 23:30:05 -0500 |
| commit | 65f5143d3e01e111afb960451e0741ddb37be240 (patch) | |
| tree | d59bc1e885aa31743fd87ebadab8e1728e2cd683 /dungeon | |
| parent | graphics: use 32bit color for atlas (diff) | |
| download | DungeonCrawl-65f5143d3e01e111afb960451e0741ddb37be240.tar.gz DungeonCrawl-65f5143d3e01e111afb960451e0741ddb37be240.tar.bz2 DungeonCrawl-65f5143d3e01e111afb960451e0741ddb37be240.zip | |
graphics: add text message rendering (and sans ig)
Diffstat (limited to 'dungeon')
| -rw-r--r-- | dungeon/src/lib.rs | 29 | ||||
| -rw-r--r-- | dungeon/src/msg.rs | 74 | ||||
| -rw-r--r-- | dungeon/src/player_input.rs | 3 |
3 files changed, 103 insertions, 3 deletions
diff --git a/dungeon/src/lib.rs b/dungeon/src/lib.rs index a475f95..0c9e055 100644 --- a/dungeon/src/lib.rs +++ b/dungeon/src/lib.rs @@ -5,6 +5,7 @@ pub mod astar; pub mod bsp; pub mod entity; pub mod map; +pub mod msg; pub mod player_input; pub mod pos; @@ -16,10 +17,23 @@ use rand::{ use crate::{ entity::{Entity, Player}, map::Floor, + msg::Message, player_input::PlayerInput, pos::FPos, }; +/// Lets the caller know what has +/// changed in the game state this +/// tick +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum UpdateResult { + /// Default, entities have moved + EntityMovement, + /// Message on screen updated. + /// Contains if a char was added. + MessageUpdated(bool), +} + /// The `Dungeon` type represents the game state of the /// dungeon crawler. #[derive(Debug, Clone)] @@ -27,6 +41,7 @@ pub struct Dungeon { pub floor: Floor, pub player: Player, pub enemies: Vec<Entity>, + pub msg: Message, seed: u64, rng: SmallRng, } @@ -48,11 +63,13 @@ impl Dungeon { let player = Player::new(floor.player_start()); // TODO: Randomize enemy positions/types let enemies = vec![Entity::zombie(floor.random_walkable_pos(&mut rng))]; + let msg = Message::empty(); Self { floor, player, enemies, + msg, seed, rng, } @@ -91,9 +108,15 @@ impl Dungeon { &mut self.rng } - pub fn update(&mut self, player_input: PlayerInput, delta_time: f32) { - self.act_player(player_input, delta_time); - self.act_non_players(delta_time); + pub fn update(&mut self, player_input: PlayerInput, delta_time: f32) -> UpdateResult { + if self.msg.visible() { + let changed = self.msg.update(player_input); + UpdateResult::MessageUpdated(changed) + } else { + self.act_player(player_input, delta_time); + self.act_non_players(delta_time); + UpdateResult::EntityMovement + } } fn act_player(&mut self, player_input: PlayerInput, delta_time: f32) { diff --git a/dungeon/src/msg.rs b/dungeon/src/msg.rs new file mode 100644 index 0000000..68a6cbd --- /dev/null +++ b/dungeon/src/msg.rs @@ -0,0 +1,74 @@ +//! The `msg` crate contains the core functionality for +//! the on screen message. + +use std::time::{Duration, Instant}; + +use crate::player_input::PlayerInput; + +/// Duration between each character printed +const DURATION_PER: Duration = Duration::from_millis(100); + +#[derive(Debug, Clone)] +pub struct Message { + text: Option<Vec<u8>>, + end: usize, + waiting: bool, + last: Instant, +} +impl Message { + /// Returns the default empty message + pub fn empty() -> Self { + Self { + text: None, + end: 0, + waiting: false, + last: Instant::now(), + } + } + + /// Sets string as the current onscreen message + pub fn set_message(&mut self, msg: &str) { + let bytes = msg.bytes().collect(); + self.text = Some(bytes); + self.end = 0; + } + + /// Attempts to update the message on screen. + /// Returns true if a character was printed + pub fn update(&mut self, input: PlayerInput) -> bool { + let Some(text) = &self.text else { return false }; + + if self.end >= text.len() { + if input.interact { + self.text = None; + } + return false; + } + + if self.waiting && !input.interact { + return false; + } + + if self.last.elapsed() < DURATION_PER { + return false; + } + self.last = Instant::now(); + + if text[self.end] == b'.' { + self.waiting = true; + } + + self.end += 1; + true + } + + /// Returns the current ascii message (if exists) + pub fn current(&self) -> Option<&[u8]> { + self.text.as_ref().map(|text| &text[..self.end]) + } + + /// Returns if the message box is visible + pub const fn visible(&self) -> bool { + self.text.is_some() + } +} diff --git a/dungeon/src/player_input.rs b/dungeon/src/player_input.rs index aa0ef14..ddaad9f 100644 --- a/dungeon/src/player_input.rs +++ b/dungeon/src/player_input.rs @@ -12,5 +12,8 @@ pub struct PlayerInput { /// (eg if the player is holding multiple keys at once, /// or a joystick) pub direction: Option<Direction>, + /// If the player is currently attempting to interact + /// with some object, entity, etc. + pub interact: bool, // other player actions are to be added later } |