From: Tomas Wenström Date: Fri, 15 Feb 2019 20:50:06 +0000 (+0100) Subject: Move boll handling and rendering into an app state X-Git-Url: http://git.dolda2000.com/gitweb/?p=kaka%2Frust-sdl-test.git;a=commitdiff_plain;h=95e3e10de390930a0f26317dae544f4a2c1bda2e Move boll handling and rendering into an app state --- diff --git a/src/app.rs b/src/app.rs index 746f98d..c8f8665 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,16 +1,29 @@ +use rand::Rng; +use sdl2::event::Event; use sdl2::EventPump; +use sdl2::keyboard::Keycode; use sdl2::pixels::Color; use sdl2::render::BlendMode; use sdl2::render::Canvas; use sdl2::video::Window; use {SCREEN_HEIGHT, SCREEN_WIDTH}; +use boll::*; +use common::Point2D; use sprites::SpriteManager; +use NS_PER_FRAME; + +macro_rules! point { // because I don't know how to import it from common.rs ... + ( $x:expr, $y:expr ) => { Point2D { x:$x, y:$y } }; +} + +pub type Nanoseconds = u64; pub struct App { pub canvas: Canvas, pub event_pump: EventPump, pub sprites: SpriteManager, + pub state: Box, } impl App { @@ -34,6 +47,7 @@ impl App { canvas, event_pump, sprites, + state: Box::new(ActiveState::new()), } } @@ -43,3 +57,84 @@ impl App { } } } + +pub trait AppState { + fn update(&mut self, dt: Nanoseconds); + fn render(&self, canvas: &mut Canvas); + fn leave(&self); + fn on_event(&mut self, event: Event); +} + +type Bollar = Vec>; + +pub struct ActiveState { + bolls: Bollar, + boll_size: u32, +} + +impl ActiveState { + fn new() -> ActiveState { + ActiveState { + bolls: Bollar::new(), + boll_size: 1, + } + } + + fn change_boll_count(&mut self, delta: i32) { + if delta > 0 { + for _i in 0..delta { + self.add_boll(); + } + } else if delta < 0 { + for _i in 0..delta { + self.bolls.pop(); + } + } + } + + fn add_boll(&mut self) { + let mut rng = rand::thread_rng(); + self.bolls.push(Box::new(SquareBoll { + pos: point!(rng.gen_range(0, SCREEN_WIDTH) as f64, rng.gen_range(0, SCREEN_HEIGHT) as f64), + vel: point!(rng.gen_range(-2.0, 2.0), rng.gen_range(-2.0, 2.0)), + })); + } +} + +impl AppState for ActiveState { + fn update(&mut self, dt: Nanoseconds) { + for mut b in &mut self.bolls { + b.update(); + } + + match dt { + ns if ns < (NS_PER_FRAME - 90_0000) as u64 => { self.change_boll_count(100) } + ns if ns > (NS_PER_FRAME + 90_0000) as u64 => { self.change_boll_count(-100) } + _ => {} + } + } + + fn render(&self, canvas: &mut Canvas) { + for mut b in &self.bolls { + b.draw(canvas, self.boll_size); + } + } + + fn leave(&self) { + println!("number of bolls: {}", self.bolls.len()); + } + + fn on_event(&mut self, event: Event) { + match event { + Event::KeyDown { keycode: Some(Keycode::KpPlus), .. } => { self.boll_size = std::cmp::min(self.boll_size + 1, 32) } + Event::KeyDown { keycode: Some(Keycode::KpMinus), .. } => { self.boll_size = std::cmp::max(self.boll_size - 1, 1) } + Event::MouseMotion { x, y, .. } => { + self.bolls.push(Box::new(CircleBoll::new( + point!(x as f64, y as f64), + point!(0.0, 0.0), + ))) + } + _ => {} + } + } +} diff --git a/src/main.rs b/src/main.rs index 8b10341..4c399c6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,7 +4,6 @@ extern crate time; use std::f32::consts::PI; -use rand::Rng; use sdl2::event::Event; use sdl2::event::WindowEvent; use sdl2::gfx::primitives::DrawRenderer; @@ -15,7 +14,6 @@ use sdl2::video::FullscreenType; use time::PreciseTime; use app::*; -use boll::{Boll, CircleBoll, SquareBoll}; use common::Point2D; mod app; @@ -28,8 +26,6 @@ const SCREEN_HEIGHT: u32 = (SCREEN_WIDTH as f64 * (1440.0 / 2560.0)) as u32; const FPS: u32 = 60; const NS_PER_FRAME: u32 = 1_000_000_000 / FPS; -type Bollar = Vec>; - fn main() { println!("starting..."); let mut app = App::new(); @@ -40,14 +36,11 @@ fn main() { let mut frame_count: u64 = 0; let mut fps_time = PreciseTime::now(); - - let mut bolls: Bollar = Bollar::new(); - let mut boll_size = 1; + let mut last_time = PreciseTime::now(); let mut mario_angle = 0.0; 'running: loop { - let loop_start = PreciseTime::now(); app.canvas.set_draw_color(Color::RGB(0, 0, 0)); app.canvas.clear(); { @@ -80,11 +73,6 @@ fn main() { app.canvas.aa_ellipse(p.x, p.y, 110, 55, Color::RGB(255, 255, 255)).unwrap(); } - for b in &mut bolls { - b.update(); - b.draw(&mut app.canvas, boll_size); - } - // window.gl_swap_window(); for event in app.event_pump.poll_iter() { match event { @@ -97,14 +85,6 @@ fn main() { _ => app.canvas.window_mut().set_fullscreen(FullscreenType::Off) }.unwrap(); } - Event::KeyDown { keycode: Some(Keycode::KpPlus), .. } => { boll_size = std::cmp::min(boll_size + 1, 32) } - Event::KeyDown { keycode: Some(Keycode::KpMinus), .. } => { boll_size = std::cmp::max(boll_size - 1, 1) } - Event::MouseMotion { x, y, .. } => { - bolls.push(Box::new(CircleBoll::new( - point!(x as f64, y as f64), - point!(0.0, 0.0), - ))) - } Event::Window { win_event: WindowEvent::Resized(x, y), .. } => { println!("window resized({}, {})", x, y) } Event::Window { win_event: WindowEvent::Maximized, .. } => { println!("window maximized") } Event::Window { win_event: WindowEvent::Restored, .. } => { println!("window restored") } @@ -112,16 +92,15 @@ fn main() { Event::Window { win_event: WindowEvent::Leave, .. } => { println!("window leave") } Event::Window { win_event: WindowEvent::FocusGained, .. } => { println!("window focus gained") } Event::Window { win_event: WindowEvent::FocusLost, .. } => { println!("window focus lost") } - _ => {} + _ => { app.state.on_event(event) } } } - app.canvas.present(); - match loop_start.to(PreciseTime::now()).num_nanoseconds() { - Some(ns) if ns < (NS_PER_FRAME - 50_0000) as i64 => { change_boll_count(&mut bolls, 100) } - Some(ns) if ns > (NS_PER_FRAME + 50_0000) as i64 => { change_boll_count(&mut bolls, -100) } - _ => {} - } + let duration = last_time.to(PreciseTime::now()).num_nanoseconds().unwrap() as Nanoseconds; + last_time = PreciseTime::now(); + app.state.update(duration); + app.state.render(&mut app.canvas); + app.canvas.present(); frame_count += 1; if frame_count == FPS as u64 { @@ -132,25 +111,5 @@ fn main() { } } - println!("number of bolls: {}", bolls.len()); -} - -fn change_boll_count(mut bolls: &mut Bollar, delta: i32) { - if delta > 0 { - for _i in 0..delta { - add_boll(&mut bolls); - } - } else if delta < 0 { - for _i in 0..delta { - bolls.pop(); - } - } -} - -fn add_boll(bolls: &mut Bollar) { - let mut rng = rand::thread_rng(); - bolls.push(Box::new(SquareBoll { - pos: point!(rng.gen_range(0, SCREEN_WIDTH) as f64, rng.gen_range(0, SCREEN_HEIGHT) as f64), - vel: point!(rng.gen_range(-2.0, 2.0), rng.gen_range(-2.0, 2.0)), - })); + app.state.leave(); }