Direction now works

This commit is contained in:
Thomas Forgione 2022-08-02 17:05:42 +02:00
parent 4cfe15de77
commit 908ae11393
5 changed files with 110 additions and 15 deletions

View File

@ -4,7 +4,7 @@ use std::time::{Duration, SystemTime, UNIX_EPOCH};
use crate::engine::bbox::Bbox; use crate::engine::bbox::Bbox;
use crate::engine::controls::Controls; 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::math::{clamp, duration_as_f64, duration_as_frame};
use crate::engine::physics; use crate::engine::physics;
use crate::engine::scene::Updatable; use crate::engine::scene::Updatable;
@ -152,11 +152,11 @@ impl Character {
} }
impl Updatable for 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); let mut force = Vector::new(0.0, 0.0);
if let Some(ref controls) = self.controls { if let Some(ref controls) = self.controls {
// force += controls.direction(); force += controls.main_direction(inputs);
} }
if let Some(side) = Side::from_force(force) { if let Some(side) = Side::from_force(force) {

View File

@ -1,8 +1,10 @@
//! This module helps to deal with controls. //! 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. /// The different types of controls.
#[derive(Clone)]
pub enum Controls { pub enum Controls {
/// Default keyboard controls. /// Default keyboard controls.
Keyboard, Keyboard,
@ -12,6 +14,31 @@ pub enum Controls {
} }
impl 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. /// Converts an event into an action if it corresponds to an action.
pub fn convert(&self, event: Event) -> Option<Action> { pub fn convert(&self, event: Event) -> Option<Action> {
match self { match self {

View File

@ -7,6 +7,8 @@ use std::rc::Rc;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast; use wasm_bindgen::JsCast;
use crate::engine::vector::Vector;
use crate::{log, Result}; use crate::{log, Result};
/// The different events that can be triggered. /// The different events that can be triggered.
@ -29,8 +31,20 @@ pub enum Event {
} }
/// The different keyboard keys we support. /// The different keyboard keys we support.
#[derive(Debug, Copy, Clone)] #[derive(Debug, Hash, Copy, Clone, PartialEq, Eq)]
pub enum Key { 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. /// The space key.
Space, Space,
} }
@ -75,6 +89,9 @@ pub enum Button {
/// This structure holds what button are pressed or released, and stores the events. /// This structure holds what button are pressed or released, and stores the events.
pub struct InputManager { pub struct InputManager {
/// The state of the keyboard.
keyboard: HashMap<Key, bool>,
/// All the connected gamepads. /// All the connected gamepads.
gamepads: Vec<Gamepad>, gamepads: Vec<Gamepad>,
@ -86,14 +103,24 @@ impl InputManager {
/// Creates a new input manager. /// Creates a new input manager.
pub fn new() -> InputManager { pub fn new() -> InputManager {
InputManager { InputManager {
keyboard: HashMap::new(),
gamepads: vec![], gamepads: vec![],
events: VecDeque::new(), 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. /// Parses a keyboard event to the key.
pub fn key(event: web_sys::KeyboardEvent) -> Option<Key> { pub fn key(event: web_sys::KeyboardEvent) -> Option<Key> {
match event.code().as_str() { 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), "Space" => Some(Key::Space),
_ => None, _ => None,
} }
@ -102,6 +129,7 @@ impl InputManager {
/// Adds a key pressed event to the list of events. /// Adds a key pressed event to the list of events.
pub fn key_pressed_event(&mut self, event: web_sys::KeyboardEvent) { pub fn key_pressed_event(&mut self, event: web_sys::KeyboardEvent) {
if let Some(key) = InputManager::key(event) { if let Some(key) = InputManager::key(event) {
self.keyboard.insert(key, true);
self.events.push_back(Event::KeyPressed(key)); self.events.push_back(Event::KeyPressed(key));
} }
} }
@ -109,6 +137,7 @@ impl InputManager {
/// Adds a key released event to the list of events. /// Adds a key released event to the list of events.
pub fn key_released_event(&mut self, event: web_sys::KeyboardEvent) { pub fn key_released_event(&mut self, event: web_sys::KeyboardEvent) {
if let Some(key) = InputManager::key(event) { if let Some(key) = InputManager::key(event) {
self.keyboard.insert(key, false);
self.events.push_back(Event::KeyReleased(key)); self.events.push_back(Event::KeyReleased(key));
} }
} }
@ -127,6 +156,11 @@ impl InputManager {
gamepad.update(&mut self.events); 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. /// Holds the gamepad information.
@ -135,8 +169,21 @@ pub struct Gamepad {
/// The javascript gamepad object. /// The javascript gamepad object.
inner: web_sys::Gamepad, inner: web_sys::Gamepad,
/// The main joystick.
main_joystick: Joystick,
/// What buttons are pressed or released. /// What buttons are pressed or released.
state: HashMap<Button, bool>, buttons: HashMap<Button, bool>,
}
/// 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 { impl Gamepad {
@ -144,10 +191,19 @@ impl Gamepad {
pub fn new(inner: web_sys::Gamepad) -> Gamepad { pub fn new(inner: web_sys::Gamepad) -> Gamepad {
Gamepad { Gamepad {
inner, 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. /// Updates the state of the gamepad and adds the corresponding events to the deque.
pub fn update(&mut self, events: &mut VecDeque<Event>) { pub fn update(&mut self, events: &mut VecDeque<Event>) {
const BUTTONS: [Button; 4] = [ const BUTTONS: [Button; 4] = [
@ -162,7 +218,7 @@ impl Gamepad {
let is_pressed = self.is_js_pressed(button); let is_pressed = self.is_js_pressed(button);
// Updates the map and returns the old state of the 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 { if was_pressed && !is_pressed {
// Button was released // Button was released
@ -178,7 +234,7 @@ impl Gamepad {
/// Checks if a button is pressed. /// Checks if a button is pressed.
pub fn is_pressed(&self, button: Button) -> bool { 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. /// Utility function to really check the state of the button.
@ -199,7 +255,7 @@ impl Gamepad {
/// A helper to easily deal with inputs. /// A helper to easily deal with inputs.
#[derive(Clone)] #[derive(Clone)]
pub struct Inputs(Rc<RefCell<InputManager>>); pub struct Inputs(pub Rc<RefCell<InputManager>>);
impl Inputs { impl Inputs {
/// Creates a new inputs object. /// Creates a new inputs object.

View File

@ -204,11 +204,22 @@ impl Engine {
} }
// let keyboard = inner.keyboard.clone(); // 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 map = Map::from_str(include_str!("../../static/levels/level1.lvl")).unwrap();
let mut scene = Scene::from_map(map); let mut scene = Scene::from_map(map);
let character = Character::new(); let character = Character::with_controls(controls);
scene.add(character); scene.add(character);
self.scene = scene; self.scene = scene;

View File

@ -5,6 +5,7 @@ use std::time::{Duration, SystemTime};
use crate::engine::bbox::Bbox; use crate::engine::bbox::Bbox;
use crate::engine::character::Character; use crate::engine::character::Character;
use crate::engine::input::Action; use crate::engine::input::Action;
use crate::engine::input::InputManager;
use crate::engine::map::Map; use crate::engine::map::Map;
use crate::engine::texture::SPRITE_SIZE; use crate::engine::texture::SPRITE_SIZE;
@ -95,7 +96,7 @@ impl Scene {
} }
/// Updates the whole 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; let mut state = State::Running;
for c in &mut self.characters { for c in &mut self.characters {
@ -107,7 +108,7 @@ impl Scene {
// Compute the offset between position and bbox // Compute the offset between position and bbox
let offset = old.position - c.position; 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()) { if let Some((axis, position, damage)) = self.map.collides_bbox(old, c.bbox()) {
c.position = position - offset; c.position = position - offset;
@ -153,7 +154,7 @@ impl Scene {
/// Trait that needs to be implemented for everything that can be updatable. /// Trait that needs to be implemented for everything that can be updatable.
pub trait Updatable { pub trait Updatable {
/// Updates the thing depending on the duration since last frame. /// 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. /// Called when an action arrives.
fn manage_action(&mut self, action: Action); fn manage_action(&mut self, action: Action);