This commit is contained in:
2018-11-19 15:30:57 +01:00
parent a8f928f488
commit f3643ba31b
11 changed files with 126 additions and 225 deletions
+49 -74
View File
@@ -1,15 +1,9 @@
use sfml::graphics::{FloatRect, IntRect};
use sfml::system::Vector2;
use sfml::graphics::{
IntRect,
FloatRect
};
use engine::texture::Texture;
use engine::math::{clamp, Matrix};
use engine::renderer::Drawable;
use engine::math::{
Matrix,
clamp,
};
use engine::texture::Texture;
/// This enum represents if the collision happens on the X axis or the Y axis.
#[derive(Copy, Clone)]
@@ -42,11 +36,9 @@ impl CollisionAxis {
}
}
/// This struct represents the different sides from which a collision can occur.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct CollisionTile {
/// If the character comes from the top, it will collide if this bool is true.
pub from_top: bool,
@@ -58,7 +50,6 @@ pub struct CollisionTile {
/// If the character comes from the bottom, it will collide if this bool is true.
pub from_bottom: bool,
}
impl CollisionTile {
@@ -118,7 +109,6 @@ pub enum GraphicTile {
}
impl GraphicTile {
/// Checks if a graphic tile has a top border.
pub fn is_top(self) -> bool {
match self {
@@ -151,8 +141,6 @@ impl GraphicTile {
}
}
/// Creates a vec containing all the non hidden graphic tiles.
pub fn all() -> Vec<GraphicTile> {
vec![
@@ -175,8 +163,8 @@ impl GraphicTile {
top: Option<CollisionTile>,
left: Option<CollisionTile>,
right: Option<CollisionTile>,
bottom: Option<CollisionTile>) -> GraphicTile {
bottom: Option<CollisionTile>,
) -> GraphicTile {
GraphicTile::from_neighbours(
top.unwrap_or_else(CollisionTile::full),
left.unwrap_or_else(CollisionTile::full),
@@ -190,15 +178,14 @@ impl GraphicTile {
top: CollisionTile,
left: CollisionTile,
right: CollisionTile,
bottom: CollisionTile) -> GraphicTile {
bottom: CollisionTile,
) -> GraphicTile {
let mut all = GraphicTile::all()
.into_iter()
.map(|x| (x, true))
.collect::<Vec<_>>();
for (ref mut tile, ref mut possible) in &mut all {
if tile.is_top() == (top == CollisionTile::full()) {
*possible = false;
}
@@ -214,7 +201,6 @@ impl GraphicTile {
if tile.is_bottom() == (bottom == CollisionTile::full()) {
*possible = false;
}
}
for (tile, possible) in all {
@@ -276,24 +262,20 @@ impl Drawable for PositionedTile {
/// The map represents the tiles contained in a level.
pub struct Map {
/// The entrace point of the character in the map.
entrance: (usize, usize),
/// The tiles contained in the level.
tiles: Matrix<(CollisionTile, GraphicTile)>,
}
impl Map {
/// Creates a map full of nothing, with a ground at the bottom.
pub fn new(rows: usize, cols: usize) -> Map {
let mut tiles = Matrix::from_size(rows, cols, CollisionTile::empty());
let rows = tiles.rows();
for i in 0 .. tiles.cols() {
for i in 0..tiles.cols() {
tiles[(rows - 1, i)] = CollisionTile::full();
}
@@ -303,7 +285,6 @@ impl Map {
tiles[(25, 15)] = CollisionTile::full();
Map::from_collision_tiles(tiles)
}
/// Creates a map from a txt file.
@@ -337,24 +318,21 @@ impl Map {
let rows = tiles.rows();
let cols = tiles.cols();
let mut matrix = Matrix::from_size(rows, cols,
(CollisionTile::empty(), GraphicTile::Hidden)
);
for i in 0 .. rows {
for j in 0 .. cols {
let mut matrix =
Matrix::from_size(rows, cols, (CollisionTile::empty(), GraphicTile::Hidden));
for i in 0..rows {
for j in 0..cols {
let graphic = if tiles[(i, j)] == CollisionTile::full() {
// TODO This is uggly
// If there is an overflow, we should give None instead
let (i, j) = (i as isize, j as isize);
GraphicTile::from_neighbour_options(
tiles.get(((i ) as usize, (j-1) as usize)).cloned(),
tiles.get(((i-1) as usize, (j ) as usize)).cloned(),
tiles.get(((i+1) as usize, (j ) as usize)).cloned(),
tiles.get(((i ) as usize, (j+1) as usize)).cloned(),
tiles.get(((i) as usize, (j - 1) as usize)).cloned(),
tiles.get(((i - 1) as usize, (j) as usize)).cloned(),
tiles.get(((i + 1) as usize, (j) as usize)).cloned(),
tiles.get(((i) as usize, (j + 1) as usize)).cloned(),
)
} else {
GraphicTile::Hidden
@@ -402,9 +380,11 @@ impl Map {
/// Checks whether the bounding box collides with elements of the map.
///
/// Returns the new correct position.
pub fn collides_bbox(&self, old: FloatRect, new: FloatRect)
-> Option<(CollisionAxis, Vector2<f32>)> {
pub fn collides_bbox(
&self,
old: FloatRect,
new: FloatRect,
) -> Option<(CollisionAxis, Vector2<f32>)> {
let cols = self.tiles.cols() - 1;
let rows = self.tiles.rows() - 1;
@@ -418,67 +398,64 @@ impl Map {
let mut collision_y = false;
let mut new = new;
for col in min_col ..= max_col {
for row in min_row ..= max_row {
for col in min_col..=max_col {
for row in min_row..=max_row {
let tile_left = col as f32 * 16.0;
let tile_top = row as f32 * 16.0;
let tile = FloatRect::new(tile_left, tile_top, 16.0, 16.0);
if ! overlap(new, tile) {
if !overlap(new, tile) {
continue;
}
// Collisions between feet and ground
if self.tiles[(row, col)].0.from_top &&
old.top + old.height <= tile_top &&
new.top + new.height >= tile_top {
collision_y = true;
new.top = tile_top - new.height;
if self.tiles[(row, col)].0.from_top
&& old.top + old.height <= tile_top
&& new.top + new.height >= tile_top
{
collision_y = true;
new.top = tile_top - new.height;
}
if ! overlap(new, tile) {
if !overlap(new, tile) {
continue;
}
// Collisions between right and right wall
if self.tiles[(row, col)].0.from_left &&
old.left + old.width <= tile_left &&
new.left + new.width >= tile_left {
if self.tiles[(row, col)].0.from_left
&& old.left + old.width <= tile_left
&& new.left + new.width >= tile_left
{
collision_x = true;
new.left = tile_left - new.width;
}
if ! overlap(new, tile) {
if !overlap(new, tile) {
continue;
}
// Collisions between left and left wall
if self.tiles[(row, col)].0.from_right &&
old.left >= tile_left + 16.0 &&
new.left <= tile_left + 16.0 {
if self.tiles[(row, col)].0.from_right
&& old.left >= tile_left + 16.0
&& new.left <= tile_left + 16.0
{
collision_x = true;
new.left = tile_left + 16.0;
}
if ! overlap(new, tile) {
if !overlap(new, tile) {
continue;
}
// Collisions between head and roof
if self.tiles[(row, col)].0.from_bottom &&
old.top >= tile_top + 16.0 &&
new.top <= tile_top + 16.0 {
if self.tiles[(row, col)].0.from_bottom
&& old.top >= tile_top + 16.0
&& new.top <= tile_top + 16.0
{
collision_y = true;
new.top = tile_top + 16.0;
}
}
}
@@ -494,10 +471,8 @@ impl Map {
/// Checks if two boxes overlap.
pub fn overlap(box1: FloatRect, box2: FloatRect) -> bool {
box2.left < box1.left + box1.width &&
box2.left + box2.width > box1.left &&
box2.top < box1.top + box1.height &&
box2.top + box2.height > box1.top
box2.left < box1.left + box1.width
&& box2.left + box2.width > box1.left
&& box2.top < box1.top + box1.height
&& box2.top + box2.height > box1.top
}