8b103419314c721a878a8f1e3e0a1cad831f7f7e
[kaka/rust-sdl-test.git] / src / main.rs
1 extern crate rand;
2 extern crate sdl2;
3 extern crate time;
4
5 use std::f32::consts::PI;
6
7 use rand::Rng;
8 use sdl2::event::Event;
9 use sdl2::event::WindowEvent;
10 use sdl2::gfx::primitives::DrawRenderer;
11 use sdl2::keyboard::Keycode;
12 use sdl2::pixels::Color;
13 use sdl2::rect::Rect;
14 use sdl2::video::FullscreenType;
15 use time::PreciseTime;
16
17 use app::*;
18 use boll::{Boll, CircleBoll, SquareBoll};
19 use common::Point2D;
20
21 mod app;
22 #[macro_use] mod common;
23 mod boll;
24 mod sprites;
25
26 const SCREEN_WIDTH: u32 = 1280;
27 const SCREEN_HEIGHT: u32 = (SCREEN_WIDTH as f64 * (1440.0 / 2560.0)) as u32;
28 const FPS: u32 = 60;
29 const NS_PER_FRAME: u32 = 1_000_000_000 / FPS;
30
31 type Bollar = Vec<Box<dyn Boll>>;
32
33 fn main() {
34     println!("starting...");
35     let mut app = App::new();
36     app.load_sprites(&[
37         ("block", "res/block.bmp"),
38         ("mario", "res/mario-trans.png"),
39     ]);
40
41     let mut frame_count: u64 = 0;
42     let mut fps_time = PreciseTime::now();
43
44     let mut bolls: Bollar = Bollar::new();
45     let mut boll_size = 1;
46
47     let mut mario_angle = 0.0;
48
49     'running: loop {
50         let loop_start = PreciseTime::now();
51         app.canvas.set_draw_color(Color::RGB(0, 0, 0));
52         app.canvas.clear();
53         {
54             let blocks = 20;
55             let size = 32;
56             let offset = point!((SCREEN_WIDTH as i32 - (blocks + 1) * size) / 2, (SCREEN_HEIGHT as i32 - (blocks + 1) * size) / 2);
57             let block = app.sprites.get("block");
58             for i in 0..blocks {
59                 app.canvas.copy(block, None, Rect::new((i) * size + offset.x, (0) * size + offset.y, size as u32, size as u32)).unwrap();
60                 app.canvas.copy(block, None, Rect::new((blocks - i) * size + offset.x, (blocks) * size + offset.y, size as u32, size as u32)).unwrap();
61                 app.canvas.copy(block, None, Rect::new((0) * size + offset.x, (blocks - i) * size + offset.y, size as u32, size as u32)).unwrap();
62                 app.canvas.copy(block, None, Rect::new((blocks) * size + offset.x, (i) * size + offset.y, size as u32, size as u32)).unwrap();
63             }
64         }
65         {
66             let size = 64;
67             let offset = point!((SCREEN_WIDTH as i32 - size) / 2, (SCREEN_HEIGHT as i32 - size) / 2);
68             let radius = 110.0 + size as f32 * 0.5;
69             let angle = (mario_angle as f32 - 90.0) * PI / 180.0;
70             let offset2 = point!((angle.cos() * radius) as i32, (angle.sin() * radius) as i32);
71             app.canvas.copy_ex(app.sprites.get("mario"), None, Rect::new(offset.x + offset2.x, offset.y + offset2.y, size as u32, size as u32), mario_angle, sdl2::rect::Point::new(size / 2, size / 2), false, false).unwrap();
72             mario_angle += 1.0;
73             if mario_angle >= 360.0 { mario_angle -= 360.0 }
74         }
75         {
76             let p = point!((SCREEN_WIDTH / 2) as i16, (SCREEN_HEIGHT / 2) as i16);
77             app.canvas.circle(p.x, p.y, 100, Color::RGB(255, 255, 255)).unwrap();
78             app.canvas.aa_circle(p.x, p.y, 110, Color::RGB(255, 255, 255)).unwrap();
79             app.canvas.ellipse(p.x, p.y, 50, 100, Color::RGB(255, 255, 255)).unwrap();
80             app.canvas.aa_ellipse(p.x, p.y, 110, 55, Color::RGB(255, 255, 255)).unwrap();
81         }
82
83         for b in &mut bolls {
84             b.update();
85             b.draw(&mut app.canvas, boll_size);
86         }
87
88 //        window.gl_swap_window();
89         for event in app.event_pump.poll_iter() {
90             match event {
91                 Event::Quit { .. } | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
92                     break 'running;
93                 }
94                 Event::KeyDown { keycode: Some(Keycode::F11), .. } => {
95                     match app.canvas.window().fullscreen_state() {
96                         FullscreenType::Off => app.canvas.window_mut().set_fullscreen(FullscreenType::Desktop),
97                         _                   => app.canvas.window_mut().set_fullscreen(FullscreenType::Off)
98                     }.unwrap();
99                 }
100                 Event::KeyDown { keycode: Some(Keycode::KpPlus), .. } => { boll_size = std::cmp::min(boll_size + 1, 32) }
101                 Event::KeyDown { keycode: Some(Keycode::KpMinus), .. } => { boll_size = std::cmp::max(boll_size - 1, 1) }
102                 Event::MouseMotion { x, y, .. } => {
103                     bolls.push(Box::new(CircleBoll::new(
104                         point!(x as f64, y as f64),
105                         point!(0.0, 0.0),
106                     )))
107                 }
108                 Event::Window { win_event: WindowEvent::Resized(x, y), .. } => { println!("window resized({}, {})", x, y) }
109                 Event::Window { win_event: WindowEvent::Maximized, .. } => { println!("window maximized") }
110                 Event::Window { win_event: WindowEvent::Restored, .. } => { println!("window restored") }
111                 Event::Window { win_event: WindowEvent::Enter, .. } => { println!("window enter") }
112                 Event::Window { win_event: WindowEvent::Leave, .. } => { println!("window leave") }
113                 Event::Window { win_event: WindowEvent::FocusGained, .. } => { println!("window focus gained") }
114                 Event::Window { win_event: WindowEvent::FocusLost, .. } => { println!("window focus lost") }
115                 _ => {}
116             }
117         }
118         app.canvas.present();
119
120         match loop_start.to(PreciseTime::now()).num_nanoseconds() {
121             Some(ns) if ns < (NS_PER_FRAME - 50_0000) as i64 => { change_boll_count(&mut bolls, 100) }
122             Some(ns) if ns > (NS_PER_FRAME + 50_0000) as i64 => { change_boll_count(&mut bolls, -100) }
123             _ => {}
124         }
125
126         frame_count += 1;
127         if frame_count == FPS as u64 {
128             let duration = fps_time.to(PreciseTime::now()).num_nanoseconds().unwrap() as f64 / 1_000_000_000.0;
129             println!("fps: {}", frame_count as f64 / duration);
130             frame_count = 0;
131             fps_time = PreciseTime::now();
132         }
133     }
134
135     println!("number of bolls: {}", bolls.len());
136 }
137
138 fn change_boll_count(mut bolls: &mut Bollar, delta: i32) {
139     if delta > 0 {
140         for _i in 0..delta {
141             add_boll(&mut bolls);
142         }
143     } else if delta < 0 {
144         for _i in 0..delta {
145             bolls.pop();
146         }
147     }
148 }
149
150 fn add_boll(bolls: &mut Bollar) {
151     let mut rng = rand::thread_rng();
152     bolls.push(Box::new(SquareBoll {
153         pos: point!(rng.gen_range(0, SCREEN_WIDTH) as f64, rng.gen_range(0, SCREEN_HEIGHT) as f64),
154         vel: point!(rng.gen_range(-2.0, 2.0), rng.gen_range(-2.0, 2.0)),
155     }));
156 }