+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<Window>,
pub event_pump: EventPump,
pub sprites: SpriteManager,
+ pub state: Box<AppState>,
}
impl App {
canvas,
event_pump,
sprites,
+ state: Box::new(ActiveState::new()),
}
}
}
}
}
+
+pub trait AppState {
+ fn update(&mut self, dt: Nanoseconds);
+ fn render(&self, canvas: &mut Canvas<Window>);
+ fn leave(&self);
+ fn on_event(&mut self, event: Event);
+}
+
+type Bollar = Vec<Box<dyn Boll>>;
+
+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<Window>) {
+ 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),
+ )))
+ }
+ _ => {}
+ }
+ }
+}
use std::f32::consts::PI;
-use rand::Rng;
use sdl2::event::Event;
use sdl2::event::WindowEvent;
use sdl2::gfx::primitives::DrawRenderer;
use time::PreciseTime;
use app::*;
-use boll::{Boll, CircleBoll, SquareBoll};
use common::Point2D;
mod app;
const FPS: u32 = 60;
const NS_PER_FRAME: u32 = 1_000_000_000 / FPS;
-type Bollar = Vec<Box<dyn Boll>>;
-
fn main() {
println!("starting...");
let mut app = App::new();
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();
{
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 {
_ => 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") }
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 {
}
}
- 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();
}