diff --git a/assets/levels/level1.txt b/assets/levels/level1.txt index bc85445..c60991c 100644 --- a/assets/levels/level1.txt +++ b/assets/levels/level1.txt @@ -3,13 +3,13 @@ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 1 1 -1 1 1 1 0 0 0 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 1 1 -1 1 1 1 0 0 0 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 diff --git a/src/engine/map/mod.rs b/src/engine/map/mod.rs index d98be1d..3d94dbb 100644 --- a/src/engine/map/mod.rs +++ b/src/engine/map/mod.rs @@ -402,21 +402,109 @@ impl Map { pub fn collides_point(&self, old: Vector2, new: Vector2) -> Option<(CollisionAxis, Vector2)> { - let height = new.y - old.y; - let mut y = (old.y / 16.0).ceil() * 16.0; + let vert = self.collides_point_vertical(old, new); + let horiz = self.collides_point_horizontal(old, new); + match (vert, horiz) { + (Some(a), Some(b)) => { + if (old.x - a.1.x).abs() < (old.x - b.1.x).abs() { + Some(a) + } else { + Some(b) + } + }, + (Some(a), None) => Some(a), + (None, Some(b)) => Some(b), + (None, None) => None, + } + } - while y < new.y { + /// Checks whether the vector (old, new) collides horizontally with an element of the map. + /// + /// Returns the height of the collision if any. + pub fn collides_point_horizontal(&self, old: Vector2, new: Vector2) + -> Option<(CollisionAxis, Vector2)> { - let current_height = y - old.y; - let x = old.x + (new.x - old.x) * current_height / height; + let width = new.y - old.y; + + if width == 0.0 { + return None; + } + + let x = if width > 0.0 { + (old.x / 16.0).ceil() * 16.0 + } else { + (old.x / 16.0).floor() * 16.0 + }; + + let mut col = (x / 16.0) as isize; + + while (col as f32 * 16.0 - new.x) * width.signum() < 0.0 { + + let current_width = col as f32 * 16.0 - old.x; + let y = old.y + (new.y - old.y) * current_width / width; // Find tile on x, y if x > 0.0 && y > 0.0 { let row = (y / 16.0) as usize; + + let col = if width > 0.0 { + col + } else { + col - 1 + }; + + if let Some((tile, _)) = self.tiles.get((row, col as usize)) { + if tile.from_top { + return Some((CollisionAxis::X, Vector2::new(x, y))); + } + } + + } + + col += width.signum() as isize; + } + + None + } + + /// Checks whether the vector (old, new) collides vertically with an element of the map. + /// + /// Returns the height of the collision if any. + pub fn collides_point_vertical(&self, old: Vector2, new: Vector2) + -> Option<(CollisionAxis, Vector2)> { + + let height = new.y - old.y; + + if height == 0.0 { + return None; + } + + let y = if height > 0.0 { + (old.y / 16.0).ceil() * 16.0 + } else { + (old.y / 16.0).floor() * 16.0 + }; + + let mut row = (y / 16.0) as isize; + + while (row as f32 * 16.0 - new.y) * height.signum() < 0.0 { + + let current_height = row as f32 * 16.0 - old.y; + let x = old.x + (new.x - old.x) * current_height / height; + + // Find tile on x, y + if x > 0.0 && y > 0.0 { + let col = (x / 16.0) as usize; - if let Some((tile, _)) = self.tiles.get((row, col)) { + let row = if height > 0.0 { + row + } else { + row - 1 + }; + + if let Some((tile, _)) = self.tiles.get((row as usize, col)) { if tile.from_top { return Some((CollisionAxis::Y, Vector2::new(x, y))); } @@ -424,10 +512,11 @@ impl Map { } - y += 16.0; + row += height.signum() as isize; } None } + }