Browse Source

lesson 4, now with lifetimes, hashmaps, etc

jmelesky 7 years ago
parent
commit
64c5d62681
7 changed files with 158 additions and 0 deletions
  1. BIN
      assets/down.bmp
  2. BIN
      assets/left.bmp
  3. BIN
      assets/press.bmp
  4. BIN
      assets/right.bmp
  5. BIN
      assets/up.bmp
  6. 7 0
      lesson04/Cargo.toml
  7. 151 0
      lesson04/src/main.rs

BIN
assets/down.bmp


BIN
assets/left.bmp


BIN
assets/press.bmp


BIN
assets/right.bmp


BIN
assets/up.bmp


+ 7 - 0
lesson04/Cargo.toml

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

+ 151 - 0
lesson04/src/main.rs

@@ -0,0 +1,151 @@
+extern crate sdl2;
+
+use sdl2::Sdl;
+use sdl2::video::{Window, WindowContext};
+use sdl2::render::{Canvas, TextureCreator, Texture};
+use sdl2::surface::Surface;
+
+use sdl2::event::Event;
+use sdl2::keyboard::Keycode;
+
+
+use std::collections::HashMap;
+use std::path::Path;
+
+
+
+// using a different window size than lazyfoo, due to high-density screen
+const WIDTH:u32  = 1280;
+const HEIGHT:u32 =  960;
+
+
+// it looks like returning the Canvas is still the best route to take
+fn init() -> (Sdl, Canvas<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 04", WIDTH, HEIGHT)
+        .position_centered()
+        .opengl()
+        .build() {
+            Ok(window) => window,
+            Err(err)   => panic!("Could not create window. Error: {}", err),
+        };
+
+    let canvas = match window.into_canvas()
+        .build() {
+            Ok(canvas) => canvas,
+            Err(err)   => panic!("Could not create renderer from window. Error: {}", err),
+        };
+
+    return (context, canvas)
+}
+
+
+
+// okay, so we can lifetimes look a little like something from Haskell
+// you can declare them for a function with `fn foo<'a>`, and then use
+// 'a  in the rest of the type signature
+//
+// in this case, I'm pretty sure we need to pass the texture_creator
+// into load_texture in order to use its lifetime for the return textures
+fn load_texture<'a>(path: &'static str, tc: &'a TextureCreator<WindowContext>) -> Texture<'a> {
+    let surface = match Surface::load_bmp(&Path::new(path)) {
+        Ok(surface) => surface,
+        Err(err)    => panic!("Could not load image: {}", err)
+    };
+
+    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;
+}
+
+// probably going to have to deal with lifetimes.
+// (unless Box<> is magic)
+fn load_media<'a>(tc: &'a TextureCreator<WindowContext>) -> HashMap<&'static str, Box<Texture>> {
+    let mut map: HashMap<&'static str, Box<Texture>> = HashMap::new();
+    map.insert("up", Box::new(load_texture("../assets/up.bmp", tc)));
+    map.insert("down", Box::new(load_texture("../assets/down.bmp", tc)));
+    map.insert("left", Box::new(load_texture("../assets/left.bmp", tc)));
+    map.insert("right", Box::new(load_texture("../assets/right.bmp", tc)));
+    map.insert("press", Box::new(load_texture("../assets/press.bmp", tc)));
+
+    return map
+
+}
+
+fn main() {
+
+    let mut running: bool = true;
+    let mut current_panel: &str = "press";
+
+    let (context, mut canvas) = init();
+
+    let tc = canvas.texture_creator();
+
+    let panels = load_media(&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(Keycode::Up) => {
+                        current_panel = "up"
+                    },
+                    Some(Keycode::Down) => {
+                        current_panel = "down"
+                    },
+                    Some(Keycode::Left) => {
+                        current_panel = "left"
+                    },
+                    Some(Keycode::Right) => {
+                        current_panel = "right"
+                    },
+                    Some(_) => {
+                        current_panel = "press"
+                    },
+                    None => {}
+                },
+
+                _ => {}
+            }
+        }
+
+
+        //canvas.clear();
+        match canvas.copy(&panels[current_panel], None, None) {
+            Ok(())   => (), // no return value == success
+            Err(err) => panic!("Could not render texture: {}", err),
+        };
+
+        canvas.present();
+
+    }
+
+}
+