From eb253fcc25b0af3ec7b804ea8e1b73426564883b Mon Sep 17 00:00:00 2001 From: =?utf8?q?Tomas=20Wenstr=C3=B6m?= Date: Tue, 26 Jan 2021 20:51:26 +0100 Subject: [PATCH] Use stack of app states --- src/core/app.rs | 76 +++++++++++++++++++++++++++++++++++++++++++------------- src/core/game.rs | 14 +++++++++-- 2 files changed, 71 insertions(+), 19 deletions(-) diff --git a/src/core/app.rs b/src/core/app.rs index 99b24ac..b4d2c01 100644 --- a/src/core/app.rs +++ b/src/core/app.rs @@ -72,7 +72,7 @@ impl AppBuilder { renderer, event_pump, sprites, - state: self.state.unwrap_or_else(|| Box::new(ActiveState::new(screen))), + states: vec!(self.state.unwrap_or_else(|| Box::new(ActiveState::new(screen)))), ctrl_man: ControllerManager::new(context.joystick()?, context.haptic()?), }) } @@ -122,7 +122,7 @@ pub struct App { renderer: Renderer, event_pump: EventPump, sprites: SpriteManager, - state: Box, + states: Vec>, pub ctrl_man: ControllerManager, } @@ -141,26 +141,53 @@ impl App { pub fn start(&mut self) { let mut last_time = Instant::now(); - self.state.enter(&mut self.ctrl_man); + self.states[0].enter(&mut self.ctrl_man); - 'running: loop { - if let Err(_) = self.handle_events() { - break 'running; + loop { + if let Some(change) = self.handle_events() { + self.handle_state_change(change); } let duration = Instant::now() - last_time; last_time = Instant::now(); self.ctrl_man.update(duration); - self.state.update(duration); + + if let Some(state) = self.states.last_mut() { + if let Some(change) = state.update(duration) { + self.handle_state_change(change); + } + } else { + break; + } self.render(); } + } - self.state.leave(); + fn handle_state_change(&mut self, change: StateChange) { + match change { + StateChange::Push(mut state) => { + // if let Some(s) = self.states.last_mut() { + // s.pause(); + // } + state.enter(&mut self.ctrl_man); + self.states.push(state); + } + StateChange::Pop => { + if let Some(mut s) = self.states.pop() { + s.leave(); + } + } + StateChange::Exit => { + while let Some(mut s) = self.states.pop() { + s.leave(); + } + } + } } - fn handle_events(&mut self) -> Result<(), ()> { + fn handle_events(&mut self) -> Option { for event in self.event_pump.poll_iter() { self.ctrl_man.handle_event(&event); match event { @@ -169,7 +196,7 @@ impl App { keycode: Some(Keycode::Escape), .. } => { - return Err(()) + return Some(StateChange::Pop) } Event::KeyDown { keycode: Some(Keycode::F11), @@ -219,25 +246,37 @@ impl App { } => { println!("window focus lost") } - _ => self.state.handle_event(event), + _ => { + if let Some(state) = self.states.last_mut() { + return state.handle_event(event) + } else { + return Some(StateChange::Exit) + } + }, } } - Ok(()) + None } fn render(&mut self) { self.renderer.clear(); - self.state.render(&mut self.renderer, &mut self.sprites); + self.states.last_mut().unwrap().render(&mut self.renderer, &mut self.sprites); self.renderer.present(); } } +pub enum StateChange { + Push(Box), + Pop, + Exit, +} + pub trait AppState { fn enter(&mut self, ctrl_man: &ControllerManager); fn leave(&mut self); - fn update(&mut self, dt: Duration); + fn update(&mut self, dt: Duration) -> Option; fn render(&mut self, renderer: &mut Renderer, sprites: &SpriteManager); - fn handle_event(&mut self, event: Event); + fn handle_event(&mut self, event: Event) -> Option; } type Bollar = Vec>; @@ -288,7 +327,7 @@ impl ActiveState { impl AppState for ActiveState { fn enter(&mut self, _ctrl_man: &ControllerManager) {} - fn update(&mut self, dt: Duration) { + fn update(&mut self, dt: Duration) -> Option { for b in &mut self.bolls { b.update(); } @@ -298,6 +337,8 @@ impl AppState for ActiveState { ns if ns > (NS_PER_FRAME + 90_0000).nanoseconds() => self.change_boll_count(-100), _ => {} } + + None } fn render(&mut self, renderer: &mut Renderer, sprites: &SpriteManager) { @@ -396,7 +437,7 @@ impl AppState for ActiveState { println!("number of bolls: {}", self.bolls.len()); } - fn handle_event(&mut self, event: Event) { + fn handle_event(&mut self, event: Event) -> Option { match event { Event::KeyDown { keycode: Some(Keycode::KpPlus), @@ -412,5 +453,6 @@ impl AppState for ActiveState { ))), _ => {} } + None } } diff --git a/src/core/game.rs b/src/core/game.rs index 1e657cb..6c04969 100644 --- a/src/core/game.rs +++ b/src/core/game.rs @@ -1,5 +1,7 @@ use AppState; +use ActiveState; use common::{Point2D, Radians}; +use core::app::StateChange; use core::controller::Controller; use core::controller::ControllerManager; use core::level::Level; @@ -38,16 +40,23 @@ impl AppState for GameState { fn leave(&mut self) {} - fn update(&mut self, dt: Duration) { + fn update(&mut self, dt: Duration) -> Option { self.world.update(dt); + None } fn render(&mut self, renderer: &mut Renderer, sprites: &SpriteManager) { self.world.render(renderer, sprites); } - fn handle_event(&mut self, event: Event) { + fn handle_event(&mut self, event: Event) -> Option { match event { + Event::KeyDown { keycode: Some(Keycode::Escape), .. } => { + return Some(StateChange::Pop) + } + Event::KeyDown { keycode: Some(Keycode::Return), .. } => { + return Some(StateChange::Push(Box::new(ActiveState::new((800, 600))))) + } Event::KeyDown { keycode: Some(Keycode::Space), .. } => { self.world.level.regenerate(); } @@ -62,6 +71,7 @@ impl AppState for GameState { } _ => {} } + None } } -- 2.11.0