Collisions with border of level, death

This commit is contained in:
Thomas Forgione 2019-03-30 14:32:04 +01:00
parent 2ff29eb0c6
commit 93171a5123
No known key found for this signature in database
GPG Key ID: BFD17A2D71B3B5E7
4 changed files with 96 additions and 8 deletions

View File

@ -8,7 +8,7 @@ use rusty::engine::character::Character;
use rusty::engine::controls::Controls; use rusty::engine::controls::Controls;
use rusty::engine::renderer::Renderer; use rusty::engine::renderer::Renderer;
use rusty::engine::map::Map; 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> { fn parse_resolution(res: &str) -> Result<(u32, u32), String> {
let split = res.split('x').collect::<Vec<_>>(); let split = res.split('x').collect::<Vec<_>>();
@ -99,7 +99,9 @@ fn main() {
let duration = Instant::now().duration_since(after_loop); let duration = Instant::now().duration_since(after_loop);
after_loop = Instant::now(); after_loop = Instant::now();
scene.update(&duration); if scene.update(&duration) == State::Finished {
running = false;
}
// Update the view // Update the view
if let Some(view) = scene.view() { if let Some(view) = scene.view() {

View File

@ -20,6 +20,19 @@ pub enum Side {
Right, 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 { impl Side {
/// Returns the side corresponding to the force. /// Returns the side corresponding to the force.
/// ///
@ -57,6 +70,9 @@ pub struct Character {
/// The side of the character. /// The side of the character.
side: Side, side: Side,
/// The number of hp of the character.
hp: u32,
/// The counter of jumps. /// The counter of jumps.
/// ///
/// When it's 0, the character can no longer jump. /// When it's 0, the character can no longer jump.
@ -82,6 +98,7 @@ impl Character {
speed: Vector2::new(0.0, 0.0), speed: Vector2::new(0.0, 0.0),
controls, controls,
side: Side::Right, side: Side::Right,
hp: 1,
jump_counter: 1, jump_counter: 1,
max_jump: 1, max_jump: 1,
animation_timer: None, animation_timer: None,
@ -138,6 +155,30 @@ impl Character {
pub fn bbox(&self) -> FloatRect { pub fn bbox(&self) -> FloatRect {
FloatRect::new(self.position.x + 8.0, self.position.y + 16.0, 16.0, 16.0) 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 { impl Updatable for Character {

View File

@ -13,6 +13,7 @@ use crate::{Error, Result};
use crate::engine::math::{clamp, Matrix}; use crate::engine::math::{clamp, Matrix};
use crate::engine::renderer::Drawable; use crate::engine::renderer::Drawable;
use crate::engine::texture::Texture; 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. /// This enum represents if the collision happens on the X axis or the Y axis.
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
@ -436,7 +437,10 @@ impl Map {
&self, &self,
old: FloatRect, old: FloatRect,
new: FloatRect, new: FloatRect,
) -> Option<(CollisionAxis, Vector2<f32>)> { ) -> Option<(CollisionAxis, Vector2<f32>, Damage)> {
let mut damage = Damage::None;
let cols = self.tiles.cols() - 1; let cols = self.tiles.cols() - 1;
let rows = self.tiles.rows() - 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); let new_pos = Vector2::new(new.left, new.top);
match (collision_x, collision_y) { match (collision_x, collision_y) {
(true, true) => Some((CollisionAxis::Both, new_pos)), (true, true) => Some((CollisionAxis::Both, new_pos, damage)),
(true, false) => Some((CollisionAxis::X, new_pos)), (true, false) => Some((CollisionAxis::X, new_pos, damage)),
(false, true) => Some((CollisionAxis::Y, new_pos)), (false, true) => Some((CollisionAxis::Y, new_pos, damage)),
(false, false) => None, (false, false) => None,
} }
} }

View File

@ -16,6 +16,16 @@ pub struct Scene {
map: Map, 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 { impl Scene {
/// Creates a scene from a map level. /// Creates a scene from a map level.
pub fn from_map(map: Map) -> Scene { pub fn from_map(map: Map) -> Scene {
@ -74,7 +84,10 @@ impl Scene {
} }
/// Updates the whole 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 { for c in &mut self.characters {
let old = c.bbox(); let old = c.bbox();
@ -83,7 +96,7 @@ impl Scene {
c.update(duration); 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; c.position = position - offset;
if axis.is_x() { if axis.is_x() {
c.speed.x = 0.0; c.speed.x = 0.0;
@ -92,10 +105,19 @@ impl Scene {
c.speed.y = 0.0; c.speed.y = 0.0;
c.ground_collision(); c.ground_collision();
} }
c.take_damage(damage);
} else { } else {
c.fall_off(); 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. /// Transfers an event to the elements contained in the scene that should receive events.