# ♿ ACCESSIBILITY OPTIONS - IMPLEMENTATION PLAN **Game:** Mrtva Dolina / Death Valley **Date:** January 4, 2026 **Priority:** HIGH (Inclusive Gaming Standard) --- ## 🎯 ACCESSIBILITY FEATURES (From Screenshot) ### **Required Features:** 1. ✅ **High Contrast Mode** 2. ✅ **Large Text Mode** 3. ✅ **Color Blind Mode** 4. ✅ **Screen Reader Support** 5. ✅ **Reduce Flashing (Epilepsy)** 6. ✅ **One-Handed Controls** 7. ✅ **Audio Cues** **Quick Toggle:** Press 1-7 to toggle features **Full Settings:** ESC → Settings → Accessibility --- ## 📋 DETAILED IMPLEMENTATION ### **1. HIGH CONTRAST MODE** 🎨 **Purpose:** Better visibility for low vision players **Changes:** - Background: Pure black (#000000) - Text: Pure white (#FFFFFF) - UI borders: Bright yellow (#FFFF00) - Buttons: High contrast colors - Dialogue box: Black with white border - Character portraits: Increased brightness +30% **Implementation:** ```javascript // src/systems/AccessibilitySystem.js class AccessibilitySystem { toggleHighContrast() { this.highContrast = !this.highContrast; if (this.highContrast) { // Override all colors this.scene.dialogueBg.setFillStyle(0x000000, 1.0); this.scene.dialogueBg.setStrokeStyle(4, 0xFFFF00); this.scene.dialogueText.setColor('#FFFFFF'); this.scene.speakerText.setColor('#FFFF00'); // Apply to all scenes this.game.scene.scenes.forEach(scene => { if (scene.applyHighContrast) { scene.applyHighContrast(); } }); } else { // Restore original colors this.restoreDefaultColors(); } this.save(); } } ``` **Keyboard:** Press **1** to toggle --- ### **2. LARGE TEXT MODE** 📝 **Purpose:** Readability for visually impaired **Changes:** - All text +50% larger - Dialogue: 18px → 27px - UI labels: 16px → 24px - Buttons: 14px → 21px - Line spacing: +25% **Implementation:** ```javascript toggleLargeText() { this.largeText = !this.largeText; const multiplier = this.largeText ? 1.5 : 1.0; // Update all text objects this.scene.dialogueText.setFontSize(18 * multiplier); this.scene.speakerText.setFontSize(22 * multiplier); // Resize dialogue box to fit const newHeight = this.largeText ? 240 : 180; this.scene.dialogueBg.setDisplaySize( this.scene.dialogueBg.width, newHeight ); this.save(); } ``` **Keyboard:** Press **2** to toggle --- ### **3. COLOR BLIND MODE** 🌈 **Purpose:** Support for color blindness (8% of men, 0.5% of women) **Types Supported:** - **Deuteranopia** (Red-Green, most common) - **Protanopia** (Red-Green) - **Tritanopia** (Blue-Yellow, rare) **Changes:** - Health bars: Red → Orange with pattern - Stamina: Blue → Cyan with stripes - Quest markers: Color + Icon - Item rarity: Color + Border style - Enemy indicators: Color + Shape **Color Palette Remapping:** ```javascript const COLOR_BLIND_PALETTES = { deuteranopia: { red: 0xFF8C00, // Orange instead of red green: 0x00CED1, // Dark cyan instead of green blue: 0x4169E1, // Royal blue (unchanged) purple: 0xFF00FF // Magenta (more distinct) }, protanopia: { red: 0xFFD700, // Gold instead of red green: 0x1E90FF, // Dodger blue instead of green blue: 0x8A2BE2, // Blue violet purple: 0xFF69B4 // Hot pink }, tritanopia: { red: 0xFF0000, // Red (unchanged) green: 0x00FF00, // Green (unchanged) blue: 0xFF1493, // Deep pink instead of blue yellow: 0x00FFFF // Cyan instead of yellow } }; ``` **Implementation:** ```javascript setColorBlindMode(type) { this.colorBlindMode = type; // 'none', 'deuteranopia', 'protanopia', 'tritanopia' if (type !== 'none') { const palette = COLOR_BLIND_PALETTES[type]; // Remap all color references this.game.registry.set('palette', palette); // Add patterns to critical elements this.addAccessibilityPatterns(); } this.save(); } addAccessibilityPatterns() { // Add stripes to health bar this.healthBar.setTexture('health_bar_striped'); // Add icons to color-coded elements this.questMarkers.forEach(marker => { marker.addIcon(); // Add symbol alongside color }); } ``` **UI:** Dropdown menu: None / Deuteranopia / Protanopia / Tritanopia **Keyboard:** Press **3** to cycle modes --- ### **4. SCREEN READER SUPPORT** 🔊 **Purpose:** Blind/low-vision accessibility **Features:** - Announce all UI changes - Read dialogue text aloud - Describe scene changes - Navigate menus with keyboard - Audio feedback for all actions **Implementation:** ```javascript class ScreenReaderSystem { constructor(game) { this.game = game; this.enabled = false; this.speechSynth = window.speechSynthesis; this.currentUtterance = null; } enable() { this.enabled = true; this.announce("Screen reader enabled. Use arrow keys to navigate."); } announce(text, interrupt = false) { if (!this.enabled) return; // Stop current speech if interrupting if (interrupt && this.speechSynth.speaking) { this.speechSynth.cancel(); } const utterance = new SpeechSynthesisUtterance(text); utterance.lang = this.game.settings.language || 'sl-SI'; utterance.rate = 1.0; utterance.pitch = 1.0; utterance.volume = 1.0; this.speechSynth.speak(utterance); this.currentUtterance = utterance; } announceDialogue(speaker, text) { const fullText = `${speaker} says: ${text}`; this.announce(fullText, true); } announceSceneChange(sceneName) { this.announce(`Entering ${sceneName}`, true); } announceButton(buttonLabel) { this.announce(`Button: ${buttonLabel}. Press Enter to activate.`); } } ``` **Integration with PrologueScene:** ```javascript showDialogue(index) { const dialogue = this.dialogueData[index]; // Screen reader support if (this.game.accessibility.screenReader.enabled) { this.game.accessibility.screenReader.announceDialogue( dialogue.speaker, dialogue.text ); } // ... rest of dialogue logic } ``` **Keyboard:** Press **4** to toggle --- ### **5. REDUCE FLASHING (EPILEPSY)** ⚡ **Purpose:** Prevent seizures (photosensitive epilepsy affects ~3%) **Changes:** - Disable camera shake - Disable screen flash effects - Reduce particle effects - Smooth transitions only - Warning on startup if disabled **Removed Effects:** ```javascript toggleReduceFlashing() { this.reduceFlashing = !this.reduceFlashing; if (this.reduceFlashing) { // Disable dangerous effects this.game.cameras.main.shake(0); // No shake this.game.cameras.main.flash(0); // No flash // Reduce particle systems this.game.particles.setEmitterRate(0.5); // 50% particles // Disable lightning this.weatherSystem.disableLightning = true; // Smooth transitions only this.transitionDuration = 2000; // Slower fades } this.save(); } ``` **Startup Warning:** ```javascript create() { if (!this.game.accessibility.reduceFlashing) { this.showFlashWarning(); } } showFlashWarning() { const warning = this.add.text( this.cameras.main.width / 2, this.cameras.main.height / 2, '⚠️ WARNING ⚠️\n\n' + 'This game contains flashing lights\n' + 'and rapid scene changes.\n\n' + 'Press 5 to enable Epilepsy Safety Mode\n' + 'Press any other key to continue', { fontSize: '24px', align: 'center', backgroundColor: '#000000', padding: { x: 40, y: 40 } } ); warning.setOrigin(0.5); // Wait for input this.input.keyboard.once('keydown', (event) => { if (event.key === '5') { this.game.accessibility.toggleReduceFlashing(); } warning.destroy(); }); } ``` **Keyboard:** Press **5** to toggle --- ### **6. ONE-HANDED CONTROLS** 🎮 **Purpose:** Physical disability support (one hand, motor impairments) **Modes:** - **Left-Hand Mode** (WASD + nearby keys) - **Right-Hand Mode** (Arrow keys + numpad) - **Both modes support mouse-only gameplay** **Left-Hand Layout:** ``` Movement: WASD Action: Q Menu: E Inventory: R Map: T Sprint: Shift Crouch: Ctrl ``` **Right-Hand Layout:** ``` Movement: Arrow Keys Action: Numpad 0 Menu: Numpad Enter Inventory: Numpad + Map: Numpad - Sprint: Numpad / Crouch: Numpad * ``` **Implementation:** ```javascript class OneHandedControls { setMode(mode) { this.mode = mode; // 'left', 'right', 'both' if (mode === 'left') { this.bindLeftHandKeys(); } else if (mode === 'right') { this.bindRightHandKeys(); } else { this.bindBothHands(); } } bindLeftHandKeys() { const keys = { up: 'W', down: 'S', left: 'A', right: 'D', action: 'Q', menu: 'E', inventory: 'R', map: 'T', sprint: 'SHIFT', crouch: 'CTRL' }; this.remapKeys(keys); } bindRightHandKeys() { const keys = { up: 'UP', down: 'DOWN', left: 'LEFT', right: 'RIGHT', action: 'NUMPAD_ZERO', menu: 'NUMPAD_ENTER', inventory: 'NUMPAD_ADD', map: 'NUMPAD_SUBTRACT', sprint: 'NUMPAD_DIVIDE', crouch: 'NUMPAD_MULTIPLY' }; this.remapKeys(keys); } } ``` **UI Toggle:** - Settings → Accessibility → One-Handed Controls - Options: Both Hands / Left Hand Only / Right Hand Only **Keyboard:** Press **6** to cycle modes --- ### **7. AUDIO CUES** 🔔 **Purpose:** Additional feedback for deaf/hard-of-hearing players **Features:** - Visual sound indicators - Subtitles for all dialogue (already done!) - Direction indicators for off-screen sounds - Vibration feedback (controller) **Visual Sound System:** ```javascript class VisualSoundCueSystem { constructor(scene) { this.scene = scene; this.cues = []; } showCue(soundType, direction, distance) { // Create visual indicator const cue = this.scene.add.sprite(x, y, 'sound_cue_' + soundType); cue.setAlpha(0.7); // Position based on direction const angle = this.getAngleFromDirection(direction); const radius = 200; // Distance from player cue.x = this.scene.player.x + Math.cos(angle) * radius; cue.y = this.scene.player.y + Math.sin(angle) * radius; // Add text label const label = this.scene.add.text(cue.x, cue.y + 30, soundType, { fontSize: '14px', backgroundColor: '#000000' }); // Fade out after 2 seconds this.scene.tweens.add({ targets: [cue, label], alpha: 0, duration: 2000, onComplete: () => { cue.destroy(); label.destroy(); } }); } // Example usage onZombieGrowl(zombiePosition) { const direction = this.getDirectionToPlayer(zombiePosition); const distance = Phaser.Math.Distance.Between( this.scene.player.x, this.scene.player.y, zombiePosition.x, zombiePosition.y ); this.showCue('Zombie Growl', direction, distance); } } ``` **Sound Types with Icons:** - 🧟 Zombie nearby - 💥 Explosion - 🔔 Quest update - 💬 NPC speaking - ⚔️ Combat - 🚪 Door opening/closing - 📦 Item pickup **Keyboard:** Press **7** to toggle --- ## 🎨 UI IMPLEMENTATION ### **Accessibility Options Menu** ```javascript class AccessibilityMenu extends Phaser.Scene { create() { // Title this.add.text(width/2, 50, '♿ ACCESSIBILITY OPTIONS', { fontSize: '32px', color: '#FFFFFF' }).setOrigin(0.5); // Options list const options = [ { id: 1, name: 'High Contrast Mode', key: '1' }, { id: 2, name: 'Large Text Mode', key: '2' }, { id: 3, name: 'Color Blind Mode', key: '3' }, { id: 4, name: 'Screen Reader Support', key: '4' }, { id: 5, name: 'Reduce Flashing (Epilepsy)', key: '5' }, { id: 6, name: 'One-Handed Controls', key: '6' }, { id: 7, name: 'Audio Cues', key: '7' } ]; let y = 150; options.forEach(option => { const text = this.add.text(100, y, `${option.id}. ${option.name}`, { fontSize: '20px' } ); // Toggle indicator const indicator = this.add.text(width - 100, y, this.getStatusText(option.id), { fontSize: '20px' } ); y += 50; }); // Footer this.add.text(width/2, height - 100, 'Full accessibility settings available\n' + 'in-game (ESC → Settings)\n\n' + 'Tip: Press 1-7 to toggle these features', { fontSize: '16px', align: 'center', color: '#AAAAAA' } ).setOrigin(0.5); // OK button const okButton = this.add.rectangle( width/2, height - 40, 200, 50, 0x0066FF ); this.add.text(width/2, height - 40, 'OK', { fontSize: '24px' }).setOrigin(0.5); okButton.setInteractive(); okButton.on('pointerdown', () => { this.scene.start('MainMenu'); }); // Keyboard shortcuts this.input.keyboard.on('keydown', (event) => { const key = parseInt(event.key); if (key >= 1 && key <= 7) { this.toggleOption(key); } }); } toggleOption(id) { const accessibility = this.game.registry.get('accessibility'); switch(id) { case 1: accessibility.toggleHighContrast(); break; case 2: accessibility.toggleLargeText(); break; case 3: accessibility.cycleColorBlindMode(); break; case 4: accessibility.toggleScreenReader(); break; case 5: accessibility.toggleReduceFlashing(); break; case 6: accessibility.cycleOneHandedMode(); break; case 7: accessibility.toggleAudioCues(); break; } // Refresh UI this.scene.restart(); } getStatusText(id) { const accessibility = this.game.registry.get('accessibility'); const statuses = [ accessibility.highContrast ? 'ON' : 'OFF', accessibility.largeText ? 'ON' : 'OFF', accessibility.colorBlindMode || 'None', accessibility.screenReader ? 'ON' : 'OFF', accessibility.reduceFlashing ? 'ON' : 'OFF', accessibility.oneHandedMode || 'Both', accessibility.audioCues ? 'ON' : 'OFF' ]; return statuses[id - 1]; } } ``` --- ## 💾 PERSISTENCE ```javascript // Save accessibility settings to localStorage class AccessibilitySystem { save() { const settings = { highContrast: this.highContrast, largeText: this.largeText, colorBlindMode: this.colorBlindMode, screenReader: this.screenReader, reduceFlashing: this.reduceFlashing, oneHandedMode: this.oneHandedMode, audioCues: this.audioCues }; localStorage.setItem('accessibility_settings', JSON.stringify(settings)); } load() { const saved = localStorage.getItem('accessibility_settings'); if (saved) { const settings = JSON.parse(saved); Object.assign(this, settings); this.applyAll(); } } applyAll() { if (this.highContrast) this.toggleHighContrast(); if (this.largeText) this.toggleLargeText(); if (this.colorBlindMode !== 'none') this.setColorBlindMode(this.colorBlindMode); if (this.screenReader) this.screenReaderSystem.enable(); if (this.reduceFlashing) this.toggleReduceFlashing(); if (this.oneHandedMode !== 'both') this.controls.setMode(this.oneHandedMode); if (this.audioCues) this.visualSoundCues.enable(); } } ``` --- ## 📊 IMPLEMENTATION TIMELINE | Week | Task | Deliverable | |------|------|-------------| | **1** | Core System | AccessibilitySystem.js | | **2** | High Contrast + Large Text | Visual modes | | **3** | Color Blind Mode | 3 palette variants | | **4** | Screen Reader | Text-to-speech | | **5** | Epilepsy Safety | Effect reduction | | **6** | One-Handed + Audio Cues | Control schemes | | **7** | UI Integration | Settings menu | | **8** | Testing | User testing | **Total Time:** 8 weeks (~2 months) --- ## ✅ SUCCESS CRITERIA - [ ] All 7 features implemented - [ ] Keyboard shortcuts (1-7) working - [ ] Settings persist across sessions - [ ] No performance impact - [ ] Screen reader announces all interactions - [ ] Color blind modes tested with simulators - [ ] One-handed mode fully playable - [ ] Epilepsy warning on first launch --- ## 🎯 PRIORITY ORDER ### **Phase 1 (Critical):** 1. **Reduce Flashing** - Safety first! 2. **Large Text Mode** - Easy win 3. **High Contrast Mode** - Visual accessibility ### **Phase 2 (Important):** 4. **Color Blind Mode** - 8% of players 5. **One-Handed Controls** - Physical accessibility 6. **Audio Cues** - Deaf/HoH support ### **Phase 3 (Advanced):** 7. **Screen Reader Support** - Complex but essential --- ## 🏆 INDUSTRY STANDARDS Following guidelines from: - **Game Accessibility Guidelines** (gameaccessibilityguidelines.com) - **Xbox Accessibility** standards - **PlayStation Accessibility** standards - **WCAG 2.1** (Web Content Accessibility Guidelines) **Certification Goal:** Xbox Accessibility Features badge --- **Last Updated:** January 4, 2026 **Status:** Planning → Implementation Starting Tonight