Gamepad controls start working

This commit is contained in:
Thomas Forgione 2022-08-02 15:35:10 +02:00
parent db8fa3ebc8
commit 10934b6209
5 changed files with 80 additions and 21 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::{Button, Event}; use crate::engine::input::{Action, Button};
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;
@ -196,15 +196,15 @@ impl Updatable for Character {
self.position += self.speed * duration; self.position += self.speed * duration;
} }
/// An event was asked to the character. /// An action was asked to the character.
fn manage_event(&mut self, event: Event) { fn manage_action(&mut self, action: Action) {
match event { match action {
Event::ButtonPressed(Button::Button1) => { Action::ButtonPressed(Button::Button1) => {
self.jump(); self.jump();
self.can_jump = false; self.can_jump = false;
} }
Event::ButtonReleased(Button::Button1) => { Action::ButtonReleased(Button::Button1) => {
self.can_jump = true; self.can_jump = true;
} }

View File

@ -1,4 +1,26 @@
//! This module helps to deal with controls. //! This module helps to deal with controls.
use crate::engine::input::{Action, Event};
/// The different types of controls. /// 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<Action> {
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,
},
}
}
}

View File

@ -9,13 +9,26 @@ use wasm_bindgen::JsCast;
use crate::{log, Result}; use crate::{log, Result};
/// The different actions that a user can do. /// The different events that can be triggered.
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub enum Event { 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), ButtonPressed(Button),
/// A button has been released. /// A certain button has been released.
ButtonReleased(Button), ButtonReleased(Button),
} }
@ -68,6 +81,8 @@ impl InputManager {
/// Adds a gamepad to the input manager. /// Adds a gamepad to the input manager.
pub fn add_gamepad(&mut self, gamepad: web_sys::Gamepad) { pub fn add_gamepad(&mut self, gamepad: web_sys::Gamepad) {
log!("Gamepad added {}", gamepad.id()); log!("Gamepad added {}", gamepad.id());
self.events
.push_back(Event::GamepadConnected(gamepad.index()));
self.gamepads.push(Gamepad::new(gamepad)); self.gamepads.push(Gamepad::new(gamepad));
} }
@ -116,12 +131,12 @@ impl Gamepad {
if was_pressed && !is_pressed { if was_pressed && !is_pressed {
// Button was released // Button was released
events.push_back(Event::ButtonReleased(button)); events.push_back(Event::ButtonReleased(self.inner.index(), button));
} }
if is_pressed && !was_pressed { if is_pressed && !was_pressed {
// Button was pressed // Button was pressed
events.push_back(Event::ButtonPressed(button)); events.push_back(Event::ButtonPressed(self.inner.index(), button));
} }
} }
} }

View File

@ -21,7 +21,7 @@ use wasm_bindgen::JsCast;
use crate::engine::bbox::Bbox; use crate::engine::bbox::Bbox;
use crate::engine::character::Character; use crate::engine::character::Character;
use crate::engine::controls::Controls; use crate::engine::controls::Controls;
use crate::engine::input::Inputs; use crate::engine::input::{Event, Inputs};
use crate::engine::map::Map; use crate::engine::map::Map;
use crate::engine::math::now; use crate::engine::math::now;
use crate::engine::scene::{Scene, State}; 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. /// Our game engine.
#[derive(Clone)] #[derive(Clone)]
pub struct Game(Rc<RefCell<Engine>>); pub struct Game(Rc<RefCell<Engine>>);
@ -181,7 +190,17 @@ impl Engine {
if self.document.has_focus()? { if self.document.has_focus()? {
// Manage events // Manage events
while let Some(event) = self.inputs.next() { 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(); // let keyboard = inner.keyboard.clone();

View File

@ -4,7 +4,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::Event; use crate::engine::input::Action;
use crate::engine::map::Map; use crate::engine::map::Map;
use crate::engine::texture::SPRITE_SIZE; use crate::engine::texture::SPRITE_SIZE;
@ -46,7 +46,7 @@ impl Scene {
} }
/// Returns the controlable. /// Returns the controlable.
fn controlable(&self) -> Option<&Character> { pub fn controlable(&self) -> Option<&Character> {
// TODO fix this // TODO fix this
return Some(&self.characters[0]); return Some(&self.characters[0]);
@ -60,6 +60,9 @@ impl Scene {
/// Returns the controlable. /// Returns the controlable.
pub fn controlable_mut(&mut self) -> Option<&mut Character> { pub fn controlable_mut(&mut self) -> Option<&mut Character> {
// TODO fix this
return Some(&mut self.characters[0]);
for character in &mut self.characters { for character in &mut self.characters {
if character.controls().is_some() { if character.controls().is_some() {
return Some(character); return Some(character);
@ -135,10 +138,10 @@ impl Scene {
state state
} }
/// Transfers an event to the elements contained in the scene that should receive events. /// Transfers an action to the elements contained in the scene that should receive actions.
pub fn manage_event(&mut self, event: Event) { pub fn manage_action(&mut self, action: Action) {
for c in &mut self.characters { 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. /// 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);
/// Called when an event arrives. /// Called when an action arrives.
fn manage_event(&mut self, event: Event); fn manage_action(&mut self, action: Action);
} }