speech bubbles and delays
This commit is contained in:
+37
-3
@@ -1,10 +1,23 @@
|
||||
use crate::log::LogLine;
|
||||
use crate::script::{Action, Direction, ScriptHost};
|
||||
use crate::script::ScriptHost;
|
||||
use std::cell::{Ref, RefCell, RefMut};
|
||||
use std::rc::Rc;
|
||||
use std::time::Duration;
|
||||
use crate::board::Board;
|
||||
use crate::utils::{ObjectId, Solid};
|
||||
use crate::utils::{Action, Direction, ObjectId, Solid};
|
||||
|
||||
/// How long a `say()` speech bubble stays on screen, in seconds.
|
||||
pub const SAY_DURATION: f64 = 3.0;
|
||||
|
||||
/// An active speech bubble emitted by a scripted object via `say()`.
|
||||
pub struct SpeechBubble {
|
||||
/// The object whose `say()` call created this bubble.
|
||||
pub object_id: ObjectId,
|
||||
/// The text to display.
|
||||
pub text: String,
|
||||
/// Seconds remaining before the bubble disappears.
|
||||
pub remaining: f64,
|
||||
}
|
||||
|
||||
/// Holds the active game world and provides game-logic operations.
|
||||
///
|
||||
@@ -22,6 +35,8 @@ pub struct GameState {
|
||||
pub log: Vec<LogLine>,
|
||||
/// The Rhai scripting runtime driving this board's scripted objects.
|
||||
scripts: ScriptHost,
|
||||
/// Active speech bubbles from `say()` calls, displayed by the front-end over the board.
|
||||
pub speech_bubbles: Vec<SpeechBubble>,
|
||||
}
|
||||
|
||||
impl GameState {
|
||||
@@ -37,6 +52,7 @@ impl GameState {
|
||||
board,
|
||||
log: Vec::new(),
|
||||
scripts,
|
||||
speech_bubbles: Vec::new(),
|
||||
};
|
||||
// Surface any compile-time script errors collected during ScriptHost::new.
|
||||
state.drain_errors();
|
||||
@@ -73,8 +89,10 @@ impl GameState {
|
||||
/// then resolves the actions that were promoted onto the board queue.
|
||||
pub fn tick(&mut self, dt: Duration) {
|
||||
let secs = dt.as_secs_f64();
|
||||
self.scripts.advance_timers(secs);
|
||||
self.scripts.run_tick(secs);
|
||||
// Expire speech bubbles before resolving new actions so a fresh say()
|
||||
// this frame isn't immediately culled.
|
||||
self.speech_bubbles.retain_mut(|b| { b.remaining -= secs; b.remaining > 0.0 });
|
||||
self.resolve();
|
||||
}
|
||||
|
||||
@@ -98,6 +116,7 @@ impl GameState {
|
||||
// below also borrows `self`.
|
||||
let mut logs: Vec<LogLine> = Vec::new();
|
||||
let mut bumps: Vec<(ObjectId, i64)> = Vec::new();
|
||||
let mut new_bubbles: Vec<SpeechBubble> = Vec::new();
|
||||
{
|
||||
let mut board = self.board_mut();
|
||||
for ba in actions {
|
||||
@@ -118,10 +137,25 @@ impl GameState {
|
||||
if present { obj.tags.insert(tag); } else { obj.tags.remove(&tag); }
|
||||
}
|
||||
}
|
||||
// Replace any existing bubble from this object so repeated say() calls
|
||||
// don't stack visually — the new text resets the timer.
|
||||
Action::Say(text) => new_bubbles.push(SpeechBubble {
|
||||
object_id: ba.source,
|
||||
text,
|
||||
remaining: SAY_DURATION,
|
||||
}),
|
||||
// Delays are consumed by ScriptHost::drain and never reach the board queue.
|
||||
Action::Delay(_) => {}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
self.log.extend(logs);
|
||||
for bubble in new_bubbles {
|
||||
// One bubble per object: replace the existing one if present.
|
||||
self.speech_bubbles.retain(|b| b.object_id != bubble.object_id);
|
||||
self.speech_bubbles.push(bubble);
|
||||
}
|
||||
for (bumped, bumper) in bumps {
|
||||
self.scripts.run_bump(bumped, bumper);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user