diff --git a/Cargo.lock b/Cargo.lock index 5646199..b5f07fe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,27 +2,27 @@ name = "super-matte-bros" version = "0.0.1" dependencies = [ - "sdl2 0.0.14 (git+https://github.com/AngryLawyer/rust-sdl2)", + "sdl2 0.0.16 (git+https://github.com/AngryLawyer/rust-sdl2)", ] [[package]] name = "pkg-config" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "sdl2" -version = "0.0.14" -source = "git+https://github.com/AngryLawyer/rust-sdl2#7ff85a93a677ed8a02f4e49109a8613a7544aa21" +version = "0.0.16" +source = "git+https://github.com/AngryLawyer/rust-sdl2#2dd0986162fa48fd930ab59c696c0eabc1ac2344" dependencies = [ - "sdl2-sys 0.0.14 (git+https://github.com/AngryLawyer/rust-sdl2)", + "sdl2-sys 0.0.16 (git+https://github.com/AngryLawyer/rust-sdl2)", ] [[package]] name = "sdl2-sys" -version = "0.0.14" -source = "git+https://github.com/AngryLawyer/rust-sdl2#7ff85a93a677ed8a02f4e49109a8613a7544aa21" +version = "0.0.16" +source = "git+https://github.com/AngryLawyer/rust-sdl2#2dd0986162fa48fd930ab59c696c0eabc1ac2344" dependencies = [ - "pkg-config 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/src/keyboard.rs b/src/keyboard.rs new file mode 100644 index 0000000..e7396b8 --- /dev/null +++ b/src/keyboard.rs @@ -0,0 +1,56 @@ +use std::collections::HashMap; + +use sdl2::keycode::KeyCode; + + +pub struct KeyboardHandler { + pressed_keys: HashMap, + released_keys: HashMap, + held_keys: HashMap +} + +impl KeyboardHandler { + pub fn new() -> KeyboardHandler { + KeyboardHandler { + pressed_keys: HashMap::new(), + released_keys: HashMap::new(), + held_keys: HashMap::new() + } + } + + pub fn clear(&mut self) { + self.pressed_keys.clear(); + self.released_keys.clear(); + } + + pub fn key_down(&mut self, keycode: KeyCode) { + self.pressed_keys.insert(keycode, true); + self.held_keys.insert(keycode, true); + } + + pub fn key_up(&mut self, keycode: KeyCode) { + self.released_keys.insert(keycode, true); + self.held_keys.insert(keycode, false); + } + + pub fn was_pressed(&self, keycode: KeyCode) -> bool { + match self.pressed_keys.get(&keycode) { + Some(state) => *state, + None => false + } + } + + pub fn was_released(&self, keycode: KeyCode) -> bool { + match self.released_keys.get(&keycode) { + Some(state) => *state, + None => false + } + } + + pub fn is_held(&self, keycode: KeyCode) -> bool { + match self.held_keys.get(&keycode) { + Some(state) => *state, + None => false + } + } +} diff --git a/src/main.rs b/src/main.rs index 0f56058..f523b15 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,24 +1,24 @@ extern crate sdl2; - -use std::num::FloatMath; +use std::num::Float; use std::iter::range_step_inclusive; use sdl2::video::{Window, WindowPos, OPENGL}; use sdl2::event::{poll_event, Event}; use sdl2::timer::{get_ticks, delay}; -use sdl2::rect::Rect; +use sdl2::rect::{Point, Rect}; use sdl2::keycode::KeyCode; use sdl2::pixels::Color; use tile::Layer; use camera::Camera; use player::Player; - +use keyboard::KeyboardHandler; mod tile; mod camera; mod player; +mod keyboard; const SCREEN_WIDTH : i32 = 960; @@ -27,7 +27,7 @@ const SCREEN_HEIGHT : i32 = 640; const TILE_WIDTH : i32 = 32; const TILE_HEIGHT : i32 = 32; -const MS_PER_UPDATE : uint = 10; +const MS_PER_UPDATE : usize = 10; #[derive(Clone)] @@ -40,7 +40,7 @@ enum Tile { fn main() { sdl2::init(sdl2::INIT_EVERYTHING); - let window = match Window::new("Super Matte Bros", WindowPos::PosCentered, WindowPos::PosCentered, SCREEN_WIDTH as int, SCREEN_HEIGHT as int, OPENGL) { + let window = match Window::new("Super Matte Bros", WindowPos::PosCentered, WindowPos::PosCentered, SCREEN_WIDTH as isize, SCREEN_HEIGHT as isize, OPENGL) { Ok(window) => window, Err(err) => panic!("failed to create window: {}", err) }; @@ -50,65 +50,89 @@ fn main() { Err(err) => panic!("failed to create renderer: {}", err) }; + let mut keyboard = KeyboardHandler::new(); + let mut layer = Layer::new(120, 20, TILE_WIDTH, TILE_HEIGHT, Tile::Empty); let colors = vec![Color::RGB(0, 0, 255), Color::RGB(0, 128, 255)]; for x in range(5, 120) { - layer.set_tile(x, 14, Tile::Floor(colors[(x % 2) as uint])); + layer.set_tile(x, 14, Tile::Floor(colors[(x % 2) as usize])); } for x in range(11, 20) { - layer.set_tile(x, 13, Tile::Floor(colors[(x % 2) as uint])); + layer.set_tile(x, 13, Tile::Floor(colors[(x % 2) as usize])); + } + for x in range(14, 20) { + layer.set_tile(x, 11, Tile::Floor(colors[(x % 2) as usize])); } let mut camera = Camera::new(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, layer.to_rect()); let mut player = Player::new(290.0, 390.0); - let mut current : uint; - let mut elapsed : uint; - let mut previous : uint = get_ticks(); - let mut lag : uint = 0; + let mut current : usize; + let mut elapsed : usize; + let mut previous : usize = get_ticks(); + let mut lag : usize = 0; - loop { + 'main : loop { current = get_ticks(); elapsed = current - previous; previous = current; lag += elapsed; - match poll_event() { - Event::Quit(_) => break, - Event::KeyDown(_, _, key, _, _, repeat) => { - if key == KeyCode::Escape { - break; - } else if key == KeyCode::Right { - player.dx = 4.0; - } else if key == KeyCode::Left { - player.dx = -4.0; - } else if key == KeyCode::Up { - if player.on_ground && repeat == false { - player.dy = -12.0; + keyboard.clear(); - player.on_ground = false; - } - } - }, - Event::KeyUp(_, _, key, _, _, _) => { - if key == KeyCode::Right { - if player.dx > 0.0 { - player.dx = 0.0; - } - } else if key == KeyCode::Left { - if player.dx < 0.0 { - player.dx = 0.0; - } - } else if key == KeyCode::Up { - if player.dy < -6.0 { - player.dy = -6.0; - } - } - }, - _ => (), + 'event : loop { + match poll_event() { + Event::Quit(_) => break 'main, + Event::KeyDown(_, _, key, _, _, repeat) => { + keyboard.key_down(key); + }, + Event::KeyUp(_, _, key, _, _, _) => { + keyboard.key_up(key); + }, + Event::None => break 'event, + _ => (), + } + } + + if keyboard.was_pressed(KeyCode::Escape) { + break 'main; + } + + if keyboard.is_held(KeyCode::Right) { + player.dx = 4.0; + } + + if keyboard.is_held(KeyCode::Left) { + player.dx = -4.0; + } + + if keyboard.was_pressed(KeyCode::Up) { + if player.on_ground { + player.dy = -12.0; + + player.on_ground = false; + } + } + + if keyboard.was_released(KeyCode::Right) { + if player.dx > 0.0 { + player.dx = 0.0; + } + } + + if keyboard.was_released(KeyCode::Left) { + if player.dx < 0.0 { + player.dx = 0.0; + } + } + + if keyboard.was_released(KeyCode::Up) { + if player.dy < -6.0 { + player.dy = -6.0; + } } while lag >= MS_PER_UPDATE { @@ -116,92 +140,92 @@ fn main() { player.on_ground = false; - let intersecting = layer.find_intersecting(&player.to_rect()); + if let Some(intersecting) = layer.find_intersecting(&player.to_rect()) { + if player.dx > 0.0 { + let p_x = player.x + player.w as f32; + let t_x = intersecting.x + intersecting.w; - if player.dx > 0.0 { - let p_x = player.x + player.w as f32; - let t_x = intersecting.x + intersecting.w; + let mut d_x = player.dx; - let mut d_x = player.dx; - - for y in range_step_inclusive(intersecting.y, intersecting.y + intersecting.h, 1) { - for x in range_step_inclusive(t_x, t_x + 1, 1) { - match *layer.get_tile(x, y) { - Tile::Empty => (), - Tile::Floor(_) => d_x = d_x.min((x * TILE_WIDTH) as f32 - p_x) + for y in range_step_inclusive(intersecting.y, intersecting.y + intersecting.h, 1) { + for x in range_step_inclusive(t_x, t_x + 1, 1) { + d_x = match *layer.get_tile(x, y) { + Tile::Empty => d_x, + Tile::Floor(_) => d_x.min((x * TILE_WIDTH) as f32 - p_x) + } } } + + if d_x > 0.0 { + player.x += d_x; + } else { + player.dx = 0.0; + } + } else if player.dx < 0.0 { + let p_x = player.x; + let t_x = intersecting.x; + + let mut d_x = player.dx; + + for y in range_step_inclusive(intersecting.y, intersecting.y + intersecting.h, 1) { + for x in range_step_inclusive(t_x, t_x - 1, -1) { + d_x = match *layer.get_tile(x, y) { + Tile::Empty => d_x, + Tile::Floor(_) => d_x.max((x * TILE_WIDTH + TILE_WIDTH) as f32 - p_x) + } + } + } + + if d_x < 0.0 { + player.x += d_x; + } else { + player.dx = 0.0; + } } - if d_x > 0.0 { - player.x += d_x; - } else { - player.dx = 0.0; - } - } else if player.dx < 0.0 { - let p_x = player.x; - let t_x = intersecting.x; + if player.dy > 0.0 { + let p_y = player.y + player.h as f32; + let t_y = intersecting.y + intersecting.h; - let mut d_x = player.dx; + let mut d_y = player.dy; - for y in range_step_inclusive(intersecting.y, intersecting.y + intersecting.h, 1) { - for x in range_step_inclusive(t_x, t_x - 1, -1) { - match *layer.get_tile(x, y) { - Tile::Empty => (), - Tile::Floor(_) => d_x = d_x.max((x * TILE_WIDTH + TILE_WIDTH) as f32 - p_x) + for y in range_step_inclusive(t_y, t_y + 1, 1) { + for x in range_step_inclusive(intersecting.x, intersecting.x + intersecting.w, 1) { + d_y = match *layer.get_tile(x, y) { + Tile::Empty => d_y, + Tile::Floor(_) => d_y.min((y * TILE_HEIGHT) as f32 - p_y) + } } } - } - if d_x < 0.0 { - player.x += d_x; - } else { - player.dx = 0.0; - } - } + if d_y > 0.0 { + player.y += d_y; + } else { + player.dy = 0.0; - if player.dy > 0.0 { - let p_y = player.y + player.h as f32; - let t_y = intersecting.y + intersecting.h; + player.on_ground = true; + } + } else if player.dy < 0.0 { + let p_y = player.y; + let t_y = intersecting.y; - let mut d_y = player.dy; + let mut d_y = player.dy; - for y in range_step_inclusive(t_y, t_y + 1, 1) { - for x in range_step_inclusive(intersecting.x, intersecting.x + intersecting.w, 1) { - match *layer.get_tile(x, y) { - Tile::Empty => (), - Tile::Floor(_) => d_y = d_y.min((y * TILE_HEIGHT) as f32 - p_y) + for y in range_step_inclusive(t_y, t_y - 1, -1) { + for x in range_step_inclusive(intersecting.x, intersecting.x + intersecting.w, 1) { + d_y = match *layer.get_tile(x, y) { + Tile::Empty => d_y, + Tile::Floor(_) => d_y.max((y * TILE_HEIGHT + TILE_HEIGHT) as f32 - p_y) + } } } - } - if d_y > 0.0 { - player.y += d_y; - } else { - player.dy = 0.0; - - player.on_ground = true; - } - } else if player.dy < 0.0 { - let p_y = player.y; - let t_y = intersecting.y; - - let mut d_y = player.dy; - - for y in range_step_inclusive(t_y, t_y - 1, -1) { - for x in range_step_inclusive(intersecting.x, intersecting.x + intersecting.w, 1) { - match *layer.get_tile(x, y) { - Tile::Empty => (), - Tile::Floor(_) => d_y = d_y.max((y * TILE_HEIGHT + TILE_HEIGHT) as f32 - p_y) - } + if d_y < 0.0 { + player.y += d_y; + } else { + player.dy = 0.0; } } - - if d_y < 0.0 { - player.y += d_y; - } else { - player.dy = 0.0; - } } camera.center(&player.to_rect()); diff --git a/src/tile.rs b/src/tile.rs index 69b12da..886dfd3 100644 --- a/src/tile.rs +++ b/src/tile.rs @@ -1,7 +1,7 @@ use std::iter::repeat; use std::cmp::{min, max}; -use sdl2::rect::Rect; +use sdl2::rect::{Point, Rect}; pub struct Layer { @@ -15,7 +15,7 @@ pub struct Layer { impl Layer where T: Clone { pub fn new(width: i32, height: i32, tile_width: i32, tile_height: i32, tile: T) -> Layer { Layer { - tiles: repeat(tile).take((width * height) as uint).collect(), + tiles: repeat(tile).take((width * height) as usize).collect(), width: width, height: height, tile_width: tile_width, @@ -24,41 +24,44 @@ impl Layer where T: Clone { } pub fn get_tile(&self, x: i32, y: i32) -> &T { - let offset = (x + y * self.width) as uint; + let offset = (x + y * self.width) as usize; &self.tiles[offset] } pub fn set_tile(&mut self, x: i32, y: i32, tile: T) { - let offset = (x + y * self.width) as uint; + let offset = (x + y * self.width) as usize; self.tiles[offset] = tile; } - pub fn find_intersecting(&self, rect: &Rect) -> Rect { + pub fn find_intersecting(&self, rect: &Rect) -> Option { let x1 = max(rect.x / self.tile_width, 0); let y1 = max(rect.y / self.tile_height, 0); let x2 = min((rect.x + rect.w - 1) / self.tile_width, self.width - 1); let y2 = min((rect.y + rect.h - 1) / self.tile_height, self.height - 1); - Rect::new(x1, y1, x2 - x1, y2 - y1) + println!("{}, {}, {}, {}", x1, y1, x2, y2); + + if x1 < 0 || x2 >= self.width { + None + } + else if y1 < 0 || y2 >= self.height { + None + } + else { + Some(Rect::new(x1, y1, x2 - x1, y2 - y1)) + } } - pub fn for_each_intersecting(&self, rect: &Rect, mut f: F) where F: FnMut(&T, &Rect) { - let intersect = self.find_intersecting(rect); + pub fn for_each_intersecting(&self, rect: &Rect, mut f: F) { + if let Some(intersect) = self.find_intersecting(rect) { + for y in range(intersect.y, intersect.y + intersect.h + 1) { + for x in range(intersect.x, intersect.x + intersect.w + 1) { + let position = Rect::new(x * self.tile_width, y * self.tile_height, self.tile_width, self.tile_height); - if intersect.x < 0 || intersect.x + intersect.w > self.width { - return; - } - else if intersect.y < 0 || intersect.y + intersect.h > self.height { - return; - } - - for y in range(intersect.y, intersect.y + intersect.h + 1) { - for x in range(intersect.x, intersect.x + intersect.w + 1) { - let position = Rect::new(x * self.tile_width, y * self.tile_height, self.tile_width, self.tile_height); - - f(self.get_tile(x, y), &position); + f(self.get_tile(x, y), &position); + } } } }