From 7fb001faabddada3e6dc8c8bcde16e78e51e8e2b Mon Sep 17 00:00:00 2001 From: GarandPLG Date: Sun, 3 May 2026 18:14:46 +0200 Subject: [PATCH] Add tick thread and Skirmish state update Introduce `AppEvent::Tick` and a background thread that emits timed events. `App` now handles `Tick` by calling a new `update` method, which advances the board and increments a `turn_counter` in `SkirmishState`. Add required imports, fields, and the `spawn_tick_thread` call in `main`. --- src/app/app.rs | 8 ++++++++ src/app/state.rs | 1 + src/app/states/skirmish.rs | 13 ++++++++++++- src/app/threads/events.rs | 1 + src/app/threads/mod.rs | 2 ++ src/app/threads/tick.rs | 22 ++++++++++++++++++++++ src/main.rs | 10 ++++++++-- 7 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 src/app/threads/tick.rs diff --git a/src/app/app.rs b/src/app/app.rs index bf84680..944529e 100644 --- a/src/app/app.rs +++ b/src/app/app.rs @@ -65,6 +65,7 @@ impl App { .board .change_resize(&window_area, state.skirmish.side_panel); } + AppEvent::Tick => self.update()?, } } @@ -90,4 +91,11 @@ impl App { handle_keybindings(self, key_event); Ok(()) } + + fn update(&mut self) -> Result<()> { + if let Some(state) = self.states_mut() { + state.skirmish.update(&self.args); + } + Ok(()) + } } diff --git a/src/app/state.rs b/src/app/state.rs index 870a269..8eed5ba 100644 --- a/src/app/state.rs +++ b/src/app/state.rs @@ -35,6 +35,7 @@ impl GameStates { false, ), side_panel: false, + turn_counter: 0, }, perk_decks: PerkDecksState { id: 2, diff --git a/src/app/states/skirmish.rs b/src/app/states/skirmish.rs index df072c0..e7c37be 100644 --- a/src/app/states/skirmish.rs +++ b/src/app/states/skirmish.rs @@ -1,4 +1,4 @@ -use crate::app::states::skirmish_states::BoardState; +use crate::{app::states::skirmish_states::BoardState, cli::Cli}; #[derive(Debug, Clone, PartialEq, Eq)] pub struct SkirmishState { @@ -6,4 +6,15 @@ pub struct SkirmishState { pub name: &'static str, pub board: BoardState, pub side_panel: bool, + pub turn_counter: u64, +} + +impl SkirmishState { + pub fn update(&mut self, cli: &Cli) { + self.board.advance_turn(); + + // if self.board.is_victory() {} + + self.turn_counter += 1; + } } diff --git a/src/app/threads/events.rs b/src/app/threads/events.rs index 57f17c4..3fbcf9b 100644 --- a/src/app/threads/events.rs +++ b/src/app/threads/events.rs @@ -5,6 +5,7 @@ use std::sync::mpsc::Sender; pub enum AppEvent { Input(KeyEvent), Resize(u16, u16), + Tick, } /// Reads *all* crossterm events and forwards the ones we care about. diff --git a/src/app/threads/mod.rs b/src/app/threads/mod.rs index b2d0250..f2b2e4b 100644 --- a/src/app/threads/mod.rs +++ b/src/app/threads/mod.rs @@ -1,5 +1,7 @@ mod audio; mod events; +mod tick; pub use audio::{AudioCmd, SoundrackParts, Soundtrack, handle_audio}; pub use events::{AppEvent, handle_events}; +pub use tick::spawn_tick_thread; diff --git a/src/app/threads/tick.rs b/src/app/threads/tick.rs new file mode 100644 index 0000000..b0e7277 --- /dev/null +++ b/src/app/threads/tick.rs @@ -0,0 +1,22 @@ +use crate::app::threads::AppEvent; +use std::{ + sync::mpsc::Sender, + thread, + time::{Duration, Instant}, +}; + +pub fn spawn_tick_thread(tx: Sender, interval_ms: u64) { + thread::spawn(move || { + let interval: Duration = Duration::from_millis(interval_ms); + loop { + if tx.send(AppEvent::Tick).is_err() { + break; + } + + let elapsed: Duration = Instant::now().elapsed(); + if interval > elapsed { + thread::sleep(interval - elapsed); + } + } + }); +} diff --git a/src/main.rs b/src/main.rs index 09b9723..3b037d5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,12 +10,14 @@ use std::{ use war_in_tunnels::{ app::{ App, - threads::{AppEvent, AudioCmd, handle_audio, handle_events}, + threads::{AppEvent, AudioCmd, handle_audio, handle_events, spawn_tick_thread}, }, cli::{Cli, get_args}, logs::init_logger, }; +const TICK_MS: u64 = 33; + /// Starts the terminal UI application. /// /// The function follows the steps outlined in the module‑level documentation. @@ -34,7 +36,11 @@ fn main() -> Result<()> { // }); thread::spawn(move || { - handle_events(app_event_tx); + handle_events(app_event_tx.clone()); + }); + + thread::spawn(move || { + spawn_tick_thread(app_event_tx, TICK_MS); }); let (audio_tx, audio_rx) = channel::();