summaryrefslogtreecommitdiff
path: root/dungeon/src/msg.rs
diff options
context:
space:
mode:
Diffstat (limited to 'dungeon/src/msg.rs')
-rw-r--r--dungeon/src/msg.rs74
1 files changed, 74 insertions, 0 deletions
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()
+ }
+}