|
@@ -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();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|