2 use sdl2::event::Event;
4 use sdl2::keyboard::Keycode;
5 use sdl2::pixels::Color;
6 use sdl2::render::BlendMode;
7 use sdl2::render::Canvas;
8 use sdl2::video::Window;
10 use ::{SCREEN_HEIGHT, SCREEN_WIDTH};
12 use common::{Point2D, Rect};
13 use sprites::SpriteManager;
15 use point; // defined in common, but loaded from main...
17 pub type Nanoseconds = u64;
20 pub struct AppBuilder {
21 resolution: Rect<u16>,
23 state: Option<Box<dyn AppState>>,
24 title: Option<String>,
28 pub fn with_resolution(mut self, width: u16, height: u16) -> Self {
29 self.resolution = Rect { width, height };
33 pub fn with_fps(mut self, fps: u8) -> Self {
39 pub fn with_state(mut self, state: Box<dyn AppState>) -> Self {
40 self.state = Some(state);
44 pub fn with_title(mut self, title: &str) -> Self {
45 self.title = Some(title.to_string());
49 pub fn start(self) -> App {
50 let context = sdl2::init().unwrap();
51 sdl2::image::init(sdl2::image::InitFlag::PNG).unwrap();
54 .window(&self.title.unwrap(), self.resolution.width.into(), self.resolution.height.into())
58 context.mouse().show_cursor(false);
60 let mut canvas = window.into_canvas().build().unwrap();
61 canvas.set_blend_mode(BlendMode::Add);
62 canvas.set_draw_color(Color::RGB(0, 0, 0));
66 let event_pump = context.event_pump().unwrap();
67 let sprites = SpriteManager::new(canvas.texture_creator());
73 state: self.state.unwrap_or(Box::new(ActiveState::new())),
79 pub canvas: Canvas<Window>,
80 pub event_pump: EventPump,
81 pub sprites: SpriteManager,
82 pub state: Box<dyn AppState>,
86 pub fn new() -> AppBuilder {
90 pub fn load_sprites(&mut self, sprites: &[(&str, &str)]) {
91 for (name, file) in sprites {
92 self.sprites.load(name, file);
98 fn update(&mut self, dt: Nanoseconds);
99 fn render(&self, canvas: &mut Canvas<Window>);
101 fn on_event(&mut self, event: Event);
104 type Bollar = Vec<Box<dyn Boll>>;
106 pub struct ActiveState {
112 pub fn new() -> ActiveState {
114 bolls: Bollar::new(),
119 fn change_boll_count(&mut self, delta: i32) {
124 } else if delta < 0 {
125 for _i in 0..(-delta) {
131 fn add_boll(&mut self) {
132 let mut rng = rand::thread_rng();
133 self.bolls.push(Box::new(SquareBoll {
134 pos: point!(rng.gen_range(0, SCREEN_WIDTH) as f64, rng.gen_range(0, SCREEN_HEIGHT) as f64),
135 vel: point!(rng.gen_range(-2.0, 2.0), rng.gen_range(-2.0, 2.0)),
140 impl AppState for ActiveState {
141 fn update(&mut self, dt: Nanoseconds) {
142 for b in &mut self.bolls {
147 ns if ns < (NS_PER_FRAME - 90_0000) as u64 => { self.change_boll_count(100) }
148 ns if ns > (NS_PER_FRAME + 90_0000) as u64 => { self.change_boll_count(-100) }
153 fn render(&self, canvas: &mut Canvas<Window>) {
154 for b in &self.bolls {
155 b.draw(canvas, self.boll_size);
160 println!("number of bolls: {}", self.bolls.len());
163 fn on_event(&mut self, event: Event) {
165 Event::KeyDown { keycode: Some(Keycode::KpPlus), .. } => { self.boll_size = std::cmp::min(self.boll_size + 1, 32) }
166 Event::KeyDown { keycode: Some(Keycode::KpMinus), .. } => { self.boll_size = std::cmp::max(self.boll_size - 1, 1) }
167 Event::MouseMotion { x, y, .. } => {
168 self.bolls.push(Box::new(CircleBoll::new(
169 point!(x as f64, y as f64),