Browse Source

add lesson 5

jmelesky 7 years ago
parent
commit
a98172a033
3 changed files with 171 additions and 0 deletions
  1. BIN
      assets/stretch.bmp
  2. 7 0
      lesson05/Cargo.toml
  3. 164 0
      lesson05/src/main.rs

BIN
assets/stretch.bmp


+ 7 - 0
lesson05/Cargo.toml

@@ -0,0 +1,7 @@
+[package]
+name = "lesson05"
+version = "0.1.0"
+authors = ["jmelesky <code@phaedrusdeinus.org>"]
+
+[dependencies]
+sdl2 = "0.30.0"

+ 164 - 0
lesson05/src/main.rs

@@ -0,0 +1,164 @@
+
+extern crate sdl2;
+
+use sdl2::Sdl;
+use sdl2::video::{Window, WindowContext};
+use sdl2::render::{TextureCreator, Texture};
+use sdl2::surface::Surface;
+use sdl2::rect::Rect;
+
+use sdl2::event::Event;
+use sdl2::keyboard::Keycode;
+
+use std::path::Path;
+
+
+
+// using a different window size than lazyfoo, due to high-density screen
+const WIDTH:u32  = 1280;
+const HEIGHT:u32 =  960;
+
+
+// need the window (blit settings) as well as the canvas
+// and still the context for the event pump
+//
+// splitting canvas out for now due to compilation reasons
+fn init() -> (Sdl, Window) {
+    let context = match sdl2::init() {
+        Ok(context) => context,
+        Err(err)    => panic!("Could not initialize SDL2. Error: {}", err),
+    };
+
+    let video = match context.video() {
+        Ok(video) => video,
+        Err(err)  => panic!("Could not gain access to the SDL2 video subsystem. Error: {}", err),
+    };
+
+    let window = match video.window("SDL Tutorial, lesson 05", WIDTH, HEIGHT)
+        .position_centered()
+        .opengl()
+        .build() {
+            Ok(window) => window,
+            Err(err)   => panic!("Could not create window. Error: {}", err),
+        };
+
+    return (context, window)
+}
+
+
+// we need to manipulate the surface post-load, so separating these functions out
+fn load_surface(path: &str) -> Surface {
+    let surface = match Surface::load_bmp(&Path::new(path)) {
+        Ok(surface) => surface,
+        Err(err)    => panic!("Could not load image: {}", err)
+    };
+
+    return surface;
+}
+
+fn surface_to_texture<'a>(surface: &Surface, tc: &'a TextureCreator<WindowContext>) -> Texture<'a> {
+    let texture = match tc.create_texture_from_surface(&surface) {
+        Ok(texture) => texture,
+        Err(err)    => panic!("Could not slap surface into a texture: {}", err)
+    };
+
+    return texture;
+}
+
+// And this becomes much simpler
+// although it's unused in this lesson
+fn load_texture<'a>(path: &'static str, tc: &'a TextureCreator<WindowContext>) -> Texture<'a> {
+    return surface_to_texture(&load_surface(path), &tc);
+}
+
+
+fn main() {
+
+    let mut running: bool = true;
+
+    let (context, window) = init();
+
+
+    let starting_surface = load_surface("../assets/stretch.bmp");
+
+    // okay, now to modify the surface
+    // this, afaict, has no perceivable benefit for this example
+    // but should optimize things for future tight loops, etc
+    //
+    //
+    // ... though we do create three separate surfaces in this process
+
+    let pixel_format = window.window_pixel_format();
+    let sf_pixel_format = starting_surface.pixel_format();
+    let optimized_surface = match starting_surface
+        .convert(&sf_pixel_format) {
+            Ok(surface) => surface,
+            Err(err)    => panic!("Could not convert surface: {}", err)
+        };
+
+    // Now stretch the optimized surface to the dimensions we want
+    let dst_rect = Rect::new(0, 0, WIDTH, HEIGHT);
+    let mut stretched_surface = match Surface::new(WIDTH, HEIGHT, pixel_format) {
+        Ok(surface) => surface,
+        Err(err)    => panic!("Could not create surface: {}", err)
+    };
+
+    // blit_scaled does not return anything, but it does return an SdlResult, so
+    // we unwrap to trigger the panic if we can't blit.
+    optimized_surface.blit_scaled(None, &mut stretched_surface, Some(dst_rect)).unwrap();
+
+
+    // couldn't figure out how to wrap the canvas creation in a function,
+    // since it involves borrowing `window`. Short enough to handle from
+    // here, but still frustrating.
+
+    let mut canvas = match window.into_canvas()
+        .build() {
+            Ok(canvas) => canvas,
+            Err(err)   => panic!("Could not create canvas from window. Error: {}", err),
+        };
+    let tc = canvas.texture_creator();
+    let texture = surface_to_texture(&stretched_surface, &tc);
+
+
+    let mut pump = match context.event_pump() {
+        Ok(pump) => pump,
+        Err(err) => panic!("Could not start pumping: {}", err)
+    };
+
+
+    while running {
+        // pull all pending events
+        for event in pump.poll_iter() {
+            match event {
+                // apparently '{..}' means "with whatever fields"
+                Event::Quit {..} => {
+                    running = false
+                },
+
+                Event::KeyDown { keycode: k, .. } => match k {
+                    Some(Keycode::Escape) | Some(Keycode::Q) => {
+                        running = false
+                    },
+                    Some(_) => {},
+                    None => {}
+                },
+
+                _ => {}
+            }
+        }
+
+
+        //canvas.clear();
+        match canvas.copy(&texture, None, None) {
+            Ok(())   => (), // no return value == success
+            Err(err) => panic!("Could not render texture: {}", err),
+        };
+
+        canvas.present();
+
+    }
+
+}
+
+