Collision on Y axis seems to work
This commit is contained in:
		
							parent
							
								
									89295b9283
								
							
						
					
					
						commit
						cd1befafa5
					
				| @ -8,6 +8,7 @@ use sfml::window::Event; | ||||
| use sfml::window::Key; | ||||
| use sfml::graphics::{ | ||||
|     IntRect, | ||||
|     FloatRect, | ||||
|     View, | ||||
| }; | ||||
| 
 | ||||
| @ -146,6 +147,10 @@ impl Character { | ||||
|         View::new(self.position, Vector2::new(24.0 * 16.0, 24.0 * 9.0)) | ||||
|     } | ||||
| 
 | ||||
|     /// Returns the collision bounding box of the character.
 | ||||
|     pub fn bbox(&self) -> FloatRect { | ||||
|         FloatRect::new(self.position.x, self.position.y, 32.0, 32.0) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Updatable for Character { | ||||
| @ -229,8 +234,4 @@ impl Drawable for Character { | ||||
|     fn position(&self) -> Vector2<f32> { | ||||
|         self.position | ||||
|     } | ||||
| 
 | ||||
|     fn origin(&self) -> Vector2<f32> { | ||||
|         Vector2::new(16.0, 16.0) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,10 +1,22 @@ | ||||
| use sfml::system::Vector2; | ||||
| use sfml::graphics::IntRect; | ||||
| use sfml::graphics::{ | ||||
|     IntRect, | ||||
|     FloatRect | ||||
| }; | ||||
| 
 | ||||
| use engine::texture::Texture; | ||||
| use engine::renderer::Drawable; | ||||
| use engine::math::Matrix; | ||||
| 
 | ||||
| /// This enum represents if the collision happens on the X axis or the Y axis.
 | ||||
| pub enum CollisionAxis { | ||||
|     /// The X axis.
 | ||||
|     X, | ||||
| 
 | ||||
|     /// The Y axis.
 | ||||
|     Y, | ||||
| } | ||||
| 
 | ||||
| /// This struct represents the different sides from which a collision can occur.
 | ||||
| #[derive(Debug, Copy, Clone, PartialEq, Eq)] | ||||
| pub struct CollisionTile { | ||||
| @ -234,10 +246,6 @@ impl Drawable for PositionedTile { | ||||
|     fn position(&self) -> Vector2<f32> { | ||||
|         self.position.into() | ||||
|     } | ||||
| 
 | ||||
|     fn origin(&self) -> Vector2<f32> { | ||||
|         Vector2::new(0.0, 0.0) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// The map represents the tiles contained in a level.
 | ||||
| @ -351,10 +359,48 @@ impl Map { | ||||
|         self.tiles.cols() | ||||
|     } | ||||
| 
 | ||||
|     /// Checks whether the bounding box collides with an element of the map
 | ||||
|     pub fn collides_bbox(&self, old: FloatRect, new: FloatRect) -> Option<(CollisionAxis, Vector2<f32>)> { | ||||
|         // Top left corner
 | ||||
|         if let Some((axis, collision)) = self.collides_point( | ||||
|             Vector2::new(old.left, old.top), | ||||
|             Vector2::new(new.left, new.top), | ||||
|         ) { | ||||
|             return Some((axis, collision)); | ||||
|         } | ||||
| 
 | ||||
|         // Top right corner
 | ||||
|         if let Some((axis, collision)) = self.collides_point( | ||||
|             Vector2::new(old.left + old.width, old.top), | ||||
|             Vector2::new(new.left + new.width, new.top), | ||||
|         ) { | ||||
|             return Some((axis, collision - Vector2::new(new.width, 0.0))); | ||||
|         } | ||||
| 
 | ||||
|         // Bottom left corner
 | ||||
|         if let Some((axis, collision)) = self.collides_point( | ||||
|             Vector2::new(old.left, old.top + old.height), | ||||
|             Vector2::new(new.left, new.top + new.height), | ||||
|         ) { | ||||
|             return Some((axis, collision - Vector2::new(0.0, new.height))); | ||||
|         } | ||||
| 
 | ||||
|         // Bottom right corner
 | ||||
|         if let Some((axis, collision)) = self.collides_point( | ||||
|             Vector2::new(old.left + old.width, old.top + old.height), | ||||
|             Vector2::new(new.left + new.width, new.top + new.height), | ||||
|         ) { | ||||
|             return Some((axis, collision - Vector2::new(new.width, new.height))); | ||||
|         } | ||||
| 
 | ||||
|         None | ||||
|     } | ||||
| 
 | ||||
|     /// Checks whether the vector (old, new) collides with an element of the map.
 | ||||
|     ///
 | ||||
|     /// Returns the height of the collision if any.
 | ||||
|     pub fn collides(&self, old: Vector2<f32>, new: Vector2<f32>) -> Option<f32> { | ||||
|     pub fn collides_point(&self, old: Vector2<f32>, new: Vector2<f32>) | ||||
|         -> Option<(CollisionAxis, Vector2<f32>)> { | ||||
| 
 | ||||
|         let height = new.y - old.y; | ||||
|         let mut y = (old.y / 16.0).ceil() * 16.0; | ||||
| @ -372,7 +418,7 @@ impl Map { | ||||
| 
 | ||||
|                 if let Some((tile, _)) = self.tiles.get((row, col)) { | ||||
|                     if tile.from_top { | ||||
|                         return Some(y); | ||||
|                         return Some((CollisionAxis::Y, Vector2::new(x, y))); | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|  | ||||
| @ -32,9 +32,6 @@ pub trait Drawable { | ||||
| 
 | ||||
|     /// Returns the position on which the drawable should be drawn.
 | ||||
|     fn position(&self) -> Vector2<f32>; | ||||
| 
 | ||||
|     /// Returns the origin of the sprite.
 | ||||
|     fn origin(&self) -> Vector2<f32>; | ||||
| } | ||||
| 
 | ||||
| /// The game window.
 | ||||
| @ -92,7 +89,6 @@ impl Renderer { | ||||
| 
 | ||||
|         use sfml::graphics::Transformable; | ||||
|         sprite.set_position(drawable.position()); | ||||
|         sprite.set_origin(drawable.origin()); | ||||
| 
 | ||||
|         self.window.draw(&sprite); | ||||
|     } | ||||
|  | ||||
| @ -4,7 +4,10 @@ use sfml::window::Event; | ||||
| use sfml::graphics::View; | ||||
| 
 | ||||
| use engine::character::Character; | ||||
| use engine::map::Map; | ||||
| use engine::map::{ | ||||
|     Map, | ||||
|     CollisionAxis | ||||
| }; | ||||
| 
 | ||||
| /// Contains everything needed to play.
 | ||||
| pub struct Scene { | ||||
| @ -75,14 +78,21 @@ impl Scene { | ||||
|     pub fn update(&mut self, duration: &Duration) { | ||||
| 
 | ||||
|         for c in &mut self.characters { | ||||
|             let old = c.position; | ||||
|             let old = c.bbox(); | ||||
|             c.update(duration); | ||||
| 
 | ||||
| 
 | ||||
|             if let Some(height) = self.map.collides(old, c.position) { | ||||
|                 c.position.y = height; | ||||
|                 c.speed.y = 0.0; | ||||
|                 c.ground_collision(); | ||||
|             if let Some((axis, position)) = self.map.collides_bbox(old, c.bbox()) { | ||||
|                 match axis { | ||||
|                     CollisionAxis::X => { | ||||
|                         c.speed.x = 0.0; | ||||
|                         c.position.x = position.x; | ||||
|                     }, | ||||
|                     CollisionAxis::Y => { | ||||
|                         c.speed.y = 0.0; | ||||
|                         c.position.y = position.y; | ||||
|                         c.ground_collision(); | ||||
|                     }, | ||||
|                 } | ||||
|             } else { | ||||
|                 c.fall_off(); | ||||
|             } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user