added gamepad section in Game Settings and related option into it

pull/685/head
Greenlamp 2024-05-08 16:40:41 +02:00
parent 22c81f1a80
commit 7a75fc925a
7 changed files with 315 additions and 16 deletions

View File

@ -29,6 +29,7 @@ import { allMoves } from "../data/move";
import { TrainerVariant } from "../field/trainer";
import { OutdatedPhase, ReloadSessionPhase } from "#app/phases";
import { Variant, variantData } from "#app/data/variant";
import {setSettingGamepad, SettingGamepad, settingGamepadDefaults} from "./system/settings-gamepad";
const saveKey = 'x0i2O7WRiANTqPmZ'; // Temporary; secure encryption is not yet necessary
@ -464,31 +465,48 @@ export class GameData {
public saveSetting(setting: Setting, valueIndex: integer): boolean {
let settings: object = {};
let settingsGamepad: object = {};
if (localStorage.hasOwnProperty('settings'))
settings = JSON.parse(localStorage.getItem('settings'));
if (localStorage.hasOwnProperty('settingsGamepad'))
settingsGamepad = JSON.parse(localStorage.getItem('settingsGamepad'));
setSetting(this.scene, setting as Setting, valueIndex);
setSettingGamepad(this.scene, settingsGamepad as SettingGamepad, valueIndex);
Object.keys(settingDefaults).forEach(s => {
if (s === setting)
settings[s] = valueIndex;
});
Object.keys(settingGamepadDefaults).forEach(s => {
if (s === setting)
settingsGamepad[s] = valueIndex;
});
localStorage.setItem('settings', JSON.stringify(settings));
localStorage.setItem('settingsGamepad', JSON.stringify(settingsGamepad));
return true;
}
private loadSettings(): boolean {
Object.values(Setting).map(setting => setting as Setting).forEach(setting => setSetting(this.scene, setting, settingDefaults[setting]));
Object.values(SettingGamepad).map(setting => setting as SettingGamepad).forEach(setting => setSettingGamepad(this.scene, setting, settingGamepadDefaults[setting]));
if (!localStorage.hasOwnProperty('settings'))
return false;
if (!localStorage.hasOwnProperty('settingsGamepad'))
return false;
const settings = JSON.parse(localStorage.getItem('settings'));
const settingsGamepad = JSON.parse(localStorage.getItem('settingsGamepad'));
for (let setting of Object.keys(settings))
setSetting(this.scene, setting as Setting, settings[setting]);
for (let setting of Object.keys(settingsGamepad))
setSettingGamepad(this.scene, setting as SettingGamepad, settingGamepadDefaults[setting]);
}
public saveTutorialFlag(tutorial: Tutorial, flag: boolean): boolean {

View File

@ -0,0 +1,30 @@
import BattleScene from "../battle-scene";
import {SettingDefaults, SettingOptions} from "#app/system/settings";
export enum SettingGamepad {
Gamepad_Support = "GAMEPAD_SUPPORT",
Swap_A_and_B = "SWAP_A_B", // Swaps which gamepad button handles ACTION and CANCEL
}
export const settingGamepadOptions: SettingOptions = {
[SettingGamepad.Gamepad_Support]: [ 'Auto', 'Disabled' ],
[SettingGamepad.Swap_A_and_B]: [ 'Enabled', 'Disabled' ],
};
export const settingGamepadDefaults: SettingDefaults = {
[SettingGamepad.Gamepad_Support]: 0,
[SettingGamepad.Swap_A_and_B]: 1, // Set to 'Disabled' by default
};
export function setSettingGamepad(scene: BattleScene, setting: SettingGamepad, value: integer): boolean {
switch (setting) {
case SettingGamepad.Gamepad_Support:
scene.gamepadSupport = settingGamepadOptions[setting][value] !== 'Disabled';
break;
case SettingGamepad.Swap_A_and_B:
scene.abSwapped = settingGamepadOptions[setting][value] !== 'Disabled';
break;
}
return true;
}

View File

@ -24,8 +24,6 @@ export enum Setting {
HP_Bar_Speed = "HP_BAR_SPEED",
Fusion_Palette_Swaps = "FUSION_PALETTE_SWAPS",
Player_Gender = "PLAYER_GENDER",
Gamepad_Support = "GAMEPAD_SUPPORT",
Swap_A_and_B = "SWAP_A_B", // Swaps which gamepad button handles ACTION and CANCEL
Touch_Controls = "TOUCH_CONTROLS",
Vibration = "VIBRATION"
}
@ -56,8 +54,6 @@ export const settingOptions: SettingOptions = {
[Setting.HP_Bar_Speed]: [ 'Normal', 'Fast', 'Faster', 'Instant' ],
[Setting.Fusion_Palette_Swaps]: [ 'Off', 'On' ],
[Setting.Player_Gender]: [ 'Boy', 'Girl' ],
[Setting.Gamepad_Support]: [ 'Auto', 'Disabled' ],
[Setting.Swap_A_and_B]: [ 'Enabled', 'Disabled' ],
[Setting.Touch_Controls]: [ 'Auto', 'Disabled' ],
[Setting.Vibration]: [ 'Auto', 'Disabled' ]
};
@ -80,8 +76,6 @@ export const settingDefaults: SettingDefaults = {
[Setting.HP_Bar_Speed]: 0,
[Setting.Fusion_Palette_Swaps]: 1,
[Setting.Player_Gender]: 0,
[Setting.Gamepad_Support]: 0,
[Setting.Swap_A_and_B]: 1, // Set to 'Disabled' by default
[Setting.Touch_Controls]: 0,
[Setting.Vibration]: 0
};
@ -148,12 +142,6 @@ export function setSetting(scene: BattleScene, setting: Setting, value: integer)
} else
return false;
break;
case Setting.Gamepad_Support:
scene.gamepadSupport = settingOptions[setting][value] !== 'Disabled';
break;
case Setting.Swap_A_and_B:
scene.abSwapped = settingOptions[setting][value] !== 'Disabled';
break;
case Setting.Touch_Controls:
scene.enableTouchControls = settingOptions[setting][value] !== 'Disabled' && hasTouchscreen();
const touchControls = document.getElementById('touchControls');

View File

@ -6,6 +6,7 @@ import StarterSelectUiHandler from "./ui/starter-select-ui-handler";
import {Setting, settingOptions} from "./system/settings";
import SettingsUiHandler from "./ui/settings-ui-handler";
import {Button} from "./enums/buttons";
import SettingsGamepadUiHandler from "#app/ui/settings-gamepad-ui-handler";
export interface ActionKeys {
[key in Button]: () => void;
@ -130,7 +131,7 @@ export class UiInputs {
}
buttonCycleOption(button: Button): void {
const whitelist = [StarterSelectUiHandler, SettingsUiHandler];
const whitelist = [StarterSelectUiHandler, SettingsUiHandler, SettingsGamepadUiHandler];
const uiHandler = this.scene.ui?.getHandler();
if (whitelist.some(handler => uiHandler instanceof handler)) {
this.scene.ui.processInput(button);

View File

@ -0,0 +1,252 @@
import BattleScene from "../battle-scene";
import { hasTouchscreen, isMobile } from "../touch-controls";
import { TextStyle, addTextObject } from "./text";
import { Mode } from "./ui";
import UiHandler from "./ui-handler";
import { addWindow } from "./ui-theme";
import {Button} from "../enums/buttons";
import {SettingGamepad, settingGamepadDefaults, settingGamepadOptions} from "../system/settings-gamepad";
export default class SettingsGamepadUiHandler extends UiHandler {
private settingsContainer: Phaser.GameObjects.Container;
private optionsContainer: Phaser.GameObjects.Container;
private scrollCursor: integer;
private optionsBg: Phaser.GameObjects.NineSlice;
private optionCursors: integer[];
private settingLabels: Phaser.GameObjects.Text[];
private optionValueLabels: Phaser.GameObjects.Text[][];
private cursorObj: Phaser.GameObjects.NineSlice;
private reloadRequired: boolean;
private reloadI18n: boolean;
constructor(scene: BattleScene, mode?: Mode) {
super(scene, mode);
this.reloadRequired = false;
this.reloadI18n = false;
}
setup() {
const ui = this.getUi();
this.settingsContainer = this.scene.add.container(1, -(this.scene.game.canvas.height / 6) + 1);
this.settingsContainer.setInteractive(new Phaser.Geom.Rectangle(0, 0, this.scene.game.canvas.width / 6, this.scene.game.canvas.height / 6), Phaser.Geom.Rectangle.Contains);
const headerBg = addWindow(this.scene, 0, 0, (this.scene.game.canvas.width / 6) - 2, 24);
headerBg.setOrigin(0, 0);
const headerText = addTextObject(this.scene, 0, 0, 'General', TextStyle.SETTINGS_LABEL);
headerText.setOrigin(0, 0);
headerText.setPositionRelative(headerBg, 8, 4);
const gamepadText = addTextObject(this.scene, 0, 0, 'Gamepad', TextStyle.SETTINGS_SELECTED);
gamepadText.setOrigin(0, 0);
gamepadText.setPositionRelative(headerBg, 50, 4);
this.optionsBg = addWindow(this.scene, 0, headerBg.height, (this.scene.game.canvas.width / 6) - 2, (this.scene.game.canvas.height / 6) - headerBg.height - 2);
this.optionsBg.setOrigin(0, 0);
this.optionsContainer = this.scene.add.container(0, 0);
this.settingLabels = [];
this.optionValueLabels = [];
Object.keys(SettingGamepad).forEach((setting, s) => {
let settingName = setting.replace(/\_/g, ' ');
this.settingLabels[s] = addTextObject(this.scene, 8, 28 + s * 16, settingName, TextStyle.SETTINGS_LABEL);
this.settingLabels[s].setOrigin(0, 0);
this.optionsContainer.add(this.settingLabels[s]);
this.optionValueLabels.push(settingGamepadOptions[SettingGamepad[setting]].map((option, o) => {
const valueLabel = addTextObject(this.scene, 0, 0, option, settingGamepadDefaults[SettingGamepad[setting]] === o ? TextStyle.SETTINGS_SELECTED : TextStyle.WINDOW);
valueLabel.setOrigin(0, 0);
this.optionsContainer.add(valueLabel);
return valueLabel;
}));
const totalWidth = this.optionValueLabels[s].map(o => o.width).reduce((total, width) => total += width, 0);
const labelWidth = Math.max(78, this.settingLabels[s].displayWidth + 8);
const totalSpace = (300 - labelWidth) - totalWidth / 6;
const optionSpacing = Math.floor(totalSpace / (this.optionValueLabels[s].length - 1));
let xOffset = 0;
for (let value of this.optionValueLabels[s]) {
value.setPositionRelative(this.settingLabels[s], labelWidth + xOffset, 0);
xOffset += value.width / 6 + optionSpacing;
}
});
this.optionCursors = Object.values(settingGamepadDefaults);
this.settingsContainer.add(headerBg);
this.settingsContainer.add(headerText);
this.settingsContainer.add(gamepadText);
this.settingsContainer.add(this.optionsBg);
this.settingsContainer.add(this.optionsContainer);
ui.add(this.settingsContainer);
this.setCursor(0);
this.setScrollCursor(0);
this.settingsContainer.setVisible(false);
}
show(args: any[]): boolean {
super.show(args);
const settings: object = localStorage.hasOwnProperty('settings') ? JSON.parse(localStorage.getItem('settings')) : {};
Object.keys(settingGamepadDefaults).forEach((setting, s) => this.setOptionCursor(s, settings.hasOwnProperty(setting) ? settings[setting] : settingGamepadDefaults[setting]));
this.settingsContainer.setVisible(true);
this.setCursor(0);
this.getUi().moveTo(this.settingsContainer, this.getUi().length - 1);
this.getUi().hideTooltip();
return true;
}
processInput(button: Button): boolean {
const ui = this.getUi();
let success = false;
if (button === Button.CANCEL) {
success = true;
this.scene.ui.revertMode();
} else {
const cursor = this.cursor + this.scrollCursor;
switch (button) {
case Button.UP:
if (cursor) {
if (this.cursor)
success = this.setCursor(this.cursor - 1);
else
success = this.setScrollCursor(this.scrollCursor - 1);
}
break;
case Button.DOWN:
if (cursor < this.optionValueLabels.length) {
if (this.cursor < 8)
success = this.setCursor(this.cursor + 1);
else if (this.scrollCursor < this.optionValueLabels.length - 9)
success = this.setScrollCursor(this.scrollCursor + 1);
}
break;
case Button.LEFT:
if (this.optionCursors[cursor])
success = this.setOptionCursor(cursor, this.optionCursors[cursor] - 1, true);
break;
case Button.RIGHT:
if (this.optionCursors[cursor] < this.optionValueLabels[cursor].length - 1)
success = this.setOptionCursor(cursor, this.optionCursors[cursor] + 1, true);
break;
case Button.LB:
this.scene.ui.setMode(Mode.SETTINGS)
success = true;
case Button.RB:
this.scene.ui.setMode(Mode.SETTINGS)
success = true;
break;
}
}
if (success)
ui.playSelect();
return success;
}
setCursor(cursor: integer): boolean {
const ret = super.setCursor(cursor);
if (!this.cursorObj) {
this.cursorObj = this.scene.add.nineslice(0, 0, 'summary_moves_cursor', null, (this.scene.game.canvas.width / 6) - 10, 16, 1, 1, 1, 1);
this.cursorObj.setOrigin(0, 0);
this.optionsContainer.add(this.cursorObj);
}
this.cursorObj.setPositionRelative(this.optionsBg, 4, 4 + (this.cursor + this.scrollCursor) * 16);
return ret;
}
setOptionCursor(settingIndex: integer, cursor: integer, save?: boolean): boolean {
const setting = SettingGamepad[Object.keys(SettingGamepad)[settingIndex]];
const lastCursor = this.optionCursors[settingIndex];
const lastValueLabel = this.optionValueLabels[settingIndex][lastCursor];
lastValueLabel.setColor(this.getTextColor(TextStyle.WINDOW));
lastValueLabel.setShadowColor(this.getTextColor(TextStyle.WINDOW, true));
this.optionCursors[settingIndex] = cursor;
const newValueLabel = this.optionValueLabels[settingIndex][cursor];
newValueLabel.setColor(this.getTextColor(TextStyle.SETTINGS_SELECTED));
newValueLabel.setShadowColor(this.getTextColor(TextStyle.SETTINGS_SELECTED, true));
if (save) {
this.scene.gameData.saveSetting(setting, cursor)
}
return true;
}
setScrollCursor(scrollCursor: integer): boolean {
if (scrollCursor === this.scrollCursor)
return false;
this.scrollCursor = scrollCursor;
this.updateSettingsScroll();
this.setCursor(this.cursor);
return true;
}
updateSettingsScroll(): void {
this.optionsContainer.setY(-16 * this.scrollCursor);
for (let s = 0; s < this.settingLabels.length; s++) {
const visible = s >= this.scrollCursor && s < this.scrollCursor + 9;
this.settingLabels[s].setVisible(visible);
for (let option of this.optionValueLabels[s])
option.setVisible(visible);
}
}
clear() {
super.clear();
this.settingsContainer.setVisible(false);
this.eraseCursor();
if (this.reloadRequired) {
this.reloadRequired = false;
this.scene.reset(true, false, true);
}
}
eraseCursor() {
if (this.cursorObj)
this.cursorObj.destroy();
this.cursorObj = null;
}
}

View File

@ -42,10 +42,14 @@ export default class SettingsUiHandler extends UiHandler {
const headerBg = addWindow(this.scene, 0, 0, (this.scene.game.canvas.width / 6) - 2, 24);
headerBg.setOrigin(0, 0);
const headerText = addTextObject(this.scene, 0, 0, 'Options', TextStyle.SETTINGS_LABEL);
const headerText = addTextObject(this.scene, 0, 0, 'General', TextStyle.SETTINGS_SELECTED);
headerText.setOrigin(0, 0);
headerText.setPositionRelative(headerBg, 8, 4);
const gamepadText = addTextObject(this.scene, 0, 0, 'Gamepad', TextStyle.SETTINGS_LABEL);
gamepadText.setOrigin(0, 0);
gamepadText.setPositionRelative(headerBg, 50, 4);
this.optionsBg = addWindow(this.scene, 0, headerBg.height, (this.scene.game.canvas.width / 6) - 2, (this.scene.game.canvas.height / 6) - headerBg.height - 2);
this.optionsBg.setOrigin(0, 0);
@ -92,6 +96,7 @@ export default class SettingsUiHandler extends UiHandler {
this.settingsContainer.add(headerBg);
this.settingsContainer.add(headerText);
this.settingsContainer.add(gamepadText);
this.settingsContainer.add(this.optionsBg);
this.settingsContainer.add(this.optionsContainer);
@ -156,10 +161,12 @@ export default class SettingsUiHandler extends UiHandler {
success = this.setOptionCursor(cursor, this.optionCursors[cursor] + 1, true);
break;
case Button.LB:
console.log('lb');
this.scene.ui.setMode(Mode.SETTINGS_GAMEPAD)
success = true;
break;
case Button.RB:
console.log('rb');
this.scene.ui.setMode(Mode.SETTINGS_GAMEPAD)
success = true;
break;
}
}

View File

@ -13,6 +13,7 @@ import StarterSelectUiHandler from './starter-select-ui-handler';
import EvolutionSceneHandler from './evolution-scene-handler';
import TargetSelectUiHandler from './target-select-ui-handler';
import SettingsUiHandler from './settings-ui-handler';
import SettingsGamepadUiHandler from "./settings-gamepad-ui-handler";
import { TextStyle, addTextObject } from './text';
import AchvBar from './achv-bar';
import MenuUiHandler from './menu-ui-handler';
@ -56,6 +57,7 @@ export enum Mode {
MENU,
MENU_OPTION_SELECT,
SETTINGS,
SETTINGS_GAMEPAD,
ACHIEVEMENTS,
GAME_STATS,
VOUCHERS,
@ -137,6 +139,7 @@ export default class UI extends Phaser.GameObjects.Container {
new MenuUiHandler(scene),
new OptionSelectUiHandler(scene, Mode.MENU_OPTION_SELECT),
new SettingsUiHandler(scene),
new SettingsGamepadUiHandler(scene),
new AchvsUiHandler(scene),
new GameStatsUiHandler(scene),
new VouchersUiHandler(scene),