Add player input bindings for gamepad and keyboard
This commit is contained in:
128
src/runtime-three/player-input-bindings.ts
Normal file
128
src/runtime-three/player-input-bindings.ts
Normal file
@@ -0,0 +1,128 @@
|
||||
import type {
|
||||
PlayerStartGamepadBinding,
|
||||
PlayerStartInputBindings
|
||||
} from "../entities/entity-instances";
|
||||
|
||||
const GAMEPAD_AXIS_DEADZONE = 0.18;
|
||||
|
||||
export interface PlayerStartMovementActionState {
|
||||
moveForward: number;
|
||||
moveBackward: number;
|
||||
moveLeft: number;
|
||||
moveRight: number;
|
||||
}
|
||||
|
||||
function clampUnitInterval(value: number): number {
|
||||
return Math.max(0, Math.min(1, value));
|
||||
}
|
||||
|
||||
function readGamepadButtonStrength(button: GamepadButton | undefined): number {
|
||||
if (button === undefined) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return clampUnitInterval(button.pressed ? Math.max(button.value, 1) : button.value);
|
||||
}
|
||||
|
||||
function readPositiveAxisStrength(value: number | undefined): number {
|
||||
if (value === undefined || !Number.isFinite(value) || value <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (value <= GAMEPAD_AXIS_DEADZONE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return clampUnitInterval(
|
||||
(value - GAMEPAD_AXIS_DEADZONE) / (1 - GAMEPAD_AXIS_DEADZONE)
|
||||
);
|
||||
}
|
||||
|
||||
function readNegativeAxisStrength(value: number | undefined): number {
|
||||
return readPositiveAxisStrength(
|
||||
value === undefined || !Number.isFinite(value) ? value : -value
|
||||
);
|
||||
}
|
||||
|
||||
function readSingleGamepadBinding(
|
||||
gamepad: Gamepad,
|
||||
binding: PlayerStartGamepadBinding
|
||||
): number {
|
||||
switch (binding) {
|
||||
case "leftStickUp":
|
||||
return readNegativeAxisStrength(gamepad.axes[1]);
|
||||
case "leftStickDown":
|
||||
return readPositiveAxisStrength(gamepad.axes[1]);
|
||||
case "leftStickLeft":
|
||||
return readNegativeAxisStrength(gamepad.axes[0]);
|
||||
case "leftStickRight":
|
||||
return readPositiveAxisStrength(gamepad.axes[0]);
|
||||
case "dpadUp":
|
||||
return readGamepadButtonStrength(gamepad.buttons[12]);
|
||||
case "dpadDown":
|
||||
return readGamepadButtonStrength(gamepad.buttons[13]);
|
||||
case "dpadLeft":
|
||||
return readGamepadButtonStrength(gamepad.buttons[14]);
|
||||
case "dpadRight":
|
||||
return readGamepadButtonStrength(gamepad.buttons[15]);
|
||||
}
|
||||
}
|
||||
|
||||
function readGamepadBindingStrength(
|
||||
gamepads: ArrayLike<Gamepad | null> | null | undefined,
|
||||
binding: PlayerStartGamepadBinding
|
||||
): number {
|
||||
if (gamepads === undefined || gamepads === null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let strength = 0;
|
||||
|
||||
for (let index = 0; index < gamepads.length; index += 1) {
|
||||
const gamepad = gamepads[index];
|
||||
|
||||
if (gamepad === null || gamepad === undefined || gamepad.connected === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
strength = Math.max(strength, readSingleGamepadBinding(gamepad, binding));
|
||||
}
|
||||
|
||||
return strength;
|
||||
}
|
||||
|
||||
export function getAvailableGamepads(): ArrayLike<Gamepad | null> | undefined {
|
||||
if (
|
||||
typeof navigator === "undefined" ||
|
||||
typeof navigator.getGamepads !== "function"
|
||||
) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return navigator.getGamepads();
|
||||
}
|
||||
|
||||
export function resolvePlayerStartMovementActions(
|
||||
pressedKeys: ReadonlySet<string>,
|
||||
bindings: PlayerStartInputBindings,
|
||||
gamepads: ArrayLike<Gamepad | null> | null | undefined = getAvailableGamepads()
|
||||
): PlayerStartMovementActionState {
|
||||
return {
|
||||
moveForward: Math.max(
|
||||
pressedKeys.has(bindings.keyboard.moveForward) ? 1 : 0,
|
||||
readGamepadBindingStrength(gamepads, bindings.gamepad.moveForward)
|
||||
),
|
||||
moveBackward: Math.max(
|
||||
pressedKeys.has(bindings.keyboard.moveBackward) ? 1 : 0,
|
||||
readGamepadBindingStrength(gamepads, bindings.gamepad.moveBackward)
|
||||
),
|
||||
moveLeft: Math.max(
|
||||
pressedKeys.has(bindings.keyboard.moveLeft) ? 1 : 0,
|
||||
readGamepadBindingStrength(gamepads, bindings.gamepad.moveLeft)
|
||||
),
|
||||
moveRight: Math.max(
|
||||
pressedKeys.has(bindings.keyboard.moveRight) ? 1 : 0,
|
||||
readGamepadBindingStrength(gamepads, bindings.gamepad.moveRight)
|
||||
)
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user