361 lines
11 KiB
JavaScript
361 lines
11 KiB
JavaScript
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) {
|
|
// Get UIScene for proper positioning
|
|
const uiScene = this.scene.scene.get('UIScene') || this.scene;
|
|
|
|
const warning = uiScene.add.container(
|
|
uiScene.scale.width / 2,
|
|
uiScene.scale.height / 2
|
|
);
|
|
warning.setDepth(99999); // ALWAYS ON TOP
|
|
warning.setScrollFactor(0);
|
|
|
|
// Dark background overlay
|
|
const bg = uiScene.add.rectangle(0, 0, 700, 500, 0x000000, 0.98);
|
|
bg.setStrokeStyle(4, 0xff0000);
|
|
|
|
const title = uiScene.add.text(0, -180, '⚠️ EPILEPSY WARNING', {
|
|
fontSize: '36px',
|
|
color: '#ff0000',
|
|
fontStyle: 'bold',
|
|
stroke: '#000000',
|
|
strokeThickness: 4
|
|
}).setOrigin(0.5);
|
|
|
|
const text = uiScene.add.text(0, -60,
|
|
'This game contains flashing lights\n' +
|
|
'that may trigger seizures in people with\n' +
|
|
'photosensitive epilepsy.\n\n' +
|
|
'Player discretion is advised.',
|
|
{
|
|
fontSize: '20px',
|
|
color: '#ffffff',
|
|
align: 'center',
|
|
wordWrap: { width: 600 },
|
|
lineSpacing: 8
|
|
}
|
|
).setOrigin(0.5);
|
|
|
|
const enableBtn = uiScene.add.text(0, 120, '[ ENABLE PROTECTION ]', {
|
|
fontSize: '24px',
|
|
color: '#00ff00',
|
|
backgroundColor: '#003300',
|
|
padding: { x: 30, y: 15 },
|
|
fontStyle: 'bold'
|
|
}).setOrigin(0.5);
|
|
|
|
enableBtn.setInteractive({ useHandCursor: true });
|
|
enableBtn.on('pointerover', () => enableBtn.setScale(1.1));
|
|
enableBtn.on('pointerout', () => enableBtn.setScale(1.0));
|
|
enableBtn.on('pointerdown', () => {
|
|
this.settings.photosensitivity = true;
|
|
this.applySettings();
|
|
this.saveSettings();
|
|
warning.destroy();
|
|
if (onContinue) onContinue();
|
|
});
|
|
|
|
const continueBtn = uiScene.add.text(0, 180, '[ CONTINUE WITHOUT ]', {
|
|
fontSize: '18px',
|
|
color: '#888888',
|
|
backgroundColor: '#222222',
|
|
padding: { x: 20, y: 10 }
|
|
}).setOrigin(0.5);
|
|
|
|
continueBtn.setInteractive({ useHandCursor: true });
|
|
continueBtn.on('pointerover', () => continueBtn.setScale(1.1));
|
|
continueBtn.on('pointerout', () => continueBtn.setScale(1.0));
|
|
continueBtn.on('pointerdown', () => {
|
|
warning.destroy();
|
|
if (onContinue) onContinue();
|
|
});
|
|
|
|
warning.add([bg, title, text, enableBtn, continueBtn]);
|
|
|
|
return warning;
|
|
}
|
|
}
|