From ff9ab152400260b8fcdbbc6ffb0291898e974d70 Mon Sep 17 00:00:00 2001 From: logaritmisk Date: Tue, 6 Jan 2015 23:12:35 +0100 Subject: [PATCH] better collision detection, i hope --- src/main.rs | 145 +++++++++++++++++++++++++++++++++----------------- src/player.rs | 35 ++++++------ src/tile.rs | 4 +- src/vec.rs | 5 -- 4 files changed, 115 insertions(+), 74 deletions(-) delete mode 100644 src/vec.rs diff --git a/src/main.rs b/src/main.rs index 355efc1..b26c1e1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,8 @@ extern crate sdl2; +use std::num::FloatMath; + use sdl2::video::{Window, WindowPos, OPENGL}; use sdl2::event::{poll_event, Event}; use sdl2::timer::{get_ticks, delay}; @@ -9,14 +11,13 @@ use sdl2::keycode::KeyCode; use sdl2::pixels::Color; use tile::Layer; -use player::Player; use camera::Camera; +use player::Player; -mod vec; mod tile; -mod player; mod camera; +mod player; const SCREEN_WIDTH : i32 = 960; @@ -77,12 +78,12 @@ fn main() { if key == KeyCode::Escape { break; } else if key == KeyCode::Right { - player.velocity.x = 4.0; + player.dx = 4.0; } else if key == KeyCode::Left { - player.velocity.x = -4.0; + player.dx = -4.0; } else if key == KeyCode::Up { if player.on_ground && repeat == false { - player.velocity.y = -12.0; + player.dy = -12.0; player.on_ground = false; } @@ -90,16 +91,16 @@ fn main() { }, Event::KeyUp(_, _, key, _, _, _) => { if key == KeyCode::Right { - if player.velocity.x > 0.0 { - player.velocity.x = 0.0; + if player.dx > 0.0 { + player.dx = 0.0; } } else if key == KeyCode::Left { - if player.velocity.x < 0.0 { - player.velocity.x = 0.0; + if player.dx < 0.0 { + player.dx = 0.0; } } else if key == KeyCode::Up { - if player.velocity.y < -6.0 { - player.velocity.y = -6.0; + if player.dy < -6.0 { + player.dy = -6.0; } } }, @@ -109,57 +110,101 @@ fn main() { while lag >= MS_PER_UPDATE { player.update(); - layer.for_each_intersecting(&player.to_rect(), |tile: &Tile, position: &Rect| { - match *tile { - Tile::Empty => (), - Tile::Floor(_) => { - if position.has_intersection(&player.to_rect()) { - match position.intersection(&player.to_rect()) { - Some(intersect) => { - if intersect.w >= intersect.h { - if player.velocity.y < 0.0 { - player.position.y += intersect.h as f32; - } else { - player.position.y -= intersect.h as f32; - } + let intersecting = layer.find_intersecting(&player.to_rect()); - player.velocity.y = 0.0; + if player.dx > 0.0 { + let p_x = player.x + player.w as f32; + let t_x = intersecting.x + intersecting.w; - player.on_ground = true; - } else { - if player.velocity.x < 0.0 { - player.position.x += intersect.w as f32; - } else { - player.position.x -= intersect.w as f32; - } + let mut d_x = player.dx; - player.velocity.x = 0.0; - } - }, - None => (), + for y in range(intersecting.y, intersecting.y + intersecting.h + 1) { + for x in range(t_x, t_x + 2) { + match *layer.get_tile(x, y) { + Tile::Empty => (), + Tile::Floor(_) => { + d_x = d_x.min((x * TILE_WIDTH) as f32 - p_x); } } } } - }); - player.on_ground = false; + 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 ground = player.to_rect(); + let mut d_x = player.dx; - ground.y += ground.h; - ground.h = 1; - - layer.for_each_intersecting(&ground, |tile: &Tile, position: &Rect| { - match *tile { - Tile::Empty => (), - Tile::Floor(_) => { - if position.has_intersection(&ground) { - player.on_ground = true; + for y in range(intersecting.y, intersecting.y + intersecting.h + 1) { + for x in range(t_x, t_x + 2) { + match *layer.get_tile(x, y) { + Tile::Empty => (), + Tile::Floor(_) => { + d_x = d_x.min((x * TILE_WIDTH) as f32 - p_x); + } } } } - }); + + if d_x < 0.0 { + player.x += d_x; + } else { + player.dx = 0.0; + } + } + + if player.dy > 0.0 { + let p_y = player.y + player.h as f32; + let t_y = intersecting.y + intersecting.h; + + let mut d_y = player.dy; + + for y in range(t_y, t_y + 2) { + for x in range(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); + } + } + } + } + + 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(t_y, t_y + 2) { + for x in range(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); + } + } + } + } + + if d_y < 0.0 { + player.y += d_y; + } else { + player.dy = 0.0; + } + } camera.center(&player.to_rect()); diff --git a/src/player.rs b/src/player.rs index 8872669..0b9d2d3 100644 --- a/src/player.rs +++ b/src/player.rs @@ -1,13 +1,13 @@ -use sdl2::render::Renderer; -use sdl2::pixels::Color; use sdl2::rect::Rect; -use vec::Vec2; - pub struct Player { - pub position: Vec2, - pub velocity: Vec2, + pub x: f32, + pub y: f32, + pub w: i32, + pub h: i32, + pub dx: f32, + pub dy: f32, pub gravity: f32, pub on_ground: bool } @@ -15,27 +15,28 @@ pub struct Player { impl Player { pub fn new(x: f32, y: f32) -> Player { Player { - position: Vec2 { x: x, y: y }, - velocity: Vec2 { x: 0.0, y: 0.0 }, + x: x, + y: y, + w: 32, + h: 32, + dx: 0.0, + dy: 0.0, gravity: 0.3, on_ground: false } } pub fn update(&mut self) { - self.velocity.y += self.gravity; + self.dy += self.gravity; - if self.velocity.y > 8.0 { - self.velocity.y = 8.0; - } else if self.velocity.y < -8.0 { - self.velocity.y = -8.0; + if self.dy > 8.0 { + self.dy = 8.0; + } else if self.dy < -8.0 { + self.dy = -8.0; } - - self.position.x += self.velocity.x; - self.position.y += self.velocity.y; } pub fn to_rect(&self) -> Rect { - Rect::new(self.position.x as i32 - 16, self.position.y as i32 - 16, 32, 32) + Rect::new(self.x as i32, self.y as i32, self.w, self.h) } } diff --git a/src/tile.rs b/src/tile.rs index cdcf7e2..69b12da 100644 --- a/src/tile.rs +++ b/src/tile.rs @@ -35,7 +35,7 @@ impl Layer where T: Clone { self.tiles[offset] = tile; } - pub fn get_intersecting(&self, rect: &Rect) -> Rect { + pub fn find_intersecting(&self, rect: &Rect) -> Rect { 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); @@ -45,7 +45,7 @@ impl Layer where T: Clone { } pub fn for_each_intersecting(&self, rect: &Rect, mut f: F) where F: FnMut(&T, &Rect) { - let intersect = self.get_intersecting(rect); + let intersect = self.find_intersecting(rect); if intersect.x < 0 || intersect.x + intersect.w > self.width { return; diff --git a/src/vec.rs b/src/vec.rs deleted file mode 100644 index 549bd87..0000000 --- a/src/vec.rs +++ /dev/null @@ -1,5 +0,0 @@ -#[derive(Show)] -pub struct Vec2 { - pub x: T, - pub y: T -}