use boll::*;
-use common::{Point2D, Rect};
use core::controller::ControllerManager;
use core::render::Renderer;
-use point; // defined in common, but loaded from main...
+use geometry::{Point, Dimension};
+use point;
use rand::Rng;
use sdl2::event::{Event, WindowEvent};
use sdl2::keyboard::Keycode;
#[derive(Default)]
pub struct AppBuilder {
- resolution: Rect<u16>,
+ resolution: Dimension<u16>,
state: Option<Box<dyn AppState>>,
title: Option<String>,
}
impl AppBuilder {
pub fn with_resolution(mut self, width: u16, height: u16) -> Self {
- self.resolution = Rect { width, height };
+ self.resolution = Dimension { width, height };
self
}
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(&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(&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() {
+ if let Some(change) = state.handle_event(event) {
+ return Some(change);
+ }
+ } 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, &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>>;
#[derive(Default)]
pub struct ActiveState {
- screen: Rect<u32>,
+ screen: Dimension<u32>,
bolls: Bollar,
boll_size: u32,
mario_angle: f64,
ActiveState {
bolls: Bollar::new(),
boll_size: 1,
- screen: Rect::from(screen),
+ screen: Dimension::from(screen),
..Default::default()
}
}
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
}
}