X-Git-Url: http://dolda2000.com/gitweb/?a=blobdiff_plain;f=src%2Fcore%2Fapp.rs;h=434f56c53a1273d37e9856acf20bd522e2d4a26d;hb=1f42d724d84ed1c014ff40ccc91058472391be0c;hp=cac2a375489c86c844ec22e38104d4d1507610d9;hpb=a82a4d23f7e76f6899919fda31e7c29e68d319bb;p=kaka%2Frust-sdl-test.git diff --git a/src/core/app.rs b/src/core/app.rs index cac2a37..434f56c 100644 --- a/src/core/app.rs +++ b/src/core/app.rs @@ -1,15 +1,13 @@ use boll::*; -use common::{Point2D, Rect}; +use common::{Point, Dimension}; use core::controller::ControllerManager; +use core::render::Renderer; use point; // defined in common, but loaded from main... use rand::Rng; use sdl2::event::{Event, WindowEvent}; -use sdl2::gfx::primitives::DrawRenderer; use sdl2::keyboard::Keycode; -use sdl2::pixels::Color; use sdl2::rect::Rect as SDLRect; -use sdl2::render::{BlendMode, Canvas}; -use sdl2::video::{FullscreenType, SwapInterval, Window}; +use sdl2::video::SwapInterval; use sdl2::{EventPump, VideoSubsystem}; use sprites::SpriteManager; use std::f32::consts::PI; @@ -20,14 +18,14 @@ const NS_PER_FRAME: u32 = 1_000_000_000 / FPS; #[derive(Default)] pub struct AppBuilder { - resolution: Rect, + resolution: Dimension, state: Option>, title: Option, } impl AppBuilder { pub fn with_resolution(mut self, width: u16, height: u16) -> Self { - self.resolution = Rect { width, height }; + self.resolution = Dimension { width, height }; self } @@ -61,23 +59,20 @@ impl AppBuilder { .unwrap(); context.mouse().show_cursor(false); - let mut canvas = window.into_canvas().build().unwrap(); - canvas.set_blend_mode(BlendMode::Add); - canvas.set_draw_color(Color::RGB(0, 0, 0)); - canvas.clear(); - canvas.present(); + let canvas = window.into_canvas().build().unwrap(); + let sprites = SpriteManager::new(canvas.texture_creator()); + let screen = canvas.output_size().unwrap(); + let renderer = Renderer::new(canvas); video.gl_set_swap_interval(SwapInterval::VSync)?; let event_pump = context.event_pump()?; - let sprites = SpriteManager::new(canvas.texture_creator()); - let screen = canvas.output_size().unwrap(); Ok(App { - canvas, + 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()?), }) } @@ -124,10 +119,10 @@ impl AppBuilder { } pub struct App { - canvas: Canvas, + renderer: Renderer, event_pump: EventPump, sprites: SpriteManager, - state: Box, + states: Vec>, pub ctrl_man: ControllerManager, } @@ -146,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 { @@ -174,20 +196,13 @@ impl App { keycode: Some(Keycode::Escape), .. } => { - return Err(()) + return Some(StateChange::Pop) } Event::KeyDown { keycode: Some(Keycode::F11), .. } => { - match self.canvas.window().fullscreen_state() { - FullscreenType::Off => self - .canvas - .window_mut() - .set_fullscreen(FullscreenType::Desktop), - _ => self.canvas.window_mut().set_fullscreen(FullscreenType::Off), - } - .unwrap(); + self.renderer.toggle_fullscreen(); } Event::Window { win_event: WindowEvent::Resized(x, y), @@ -231,33 +246,44 @@ 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.canvas.set_draw_color(Color::RGB(0, 0, 0)); - self.canvas.clear(); - self.state.render(&mut self.canvas, &mut self.sprites); - self.canvas.present(); + self.renderer.clear(); + 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 render(&mut self, canvas: &mut Canvas, sprites: &SpriteManager); - fn handle_event(&mut self, event: Event); + fn update(&mut self, dt: Duration) -> Option; + fn render(&mut self, renderer: &mut Renderer, sprites: &SpriteManager); + fn handle_event(&mut self, event: Event) -> Option; } type Bollar = Vec>; #[derive(Default)] pub struct ActiveState { - screen: Rect, + screen: Dimension, bolls: Bollar, boll_size: u32, mario_angle: f64, @@ -268,7 +294,7 @@ impl ActiveState { ActiveState { bolls: Bollar::new(), boll_size: 1, - screen: Rect::from(screen), + screen: Dimension::from(screen), ..Default::default() } } @@ -301,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(); } @@ -311,9 +337,11 @@ impl AppState for ActiveState { ns if ns > (NS_PER_FRAME + 90_0000).nanoseconds() => self.change_boll_count(-100), _ => {} } + + None } - fn render(&mut self, canvas: &mut Canvas, sprites: &SpriteManager) { + fn render(&mut self, renderer: &mut Renderer, sprites: &SpriteManager) { /* draw square of blocks */ { let blocks = 20; let size = 32; @@ -323,15 +351,14 @@ impl AppState for ActiveState { ); let block = sprites.get("block"); for i in 0..blocks { - canvas - .copy( + renderer + .blit( block, None, SDLRect::new((i) * size + offset.x, offset.y, size as u32, size as u32), - ) - .unwrap(); - canvas - .copy( + ); + renderer + .blit( block, None, SDLRect::new( @@ -340,10 +367,9 @@ impl AppState for ActiveState { size as u32, size as u32, ), - ) - .unwrap(); - canvas - .copy( + ); + renderer + .blit( block, None, SDLRect::new( @@ -352,10 +378,9 @@ impl AppState for ActiveState { size as u32, size as u32, ), - ) - .unwrap(); - canvas - .copy( + ); + renderer + .blit( block, None, SDLRect::new( @@ -364,8 +389,7 @@ impl AppState for ActiveState { size as u32, size as u32, ), - ) - .unwrap(); + ); } } @@ -378,8 +402,8 @@ impl AppState for ActiveState { let radius = 110.0 + size as f32 * 0.5; let angle = (self.mario_angle as f32 - 90.0) * PI / 180.0; let offset2 = point!((angle.cos() * radius) as i32, (angle.sin() * radius) as i32); - canvas - .copy_ex( + renderer + .blit_ex( sprites.get("mario"), None, SDLRect::new( @@ -392,29 +416,20 @@ impl AppState for ActiveState { sdl2::rect::Point::new(size / 2, size / 2), false, false, - ) - .unwrap(); + ); self.mario_angle = (self.mario_angle + 1.0) % 360.0; } /* draw circles and ellipses*/ { let p = point!((self.screen.width / 2) as i16, (self.screen.height / 2) as i16); - canvas - .circle(p.x, p.y, 100, Color::RGB(255, 255, 255)) - .unwrap(); - canvas - .aa_circle(p.x, p.y, 110, Color::RGB(255, 255, 255)) - .unwrap(); - canvas - .ellipse(p.x, p.y, 50, 100, Color::RGB(255, 255, 255)) - .unwrap(); - canvas - .aa_ellipse(p.x, p.y, 110, 55, Color::RGB(255, 255, 255)) - .unwrap(); + renderer.circle(p, 100, (255, 255, 255)); + renderer.circle(p, 110, (255, 255, 255)); + renderer.ellipse(p, (50, 100), (255, 255, 255)); + renderer.ellipse(p, (110, 55), (255, 255, 255)); } for b in &self.bolls { - b.draw(canvas, self.boll_size); + b.draw(renderer, self.boll_size); } } @@ -422,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), @@ -438,5 +453,6 @@ impl AppState for ActiveState { ))), _ => {} } + None } }