posodobitve
This commit is contained in:
345
src/systems/AccessibilitySystem.js
Normal file
345
src/systems/AccessibilitySystem.js
Normal file
@@ -0,0 +1,345 @@
|
||||
class AccessibilitySystem {
|
||||
constructor(scene) {
|
||||
this.scene = scene;
|
||||
|
||||
// Settings
|
||||
this.settings = {
|
||||
highContrast: 'none', // 'none', 'bw', 'yellow_black'
|
||||
largeUI: 1.0, // 1.0, 1.5, 2.0
|
||||
boldOutlines: false,
|
||||
colorBlindMode: 'none', // 'none', 'protanopia', 'deuteranopia', 'tritanopia', 'achromatopsia'
|
||||
photosensitivity: false,
|
||||
motionSickness: false,
|
||||
brightnessLimit: 1.0 // 0.5 - 1.0
|
||||
};
|
||||
|
||||
// Flash limiter
|
||||
this.flashCount = 0;
|
||||
this.flashWindow = 1000; // 1 second
|
||||
this.maxFlashes = 3;
|
||||
this.lastFlashTime = 0;
|
||||
|
||||
// Load saved settings
|
||||
this.loadSettings();
|
||||
|
||||
// Apply settings
|
||||
this.applySettings();
|
||||
|
||||
console.log('♿ AccessibilitySystem: Initialized');
|
||||
}
|
||||
|
||||
// HIGH CONTRAST MODES
|
||||
enableBlackWhite() {
|
||||
// Apply grayscale filter
|
||||
this.scene.cameras.main.setPostPipeline('GrayscalePipeline');
|
||||
console.log('🎨 Black & White mode enabled');
|
||||
}
|
||||
|
||||
disableBlackWhite() {
|
||||
this.scene.cameras.main.clearPostPipeline();
|
||||
}
|
||||
|
||||
enableYellowOnBlack() {
|
||||
// Simple color replacement - make everything yellow/white on black
|
||||
const cam = this.scene.cameras.main;
|
||||
cam.setBackgroundColor('#000000');
|
||||
|
||||
// Apply tint to all sprites (simplified version)
|
||||
this.scene.children.list.forEach(child => {
|
||||
if (child.setTint) {
|
||||
child.setTint(0xffff00); // Yellow tint
|
||||
}
|
||||
});
|
||||
|
||||
console.log('🎨 Yellow on Black mode enabled');
|
||||
}
|
||||
|
||||
disableYellowOnBlack() {
|
||||
this.scene.cameras.main.setBackgroundColor('#87CEEB'); // Sky blue
|
||||
|
||||
this.scene.children.list.forEach(child => {
|
||||
if (child.clearTint) {
|
||||
child.clearTint();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// LARGE UI
|
||||
setUIScale(scale) {
|
||||
const uiScene = this.scene.scene.get('UIScene');
|
||||
if (!uiScene) return;
|
||||
|
||||
// Scale UI elements (simplified - would need more work for production)
|
||||
uiScene.scale.setZoom(scale);
|
||||
|
||||
console.log(`🔍 UI Scale: ${scale * 100}%`);
|
||||
}
|
||||
|
||||
// BOLD OUTLINES
|
||||
enableBoldOutlines() {
|
||||
const uiScene = this.scene.scene.get('UIScene');
|
||||
if (!uiScene) return;
|
||||
|
||||
// Increase stroke on all text elements
|
||||
uiScene.children.list.forEach(child => {
|
||||
if (child.type === 'Text') {
|
||||
child.setStroke('#000000', 6);
|
||||
child.setShadow(2, 2, '#000000', 2, true, true);
|
||||
}
|
||||
});
|
||||
|
||||
console.log('✏️ Bold outlines enabled');
|
||||
}
|
||||
|
||||
disableBoldOutlines() {
|
||||
const uiScene = this.scene.scene.get('UIScene');
|
||||
if (!uiScene) return;
|
||||
|
||||
uiScene.children.list.forEach(child => {
|
||||
if (child.type === 'Text') {
|
||||
child.setStroke('#000000', 3); // Normal stroke
|
||||
child.setShadow(0, 0, '#000000', 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// COLOR BLIND MODES (Simplified - full implementation would use shaders)
|
||||
setColorBlindMode(mode) {
|
||||
this.settings.colorBlindMode = mode;
|
||||
|
||||
switch (mode) {
|
||||
case 'protanopia':
|
||||
// Red-blind: Replace reds with browns/grays
|
||||
this.applyColorFilter(0xaa8866);
|
||||
break;
|
||||
case 'deuteranopia':
|
||||
// Green-blind: Replace greens with yellows/browns
|
||||
this.applyColorFilter(0xccaa66);
|
||||
break;
|
||||
case 'tritanopia':
|
||||
// Blue-blind: Replace blues with greens/grays
|
||||
this.applyColorFilter(0x88aa88);
|
||||
break;
|
||||
case 'achromatopsia':
|
||||
// Total color blind: Grayscale
|
||||
this.enableBlackWhite();
|
||||
break;
|
||||
default:
|
||||
this.clearColorFilter();
|
||||
}
|
||||
|
||||
console.log(`👁️ Color Blind Mode: ${mode}`);
|
||||
}
|
||||
|
||||
applyColorFilter(tint) {
|
||||
// Simplified color filter
|
||||
this.scene.children.list.forEach(child => {
|
||||
if (child.setTint) {
|
||||
child.setTint(tint);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
clearColorFilter() {
|
||||
this.scene.children.list.forEach(child => {
|
||||
if (child.clearTint) {
|
||||
child.clearTint();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// PHOTOSENSITIVITY PROTECTION
|
||||
canFlash() {
|
||||
if (!this.settings.photosensitivity) return true;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
disableLightning() {
|
||||
if (this.scene.weatherSystem) {
|
||||
this.scene.weatherSystem.lightningEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
reduceParticles(level = 0.5) {
|
||||
this.scene.children.list.forEach(child => {
|
||||
if (child.type === 'ParticleEmitter') {
|
||||
const originalFreq = child.frequency || 100;
|
||||
child.setFrequency(originalFreq / level);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
enableBrightnessLimiter(maxBrightness = 0.8) {
|
||||
if (this.brightnessOverlay) {
|
||||
this.brightnessOverlay.destroy();
|
||||
}
|
||||
|
||||
const overlay = this.scene.add.graphics();
|
||||
overlay.fillStyle(0x000000, 1 - maxBrightness);
|
||||
overlay.fillRect(0, 0, this.scene.cameras.main.width * 2, this.scene.cameras.main.height * 2);
|
||||
overlay.setScrollFactor(0);
|
||||
overlay.setDepth(9999);
|
||||
|
||||
this.brightnessOverlay = overlay;
|
||||
|
||||
console.log(`💡 Brightness limited to ${maxBrightness * 100}%`);
|
||||
}
|
||||
|
||||
disableBrightnessLimiter() {
|
||||
if (this.brightnessOverlay) {
|
||||
this.brightnessOverlay.destroy();
|
||||
this.brightnessOverlay = null;
|
||||
}
|
||||
}
|
||||
|
||||
// MOTION SICKNESS MODE
|
||||
enableMotionSicknessMode() {
|
||||
// Disable camera shake
|
||||
const originalShake = this.scene.cameras.main.shake;
|
||||
this.scene.cameras.main.shake = () => {
|
||||
console.log('🚫 Camera shake disabled (motion sickness mode)');
|
||||
};
|
||||
|
||||
// Disable parallax
|
||||
if (this.scene.parallaxSystem) {
|
||||
this.scene.parallaxSystem.enabled = false;
|
||||
}
|
||||
|
||||
console.log('🤢 Motion sickness mode enabled');
|
||||
}
|
||||
|
||||
disableMotionSicknessMode() {
|
||||
// Re-enable effects
|
||||
if (this.scene.parallaxSystem) {
|
||||
this.scene.parallaxSystem.enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
// SETTINGS MANAGEMENT
|
||||
applySettings() {
|
||||
// High Contrast
|
||||
if (this.settings.highContrast === 'bw') {
|
||||
this.enableBlackWhite();
|
||||
} else if (this.settings.highContrast === 'yellow_black') {
|
||||
this.enableYellowOnBlack();
|
||||
}
|
||||
|
||||
// Large UI
|
||||
if (this.settings.largeUI > 1.0) {
|
||||
this.setUIScale(this.settings.largeUI);
|
||||
}
|
||||
|
||||
// Bold Outlines
|
||||
if (this.settings.boldOutlines) {
|
||||
this.enableBoldOutlines();
|
||||
}
|
||||
|
||||
// Color Blind Mode
|
||||
if (this.settings.colorBlindMode !== 'none') {
|
||||
this.setColorBlindMode(this.settings.colorBlindMode);
|
||||
}
|
||||
|
||||
// Photosensitivity
|
||||
if (this.settings.photosensitivity) {
|
||||
this.disableLightning();
|
||||
this.reduceParticles(0.3);
|
||||
this.enableBrightnessLimiter(this.settings.brightnessLimit);
|
||||
}
|
||||
|
||||
// Motion Sickness
|
||||
if (this.settings.motionSickness) {
|
||||
this.enableMotionSicknessMode();
|
||||
}
|
||||
}
|
||||
|
||||
saveSettings() {
|
||||
localStorage.setItem('novafarma_accessibility', JSON.stringify(this.settings));
|
||||
console.log('💾 Accessibility settings saved');
|
||||
}
|
||||
|
||||
loadSettings() {
|
||||
const saved = localStorage.getItem('novafarma_accessibility');
|
||||
if (saved) {
|
||||
this.settings = JSON.parse(saved);
|
||||
console.log('📂 Accessibility settings loaded');
|
||||
}
|
||||
}
|
||||
|
||||
// EPILEPSY WARNING
|
||||
showEpilepsyWarning(onContinue) {
|
||||
const warning = this.scene.add.container(
|
||||
this.scene.cameras.main.centerX,
|
||||
this.scene.cameras.main.centerY
|
||||
);
|
||||
warning.setDepth(10000);
|
||||
warning.setScrollFactor(0);
|
||||
|
||||
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\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, 100, '[ ENABLE PROTECTION ]', {
|
||||
fontSize: '20px',
|
||||
color: '#00ff00',
|
||||
backgroundColor: '#003300',
|
||||
padding: { x: 20, y: 10 }
|
||||
}).setOrigin(0.5);
|
||||
|
||||
enableBtn.setInteractive({ useHandCursor: true });
|
||||
enableBtn.on('pointerdown', () => {
|
||||
this.settings.photosensitivity = true;
|
||||
this.applySettings();
|
||||
this.saveSettings();
|
||||
warning.destroy();
|
||||
if (onContinue) onContinue();
|
||||
});
|
||||
|
||||
const continueBtn = this.scene.add.text(0, 150, '[ CONTINUE WITHOUT ]', {
|
||||
fontSize: '16px',
|
||||
color: '#888888'
|
||||
}).setOrigin(0.5);
|
||||
|
||||
continueBtn.setInteractive({ useHandCursor: true });
|
||||
continueBtn.on('pointerdown', () => {
|
||||
warning.destroy();
|
||||
if (onContinue) onContinue();
|
||||
});
|
||||
|
||||
warning.add([bg, title, text, enableBtn, continueBtn]);
|
||||
|
||||
return warning;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user