Working on gamepads

This commit is contained in:
Thomas Forgione 2022-08-01 16:54:11 +02:00
parent 2858e3d5ec
commit c771d1ccea
5 changed files with 114 additions and 15 deletions

View File

@ -23,4 +23,6 @@ features = [
'HtmlImageElement',
'Window',
'Performance',
'Gamepad',
'GamepadEvent',
]

View File

@ -135,6 +135,11 @@ impl Character {
&self.controls
}
/// Changes the controls.
pub fn set_controls(&mut self, controls: Option<Controls>) {
self.controls = controls;
}
/// Returns a view that looks at the character.
pub fn view(&self) -> Bbox {
Bbox::from_center_and_size(self.position, Vector::new(24.0 * 16.0, 24.0 * 9.0))

View File

@ -16,6 +16,9 @@ pub enum Action {
pub enum Controls {
/// A keyboard controller.
Keyboard(KeyboardMap),
/// A gamepad controller.
Gamepad(GamepadMap),
}
impl Controls {
@ -24,15 +27,12 @@ impl Controls {
Controls::Keyboard(KeyboardMap::default())
}
// /// Returns the default gamepad controls from id.
// ///
// /// Returns None if the gamepad corresponding to the id is not connected.
// pub fn default_gamepad_from_id(id: u32) -> Option<Controls> {
// match GamepadMap::from_id(id) {
// Some(map) => Some(Controls::Gamepad(map)),
// None => None,
// }
// }
/// Returns the default gamepad controls from id.
///
/// Returns None if the gamepad corresponding to the id is not connected.
pub fn default_gamepad(gamepad: web_sys::Gamepad) -> Controls {
Controls::Gamepad(GamepadMap::from_gamepad(gamepad))
}
// /// Returns the default gamepad controls from id.
// ///
@ -48,7 +48,7 @@ impl Controls {
pub fn convert(&self, event: &Event) -> Option<Action> {
match self {
Controls::Keyboard(ref map) => map.convert(event),
// Controls::Gamepad(ref map) => map.convert(event),
Controls::Gamepad(ref map) => map.convert(event),
}
}
@ -56,7 +56,7 @@ impl Controls {
pub fn direction(&self, keyboard: &Keyboard) -> Vector {
match self {
Controls::Keyboard(ref map) => map.direction(keyboard),
// Controls::Gamepad(ref map) => map.direction(),
Controls::Gamepad(ref map) => map.direction(),
}
}
@ -120,3 +120,60 @@ impl KeyboardMap {
ret
}
}
/// A map between gamepad buttons and actions.
#[derive(Clone)]
pub struct GamepadMap {
/// Id of the gamepad.
inner: web_sys::Gamepad,
/// Number of the jump button.
jump_button: u32,
/// Number of the run button.
run_button: u32,
// /// Left / Right axis.
// left_right_axis: Axis,
}
impl GamepadMap {
/// Creates a gamepad map from a javascript gamepad.
pub fn from_gamepad(gamepad: web_sys::Gamepad) -> GamepadMap {
GamepadMap {
inner: gamepad,
jump_button: 0,
run_button: 3,
}
}
/// Converts an event and depending on the config, returns the corresponding action.
pub fn convert(&self, event: &Event) -> Option<Action> {
None
// match event {
// Event::JoystickButtonPressed { joystickid, button }
// if *joystickid == self.id && *button == self.jump_button =>
// {
// Some(Action::Jump(true))
// }
// Event::JoystickButtonReleased { joystickid, button }
// if *joystickid == self.id && *button == self.jump_button =>
// {
// Some(Action::Jump(false))
// }
// _ => None,
// }
}
/// Returns the direction of the directionnal buttons of the gamepad.
pub fn direction(&self) -> Vector {
Vector::new(0.0, 0.0)
// Vector2::new(axis_position(self.id, self.left_right_axis) / 100.0, 0.0)
}
// /// Returns whether the run button is held down.
// pub fn is_running(&self) -> bool {
// is_button_pressed(self.id, self.run_button)
// }
}

View File

@ -20,7 +20,7 @@ use wasm_bindgen::JsCast;
use crate::engine::bbox::Bbox;
use crate::engine::character::Character;
use crate::engine::controls::Controls;
use crate::engine::controls::{Controls, GamepadMap};
use crate::engine::event::{Key, Keyboard};
use crate::engine::map::Map;
use crate::engine::math::now;
@ -84,13 +84,24 @@ impl Engine {
let inner = InnerEngine::new(&document, &performance, scene)?;
let inner = Rc::new(RefCell::new(inner));
let window = Rc::new(window);
let document = Rc::new(document);
let performance = Rc::new(performance);
let context = Rc::new(context);
let clone = inner.clone();
let cb = Closure::<dyn FnMut(_)>::new(move |event: web_sys::GamepadEvent| {
let mut inner = clone.borrow_mut();
inner.add_gamepad(&event);
});
(*window).add_event_listener_with_callback("gamepadconnected", cb.as_ref().unchecked_ref());
cb.forget();
Ok(Engine {
inner: Rc::new(RefCell::new(inner)),
inner,
window,
document,
performance,
@ -146,7 +157,7 @@ impl Engine {
let duration = unwrap!(now.duration_since(inner.after_loop).ok());
inner.after_loop = now;
if (self.document.has_focus()?) {
if self.document.has_focus()? {
// Manage events
while let Some(event) = inner.keyboard.pop() {
inner.scene.manage_event(&event);
@ -231,6 +242,9 @@ pub struct InnerEngine {
/// The keyboard.
pub keyboard: Keyboard,
/// The gamepads.
pub gamepads: Vec<GamepadMap>,
/// The texture manager.
pub textures: TextureManager,
}
@ -246,9 +260,20 @@ impl InnerEngine {
scene,
after_loop: now(&performance),
keyboard: Keyboard::new(document)?,
gamepads: vec![],
textures: TextureManager::new()?,
})
}
/// Adds a gamepad.
pub fn add_gamepad(&mut self, gamepad: &web_sys::GamepadEvent) {
let gamepad = GamepadMap::from_gamepad(gamepad.gamepad().unwrap());
let clone = gamepad.clone();
self.gamepads.push(clone);
let controlable = self.scene.controlable_mut().unwrap();
controlable.set_controls(Some(Controls::Gamepad(gamepad)));
}
}
/// Our custom drawable trait.

View File

@ -55,6 +55,16 @@ impl Scene {
None
}
/// Returns the controlable.
pub fn controlable_mut(&mut self) -> Option<&mut Character> {
for character in &mut self.characters {
if character.controls().is_some() {
return Some(character);
}
}
None
}
/// Returns the right view.
pub fn view(&self) -> Option<Bbox> {
let view = self.controlable()?.view();
@ -109,7 +119,7 @@ impl Scene {
c.ground_collision();
}
if (damage) {
if damage {
c.die();
state = State::Finished;
}