From 93171a512306be6ea74d112bbc1208443be843ed Mon Sep 17 00:00:00 2001 From: Thomas Forgione Date: Sat, 30 Mar 2019 14:32:04 +0100 Subject: [PATCH] Collisions with border of level, death --- src/app/game.rs | 6 ++++-- src/engine/character/mod.rs | 41 +++++++++++++++++++++++++++++++++++++ src/engine/map/mod.rs | 31 ++++++++++++++++++++++++---- src/engine/scene/mod.rs | 26 +++++++++++++++++++++-- 4 files changed, 96 insertions(+), 8 deletions(-) diff --git a/src/app/game.rs b/src/app/game.rs index 3ec0ebb..802dc5f 100644 --- a/src/app/game.rs +++ b/src/app/game.rs @@ -8,7 +8,7 @@ use rusty::engine::character::Character; use rusty::engine::controls::Controls; use rusty::engine::renderer::Renderer; use rusty::engine::map::Map; -use rusty::engine::scene::Scene; +use rusty::engine::scene::{Scene, State}; fn parse_resolution(res: &str) -> Result<(u32, u32), String> { let split = res.split('x').collect::>(); @@ -99,7 +99,9 @@ fn main() { let duration = Instant::now().duration_since(after_loop); after_loop = Instant::now(); - scene.update(&duration); + if scene.update(&duration) == State::Finished { + running = false; + } // Update the view if let Some(view) = scene.view() { diff --git a/src/engine/character/mod.rs b/src/engine/character/mod.rs index 7e67fef..c98b57b 100644 --- a/src/engine/character/mod.rs +++ b/src/engine/character/mod.rs @@ -20,6 +20,19 @@ pub enum Side { Right, } +/// This enum represents the type of damages that the character can get. +#[derive(Copy, Clone)] +pub enum Damage { + /// No damage were made + None, + + /// A single point of life has been taken from the character. + One, + + /// The character died. + Death, +} + impl Side { /// Returns the side corresponding to the force. /// @@ -57,6 +70,9 @@ pub struct Character { /// The side of the character. side: Side, + /// The number of hp of the character. + hp: u32, + /// The counter of jumps. /// /// When it's 0, the character can no longer jump. @@ -82,6 +98,7 @@ impl Character { speed: Vector2::new(0.0, 0.0), controls, side: Side::Right, + hp: 1, jump_counter: 1, max_jump: 1, animation_timer: None, @@ -138,6 +155,30 @@ impl Character { pub fn bbox(&self) -> FloatRect { FloatRect::new(self.position.x + 8.0, self.position.y + 16.0, 16.0, 16.0) } + + /// Returns the number of hp of the character. + pub fn hp(&self) -> u32 { + self.hp + } + + /// Returns true if the character is alive. + pub fn is_alive(&self) -> bool { + self.hp > 0 + } + + /// Returns true if the character is dead. + pub fn is_dead(&self) -> bool { + self.hp == 0 + } + + /// Takes the corresponding damage. + pub fn take_damage(&mut self, damage: Damage) { + match damage { + Damage::None => (), + Damage::One => self.hp -= 1, + Damage::Death => self.hp = 0, + } + } } impl Updatable for Character { diff --git a/src/engine/map/mod.rs b/src/engine/map/mod.rs index 07f61fc..6224dbf 100644 --- a/src/engine/map/mod.rs +++ b/src/engine/map/mod.rs @@ -13,6 +13,7 @@ use crate::{Error, Result}; use crate::engine::math::{clamp, Matrix}; use crate::engine::renderer::Drawable; use crate::engine::texture::Texture; +use crate::engine::character::Damage; /// This enum represents if the collision happens on the X axis or the Y axis. #[derive(Copy, Clone)] @@ -436,7 +437,10 @@ impl Map { &self, old: FloatRect, new: FloatRect, - ) -> Option<(CollisionAxis, Vector2)> { + ) -> Option<(CollisionAxis, Vector2, Damage)> { + + let mut damage = Damage::None; + let cols = self.tiles.cols() - 1; let rows = self.tiles.rows() - 1; @@ -511,11 +515,30 @@ impl Map { } } + // Collision between the player and left border of the level + if new.left < 0.0 { + new.left = 0.0; + collision_x = true; + } + + // Collision between the player and right border of the level + if new.left > cols as f32 * 16.0 { + new.left = cols as f32 * 16.0; + collision_x = true; + } + + // Collision between the player and the void + if new.top > self.tiles.rows() as f32 * 16.0 { + new.top = self.tiles.rows() as f32 * 16.0; + collision_y = true; + damage = Damage::Death; + } + let new_pos = Vector2::new(new.left, new.top); match (collision_x, collision_y) { - (true, true) => Some((CollisionAxis::Both, new_pos)), - (true, false) => Some((CollisionAxis::X, new_pos)), - (false, true) => Some((CollisionAxis::Y, new_pos)), + (true, true) => Some((CollisionAxis::Both, new_pos, damage)), + (true, false) => Some((CollisionAxis::X, new_pos, damage)), + (false, true) => Some((CollisionAxis::Y, new_pos, damage)), (false, false) => None, } } diff --git a/src/engine/scene/mod.rs b/src/engine/scene/mod.rs index fbe239c..4fff52a 100644 --- a/src/engine/scene/mod.rs +++ b/src/engine/scene/mod.rs @@ -16,6 +16,16 @@ pub struct Scene { map: Map, } +/// The type used to represent whether a a scene is running or finished. +#[derive(Copy, Clone, PartialEq, Eq)] +pub enum State { + /// The scene is running. + Running, + + /// The scene is finished. + Finished, +} + impl Scene { /// Creates a scene from a map level. pub fn from_map(map: Map) -> Scene { @@ -74,7 +84,10 @@ impl Scene { } /// Updates the whole scene. - pub fn update(&mut self, duration: &Duration) { + pub fn update(&mut self, duration: &Duration) -> State { + + let mut state = State::Finished; + for c in &mut self.characters { let old = c.bbox(); @@ -83,7 +96,7 @@ impl Scene { c.update(duration); - if let Some((axis, position)) = self.map.collides_bbox(old, c.bbox()) { + if let Some((axis, position, damage)) = self.map.collides_bbox(old, c.bbox()) { c.position = position - offset; if axis.is_x() { c.speed.x = 0.0; @@ -92,10 +105,19 @@ impl Scene { c.speed.y = 0.0; c.ground_collision(); } + + c.take_damage(damage); + } else { c.fall_off(); } + + if c.controls().is_some() && c.is_alive() { + state = State::Running; + } } + + state } /// Transfers an event to the elements contained in the scene that should receive events.