From 466760c6a7a776fbf5efa637942aa15597e3238b Mon Sep 17 00:00:00 2001 From: Thomas Forgione Date: Sat, 30 Jul 2022 13:37:34 +0200 Subject: [PATCH] Something that compiles --- src/engine/bbox.rs | 1 + src/engine/character.rs | 16 ++-- src/engine/controls.rs | 12 +-- src/engine/image.rs | 1 - src/engine/map.rs | 182 +++++++++++++++++++++++++--------------- src/engine/mod.rs | 1 + src/engine/scene.rs | 11 +-- 7 files changed, 135 insertions(+), 89 deletions(-) delete mode 100644 src/engine/image.rs diff --git a/src/engine/bbox.rs b/src/engine/bbox.rs index 1fb393b..420a6a7 100644 --- a/src/engine/bbox.rs +++ b/src/engine/bbox.rs @@ -3,6 +3,7 @@ use crate::engine::vector::Vector; /// This struct represents a bounding box. +#[derive(Copy, Clone)] pub struct Bbox { /// The position of the top right corner of the box. pub position: Vector, diff --git a/src/engine/character.rs b/src/engine/character.rs index 1818cff..821b915 100644 --- a/src/engine/character.rs +++ b/src/engine/character.rs @@ -3,17 +3,13 @@ use std::time::{Duration, Instant}; use crate::engine::bbox::Bbox; +use crate::engine::controls::Controls; +use crate::engine::event::Keyboard; +use crate::engine::math::{clamp, duration_as_f64}; use crate::engine::physics; use crate::engine::scene::Updatable; use crate::engine::vector::Vector; -use crate::engine::controls::Controls; -use crate::engine::math::{clamp, duration_as_f64, duration_as_frame}; -// use crate::engine::physics; -// use crate::engine::renderer::Drawable; -// use crate::engine::scene::Updatable; -// use crate::engine::texture::Texture; - /// The different sides a character can face. pub enum Side { /// The character looks to the left. @@ -148,11 +144,11 @@ impl Character { } impl Updatable for Character { - fn update(&mut self, duration: &Duration) { + fn update(&mut self, duration: &Duration, keyboard: &Keyboard) { let mut force = Vector::new(0.0, 0.0); if let Some(ref controls) = self.controls { - force += controls.direction(); + force += controls.direction(keyboard); } if let Some(side) = Side::from_force(force) { @@ -182,7 +178,7 @@ impl Updatable for Character { } let limit = match self.controls { - Some(controls) if controls.is_running() => physics::MAXIMUM_RUNNING_SPEED, + Some(ref controls) if controls.is_running() => physics::MAXIMUM_RUNNING_SPEED, _ => physics::MAXIMUM_WALKING_SPEED, }; diff --git a/src/engine/controls.rs b/src/engine/controls.rs index d7a2ba2..bf8a36f 100644 --- a/src/engine/controls.rs +++ b/src/engine/controls.rs @@ -1,6 +1,6 @@ //! This module helps to deal with controls. -use crate::engine::event::{Event, Key}; +use crate::engine::event::{Event, Key, Keyboard}; use crate::engine::vector::Vector; /// The different actions that a user can do. @@ -52,9 +52,9 @@ impl Controls { } /// Returns the direction of the controls. - pub fn direction(&self) -> Vector { + pub fn direction(&self, keyboard: &Keyboard) -> Vector { match self { - Controls::Keyboard(ref map) => map.direction(), + Controls::Keyboard(ref map) => map.direction(keyboard), // Controls::Gamepad(ref map) => map.direction(), } } @@ -106,14 +106,14 @@ impl KeyboardMap { } /// Returns the direction of the keys. - pub fn direction(&self) -> Vector { + pub fn direction(&self, keyboard: &Keyboard) -> Vector { let mut ret = Vector::new(0.0, 0.0); const RIGHT: Vector = Vector { x: 1.0, y: 0.0 }; - if self.right_key.is_pressed() { + if keyboard.is_key_pressed(self.right_key) { ret += RIGHT; } - if self.left_key.is_pressed() { + if keyboard.is_key_pressed(self.left_key) { ret -= RIGHT; } ret diff --git a/src/engine/image.rs b/src/engine/image.rs deleted file mode 100644 index e127ae1..0000000 --- a/src/engine/image.rs +++ /dev/null @@ -1 +0,0 @@ -//! A module that makes it easier to deal with images. diff --git a/src/engine/map.rs b/src/engine/map.rs index ac83743..0cd4f35 100644 --- a/src/engine/map.rs +++ b/src/engine/map.rs @@ -4,14 +4,66 @@ use std::fs::File; use std::io::Read; use std::path::Path; -use sfml::graphics::{FloatRect, IntRect}; -use sfml::system::Vector2; - -use crate::engine::character::Damage; +use crate::engine::bbox::Bbox; use crate::engine::math::{clamp, Matrix}; -use crate::engine::renderer::Drawable; -use crate::engine::texture::{byte_to_index, Texture, SPRITE_SIZE_F32, SPRITE_SIZE_I32}; -use crate::{Error, Result}; +use crate::engine::texture::SPRITE_SIZE; +use crate::engine::vector::Vector; +use crate::Result; + +/// Converts the byte with bits corresponding to the neighbours to the offset on the generated +/// tileset. +pub fn byte_to_index(byte: u8) -> i32 { + match byte { + 0 => 0, + 1 => 1, + 4 => 2, + 5 => 3, + 7 => 4, + 16 => 5, + 17 => 6, + 20 => 7, + 21 => 8, + 23 => 9, + 28 => 10, + 29 => 11, + 31 => 12, + 64 => 13, + 65 => 14, + 68 => 15, + 69 => 16, + 71 => 17, + 80 => 18, + 81 => 19, + 84 => 20, + 85 => 21, + 87 => 22, + 92 => 23, + 93 => 24, + 95 => 25, + 112 => 26, + 113 => 27, + 116 => 28, + 117 => 29, + 119 => 30, + 124 => 31, + 125 => 32, + 127 => 33, + 193 => 34, + 197 => 35, + 199 => 36, + 209 => 37, + 213 => 38, + 215 => 39, + 221 => 40, + 223 => 41, + 241 => 42, + 245 => 43, + 247 => 44, + 253 => 45, + 255 => 46, + _ => panic!("Incorrect byte {}", byte), + } +} /// This enum represents if the collision happens on the X axis or the Y axis. #[derive(Copy, Clone)] @@ -175,23 +227,23 @@ pub struct PositionedTile { pub collision: CollisionTile, /// The position of the positioned tile. - pub position: (f32, f32), + pub position: Vector, } -impl Drawable for PositionedTile { - fn texture(&self) -> Texture { - Texture::Overworld - } - - fn texture_rect(&self) -> IntRect { - let offset = self.graphic.offset(); - IntRect::new(offset.0, offset.1, SPRITE_SIZE_I32, SPRITE_SIZE_I32) - } - - fn position(&self) -> Vector2 { - self.position.into() - } -} +// impl Drawable for PositionedTile { +// fn texture(&self) -> Texture { +// Texture::Overworld +// } +// +// fn texture_rect(&self) -> Bbox { +// let offset = self.graphic.offset(); +// Bbox::new(offset.x, offset.x, SPRITE_SIZE, SPRITE_SIZE) +// } +// +// fn position(&self) -> Vector { +// self.position +// } +// } /// The map represents the tiles contained in a level. #[derive(Clone)] @@ -219,14 +271,6 @@ impl Map { Map::from_collision_tiles(tiles) } - /// Loads a map from a file. - pub fn from_file>(path: P) -> Result { - let mut file = File::open(path.as_ref()).map_err(Error::Load)?; - let mut s = String::new(); - file.read_to_string(&mut s).map_err(Error::Load)?; - Map::from_str(&s) - } - /// Loads a map from a string. pub fn from_str(text: &str) -> Result { let split = text.split('\n').collect::>(); @@ -390,7 +434,7 @@ impl Map { PositionedTile { collision: self.collision_tiles[(row, col)], graphic: self.graphic_tiles[(row, col)], - position: (col as f32 * SPRITE_SIZE_F32, row as f32 * SPRITE_SIZE_F32), + position: Vector::new(col as f64 * SPRITE_SIZE, row as f64 * SPRITE_SIZE), } } @@ -407,21 +451,26 @@ impl Map { /// Checks whether the bounding box collides with elements of the map. /// /// Returns the new correct position. - pub fn collides_bbox( - &self, - old: Bbox, - new: Bbox, - ) -> Option<(CollisionAxis, Vector2, Damage)> { - let mut damage = Damage::None; + pub fn collides_bbox(&self, old: Bbox, new: Bbox) -> Option<(CollisionAxis, Vector, bool)> { + let mut death = false; let cols = self.collision_tiles.cols() - 1; let rows = self.collision_tiles.rows() - 1; - let min_col = clamp(new.left / SPRITE_SIZE_F32, 0.0, cols as f32) as usize; - let min_row = clamp(new.top / SPRITE_SIZE_F32, 0.0, rows as f32) as usize; + let min_col = clamp(new.position.x / SPRITE_SIZE, 0.0, cols as f64) as usize; + let min_row = clamp(new.position.y / SPRITE_SIZE, 0.0, rows as f64) as usize; - let max_col = clamp((new.left + new.width) / SPRITE_SIZE_F32, 0.0, cols as f32) as usize; - let max_row = clamp((new.top + new.height) / SPRITE_SIZE_F32, 0.0, rows as f32) as usize; + let max_col = clamp( + (new.position.x + new.size.x) / SPRITE_SIZE, + 0.0, + cols as f64, + ) as usize; + + let max_row = clamp( + (new.position.y + new.size.y) / SPRITE_SIZE, + 0.0, + rows as f64, + ) as usize; let mut collision_x = false; let mut collision_y = false; @@ -429,10 +478,10 @@ impl Map { for col in min_col..=max_col { for row in min_row..=max_row { - let tile_left = col as f32 * SPRITE_SIZE_F32; - let tile_top = row as f32 * SPRITE_SIZE_F32; + let tile_left = col as f64 * SPRITE_SIZE; + let tile_top = row as f64 * SPRITE_SIZE; - let tile = Bbox::new(tile_left, tile_top, SPRITE_SIZE_F32, SPRITE_SIZE_F32); + let tile = Bbox::new(tile_left, tile_top, SPRITE_SIZE, SPRITE_SIZE); if !overlap(new, tile) { continue; @@ -440,11 +489,11 @@ impl Map { // Collisions between feet and ground if self.collision_tiles[(row, col)].from_top - && old.top + old.height <= tile_top - && new.top + new.height >= tile_top + && old.position.y + old.size.y <= tile_top + && new.position.y + new.size.y >= tile_top { collision_y = true; - new.top = tile_top - new.height; + new.position.y = tile_top - new.size.y; } if !overlap(new, tile) { @@ -453,11 +502,11 @@ impl Map { // Collisions between right and right wall if self.collision_tiles[(row, col)].from_left - && old.left + old.width <= tile_left - && new.left + new.width >= tile_left + && old.position.x + old.size.x <= tile_left + && new.position.x + new.size.x >= tile_left { collision_x = true; - new.left = tile_left - new.width; + new.position.x = tile_left - new.size.x; } if !overlap(new, tile) { @@ -466,11 +515,11 @@ impl Map { // Collisions between left and left wall if self.collision_tiles[(row, col)].from_right - && old.left >= tile_left + SPRITE_SIZE_F32 - && new.left <= tile_left + SPRITE_SIZE_F32 + && old.position.x >= tile_left + SPRITE_SIZE + && new.position.x <= tile_left + SPRITE_SIZE { collision_x = true; - new.left = tile_left + SPRITE_SIZE_F32; + new.position.x = tile_left + SPRITE_SIZE; } if !overlap(new, tile) { @@ -479,39 +528,38 @@ impl Map { // Collisions between head and roof if self.collision_tiles[(row, col)].from_bottom - && old.top >= tile_top + SPRITE_SIZE_F32 - && new.top <= tile_top + SPRITE_SIZE_F32 + && old.position.y >= tile_top + SPRITE_SIZE + && new.position.y <= tile_top + SPRITE_SIZE { collision_y = true; - new.top = tile_top + SPRITE_SIZE_F32; + new.position.y = tile_top + SPRITE_SIZE; } } } // Collision between the player and left border of the level - if new.left < 0.0 { - new.left = 0.0; + if new.position.x < 0.0 { + new.position.x = 0.0; collision_x = true; } // Collision between the player and right border of the level - if new.left > cols as f32 * SPRITE_SIZE_F32 { - new.left = cols as f32 * SPRITE_SIZE_F32; + if new.position.x > cols as f64 * SPRITE_SIZE { + new.position.x = cols as f64 * SPRITE_SIZE; collision_x = true; } // Collision between the player and the void - if new.top > self.collision_tiles.rows() as f32 * SPRITE_SIZE_F32 { - new.top = self.collision_tiles.rows() as f32 * SPRITE_SIZE_F32; + if new.position.y > self.collision_tiles.rows() as f64 * SPRITE_SIZE { + new.position.y = self.collision_tiles.rows() as f64 * SPRITE_SIZE; collision_y = true; - damage = Damage::Death; + death = true; } - let new_pos = Vector2::new(new.left, new.top); match (collision_x, collision_y) { - (true, true) => Some((CollisionAxis::Both, new_pos, damage)), - (true, false) => Some((CollisionAxis::X, new_pos, damage)), - (false, true) => Some((CollisionAxis::Y, new_pos, damage)), + (true, true) => Some((CollisionAxis::Both, new.position, death)), + (true, false) => Some((CollisionAxis::X, new.position, death)), + (false, true) => Some((CollisionAxis::Y, new.position, death)), (false, false) => None, } } diff --git a/src/engine/mod.rs b/src/engine/mod.rs index 1d37d96..66bd186 100644 --- a/src/engine/mod.rs +++ b/src/engine/mod.rs @@ -4,6 +4,7 @@ pub mod bbox; pub mod character; pub mod controls; pub mod event; +pub mod map; pub mod math; pub mod physics; pub mod scene; diff --git a/src/engine/scene.rs b/src/engine/scene.rs index c79eb60..7412db9 100644 --- a/src/engine/scene.rs +++ b/src/engine/scene.rs @@ -3,6 +3,7 @@ use std::time::Duration; use crate::engine::character::Character; +use crate::engine::event::Keyboard; use crate::engine::map::Map; use crate::engine::texture::SPRITE_SIZE; @@ -37,8 +38,8 @@ impl Scene { /// Adds a character to the scene. pub fn add(&mut self, character: Character) { let mut character = character; - character.position.x = self.map.entrance().1 * SPRITE_SIZE; - character.position.y = self.map.entrance().0 * SPRITE_SIZE; + character.position.x = self.map.entrance().1 as f64 * SPRITE_SIZE; + character.position.y = self.map.entrance().0 as f64 * SPRITE_SIZE; self.characters.push(character); } @@ -83,7 +84,7 @@ impl Scene { // } /// Updates the whole scene. - pub fn update(&mut self, duration: &Duration) -> State { + pub fn update(&mut self, duration: &Duration, keyboard: &Keyboard) -> State { let mut state = State::Finished; for c in &mut self.characters { @@ -95,7 +96,7 @@ impl Scene { // Compute the offset between position and bbox let offset = old.position - c.position; - c.update(duration); + c.update(duration, keyboard); if let Some((axis, position, damage)) = self.map.collides_bbox(old, c.bbox()) { c.position = position - offset; @@ -143,7 +144,7 @@ impl Scene { /// Trait that needs to be implemented for everything that can be updatable. pub trait Updatable { /// Updates the thing depending on the duration since last frame. - fn update(&mut self, duration: &Duration); + fn update(&mut self, duration: &Duration, keyboard: &Keyboard); // /// Called when an event arrives. // fn manage_event(&mut self, event: &Event);