/** * ACCESSIBILITY MANAGER - STREAMER-READY FEATURES * One-Handed Mode, High Contrast, Font Scaling */ class AccessibilityManager { constructor(scene) { this.scene = scene; // Accessibility settings this.settings = { oneHandedMode: false, oneHandedSide: 'left', // 'left' or 'right' highContrast: false, colorBlindMode: 'none', // 'none', 'protanopia', 'deuteranopia', 'tritanopia' fontScale: 1.0, // 0.8 - 2.0 subtitleSize: 'medium', // 'small', 'medium', 'large', 'xlarge' reduceMotion: false, screenReader: false }; // Load saved settings this.load(); // Apply settings this.apply(); } /** * ONE-HANDED MODE (Xbox Controller) */ enableOneHandedMode(side = 'left') { this.settings.oneHandedMode = true; this.settings.oneHandedSide = side; console.log(`♿ ONE-HANDED MODE ENABLED (${side.toUpperCase()} hand)`); console.log(' Movement: Left stick'); if (side === 'left') { console.log(' Actions mapped to LEFT side:'); console.log(' - LB: Interact (was A)'); console.log(' - LT: Attack (was X)'); console.log(' - L3 (click stick): Menu (was B)'); console.log(' - D-Pad Up: Whistle Susi (was Y)'); } else { console.log(' Actions mapped to RIGHT side:'); console.log(' - RB: Interact (was A)'); console.log(' - RT: Attack (was X)'); console.log(' - R3 (click stick): Menu (was B)'); console.log(' - Right Stick Click: Whistle (was Y)'); } this.save(); // Emit event for gamepad controller if (this.scene.events) { this.scene.events.emit('accessibility-changed', this.settings); } } disableOneHandedMode() { this.settings.oneHandedMode = false; console.log('♿ One-handed mode disabled - Back to standard controls'); this.save(); } /** * GET BUTTON MAPPING FOR ONE-HANDED MODE */ getButtonMapping() { if (!this.settings.oneHandedMode) { // Standard mapping return { interact: 'A', attack: 'X', whistle: 'Y', menu: 'B', movement: 'LEFT_STICK' }; } if (this.settings.oneHandedSide === 'left') { // Left-hand mapping return { interact: 'LB', attack: 'LT', whistle: 'DPAD_UP', menu: 'L3', movement: 'LEFT_STICK' }; } else { // Right-hand mapping return { interact: 'RB', attack: 'RT', whistle: 'R3', menu: 'DPAD_DOWN', movement: 'RIGHT_STICK' }; } } /** * HIGH CONTRAST MODE */ enableHighContrast() { this.settings.highContrast = true; console.log('♿ HIGH CONTRAST MODE ENABLED'); // Apply high contrast shader this.applyHighContrastShader(); this.save(); } disableHighContrast() { this.settings.highContrast = false; console.log('♿ High contrast mode disabled'); // Remove shader this.removeHighContrastShader(); this.save(); } applyHighContrastShader() { if (!this.scene.cameras || !this.scene.cameras.main) return; // Increase contrast using post-processing const camera = this.scene.cameras.main; // Store original values if (!this.originalContrast) { this.originalContrast = { alpha: camera.alpha, brightness: 1.0 }; } // Boost contrast camera.setAlpha(1.0); // Add vignette for edge clarity (reverse of normal vignette) if (this.contrastOverlay) { this.contrastOverlay.destroy(); } const width = this.scene.cameras.main.width; const height = this.scene.cameras.main.height; this.contrastOverlay = this.scene.add.rectangle( width / 2, height / 2, width, height, 0xFFFFFF, 0.1 ); this.contrastOverlay.setScrollFactor(0); this.contrastOverlay.setDepth(10000); this.contrastOverlay.setBlendMode(Phaser.BlendModes.OVERLAY); console.log('✅ High contrast shader applied'); } removeHighContrastShader() { if (this.contrastOverlay) { this.contrastOverlay.destroy(); this.contrastOverlay = null; } if (this.originalContrast && this.scene.cameras && this.scene.cameras.main) { this.scene.cameras.main.setAlpha(this.originalContrast.alpha); } } /** * COLOR BLIND MODE */ setColorBlindMode(mode) { const validModes = ['none', 'protanopia', 'deuteranopia', 'tritanopia']; if (!validModes.includes(mode)) { console.warn('Invalid color blind mode:', mode); return; } this.settings.colorBlindMode = mode; console.log(`♿ COLOR BLIND MODE: ${mode.toUpperCase()}`); // Apply color filter this.applyColorBlindFilter(mode); this.save(); } applyColorBlindFilter(mode) { // Remove existing filter if (this.colorBlindFilter) { this.colorBlindFilter.destroy(); this.colorBlindFilter = null; } if (mode === 'none') return; const width = this.scene.cameras.main.width; const height = this.scene.cameras.main.height; // Apply color tint based on mode const tints = { protanopia: 0xFFCCCC, // Red-blind (pink tint) deuteranopia: 0xCCFFCC, // Green-blind (light green tint) tritanopia: 0xCCCCFF // Blue-blind (light blue tint) }; this.colorBlindFilter = this.scene.add.rectangle( width / 2, height / 2, width, height, tints[mode], 0.15 ); this.colorBlindFilter.setScrollFactor(0); this.colorBlindFilter.setDepth(9999); this.colorBlindFilter.setBlendMode(Phaser.BlendModes.MULTIPLY); console.log(`✅ ${mode} filter applied`); } /** * FONT SCALING (for subtitles, UI) */ setFontScale(scale) { // Clamp between 0.8 and 2.0 this.settings.fontScale = Phaser.Math.Clamp(scale, 0.8, 2.0); console.log(`♿ FONT SCALE: ${this.settings.fontScale}x`); // Emit event for UI to update if (this.scene.events) { this.scene.events.emit('font-scale-changed', this.settings.fontScale); } this.save(); } /** * SUBTITLE SIZE PRESETS */ setSubtitleSize(size) { const sizes = { small: 0.8, medium: 1.0, large: 1.5, xlarge: 2.0 }; if (sizes[size]) { this.settings.subtitleSize = size; this.setFontScale(sizes[size]); console.log(`♿ SUBTITLE SIZE: ${size.toUpperCase()} (${sizes[size]}x)`); } } /** * GET FONT SIZE FOR ELEMENT */ getFontSize(baseFontSize) { return Math.floor(baseFontSize * this.settings.fontScale); } /** * REDUCE MOTION MODE */ enableReduceMotion() { this.settings.reduceMotion = true; console.log('♿ REDUCE MOTION ENABLED'); console.log(' - Disabled screen shake'); console.log(' - Reduced particle effects'); console.log(' - Slower transitions'); this.save(); } disableReduceMotion() { this.settings.reduceMotion = false; console.log('♿ Reduce motion disabled'); this.save(); } /** * APPLY ALL SETTINGS */ apply() { if (this.settings.highContrast) { this.applyHighContrastShader(); } if (this.settings.colorBlindMode !== 'none') { this.applyColorBlindFilter(this.settings.colorBlindMode); } if (this.settings.oneHandedMode) { console.log(`♿ One-handed mode active (${this.settings.oneHandedSide})`); } console.log(`♿ Font scale: ${this.settings.fontScale}x`); } /** * GET ALL SETTINGS */ getSettings() { return { ...this.settings }; } /** * SAVE TO LOCALSTORAGE */ save() { localStorage.setItem('accessibility_settings', JSON.stringify(this.settings)); console.log('💾 Accessibility settings saved'); } /** * LOAD FROM LOCALSTORAGE */ load() { const stored = localStorage.getItem('accessibility_settings'); if (stored) { try { this.settings = { ...this.settings, ...JSON.parse(stored) }; console.log('✅ Accessibility settings loaded:', this.settings); } catch (e) { console.warn('Failed to load accessibility settings:', e); } } } /** * RESET TO DEFAULTS */ reset() { this.settings = { oneHandedMode: false, oneHandedSide: 'left', highContrast: false, colorBlindMode: 'none', fontScale: 1.0, subtitleSize: 'medium', reduceMotion: false, screenReader: false }; this.removeHighContrastShader(); this.applyColorBlindFilter('none'); this.save(); console.log('♿ Accessibility settings reset to defaults'); } /** * CLEANUP */ destroy() { this.removeHighContrastShader(); if (this.colorBlindFilter) { this.colorBlindFilter.destroy(); } console.log('♿ AccessibilityManager destroyed'); } }