retrolib
Version:
Render low-res scenes to the canvas in a retro 8-bit era style. Aseprite exported animation wrapper, scene management, sound and image management, particle support.
247 lines • 9.35 kB
JavaScript
import { settings, InputState, handleInputPressed, handleInputReleased, inputMaps } from "./input";
/**
* Current axes states as of the last updated frame by input name.
*/
export var axisState = {};
/**
* Current buttons state as of the last upated frame by input name.
*/
export var buttonsState = {};
/**
* List of input names (IE: action, cancel, etc.) and the button index number they map to.
*/
export var buttonsMap = {};
/**
* List of input names (IE: left/right/up/down) and the axis index number they map to.
*/
export var axisMap = {};
/**
* Gamepad timestamp value as of last frame update.
*/
export var gamepadsTimestamps = {};
/**
* Event handler function for when a new gamepad is connected.
*/
export var gamepadConnected = function () { };
/**
* Event handler function for when a gamepad is disconnected.
*/
export var gamepadDisconnected = function () { };
/**
* Event handler function for when a gamepad has updated its state.
*/
export var gamepadUpdated = function () { };
/**
* Reset buttons state object to empty.
*/
export function resetButtonsState() {
buttonsState = {};
}
/**
* Reset gamepad timestamps to empty.
*/
export function resetGamepadTimestamps() {
gamepadsTimestamps = {};
}
/**
* Set gamepad timestamp value by index.
* @param gamepadNumber Gamepad/controller index.
* @param timestamp Updated timestamp value.
*/
export function setGamepadTimestamps(gamepadNumber, timestamp) {
gamepadsTimestamps[gamepadNumber] = timestamp;
}
/**
* Reset button mappings to defaults.
*/
export function resetGamepadButtonMappings() {
buttonsMap = { 'action': 0, 'cancel': 1 };
}
/**
* Reset axis mappings to defaults.
*/
export function resetGamepadAxisMappings() {
axisMap = { 'leftJoystick': [0, 1], 'rightJoystick': [3, 4], 'dPad': [6, 7], 'trigger': [2, 5] };
}
/**
* Set the callback for the gamepadconnected event.
* https://developer.mozilla.org/en-US/docs/Web/API/Window/gamepadconnected_event
* @param fn Callback function for when a gamepad connects.
*/
export function onGamepadConnected(fn) {
gamepadConnected = fn;
}
/** Set the callback for the gamepaddisconnected event.
* https://developer.mozilla.org/en-US/docs/Web/API/Window/gamepaddisconnected_event
*/
export function onGamepadDisconnected(fn) {
gamepadDisconnected = fn;
}
/**
* Set the callback for when a gamepad input or axis state has changed.
* @param fn Callback function.
*/
export function onGamepadUpdated(fn) {
gamepadUpdated = fn;
}
/**
* Run once per frame to update internal state objects and trigger event callbacks.
*/
export function gamepadsDidUpdate() {
getGamepads().forEach(function (g) {
if (gamepadsTimestamps[g.index] !== undefined && gamepadsTimestamps[g.index] < g.timestamp) {
gamepadUpdated(g);
Object.keys(axisMap).forEach(function (axis) {
var maps = [];
Object.keys(inputMaps).forEach(function (input) {
if (inputMaps[input].filter(function (f) { return f.mapKey === axis; }).length > 0) {
maps.push.apply(maps, inputMaps[input].filter(function (f) { return f.mapKey === axis; }));
}
});
if (maps.length > 0) {
for (var _i = 0, maps_1 = maps; _i < maps_1.length; _i++) {
var map = maps_1[_i];
if (!isAxisPressed(map.parent) && axisState[map.parent] === InputState.Pressed) {
axisState[map.parent] = InputState.Released;
handleInputReleased(map.parent, g.index);
break;
}
if (isAxisPressed(map.parent) && axisState[map.parent] !== InputState.Pressed) {
axisState[map.parent] = InputState.Pressed;
handleInputPressed(map.parent, g.index);
break;
}
}
}
});
getMappedButtons().forEach(function (inputRel) {
if (getButtonState(inputRel.inputName)[g.index].pressed && buttonsState[inputRel.inputName] !== InputState.Pressed) {
buttonsState[inputRel.inputName] = InputState.Pressed;
handleInputPressed(inputRel.inputName, g.index);
}
else if (!getButtonState(inputRel.inputName)[g.index].pressed && buttonsState[inputRel.inputName] === InputState.Pressed) {
buttonsState[inputRel.inputName] = InputState.Released;
handleInputReleased(inputRel.inputName, g.index);
}
});
}
gamepadsTimestamps[g.index] = g.timestamp;
});
}
export function isAxisPressed(inputName, controller) {
controller = controller === undefined ? 0 : controller;
var axes = Object.keys(axisMap);
var _loop_1 = function (axis) {
var maps = [];
Object.keys(inputMaps).forEach(function (input) {
if (inputMaps[input].filter(function (f) { return f.mapKey === axis && f.parent === inputName; }).length > 0) {
maps.push.apply(maps, inputMaps[input].filter(function (f) { return f.mapKey === axis; }));
}
});
if (maps.length > 0) {
for (var _a = 0, maps_2 = maps; _a < maps_2.length; _a++) {
var map = maps_2[_a];
var state = getAxisData(map.mapKey)[controller];
if (state) {
if (map.axisCheckDirection < 0 && map.axisPlane === 'x' && state.x < -settings.axisPressedThreshold) {
return { value: true };
}
else if (map.axisCheckDirection > 0 && map.axisPlane === 'x' && state.x > settings.axisPressedThreshold) {
return { value: true };
}
if (map.axisCheckDirection < 0 && map.axisPlane === 'y' && state.y < -settings.axisPressedThreshold) {
return { value: true };
}
else if (map.axisCheckDirection > 0 && map.axisPlane === 'y' && state.y > settings.axisPressedThreshold) {
return { value: true };
}
}
}
}
};
//.forEach(axis => {
for (var _i = 0, axes_1 = axes; _i < axes_1.length; _i++) {
var axis = axes_1[_i];
var state_1 = _loop_1(axis);
if (typeof state_1 === "object")
return state_1.value;
}
return false;
}
/**
* Get the list of currently connected Gamepad typed objects.
* https://developer.mozilla.org/en-US/docs/Web/API/Gamepad
* @returns Array of gamepad objects in order by Gamepad.index property.
*/
export function getGamepads() {
return navigator.getGamepads().sort(function (a, b) { return a.index - b.index; });
}
/**
* Get the gamepad button index mapped to inputName.
* @param inputName Input name.
* @returns
*/
export function getMappedButtonIndex(inputName) {
return buttonsMap[inputName] !== undefined ? buttonsMap[inputName] : null;
}
/**
* List all input relationships mapped to the gamepad buttons.
*/
export function getMappedButtons() {
var inputMap = [];
Object.keys(buttonsMap).forEach(function (key) {
var rel = { inputName: key, button: buttonsMap[key] };
inputMap.push(rel);
});
return inputMap;
}
/**
* Set a button mapping by input name.
* @param inputName Input name.
* @param buttonIndex Gamepad object's button index to assign to this input name.
*/
export function setMappedButton(inputName, buttonIndex) {
buttonsMap[inputName] = buttonIndex;
}
/**
* Get the current gamepad button state by input name.
* @param inputName Input name.
* @returns Current gamepad button state.
*/
export function getButtonState(inputName) {
var states = [];
getGamepads().forEach(function (g) {
var buttonIndex = getMappedButtonIndex(inputName);
if (buttonIndex !== null) {
var button = g.buttons[buttonIndex];
var buttonState = { controller: g.index, inputName: inputName, value: button.value, pressed: button.pressed, touched: button.touched };
states.push(buttonState);
}
});
return states.sort(function (a, b) { return a.controller - b.controller; });
}
/**
* Get the current axis input state by input name.
* @param inputName Input name.
* @returns Gamepad object's axis input state.
*/
export function getAxisInputState(inputName) {
return axisState[inputName];
}
/**
* Gets the current axis state data from the connected gamepads and returns a
* transformed object showing only controller indices and x/y states.
* @param inputName Input name.
* @returns
*/
export function getAxisData(inputName) {
var states = [];
getGamepads().forEach(function (g) {
if (axisMap[inputName] !== undefined) {
var axisState_1 = { controller: g.index, x: g.axes[axisMap[inputName][0]], y: g.axes[axisMap[inputName][1]] };
states.push(axisState_1);
}
});
return states.sort(function (a, b) { return a.controller - b.controller; });
}
//# sourceMappingURL=input-gamepad.js.map