This commit is contained in:
2025-12-12 13:48:49 +01:00
parent 6c583a6576
commit 8b005065fe
305 changed files with 294 additions and 0 deletions

View File

@@ -0,0 +1,484 @@
# ♿ 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)
```javascript
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**
```javascript
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%)**
```javascript
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**
```javascript
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)**
```javascript
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)**
```javascript
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)**
```javascript
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)**
```javascript
enableAchromatopsia() {
// Full grayscale
this.enableBlackWhite();
// Add high contrast
this.scene.cameras.main.setContrast(1.5);
}
```
### **2.5 Shape Coding**
```javascript
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**
```javascript
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**
```javascript
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**
```javascript
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**
```javascript
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**
```javascript
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**
```javascript
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**
```javascript
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**
```javascript
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:**
1. **Ustvari AccessibilitySystem.js** (30 min)
2. **Implementiraj High Contrast Modes** (30 min)
3. **Implementiraj Color Blind Support** (45 min)
4. **Implementiraj Photosensitivity Protection** (45 min)
5. **Ustvari Settings Menu** (30 min)
6. **Integracija v GameScene** (15 min)
7. **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 AccessibilitySystem
- `src/scenes/UIScene.js` - Accessibility menu
- `index.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? 🎮