Vsync instead of fps + print display modes
[kaka/rust-sdl-test.git] / src / game / app.rs
index 438f2e7..362af2e 100644 (file)
 use rand::Rng;
 use sdl2::event::Event;
-use sdl2::EventPump;
+use sdl2::{EventPump, VideoSubsystem};
 use sdl2::keyboard::Keycode;
 use sdl2::pixels::Color;
 use sdl2::render::BlendMode;
 use sdl2::render::Canvas;
-use sdl2::video::Window;
+use sdl2::video::{SwapInterval, Window};
 
 use ::{SCREEN_HEIGHT, SCREEN_WIDTH};
 use boll::*;
-use common::Point2D;
+use common::{Point2D, Rect};
 use sprites::SpriteManager;
 use NS_PER_FRAME;
 use point; // defined in common, but loaded from main...
 
 pub type Nanoseconds = u64;
 
-pub struct App {
-    pub canvas: Canvas<Window>,
-    pub event_pump: EventPump,
-    pub sprites: SpriteManager,
-    pub state: Box<dyn AppState>,
+#[derive(Default)]
+pub struct AppBuilder {
+    resolution: Rect<u16>,
+    state: Option<Box<dyn AppState>>,
+    title: Option<String>,
 }
 
-impl App {
-    pub fn new() -> App {
+impl AppBuilder {
+    pub fn with_resolution(mut self, width: u16, height: u16) -> Self {
+       self.resolution = Rect { width, height };
+       self
+    }
+
+    pub fn with_state(mut self, state: Box<dyn AppState>) -> Self {
+       self.state = Some(state);
+       self
+    }
+
+    pub fn with_title(mut self, title: &str) -> Self {
+       self.title = Some(title.to_string());
+       self
+    }
+
+    pub fn build(self) -> Result<App, String> {
         let context = sdl2::init().unwrap();
-        sdl2::image::init(sdl2::image::InitFlag::PNG).unwrap();
-        let window = context.video().unwrap().window("SDL test", SCREEN_WIDTH, SCREEN_HEIGHT)
+        sdl2::image::init(sdl2::image::InitFlag::PNG)?;
+       let video = context.video()?;
+
+       self.print_video_display_modes(&video);
+
+        let window = video
+           .window(&self.title.unwrap(), self.resolution.width.into(), self.resolution.height.into())
             .position_centered()
+       // .fullscreen()
+       // .fullscreen_desktop()
             .opengl()
-            .build()
-            .unwrap();
+            .build().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 event_pump = context.event_pump().unwrap();
+
+       video.gl_set_swap_interval(SwapInterval::VSync)?;
+
+        let event_pump = context.event_pump()?;
         let sprites = SpriteManager::new(canvas.texture_creator());
-        App {
+
+        Ok(App {
             canvas,
             event_pump,
             sprites,
-            state: Box::new(ActiveState::new()),
-        }
+            state: self.state.unwrap_or(Box::new(ActiveState::new())),
+        })
+    }
+
+    fn print_video_display_modes(&self, video: &VideoSubsystem) {
+       println!("video subsystem: {:?}", video);
+       println!("current_video_driver: {:?}", video.current_video_driver());
+       for display in 0..video.num_video_displays().unwrap() {
+           println!("=== display {} - {} ===", display, video.display_name(display).unwrap());
+           println!(" display_bounds: {:?}", video.display_bounds(display).unwrap());
+           println!(" num_display_modes: {:?}", video.num_display_modes(display).unwrap());
+           println!(" desktop_display_mode: {:?}", video.desktop_display_mode(display).unwrap());
+           println!(" current_display_mode: {:?}", video.current_display_mode(display).unwrap());
+           for mode in 0..video.num_display_modes(display).unwrap() {
+               println!("  {:2}: {:?}", mode, video.display_mode(display, mode).unwrap());
+           }
+       }
+       println!("swap interval: {:?}", video.gl_get_swap_interval());
+    }
+}
+
+pub struct App {
+    pub canvas: Canvas<Window>,
+    pub event_pump: EventPump,
+    pub sprites: SpriteManager,
+    pub state: Box<dyn AppState>,
+}
+
+impl App {
+    pub fn new() -> AppBuilder {
+       Default::default()
     }
 
-    pub fn load_sprites(&mut self, sprites: &[(&'static str, &str)]) {
+    pub fn load_sprites(&mut self, sprites: &[(&str, &str)]) {
         for (name, file) in sprites {
             self.sprites.load(name, file);
         }
@@ -70,7 +125,7 @@ pub struct ActiveState {
 }
 
 impl ActiveState {
-    fn new() -> ActiveState {
+    pub fn new() -> ActiveState {
         ActiveState {
             bolls: Bollar::new(),
             boll_size: 1,
@@ -83,7 +138,7 @@ impl ActiveState {
                 self.add_boll();
             }
         } else if delta < 0 {
-            for _i in 0..delta {
+            for _i in 0..(-delta) {
                 self.bolls.pop();
             }
         }