12 KiB
12 KiB
♿ ACCESSIBILITY FEATURES - IMPLEMENTATION PLAN
Datum: 12. December 2025
Prioriteta: HIGH
Estimated Time: 2-3 ure
🎯 CILJI:
Implementirati celovit accessibility sistem za:
- High Contrast Modes
- Color Blind Support
- Photosensitivity Protection
📋 FAZA 1: HIGH CONTRAST MODES (30 min)
1.1 Black & White Mode
Datoteka: src/systems/AccessibilitySystem.js (nova)
class AccessibilitySystem {
constructor(scene) {
this.scene = scene;
this.settings = {
highContrast: 'none', // 'none', 'bw', 'yellow_black'
largeUI: false,
boldOutlines: false,
colorBlindMode: 'none',
photosensitivity: false
};
this.loadSettings();
}
enableBlackWhite() {
// Apply grayscale filter to entire game
this.scene.cameras.main.setPostPipeline('GrayscalePipeline');
// Increase contrast
this.scene.cameras.main.setAlpha(1.2);
console.log('🎨 Black & White mode enabled');
}
disableBlackWhite() {
this.scene.cameras.main.clearPostPipeline();
this.scene.cameras.main.setAlpha(1.0);
}
}
1.2 Yellow on Black Mode
enableYellowOnBlack() {
// Create color replacement pipeline
const pipeline = this.scene.game.renderer.pipelines.add('YellowBlackPipeline', {
fragShader: `
precision mediump float;
uniform sampler2D uMainSampler;
varying vec2 outTexCoord;
void main(void) {
vec4 color = texture2D(uMainSampler, outTexCoord);
float gray = dot(color.rgb, vec3(0.299, 0.587, 0.114));
// Yellow on black
vec3 yellow = vec3(1.0, 1.0, 0.0);
vec3 result = yellow * gray;
gl_FragColor = vec4(result, color.a);
}
`
});
this.scene.cameras.main.setPostPipeline(pipeline);
}
1.3 Large UI (150%-200%)
enableLargeUI(scale = 1.5) {
const uiScene = this.scene.scene.get('UIScene');
if (!uiScene) return;
// Scale all UI elements
uiScene.children.list.forEach(child => {
if (child.setScale) {
child.setScale(child.scaleX * scale, child.scaleY * scale);
}
});
// Adjust positions
this.repositionUIElements(scale);
console.log(`🔍 Large UI enabled: ${scale * 100}%`);
}
1.4 Bold Outlines
enableBoldOutlines() {
// Increase stroke thickness on all text
const uiScene = this.scene.scene.get('UIScene');
if (!uiScene) return;
uiScene.children.list.forEach(child => {
if (child.type === 'Text') {
child.setStroke('#000000', 6); // Thicker stroke
child.setShadow(2, 2, '#000000', 2, true, true);
}
});
}
📋 FAZA 2: COLOR BLIND SUPPORT (45 min)
2.1 Protanopia Mode (Red-Blind)
enableProtanopia() {
const pipeline = this.createColorBlindPipeline('protanopia', `
// Protanopia simulation
mat3 protanopia = mat3(
0.567, 0.433, 0.0,
0.558, 0.442, 0.0,
0.0, 0.242, 0.758
);
vec3 result = protanopia * color.rgb;
`);
this.scene.cameras.main.setPostPipeline(pipeline);
}
2.2 Deuteranopia Mode (Green-Blind)
enableDeuteranopia() {
const pipeline = this.createColorBlindPipeline('deuteranopia', `
mat3 deuteranopia = mat3(
0.625, 0.375, 0.0,
0.7, 0.3, 0.0,
0.0, 0.3, 0.7
);
vec3 result = deuteranopia * color.rgb;
`);
this.scene.cameras.main.setPostPipeline(pipeline);
}
2.3 Tritanopia Mode (Blue-Blind)
enableTritanopia() {
const pipeline = this.createColorBlindPipeline('tritanopia', `
mat3 tritanopia = mat3(
0.95, 0.05, 0.0,
0.0, 0.433, 0.567,
0.0, 0.475, 0.525
);
vec3 result = tritanopia * color.rgb;
`);
this.scene.cameras.main.setPostPipeline(pipeline);
}
2.4 Achromatopsia Mode (Total Color Blind)
enableAchromatopsia() {
// Full grayscale
this.enableBlackWhite();
// Add high contrast
this.scene.cameras.main.setContrast(1.5);
}
2.5 Shape Coding
addShapeCoding() {
// Replace color-only indicators with shapes
// Example: HP bar = ❤️, Hunger = 🍖, Thirst = 💧
const uiScene = this.scene.scene.get('UIScene');
if (!uiScene) return;
// Add icons to bars
if (uiScene.healthBar) {
const icon = uiScene.add.text(
uiScene.healthBar.x - 20,
uiScene.healthBar.y,
'❤️',
{ fontSize: '16px' }
);
icon.setScrollFactor(0);
}
}
2.6 Pattern Overlays
addPatternOverlays() {
// Add patterns to differentiate elements
// Example: HP = solid, Hunger = stripes, Thirst = dots
const createPattern = (type) => {
const graphics = this.scene.add.graphics();
if (type === 'stripes') {
for (let i = 0; i < 10; i++) {
graphics.lineStyle(2, 0xffffff, 0.3);
graphics.lineBetween(i * 10, 0, i * 10, 100);
}
} else if (type === 'dots') {
for (let i = 0; i < 5; i++) {
for (let j = 0; j < 5; j++) {
graphics.fillStyle(0xffffff, 0.3);
graphics.fillCircle(i * 20, j * 20, 3);
}
}
}
return graphics;
};
}
📋 FAZA 3: PHOTOSENSITIVITY PROTECTION (45 min)
3.1 Flash Limiter
class FlashLimiter {
constructor(scene) {
this.scene = scene;
this.flashCount = 0;
this.flashWindow = 1000; // 1 second
this.maxFlashes = 3; // Max 3 flashes per second
this.lastFlashTime = 0;
}
canFlash() {
const now = Date.now();
// Reset counter if window passed
if (now - this.lastFlashTime > this.flashWindow) {
this.flashCount = 0;
this.lastFlashTime = now;
}
// Check limit
if (this.flashCount >= this.maxFlashes) {
console.warn('⚠️ Flash limit reached - skipping flash');
return false;
}
this.flashCount++;
return true;
}
}
3.2 Disable Lightning Effects
disableLightning() {
if (this.scene.weatherSystem) {
this.scene.weatherSystem.lightningEnabled = false;
}
// Remove existing lightning effects
this.scene.children.list.forEach(child => {
if (child.name === 'lightning') {
child.destroy();
}
});
}
3.3 Reduce Particles
reduceParticles(level = 0.5) {
// Reduce particle emission rate
this.scene.children.list.forEach(child => {
if (child.type === 'ParticleEmitter') {
child.setFrequency(child.frequency / level);
child.setQuantity(Math.floor(child.quantity * level));
}
});
}
3.4 Epilepsy Warning Screen
showEpilepsyWarning() {
const warning = this.scene.add.container(
this.scene.cameras.main.centerX,
this.scene.cameras.main.centerY
);
warning.setDepth(10000);
const bg = this.scene.add.rectangle(0, 0, 600, 400, 0x000000, 0.95);
const title = this.scene.add.text(0, -150, '⚠️ EPILEPSY WARNING', {
fontSize: '32px',
color: '#ff0000',
fontStyle: 'bold'
}).setOrigin(0.5);
const text = this.scene.add.text(0, -50,
'This game contains flashing lights and patterns\n' +
'that may trigger seizures in people with\n' +
'photosensitive epilepsy.\n\n' +
'Player discretion is advised.',
{
fontSize: '18px',
color: '#ffffff',
align: 'center',
wordWrap: { width: 500 }
}
).setOrigin(0.5);
const enableBtn = this.scene.add.text(0, 120, '[ ENABLE PHOTOSENSITIVITY MODE ]', {
fontSize: '20px',
color: '#00ff00',
backgroundColor: '#003300',
padding: { x: 20, y: 10 }
}).setOrigin(0.5);
enableBtn.setInteractive({ useHandCursor: true });
enableBtn.on('pointerdown', () => {
this.enablePhotosensitivityMode();
warning.destroy();
});
const continueBtn = this.scene.add.text(0, 170, '[ CONTINUE WITHOUT ]', {
fontSize: '16px',
color: '#888888'
}).setOrigin(0.5);
continueBtn.setInteractive({ useHandCursor: true });
continueBtn.on('pointerdown', () => {
warning.destroy();
});
warning.add([bg, title, text, enableBtn, continueBtn]);
}
3.5 Motion Sickness Options
enableMotionSicknessMode() {
// Reduce camera shake
this.scene.cameras.main.shake = () => {};
// Reduce screen transitions
this.scene.cameras.main.fadeEffect.duration = 100; // Faster fades
// Disable parallax
if (this.scene.parallaxSystem) {
this.scene.parallaxSystem.enabled = false;
}
// Reduce zoom changes
this.scene.cameras.main.zoomTo = (zoom, duration) => {
this.scene.cameras.main.setZoom(zoom); // Instant
};
}
3.6 Brightness Limiter
enableBrightnessLimiter(maxBrightness = 0.8) {
// Limit maximum brightness
const overlay = this.scene.add.graphics();
overlay.fillStyle(0x000000, 1 - maxBrightness);
overlay.fillRect(0, 0, this.scene.cameras.main.width, this.scene.cameras.main.height);
overlay.setScrollFactor(0);
overlay.setDepth(9999);
this.brightnessOverlay = overlay;
}
📋 FAZA 4: SETTINGS MENU INTEGRATION (30 min)
4.1 Accessibility Settings Menu
createAccessibilityMenu() {
const menu = this.scene.add.container(
this.scene.cameras.main.centerX,
this.scene.cameras.main.centerY
);
// Title
const title = this.scene.add.text(0, -200, '♿ ACCESSIBILITY', {
fontSize: '32px',
fontStyle: 'bold'
}).setOrigin(0.5);
// High Contrast
this.addToggle(menu, 0, -150, 'High Contrast', [
'None', 'Black & White', 'Yellow on Black'
], (value) => this.setHighContrast(value));
// Large UI
this.addToggle(menu, 0, -100, 'UI Size', [
'100%', '150%', '200%'
], (value) => this.setUISize(value));
// Color Blind Mode
this.addToggle(menu, 0, -50, 'Color Blind Mode', [
'None', 'Protanopia', 'Deuteranopia', 'Tritanopia', 'Achromatopsia'
], (value) => this.setColorBlindMode(value));
// Photosensitivity
this.addCheckbox(menu, 0, 0, 'Photosensitivity Protection',
(checked) => this.setPhotosensitivity(checked));
// Motion Sickness
this.addCheckbox(menu, 0, 50, 'Motion Sickness Mode',
(checked) => this.setMotionSickness(checked));
menu.add(title);
return menu;
}
📝 IMPLEMENTATION STEPS:
- Ustvari AccessibilitySystem.js (30 min)
- Implementiraj High Contrast Modes (30 min)
- Implementiraj Color Blind Support (45 min)
- Implementiraj Photosensitivity Protection (45 min)
- Ustvari Settings Menu (30 min)
- Integracija v GameScene (15 min)
- Testing (30 min)
Total: 3h 45min
🔧 DATOTEKE:
Nove:
src/systems/AccessibilitySystem.js(~500 vrstic)src/pipelines/ColorBlindPipeline.js(~200 vrstic)src/pipelines/GrayscalePipeline.js(~50 vrstic)
Posodobljene:
src/scenes/GameScene.js- Initialize AccessibilitySystemsrc/scenes/UIScene.js- Accessibility menuindex.html- Dodaj nove skripte
🎯 PRIORITETA:
HIGH - Accessibility je pomemben za:
- Večjo dostopnost
- Širše občinstvo
- Boljšo uporabniško izkušnjo
- Compliance s standardi
Status: ⏳ PLAN PRIPRAVLJEN - ČAKA NA IMPLEMENTACIJO
Priporočam: Implementacija v naslednji seji (jutri)
Razlog: Seja že traja 2h 14min, accessibility zahteva 3-4 ure dela.
Želite začeti zdaj ali pustim za jutri? 🎮