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`.
This commit is contained in:
2026-05-03 18:14:46 +02:00
parent b639531841
commit 7fb001faab
7 changed files with 54 additions and 3 deletions
+8
View File
@@ -65,6 +65,7 @@ impl App {
.board .board
.change_resize(&window_area, state.skirmish.side_panel); .change_resize(&window_area, state.skirmish.side_panel);
} }
AppEvent::Tick => self.update()?,
} }
} }
@@ -90,4 +91,11 @@ impl App {
handle_keybindings(self, key_event); handle_keybindings(self, key_event);
Ok(()) Ok(())
} }
fn update(&mut self) -> Result<()> {
if let Some(state) = self.states_mut() {
state.skirmish.update(&self.args);
}
Ok(())
}
} }
+1
View File
@@ -35,6 +35,7 @@ impl GameStates {
false, false,
), ),
side_panel: false, side_panel: false,
turn_counter: 0,
}, },
perk_decks: PerkDecksState { perk_decks: PerkDecksState {
id: 2, id: 2,
+12 -1
View File
@@ -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)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct SkirmishState { pub struct SkirmishState {
@@ -6,4 +6,15 @@ pub struct SkirmishState {
pub name: &'static str, pub name: &'static str,
pub board: BoardState, pub board: BoardState,
pub side_panel: bool, 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;
}
} }
+1
View File
@@ -5,6 +5,7 @@ use std::sync::mpsc::Sender;
pub enum AppEvent { pub enum AppEvent {
Input(KeyEvent), Input(KeyEvent),
Resize(u16, u16), Resize(u16, u16),
Tick,
} }
/// Reads *all* crossterm events and forwards the ones we care about. /// Reads *all* crossterm events and forwards the ones we care about.
+2
View File
@@ -1,5 +1,7 @@
mod audio; mod audio;
mod events; mod events;
mod tick;
pub use audio::{AudioCmd, SoundrackParts, Soundtrack, handle_audio}; pub use audio::{AudioCmd, SoundrackParts, Soundtrack, handle_audio};
pub use events::{AppEvent, handle_events}; pub use events::{AppEvent, handle_events};
pub use tick::spawn_tick_thread;
+22
View File
@@ -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<AppEvent>, 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);
}
}
});
}
+8 -2
View File
@@ -10,12 +10,14 @@ use std::{
use war_in_tunnels::{ use war_in_tunnels::{
app::{ app::{
App, App,
threads::{AppEvent, AudioCmd, handle_audio, handle_events}, threads::{AppEvent, AudioCmd, handle_audio, handle_events, spawn_tick_thread},
}, },
cli::{Cli, get_args}, cli::{Cli, get_args},
logs::init_logger, logs::init_logger,
}; };
const TICK_MS: u64 = 33;
/// Starts the terminal UI application. /// Starts the terminal UI application.
/// ///
/// The function follows the steps outlined in the modulelevel documentation. /// The function follows the steps outlined in the modulelevel documentation.
@@ -34,7 +36,11 @@ fn main() -> Result<()> {
// }); // });
thread::spawn(move || { 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::<AudioCmd>(); let (audio_tx, audio_rx) = channel::<AudioCmd>();