acesesibiliti

This commit is contained in:
2025-12-12 22:46:38 +01:00
parent 3809ee2c97
commit 93757fc8c4
20 changed files with 5740 additions and 89 deletions

View File

@@ -0,0 +1,525 @@
/**
* INPUT REMAPPING SYSTEM
* Allows players to customize keyboard and controller bindings
* Supports multiple control profiles and one-handed layouts
*/
class InputRemappingSystem {
constructor(scene) {
this.scene = scene;
this.enabled = true;
// Default key bindings
this.defaultBindings = {
// Movement
'move_up': ['W', 'UP'],
'move_down': ['S', 'DOWN'],
'move_left': ['A', 'LEFT'],
'move_right': ['D', 'RIGHT'],
// Actions
'interact': ['E', 'SPACE'],
'attack': ['MOUSE_LEFT', 'J'],
'use_tool': ['MOUSE_LEFT', 'J'],
'cancel': ['ESC', 'X'],
'confirm': ['ENTER', 'E'],
// Inventory & UI
'inventory': ['I', 'TAB'],
'crafting': ['C'],
'map': ['M'],
'quest_log': ['Q'],
'pause': ['ESC', 'P'],
// Tools
'tool_1': ['1'],
'tool_2': ['2'],
'tool_3': ['3'],
'tool_4': ['4'],
'tool_5': ['5'],
// Quick actions
'quick_heal': ['H'],
'quick_eat': ['F'],
'sprint': ['SHIFT'],
'crouch': ['CTRL'],
// Camera
'zoom_in': ['PLUS', 'MOUSE_WHEEL_UP'],
'zoom_out': ['MINUS', 'MOUSE_WHEEL_DOWN'],
'camera_reset': ['R']
};
// Controller bindings (Xbox/PlayStation layout)
this.controllerBindings = {
'move': 'LEFT_STICK',
'camera': 'RIGHT_STICK',
'interact': 'A', // Xbox A / PS Cross
'attack': 'X', // Xbox X / PS Square
'cancel': 'B', // Xbox B / PS Circle
'inventory': 'Y', // Xbox Y / PS Triangle
'sprint': 'LB',
'use_tool': 'RT',
'quick_menu': 'LT',
'pause': 'START',
'map': 'SELECT'
};
// Control profiles
this.profiles = {
'default': JSON.parse(JSON.stringify(this.defaultBindings)),
'wasd': JSON.parse(JSON.stringify(this.defaultBindings)),
'arrows': this.createArrowsProfile(),
'left-handed': this.createLeftHandedProfile(),
'right-handed': this.createRightHandedProfile(),
'custom-1': JSON.parse(JSON.stringify(this.defaultBindings)),
'custom-2': JSON.parse(JSON.stringify(this.defaultBindings)),
'custom-3': JSON.parse(JSON.stringify(this.defaultBindings))
};
// Current active profile
this.activeProfile = 'default';
this.currentBindings = this.profiles[this.activeProfile];
// Rebinding state
this.isRebinding = false;
this.rebindingAction = null;
this.rebindingCallback = null;
// Input buffer for detecting key presses
this.inputBuffer = [];
this.maxBufferSize = 10;
this.loadSettings();
this.init();
console.log('✅ Input Remapping System initialized');
}
init() {
// Set up input listeners
this.setupInputListeners();
}
setupInputListeners() {
// Keyboard input
this.scene.input.keyboard.on('keydown', (event) => {
if (this.isRebinding) {
this.handleRebindInput(event.key.toUpperCase());
}
});
// Mouse input
this.scene.input.on('pointerdown', (pointer) => {
if (this.isRebinding) {
const button = pointer.leftButtonDown() ? 'MOUSE_LEFT' :
pointer.rightButtonDown() ? 'MOUSE_RIGHT' :
pointer.middleButtonDown() ? 'MOUSE_MIDDLE' : null;
if (button) {
this.handleRebindInput(button);
}
}
});
// Mouse wheel
this.scene.input.on('wheel', (pointer, gameObjects, deltaX, deltaY, deltaZ) => {
if (this.isRebinding) {
const input = deltaY < 0 ? 'MOUSE_WHEEL_UP' : 'MOUSE_WHEEL_DOWN';
this.handleRebindInput(input);
}
});
}
/**
* Create arrows-based profile (arrow keys for movement)
*/
createArrowsProfile() {
const profile = JSON.parse(JSON.stringify(this.defaultBindings));
profile.move_up = ['UP', 'W'];
profile.move_down = ['DOWN', 'S'];
profile.move_left = ['LEFT', 'A'];
profile.move_right = ['RIGHT', 'D'];
return profile;
}
/**
* Create left-handed profile (numpad for movement)
*/
createLeftHandedProfile() {
return {
// Movement on numpad
'move_up': ['NUMPAD_8', 'I'],
'move_down': ['NUMPAD_5', 'K'],
'move_left': ['NUMPAD_4', 'J'],
'move_right': ['NUMPAD_6', 'L'],
// Actions on left side
'interact': ['Q', 'SPACE'],
'attack': ['MOUSE_LEFT', 'W'],
'use_tool': ['MOUSE_LEFT', 'W'],
'cancel': ['ESC', 'E'],
'confirm': ['ENTER', 'Q'],
// Inventory & UI
'inventory': ['TAB', 'U'],
'crafting': ['R'],
'map': ['T'],
'quest_log': ['Y'],
'pause': ['ESC', 'P'],
// Tools (right side for easy access)
'tool_1': ['7'],
'tool_2': ['8'],
'tool_3': ['9'],
'tool_4': ['0'],
'tool_5': ['MINUS'],
// Quick actions
'quick_heal': ['A'],
'quick_eat': ['S'],
'sprint': ['SHIFT'],
'crouch': ['CTRL'],
// Camera
'zoom_in': ['PLUS', 'MOUSE_WHEEL_UP'],
'zoom_out': ['EQUALS', 'MOUSE_WHEEL_DOWN'],
'camera_reset': ['BACKSPACE']
};
}
/**
* Create right-handed profile (standard WASD)
*/
createRightHandedProfile() {
return JSON.parse(JSON.stringify(this.defaultBindings));
}
/**
* Check if an action is pressed
*/
isActionPressed(action) {
const bindings = this.currentBindings[action];
if (!bindings) return false;
for (const key of bindings) {
if (this.isKeyPressed(key)) {
return true;
}
}
return false;
}
/**
* Check if a specific key is pressed
*/
isKeyPressed(key) {
if (key.startsWith('MOUSE_')) {
const pointer = this.scene.input.activePointer;
if (key === 'MOUSE_LEFT') return pointer.leftButtonDown();
if (key === 'MOUSE_RIGHT') return pointer.rightButtonDown();
if (key === 'MOUSE_MIDDLE') return pointer.middleButtonDown();
return false;
}
const keyObj = this.scene.input.keyboard.addKey(key, false);
return keyObj && keyObj.isDown;
}
/**
* Check if an action was just pressed (single frame)
*/
isActionJustPressed(action) {
const bindings = this.currentBindings[action];
if (!bindings) return false;
for (const key of bindings) {
if (this.isKeyJustPressed(key)) {
return true;
}
}
return false;
}
/**
* Check if a key was just pressed
*/
isKeyJustPressed(key) {
if (key.startsWith('MOUSE_')) {
const pointer = this.scene.input.activePointer;
if (key === 'MOUSE_LEFT') return pointer.leftButtonDown() && pointer.getDuration() < 100;
if (key === 'MOUSE_RIGHT') return pointer.rightButtonDown() && pointer.getDuration() < 100;
if (key === 'MOUSE_MIDDLE') return pointer.middleButtonDown() && pointer.getDuration() < 100;
return false;
}
const keyObj = this.scene.input.keyboard.addKey(key, false);
return keyObj && Phaser.Input.Keyboard.JustDown(keyObj);
}
/**
* Start rebinding an action
*/
startRebinding(action, callback) {
if (!this.currentBindings[action]) {
console.error(`Action "${action}" does not exist`);
return;
}
this.isRebinding = true;
this.rebindingAction = action;
this.rebindingCallback = callback;
console.log(`🎮 Rebinding action: ${action}. Press any key...`);
}
/**
* Handle rebind input
*/
handleRebindInput(input) {
if (!this.isRebinding) return;
// Ignore ESC (cancel rebinding)
if (input === 'ESC' || input === 'ESCAPE') {
this.cancelRebinding();
return;
}
// Set new binding (replace first binding)
this.currentBindings[this.rebindingAction][0] = input;
console.log(`✅ Action "${this.rebindingAction}" rebound to: ${input}`);
// Call callback if provided
if (this.rebindingCallback) {
this.rebindingCallback(this.rebindingAction, input);
}
this.isRebinding = false;
this.rebindingAction = null;
this.rebindingCallback = null;
this.saveSettings();
}
/**
* Cancel rebinding
*/
cancelRebinding() {
console.log('❌ Rebinding cancelled');
this.isRebinding = false;
this.rebindingAction = null;
this.rebindingCallback = null;
}
/**
* Reset action to default binding
*/
resetAction(action) {
if (!this.defaultBindings[action]) {
console.error(`Action "${action}" does not exist`);
return;
}
this.currentBindings[action] = JSON.parse(JSON.stringify(this.defaultBindings[action]));
this.saveSettings();
console.log(`🔄 Action "${action}" reset to default`);
}
/**
* Reset all bindings to default
*/
resetAllBindings() {
this.currentBindings = JSON.parse(JSON.stringify(this.defaultBindings));
this.profiles[this.activeProfile] = this.currentBindings;
this.saveSettings();
console.log('🔄 All bindings reset to default');
}
/**
* Switch to a different profile
*/
switchProfile(profileName) {
if (!this.profiles[profileName]) {
console.error(`Profile "${profileName}" does not exist`);
return;
}
this.activeProfile = profileName;
this.currentBindings = this.profiles[profileName];
this.saveSettings();
console.log(`🎮 Switched to profile: ${profileName}`);
}
/**
* Save current bindings to a custom profile
*/
saveToProfile(profileName) {
if (!profileName.startsWith('custom-')) {
console.error('Can only save to custom profiles (custom-1, custom-2, custom-3)');
return;
}
this.profiles[profileName] = JSON.parse(JSON.stringify(this.currentBindings));
this.saveSettings();
console.log(`💾 Bindings saved to profile: ${profileName}`);
}
/**
* Get binding display name
*/
getBindingDisplay(action) {
const bindings = this.currentBindings[action];
if (!bindings || bindings.length === 0) return 'Not bound';
return bindings.map(key => this.formatKeyName(key)).join(' / ');
}
/**
* Format key name for display
*/
formatKeyName(key) {
const keyMap = {
'MOUSE_LEFT': 'Left Click',
'MOUSE_RIGHT': 'Right Click',
'MOUSE_MIDDLE': 'Middle Click',
'MOUSE_WHEEL_UP': 'Scroll Up',
'MOUSE_WHEEL_DOWN': 'Scroll Down',
'SPACE': 'Space',
'ENTER': 'Enter',
'ESC': 'Escape',
'SHIFT': 'Shift',
'CTRL': 'Ctrl',
'ALT': 'Alt',
'TAB': 'Tab',
'BACKSPACE': 'Backspace',
'UP': '↑',
'DOWN': '↓',
'LEFT': '←',
'RIGHT': '→',
'PLUS': '+',
'MINUS': '-',
'EQUALS': '='
};
return keyMap[key] || key;
}
/**
* Get all available profiles
*/
getProfiles() {
return Object.keys(this.profiles);
}
/**
* Get current profile name
*/
getCurrentProfile() {
return this.activeProfile;
}
/**
* Export bindings as JSON
*/
exportBindings() {
const data = {
activeProfile: this.activeProfile,
profiles: this.profiles
};
return JSON.stringify(data, null, 2);
}
/**
* Import bindings from JSON
*/
importBindings(jsonString) {
try {
const data = JSON.parse(jsonString);
this.activeProfile = data.activeProfile || 'default';
this.profiles = data.profiles || this.profiles;
this.currentBindings = this.profiles[this.activeProfile];
this.saveSettings();
console.log('✅ Bindings imported successfully');
return true;
} catch (error) {
console.error('❌ Failed to import bindings:', error);
return false;
}
}
/**
* Save settings to localStorage
*/
saveSettings() {
const data = {
activeProfile: this.activeProfile,
profiles: this.profiles
};
localStorage.setItem('novafarma_input_bindings', JSON.stringify(data));
}
/**
* Load settings from localStorage
*/
loadSettings() {
const saved = localStorage.getItem('novafarma_input_bindings');
if (saved) {
try {
const data = JSON.parse(saved);
this.activeProfile = data.activeProfile || 'default';
this.profiles = { ...this.profiles, ...data.profiles };
this.currentBindings = this.profiles[this.activeProfile];
console.log('✅ Input bindings loaded from localStorage');
} catch (error) {
console.error('❌ Failed to load input bindings:', error);
}
}
}
/**
* Get controller button name
*/
getControllerButtonName(button) {
const buttonMap = {
'A': 'A (Cross)',
'B': 'B (Circle)',
'X': 'X (Square)',
'Y': 'Y (Triangle)',
'LB': 'LB (L1)',
'RB': 'RB (R1)',
'LT': 'LT (L2)',
'RT': 'RT (R2)',
'START': 'Start',
'SELECT': 'Select (Share)',
'LEFT_STICK': 'Left Stick',
'RIGHT_STICK': 'Right Stick'
};
return buttonMap[button] || button;
}
/**
* Check if controller is connected
*/
isControllerConnected() {
return this.scene.input.gamepad && this.scene.input.gamepad.total > 0;
}
/**
* Get connected controller info
*/
getControllerInfo() {
if (!this.isControllerConnected()) return null;
const pad = this.scene.input.gamepad.getPad(0);
return {
id: pad.id,
index: pad.index,
buttons: pad.buttons.length,
axes: pad.axes.length
};
}
destroy() {
this.saveSettings();
console.log('🎮 Input Remapping System destroyed');
}
}