diff --git a/src/engine/character.rs b/src/engine/character.rs index e562d02..67ed4af 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::{Button, Event}; +use crate::engine::input::{Action, Button}; use crate::engine::math::{clamp, duration_as_f64, duration_as_frame}; use crate::engine::physics; use crate::engine::scene::Updatable; @@ -196,15 +196,15 @@ impl Updatable for Character { self.position += self.speed * duration; } - /// An event was asked to the character. - fn manage_event(&mut self, event: Event) { - match event { - Event::ButtonPressed(Button::Button1) => { + /// An action was asked to the character. + fn manage_action(&mut self, action: Action) { + match action { + Action::ButtonPressed(Button::Button1) => { self.jump(); self.can_jump = false; } - Event::ButtonReleased(Button::Button1) => { + Action::ButtonReleased(Button::Button1) => { self.can_jump = true; } diff --git a/src/engine/controls.rs b/src/engine/controls.rs index 2945f19..d8b4129 100644 --- a/src/engine/controls.rs +++ b/src/engine/controls.rs @@ -1,4 +1,26 @@ //! This module helps to deal with controls. +use crate::engine::input::{Action, Event}; + /// The different types of controls. -pub enum Controls {} +pub enum Controls { + /// A gamepad controls the scene. + Gamepad(u32), +} + +impl Controls { + /// Converts an event into an action if it corresponds to an action. + pub fn convert(&self, event: Event) -> Option { + match self { + Controls::Gamepad(ig) => match event { + Event::ButtonPressed(ie, button) if *ig == ie => { + Some(Action::ButtonPressed(button)) + } + Event::ButtonReleased(ie, button) if *ig == ie => { + Some(Action::ButtonReleased(button)) + } + _ => None, + }, + } + } +} diff --git a/src/engine/input.rs b/src/engine/input.rs index c461429..3eb25f3 100644 --- a/src/engine/input.rs +++ b/src/engine/input.rs @@ -9,13 +9,26 @@ use wasm_bindgen::JsCast; use crate::{log, Result}; -/// The different actions that a user can do. +/// The different events that can be triggered. #[derive(Debug, Copy, Clone)] pub enum Event { - /// A button has been pressed. + /// A gamepad has been connected. + GamepadConnected(u32), + + /// A button has been pressed on a certain gamepad. + ButtonPressed(u32, Button), + + /// A button has been released on a certain gamepad. + ButtonReleased(u32, Button), +} + +/// The different actions a user can do. +#[derive(Debug, Copy, Clone)] +pub enum Action { + /// A certain button has been pressed. ButtonPressed(Button), - /// A button has been released. + /// A certain button has been released. ButtonReleased(Button), } @@ -68,6 +81,8 @@ impl InputManager { /// Adds a gamepad to the input manager. pub fn add_gamepad(&mut self, gamepad: web_sys::Gamepad) { log!("Gamepad added {}", gamepad.id()); + self.events + .push_back(Event::GamepadConnected(gamepad.index())); self.gamepads.push(Gamepad::new(gamepad)); } @@ -116,12 +131,12 @@ impl Gamepad { if was_pressed && !is_pressed { // Button was released - events.push_back(Event::ButtonReleased(button)); + events.push_back(Event::ButtonReleased(self.inner.index(), button)); } if is_pressed && !was_pressed { // Button was pressed - events.push_back(Event::ButtonPressed(button)); + events.push_back(Event::ButtonPressed(self.inner.index(), button)); } } } diff --git a/src/engine/mod.rs b/src/engine/mod.rs index 44151b9..859bf2b 100644 --- a/src/engine/mod.rs +++ b/src/engine/mod.rs @@ -21,7 +21,7 @@ use wasm_bindgen::JsCast; use crate::engine::bbox::Bbox; use crate::engine::character::Character; use crate::engine::controls::Controls; -use crate::engine::input::Inputs; +use crate::engine::input::{Event, Inputs}; use crate::engine::map::Map; use crate::engine::math::now; use crate::engine::scene::{Scene, State}; @@ -38,6 +38,15 @@ macro_rules! unwrap { }}; } +macro_rules! unwrap_or_continue { + ($t: expr) => {{ + match $t { + Some(x) => x, + None => continue, + } + }}; +} + /// Our game engine. #[derive(Clone)] pub struct Game(Rc>); @@ -181,7 +190,17 @@ impl Engine { if self.document.has_focus()? { // Manage events while let Some(event) = self.inputs.next() { - self.scene.manage_event(event); + // Convert events into actions + let mut controlable = unwrap_or_continue!(self.scene.controlable_mut()); + + // If gamepad connected, make it control the character + if let Event::GamepadConnected(id) = event { + controlable.set_controls(Some(Controls::Gamepad(id))); + } + + let controls = unwrap_or_continue!(controlable.controls()); + let action = unwrap_or_continue!(controls.convert(event)); + self.scene.manage_action(action); } // let keyboard = inner.keyboard.clone(); diff --git a/src/engine/scene.rs b/src/engine/scene.rs index dd81cd5..3122536 100644 --- a/src/engine/scene.rs +++ b/src/engine/scene.rs @@ -4,7 +4,7 @@ use std::time::{Duration, SystemTime}; use crate::engine::bbox::Bbox; use crate::engine::character::Character; -use crate::engine::input::Event; +use crate::engine::input::Action; use crate::engine::map::Map; use crate::engine::texture::SPRITE_SIZE; @@ -46,7 +46,7 @@ impl Scene { } /// Returns the controlable. - fn controlable(&self) -> Option<&Character> { + pub fn controlable(&self) -> Option<&Character> { // TODO fix this return Some(&self.characters[0]); @@ -60,6 +60,9 @@ impl Scene { /// Returns the controlable. pub fn controlable_mut(&mut self) -> Option<&mut Character> { + // TODO fix this + return Some(&mut self.characters[0]); + for character in &mut self.characters { if character.controls().is_some() { return Some(character); @@ -135,10 +138,10 @@ impl Scene { state } - /// Transfers an event to the elements contained in the scene that should receive events. - pub fn manage_event(&mut self, event: Event) { + /// Transfers an action to the elements contained in the scene that should receive actions. + pub fn manage_action(&mut self, action: Action) { for c in &mut self.characters { - c.manage_event(event); + c.manage_action(action); } } @@ -158,6 +161,6 @@ pub trait Updatable { /// Updates the thing depending on the duration since last frame. fn update(&mut self, now: SystemTime, duration: Duration); - /// Called when an event arrives. - fn manage_event(&mut self, event: Event); + /// Called when an action arrives. + fn manage_action(&mut self, action: Action); }