Skip to content

Commit

Permalink
fix: Gamepad button progresses loader + additional gamepad event details
Browse files Browse the repository at this point in the history
  • Loading branch information
eonarheim committed Jan 1, 2025
1 parent 3f06ce3 commit e3d6c92
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 3 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).

### Fixed

- Fixed issue where gamepad buttons wouldn't progress the default loader play button
- Add defense around middling Safari fullscreen support and update documentation
- Fixed issue where non-standard gamepad buttons would not be emitted by Excalibur
- Added an additional param to the `ex.GamepadButtonEvent` `index`to disabiguate between `ex.Buttons.Unknown`
- Fixed issue where Realistic solver would not sort contacts by distance causing some artifacts on seams
- Fixed issue with CompositeCollider where large TileMaps would sometimes causes odd collision behavior in the Realistic Solver when the body & collider components are far apart in a TileMap.
- Fixed crash on Xiaomi Redmi Phones by lazy loading the GPU particle renderer, GPU particles still do not work on these phones
Expand Down
2 changes: 1 addition & 1 deletion sandbox/tests/input/gamepad.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ function start() {
console.log('Gamepad connect');
});

game.input.gamepads.on('disconnect', (evet: ex.GamepadDisconnectEvent) => {
game.input.gamepads.on('disconnect', (evt: ex.GamepadDisconnectEvent) => {
console.log('Gamepad disconnect');
});

Expand Down
1 change: 1 addition & 0 deletions src/engine/Director/Loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ export class Loader extends DefaultLoader {
this._playButton.addEventListener('click', startButtonHandler);
this._playButton.addEventListener('touchend', startButtonHandler);
this._playButton.addEventListener('pointerup', startButtonHandler);
this.engine.input.gamepads.once('button', () => startButtonHandler(new Event('button')));
});

return await playButtonClicked;
Expand Down
27 changes: 26 additions & 1 deletion src/engine/Events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -427,12 +427,27 @@ export class GamepadDisconnectEvent extends GameEvent<Gamepad> {
*/
export class GamepadButtonEvent extends GameEvent<Gamepad> {
/**
* @param button The Gamepad button
* @param button The Gamepad {@apilink Buttons} if not known by excalibur {@apilink Buttons.Unknown} is returned, use index to disambiguate.
* @param index The canonical index of the gamepad button from the system
* @param value A numeric value between 0 and 1
* @param self Reference to the gamepad
*/
constructor(
/**
* The Gamepad {@apilink Buttons} if not known by excalibur {@apilink Buttons.Unknown} is returned, use index to disambiguate.
*/
public button: Buttons,
/**
* The canonical index of the gamepad button from the system
*/
public index: number,
/**
* A numeric value between 0 and 1
*/
public value: number,
/**
* Reference to the gamepad
*/
public self: Gamepad
) {
super();
Expand All @@ -447,10 +462,20 @@ export class GamepadAxisEvent extends GameEvent<Gamepad> {
/**
* @param axis The Gamepad axis
* @param value A numeric value between -1 and 1
* @param self Reference to the gamepad
*/
constructor(
/**
* The Gamepad {@apilink Axis}
*/
public axis: Axes,
/**
* A numeric value between -1 and 1, 0 is the neutral axis position.
*/
public value: number,
/**
* Reference to the gamepad
*/
public self: Gamepad
) {
super();
Expand Down
13 changes: 12 additions & 1 deletion src/engine/Input/Gamepad.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ export class Gamepads {
public once<TEventName extends EventKey<GamepadEvents>>(eventName: TEventName, handler: Handler<GamepadEvents[TEventName]>): Subscription;
public once(eventName: string, handler: Handler<unknown>): Subscription;
public once<TEventName extends EventKey<GamepadEvents> | string>(eventName: TEventName, handler: Handler<any>): Subscription {
this._enableAndUpdate(); // implicitly enable
return this.events.once(eventName, handler);
}

Expand Down Expand Up @@ -151,12 +152,15 @@ export class Gamepads {
// If was connected, but now isn't emit the disconnect event
if (gamepad.connected) {
this.events.emit('disconnect', new GamepadDisconnectEvent(i, gamepad));
gamepad.events.unpipe(this.events);
}
// Reset connection status
gamepad.connected = false;
continue;
} else {
const gamepad = this.at(i);
if (!this.at(i).connected && this._isGamepadValid(gamepads[i])) {
gamepad.events.pipe(this.events);
this.events.emit('connect', new GamepadConnectEvent(i, this.at(i)));
}
// Set connection status
Expand Down Expand Up @@ -186,7 +190,14 @@ export class Gamepads {
if (value !== this._oldPads[i]?.getButton(buttonIndex)) {
if (button?.pressed) {
this.at(i).updateButton(buttonIndex, value);
this.at(i).events.emit('button', new GamepadButtonEvent(buttonIndex, value, this.at(i)));
// Fallback to unknown if not mapped
// prettier-ignore
this.at(i).events.emit('button', new GamepadButtonEvent(
buttonIndex in Buttons ? buttonIndex as Buttons : Buttons.Unknown,
buttonIndex,
value,
this.at(i))
);
} else {
this.at(i).updateButton(buttonIndex, 0);
}
Expand Down

0 comments on commit e3d6c92

Please sign in to comment.