From 908ae113932f63de7be46cc1a555c28691e54aef Mon Sep 17 00:00:00 2001 From: Thomas Forgione Date: Tue, 2 Aug 2022 17:05:42 +0200 Subject: [PATCH] Direction now works --- src/engine/character.rs | 6 ++-- src/engine/controls.rs | 29 +++++++++++++++++- src/engine/input.rs | 68 +++++++++++++++++++++++++++++++++++++---- src/engine/mod.rs | 15 +++++++-- src/engine/scene.rs | 7 +++-- 5 files changed, 110 insertions(+), 15 deletions(-) diff --git a/src/engine/character.rs b/src/engine/character.rs index 67ed4af..9f42026 100644 --- a/src/engine/character.rs +++ b/src/engine/character.rs @@ -4,7 +4,7 @@ use std::time::{Duration, SystemTime, UNIX_EPOCH}; use crate::engine::bbox::Bbox; use crate::engine::controls::Controls; -use crate::engine::input::{Action, Button}; +use crate::engine::input::{Action, Button, InputManager}; use crate::engine::math::{clamp, duration_as_f64, duration_as_frame}; use crate::engine::physics; use crate::engine::scene::Updatable; @@ -152,11 +152,11 @@ impl Character { } impl Updatable for Character { - fn update(&mut self, now: SystemTime, duration: Duration) { + fn update(&mut self, now: SystemTime, duration: Duration, inputs: &InputManager) { let mut force = Vector::new(0.0, 0.0); if let Some(ref controls) = self.controls { - // force += controls.direction(); + force += controls.main_direction(inputs); } if let Some(side) = Side::from_force(force) { diff --git a/src/engine/controls.rs b/src/engine/controls.rs index 46c1fbc..3a98eb1 100644 --- a/src/engine/controls.rs +++ b/src/engine/controls.rs @@ -1,8 +1,10 @@ //! This module helps to deal with controls. -use crate::engine::input::{Action, Button, Event, Key}; +use crate::engine::input::{Action, Button, Event, InputManager, Key}; +use crate::engine::vector::Vector; /// The different types of controls. +#[derive(Clone)] pub enum Controls { /// Default keyboard controls. Keyboard, @@ -12,6 +14,31 @@ pub enum Controls { } impl Controls { + /// Returns the main direction held by the user. + pub fn main_direction(&self, input: &InputManager) -> Vector { + match self { + Controls::Keyboard => { + let mut dir = Vector::new(0.0, 0.0); + if input.is_key_pressed(Key::ArrowLeft) { + dir.x -= 1.0; + } + + if input.is_key_pressed(Key::ArrowRight) { + dir.x += 1.0; + } + + dir + } + Controls::Gamepad(id) => { + if let Some(gamepad) = input.gamepad(*id) { + gamepad.main_direction() + } else { + Vector::new(0.0, 0.0) + } + } + } + } + /// Converts an event into an action if it corresponds to an action. pub fn convert(&self, event: Event) -> Option { match self { diff --git a/src/engine/input.rs b/src/engine/input.rs index 198d304..7466b82 100644 --- a/src/engine/input.rs +++ b/src/engine/input.rs @@ -7,6 +7,8 @@ use std::rc::Rc; use wasm_bindgen::prelude::*; use wasm_bindgen::JsCast; +use crate::engine::vector::Vector; + use crate::{log, Result}; /// The different events that can be triggered. @@ -29,8 +31,20 @@ pub enum Event { } /// The different keyboard keys we support. -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Hash, Copy, Clone, PartialEq, Eq)] pub enum Key { + /// The left arrow key. + ArrowLeft, + + /// The right arrow key. + ArrowRight, + + /// The up arrow key. + ArrowUp, + + /// The down arrow key. + ArrowDown, + /// The space key. Space, } @@ -75,6 +89,9 @@ pub enum Button { /// This structure holds what button are pressed or released, and stores the events. pub struct InputManager { + /// The state of the keyboard. + keyboard: HashMap, + /// All the connected gamepads. gamepads: Vec, @@ -86,14 +103,24 @@ impl InputManager { /// Creates a new input manager. pub fn new() -> InputManager { InputManager { + keyboard: HashMap::new(), gamepads: vec![], events: VecDeque::new(), } } + /// Gets the gamepad from its id. + pub fn gamepad(&self, id: u32) -> Option<&Gamepad> { + self.gamepads.iter().find(|x| x.inner.index() == id) + } + /// Parses a keyboard event to the key. pub fn key(event: web_sys::KeyboardEvent) -> Option { match event.code().as_str() { + "ArrowDown" => Some(Key::ArrowDown), + "ArrowUp" => Some(Key::ArrowUp), + "ArrowLeft" => Some(Key::ArrowLeft), + "ArrowRight" => Some(Key::ArrowRight), "Space" => Some(Key::Space), _ => None, } @@ -102,6 +129,7 @@ impl InputManager { /// Adds a key pressed event to the list of events. pub fn key_pressed_event(&mut self, event: web_sys::KeyboardEvent) { if let Some(key) = InputManager::key(event) { + self.keyboard.insert(key, true); self.events.push_back(Event::KeyPressed(key)); } } @@ -109,6 +137,7 @@ impl InputManager { /// Adds a key released event to the list of events. pub fn key_released_event(&mut self, event: web_sys::KeyboardEvent) { if let Some(key) = InputManager::key(event) { + self.keyboard.insert(key, false); self.events.push_back(Event::KeyReleased(key)); } } @@ -127,6 +156,11 @@ impl InputManager { gamepad.update(&mut self.events); } } + + /// Checks if a specific key is pressed. + pub fn is_key_pressed(&self, key: Key) -> bool { + *self.keyboard.get(&key).unwrap_or(&false) + } } /// Holds the gamepad information. @@ -135,8 +169,21 @@ pub struct Gamepad { /// The javascript gamepad object. inner: web_sys::Gamepad, + /// The main joystick. + main_joystick: Joystick, + /// What buttons are pressed or released. - state: HashMap, + buttons: HashMap, +} + +/// The joysticks. +#[derive(Clone)] +pub struct Joystick { + /// The id of the X axis of the joystick. + pub x_id: u32, + + /// The id of the Y axis of the joystick. + pub y_id: u32, } impl Gamepad { @@ -144,10 +191,19 @@ impl Gamepad { pub fn new(inner: web_sys::Gamepad) -> Gamepad { Gamepad { inner, - state: HashMap::new(), + main_joystick: Joystick { x_id: 0, y_id: 1 }, + buttons: HashMap::new(), } } + /// Returns the direction of the main joystick. + pub fn main_direction(&self) -> Vector { + let axes = self.inner.axes(); + let x = axes.get(self.main_joystick.x_id).as_f64().unwrap(); + let y = axes.get(self.main_joystick.y_id).as_f64().unwrap(); + Vector::new(x, y) + } + /// Updates the state of the gamepad and adds the corresponding events to the deque. pub fn update(&mut self, events: &mut VecDeque) { const BUTTONS: [Button; 4] = [ @@ -162,7 +218,7 @@ impl Gamepad { let is_pressed = self.is_js_pressed(button); // Updates the map and returns the old state of the button - let was_pressed = self.state.insert(button, is_pressed).unwrap_or(false); + let was_pressed = self.buttons.insert(button, is_pressed).unwrap_or(false); if was_pressed && !is_pressed { // Button was released @@ -178,7 +234,7 @@ impl Gamepad { /// Checks if a button is pressed. pub fn is_pressed(&self, button: Button) -> bool { - *self.state.get(&button).unwrap_or(&false) + *self.buttons.get(&button).unwrap_or(&false) } /// Utility function to really check the state of the button. @@ -199,7 +255,7 @@ impl Gamepad { /// A helper to easily deal with inputs. #[derive(Clone)] -pub struct Inputs(Rc>); +pub struct Inputs(pub Rc>); impl Inputs { /// Creates a new inputs object. diff --git a/src/engine/mod.rs b/src/engine/mod.rs index 0aed3e0..3e1e5a8 100644 --- a/src/engine/mod.rs +++ b/src/engine/mod.rs @@ -204,11 +204,22 @@ impl Engine { } // let keyboard = inner.keyboard.clone(); - if self.scene.update(now, duration) == State::Finished { + let input_manager = self.inputs.0.borrow(); + if self.scene.update(now, duration, &input_manager) == State::Finished { + let controls = self + .scene + .controlable() + .as_ref() + .unwrap() + .controls() + .as_ref() + .unwrap() + .clone(); + let map = Map::from_str(include_str!("../../static/levels/level1.lvl")).unwrap(); let mut scene = Scene::from_map(map); - let character = Character::new(); + let character = Character::with_controls(controls); scene.add(character); self.scene = scene; diff --git a/src/engine/scene.rs b/src/engine/scene.rs index 0945369..d84184b 100644 --- a/src/engine/scene.rs +++ b/src/engine/scene.rs @@ -5,6 +5,7 @@ use std::time::{Duration, SystemTime}; use crate::engine::bbox::Bbox; use crate::engine::character::Character; use crate::engine::input::Action; +use crate::engine::input::InputManager; use crate::engine::map::Map; use crate::engine::texture::SPRITE_SIZE; @@ -95,7 +96,7 @@ impl Scene { } /// Updates the whole scene. - pub fn update(&mut self, now: SystemTime, duration: Duration) -> State { + pub fn update(&mut self, now: SystemTime, duration: Duration, inputs: &InputManager) -> State { let mut state = State::Running; for c in &mut self.characters { @@ -107,7 +108,7 @@ impl Scene { // Compute the offset between position and bbox let offset = old.position - c.position; - c.update(now, duration); + c.update(now, duration, inputs); if let Some((axis, position, damage)) = self.map.collides_bbox(old, c.bbox()) { c.position = position - offset; @@ -153,7 +154,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, now: SystemTime, duration: Duration); + fn update(&mut self, now: SystemTime, duration: Duration, inputs: &InputManager); /// Called when an action arrives. fn manage_action(&mut self, action: Action);