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()?),
})
}
renderer: Renderer,
event_pump: EventPump,
sprites: SpriteManager,
- state: Box<dyn AppState>,
+ states: Vec<Box<dyn AppState>>,
pub ctrl_man: ControllerManager,
}
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<StateChange> {
for event in self.event_pump.poll_iter() {
self.ctrl_man.handle_event(&event);
match event {
keycode: Some(Keycode::Escape),
..
} => {
- return Err(())
+ return Some(StateChange::Pop)
}
Event::KeyDown {
keycode: Some(Keycode::F11),
} => {
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<dyn AppState>),
+ 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<StateChange>;
fn render(&mut self, renderer: &mut Renderer, sprites: &SpriteManager);
- fn handle_event(&mut self, event: Event);
+ fn handle_event(&mut self, event: Event) -> Option<StateChange>;
}
type Bollar = Vec<Box<dyn Boll>>;
impl AppState for ActiveState {
fn enter(&mut self, _ctrl_man: &ControllerManager) {}
- fn update(&mut self, dt: Duration) {
+ fn update(&mut self, dt: Duration) -> Option<StateChange> {
for b in &mut self.bolls {
b.update();
}
ns if ns > (NS_PER_FRAME + 90_0000).nanoseconds() => self.change_boll_count(-100),
_ => {}
}
+
+ None
}
fn render(&mut self, renderer: &mut Renderer, sprites: &SpriteManager) {
println!("number of bolls: {}", self.bolls.len());
}
- fn handle_event(&mut self, event: Event) {
+ fn handle_event(&mut self, event: Event) -> Option<StateChange> {
match event {
Event::KeyDown {
keycode: Some(Keycode::KpPlus),
))),
_ => {}
}
+ None
}
}
use AppState;
+use ActiveState;
use common::{Point2D, Radians};
+use core::app::StateChange;
use core::controller::Controller;
use core::controller::ControllerManager;
use core::level::Level;
fn leave(&mut self) {}
- fn update(&mut self, dt: Duration) {
+ fn update(&mut self, dt: Duration) -> Option<StateChange> {
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<StateChange> {
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();
}
}
_ => {}
}
+ None
}
}