From 23fe290c57f8a644d3264af72283f24a1fce7f4e Mon Sep 17 00:00:00 2001 From: Greenlamp Date: Fri, 3 May 2024 14:34:24 +0200 Subject: [PATCH] added back repeated input feature on keeping down a key --- src/battle-scene.ts | 42 ++++++-------------- src/inputsController.ts | 88 +++++++++++++++++++++++++++++++++-------- 2 files changed, 83 insertions(+), 47 deletions(-) diff --git a/src/battle-scene.ts b/src/battle-scene.ts index d5f4ba9c91b..866616ab3a0 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -170,11 +170,6 @@ export default class BattleScene extends SceneBase { private bgmResumeTimer: Phaser.Time.TimerEvent; private bgmCache: Set = new Set(); private playTimeTimer: Phaser.Time.TimerEvent; - - private lastProcessedButtonPressTimes: Map = new Map(); - // movementButtonLock ensures only a single movement key is firing repeated inputs - // (i.e. by holding down a button) at a time - private movementButtonLock: Button; public rngCounter: integer = 0; public rngSeedOverride: string = ''; @@ -248,7 +243,7 @@ export default class BattleScene extends SceneBase { this.ui?.update(); } - listenInputs() { + listenInputs(): void { this.inputController.events.on('input_down', (event) => { const actions = this.getActionsKeyDown(); if (!actions.hasOwnProperty(event.button)) return; @@ -1281,45 +1276,41 @@ export default class BattleScene extends SceneBase { return biomes[Utils.randSeedInt(biomes.length)]; } - buttonDirection(direction) { + buttonDirection(direction): Array { const inputSuccess = this.ui.processInput(direction); const vibrationLength = 5; - this.setLastProcessedMovementTime(direction); return [inputSuccess, vibrationLength]; } - buttonAb(button) { + buttonAb(button): Array { const inputSuccess = this.ui.processInput(button); - this.setLastProcessedMovementTime(button); return [inputSuccess, 0]; } - buttonTouch() { + buttonTouch(): Array { const inputSuccess = this.ui.processInput(Button.SUBMIT) || this.ui.processInput(Button.ACTION); - this.setLastProcessedMovementTime(Button.SUBMIT); return [inputSuccess, 0]; } - buttonStats(pressed = true) { + buttonStats(pressed = true): Array { if (pressed) { for (let p of this.getField().filter(p => p?.isActive(true))) p.toggleStats(true); - this.setLastProcessedMovementTime(Button.STATS); } else { for (let p of this.getField().filter(p => p?.isActive(true))) p.toggleStats(false); } - return [0, 0]; + return [true, 0]; } - buttonMenu() { + buttonMenu(): Array { let inputSuccess; if (this.disableMenu) - return [0, 0]; + return [true, 0]; switch (this.ui?.getMode()) { case Mode.MESSAGE: if (!(this.ui.getHandler() as MessageUiHandler).pendingPrompt) - return [0, 0]; + return [true, 0]; case Mode.TITLE: case Mode.COMMAND: case Mode.FIGHT: @@ -1342,23 +1333,21 @@ export default class BattleScene extends SceneBase { inputSuccess = true; break; default: - return [0, 0]; + return [true, 0]; } return [inputSuccess, 0]; } - buttonCycleOption(button) { + buttonCycleOption(button): Array { let inputSuccess; if (this.ui?.getHandler() instanceof StarterSelectUiHandler) { inputSuccess = this.ui.processInput(button); - this.setLastProcessedMovementTime(button); } return [inputSuccess, 0]; } - buttonSpeedChange(up= true) { + buttonSpeedChange(up= true): Array { if (up) { - console.log('speed up'); if (this.gameSpeed < 5) { this.gameData.saveSetting(Setting.Game_Speed, settingOptions[Setting.Game_Speed].indexOf(`${this.gameSpeed}x`) + 1); if (this.ui?.getMode() === Mode.SETTINGS) @@ -1367,7 +1356,6 @@ export default class BattleScene extends SceneBase { return [0, 0]; } if (this.gameSpeed > 1) { - console.log('speed down'); this.gameData.saveSetting(Setting.Game_Speed, Math.max(settingOptions[Setting.Game_Speed].indexOf(`${this.gameSpeed}x`) - 1, 0)); if (this.ui?.getMode() === Mode.SETTINGS) (this.ui.getHandler() as SettingsUiHandler).show([]); @@ -1403,12 +1391,6 @@ export default class BattleScene extends SceneBase { return actions; } - - setLastProcessedMovementTime(button: Button) { - this.lastProcessedButtonPressTimes.set(button, this.time.now); - this.movementButtonLock = button; - } - isBgmPlaying(): boolean { return this.bgm && this.bgm.isPlaying; } diff --git a/src/inputsController.ts b/src/inputsController.ts index 4c9a0c7512c..79f1d735538 100644 --- a/src/inputsController.ts +++ b/src/inputsController.ts @@ -1,4 +1,4 @@ -import Phaser from "phaser"; +import Phaser, { Time } from "phaser"; import * as Utils from "./utils"; import {initTouchControls} from './touch-controls'; import pad_generic from "#app/configs/pad_generic"; @@ -26,27 +26,41 @@ export enum Button { SPEED_UP, SLOW_DOWN } +const repeatInputDelayMillis = 250; export class InputsController extends Phaser.Plugins.ScenePlugin { private game: Phaser.Game; - private buttonKeys; - private gamepads; - private scene; - private isButtonPressing; + private buttonKeys: Phaser.Input.Keyboard.Key[][]; + private gamepads: Array = new Array(); + private scene: Phaser.Scene; + + // buttonLock ensures only a single movement key is firing repeated inputs + // (i.e. by holding down a button) at a time + private buttonLock: Button; + private interactions: Map> = new Map(); + private time: Time; constructor(scene: Phaser.Scene, pluginManager: Phaser.Plugins.PluginManager, pluginKey: string) { super(scene, pluginManager, pluginKey); this.game = pluginManager.game; this.scene = scene; - // Keys object to store Phaser key objects. We'll check these during update - this.buttonKeys = {}; - this.gamepads = []; - this.isButtonPressing = false; + this.time = this.scene.time; + this.buttonKeys = []; + + for (const b of Utils.getEnumValues(Button)) { + this.interactions[b] = { + pressTime: false, + isPressed: false, + } + } + delete this.interactions[Button.MENU]; + delete this.interactions[Button.SUBMIT]; } boot() { this.eventEmitter = this.systems.events; this.events = new Phaser.Events.EventEmitter(); + this.game.events.on(Phaser.Core.Events.STEP, this.update, this); if (typeof this.systems.input.gamepad !== 'undefined') { this.systems.input.gamepad.on('connected', function (thisGamepad) { @@ -59,7 +73,6 @@ export class InputsController extends Phaser.Plugins.ScenePlugin { if (this.systems.input.gamepad.total) { this.refreshGamepads(); for (const thisGamepad of this.gamepads) { - console.log('thisGamepad', thisGamepad); this.systems.input.gamepad.emit('connected', thisGamepad); } } @@ -72,6 +85,19 @@ export class InputsController extends Phaser.Plugins.ScenePlugin { this.setupKeyboardControls(); } + update() { + for (const b of Utils.getEnumValues(Button)) { + if (!this.interactions.hasOwnProperty(b)) continue; + if (this.repeatInputDurationJustPassed(b)) { + this.events.emit('input_down', { + controller_type: 'keyboard', + button: b, + }); + this.setLastProcessedMovementTime(b); + } + } + } + setupGamepad(thisGamepad) { let gamepadID = thisGamepad.id.toLowerCase(); const mappedPad = this.mapGamepad(gamepadID); @@ -116,24 +142,24 @@ export class InputsController extends Phaser.Plugins.ScenePlugin { gamepadButtonDown(pad, button, value) { const actionMapping = this.getActionGamepadMapping(); const buttonDown = actionMapping.hasOwnProperty(button.index) && actionMapping[button.index]; - if (buttonDown !== undefined && !this.isButtonPressing) { - this.isButtonPressing = true; + if (buttonDown !== undefined) { this.events.emit('input_down', { controller_type: 'gamepad', button: buttonDown, }); + this.setLastProcessedMovementTime(buttonDown); } } gamepadButtonUp(pad, button, value) { const actionMapping = this.getActionGamepadMapping(); const buttonUp = actionMapping.hasOwnProperty(button.index) && actionMapping[button.index]; - if (buttonUp !== undefined && this.isButtonPressing) { - this.isButtonPressing = false; + if (buttonUp !== undefined) { this.events.emit('input_up', { controller_type: 'gamepad', button: buttonUp, }); + this.delLastProcessedMovementTime(buttonUp); } } @@ -159,8 +185,7 @@ export class InputsController extends Phaser.Plugins.ScenePlugin { [Button.SLOW_DOWN]: [keyCodes.MINUS] }; const mobileKeyConfig = {}; - this.buttonKeys = []; - for (let b of Utils.getEnumValues(Button)) { + for (const b of Utils.getEnumValues(Button)) { const keys: Phaser.Input.Keyboard.Key[] = []; if (keyConfig.hasOwnProperty(b)) { for (let k of keyConfig[b]) @@ -177,17 +202,19 @@ export class InputsController extends Phaser.Plugins.ScenePlugin { listenInputKeyboard() { this.buttonKeys.forEach((row, index) => { for (const key of row) { - key.on('down', (event) => { + key.on('down', () => { this.events.emit('input_down', { controller_type: 'keyboard', button: index, }); + this.setLastProcessedMovementTime(index); }); key.on('up', () => { this.events.emit('input_up', { controller_type: 'keyboard', button: index, }); + this.delLastProcessedMovementTime(index); }); } }) @@ -209,4 +236,31 @@ export class InputsController extends Phaser.Plugins.ScenePlugin { return padConfig; } + + /** + * repeatInputDurationJustPassed returns true if @param button has been held down long + * enough to fire a repeated input. A button must claim the buttonLock before + * firing a repeated input - this is to prevent multiple buttons from firing repeatedly. + */ + repeatInputDurationJustPassed(button: Button): boolean { + if (this.buttonLock === null || this.buttonLock !== button) { + return false; + } + if (this.time.now - this.interactions[button].pressTime >= repeatInputDelayMillis) { + this.buttonLock = null; + return true; + } + } + + setLastProcessedMovementTime(button: Button) { + if (!this.interactions.hasOwnProperty(button)) return; + this.buttonLock = button; + this.interactions[button].pressTime = this.time.now; + } + + delLastProcessedMovementTime(button: Button) { + if (!this.interactions.hasOwnProperty(button)) return; + this.buttonLock = null; + this.interactions[button].pressTime = null; + } } \ No newline at end of file