posodobitve

This commit is contained in:
2025-12-12 13:40:51 +01:00
parent a210638002
commit 6c583a6576
32 changed files with 6586 additions and 703 deletions

View 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;
}
}

320
src/systems/CameraSystem.js Normal file
View File

@@ -0,0 +1,320 @@
class CameraSystem {
constructor(scene) {
this.scene = scene;
this.camera = scene.cameras.main;
// Camera modes
this.mode = 'follow'; // 'follow', 'free', 'cinematic', 'screenshot'
// Free camera controls
this.freeCamSpeed = 5;
this.freeCamZoom = 1.0;
// Cinematic mode
this.cinematicPath = [];
this.cinematicIndex = 0;
this.cinematicPlaying = false;
// Screenshot mode
this.screenshotMode = false;
this.uiHidden = false;
// Saved camera positions
this.savedPositions = [];
this.setupControls();
console.log('📷 CameraSystem: Initialized');
}
setupControls() {
// F6 - Free Camera Mode
this.scene.input.keyboard.on('keydown-F6', () => {
this.toggleFreeCamera();
});
// F7 - Screenshot Mode (hide UI)
this.scene.input.keyboard.on('keydown-F7', () => {
this.toggleScreenshotMode();
});
// F8 - Save Camera Position
this.scene.input.keyboard.on('keydown-F8', () => {
this.saveCameraPosition();
});
// F9 - Cinematic Mode
this.scene.input.keyboard.on('keydown-F10', () => {
this.toggleCinematicMode();
});
// Arrow keys for free camera
this.cursors = this.scene.input.keyboard.createCursorKeys();
// Page Up/Down for zoom
this.scene.input.keyboard.on('keydown-PAGEUP', () => {
this.adjustZoom(0.1);
});
this.scene.input.keyboard.on('keydown-PAGEDOWN', () => {
this.adjustZoom(-0.1);
});
}
// FREE CAMERA MODE
toggleFreeCamera() {
if (this.mode === 'free') {
this.mode = 'follow';
this.camera.startFollow(this.scene.player.sprite);
console.log('📷 Camera: Follow mode');
} else {
this.mode = 'free';
this.camera.stopFollow();
console.log('📷 Camera: Free mode (Arrow keys to move, PgUp/PgDn to zoom)');
}
}
updateFreeCamera(delta) {
if (this.mode !== 'free') return;
const speed = this.freeCamSpeed * (delta / 16);
if (this.cursors.left.isDown) {
this.camera.scrollX -= speed;
}
if (this.cursors.right.isDown) {
this.camera.scrollX += speed;
}
if (this.cursors.up.isDown) {
this.camera.scrollY -= speed;
}
if (this.cursors.down.isDown) {
this.camera.scrollY += speed;
}
}
adjustZoom(delta) {
this.freeCamZoom = Phaser.Math.Clamp(this.freeCamZoom + delta, 0.3, 3.0);
this.camera.setZoom(this.freeCamZoom);
console.log(`📷 Zoom: ${this.freeCamZoom.toFixed(2)}x`);
}
// SCREENSHOT MODE
toggleScreenshotMode() {
this.screenshotMode = !this.screenshotMode;
const uiScene = this.scene.scene.get('UIScene');
if (!uiScene) return;
if (this.screenshotMode) {
// Hide all UI
uiScene.children.list.forEach(child => {
if (child.setVisible) {
child.wasVisible = child.visible;
child.setVisible(false);
}
});
this.uiHidden = true;
console.log('📷 Screenshot mode: UI hidden (F7 to restore)');
} else {
// Restore UI
uiScene.children.list.forEach(child => {
if (child.setVisible && child.wasVisible !== undefined) {
child.setVisible(child.wasVisible);
}
});
this.uiHidden = false;
console.log('📷 Screenshot mode: UI restored');
}
}
// SAVE CAMERA POSITION
saveCameraPosition() {
const pos = {
x: this.camera.scrollX,
y: this.camera.scrollY,
zoom: this.camera.zoom
};
this.savedPositions.push(pos);
console.log(`📷 Camera position saved (${this.savedPositions.length}): x=${pos.x.toFixed(0)}, y=${pos.y.toFixed(0)}, zoom=${pos.zoom.toFixed(2)}`);
}
loadCameraPosition(index) {
if (index < 0 || index >= this.savedPositions.length) return;
const pos = this.savedPositions[index];
this.scene.tweens.add({
targets: this.camera,
scrollX: pos.x,
scrollY: pos.y,
zoom: pos.zoom,
duration: 1000,
ease: 'Sine.easeInOut'
});
console.log(`📷 Camera position loaded (${index + 1})`);
}
// CINEMATIC MODE
toggleCinematicMode() {
if (this.cinematicPlaying) {
this.stopCinematic();
} else {
this.startCinematic();
}
}
startCinematic() {
if (this.savedPositions.length < 2) {
console.log('📷 Need at least 2 saved positions for cinematic!');
return;
}
this.cinematicPlaying = true;
this.cinematicIndex = 0;
this.mode = 'cinematic';
this.playCinematicStep();
console.log('📷 Cinematic mode: Playing...');
}
playCinematicStep() {
if (!this.cinematicPlaying) return;
if (this.cinematicIndex >= this.savedPositions.length) {
this.stopCinematic();
return;
}
const pos = this.savedPositions[this.cinematicIndex];
this.scene.tweens.add({
targets: this.camera,
scrollX: pos.x,
scrollY: pos.y,
zoom: pos.zoom,
duration: 3000,
ease: 'Sine.easeInOut',
onComplete: () => {
this.cinematicIndex++;
this.scene.time.delayedCall(500, () => {
this.playCinematicStep();
});
}
});
}
stopCinematic() {
this.cinematicPlaying = false;
this.mode = 'follow';
this.camera.startFollow(this.scene.player.sprite);
console.log('📷 Cinematic mode: Stopped');
}
// PRESET CAMERA ANGLES
setPresetAngle(preset) {
const presets = {
'overview': { zoom: 0.5, y: -200 },
'closeup': { zoom: 1.5, y: 0 },
'wide': { zoom: 0.3, y: -300 },
'action': { zoom: 1.2, y: -50 }
};
const p = presets[preset];
if (!p) return;
this.scene.tweens.add({
targets: this.camera,
zoom: p.zoom,
scrollY: this.camera.scrollY + p.y,
duration: 1000,
ease: 'Sine.easeInOut'
});
console.log(`📷 Preset angle: ${preset}`);
}
// SHAKE EFFECTS
shake(intensity = 0.005, duration = 200) {
this.camera.shake(duration, intensity);
}
// FLASH EFFECTS
flash(color = 0xffffff, duration = 200) {
this.camera.flash(duration,
(color >> 16) & 0xff,
(color >> 8) & 0xff,
color & 0xff
);
}
// FADE EFFECTS
fadeOut(duration = 1000, callback) {
this.camera.fadeOut(duration, 0, 0, 0);
if (callback) {
this.camera.once('camerafadeoutcomplete', callback);
}
}
fadeIn(duration = 1000, callback) {
this.camera.fadeIn(duration, 0, 0, 0);
if (callback) {
this.camera.once('camerafadeincomplete', callback);
}
}
// PAN TO LOCATION
panTo(x, y, duration = 2000) {
this.scene.tweens.add({
targets: this.camera,
scrollX: x - this.camera.width / 2,
scrollY: y - this.camera.height / 2,
duration: duration,
ease: 'Sine.easeInOut'
});
}
// ZOOM TO
zoomTo(zoom, duration = 1000) {
this.scene.tweens.add({
targets: this.camera,
zoom: zoom,
duration: duration,
ease: 'Sine.easeInOut'
});
}
// UPDATE
update(delta) {
this.updateFreeCamera(delta);
}
// EXPORT CAMERA DATA (for trailer editing)
exportCameraData() {
const data = {
savedPositions: this.savedPositions,
timestamp: Date.now()
};
const json = JSON.stringify(data, null, 2);
console.log('📷 Camera data:', json);
// Copy to clipboard (if available)
if (navigator.clipboard) {
navigator.clipboard.writeText(json);
console.log('📷 Camera data copied to clipboard!');
}
return data;
}
// IMPORT CAMERA DATA
importCameraData(data) {
if (data.savedPositions) {
this.savedPositions = data.savedPositions;
console.log(`📷 Imported ${this.savedPositions.length} camera positions`);
}
}
}

View File

@@ -29,6 +29,11 @@ class LocalizationSystem {
'ui.oxygen': 'Kisik',
'ui.day': 'Dan',
'ui.season': 'Letni čas',
'ui.hp': 'ZDR',
'ui.hun': 'LAK',
'ui.h2o': 'H2O',
'ui.xp': 'IZK',
'ui.lv': 'NIV',
// Items
'item.wood': 'Les',
@@ -49,6 +54,14 @@ class LocalizationSystem {
'season.autumn': 'Jesen',
'season.winter': 'Zima',
// Pause Menu
'pause.title': 'PAVZA',
'pause.resume': '▶ Nadaljuj',
'pause.save': '💾 Shrani igro',
'pause.settings': '⚙️ Nastavitve',
'pause.quit': '🚪 Izhod v meni',
'pause.hint': 'Pritisni ESC za nadaljevanje',
// Messages
'msg.demo_end': 'Demo končan! Hvala za igranje.',
'msg.freezing': '❄️ Zmrzuješ!',
@@ -63,6 +76,11 @@ class LocalizationSystem {
'ui.oxygen': 'Oxygen',
'ui.day': 'Day',
'ui.season': 'Season',
'ui.hp': 'HP',
'ui.hun': 'HUN',
'ui.h2o': 'H2O',
'ui.xp': 'XP',
'ui.lv': 'LV',
// Items
'item.wood': 'Wood',
@@ -83,35 +101,159 @@ class LocalizationSystem {
'season.autumn': 'Autumn',
'season.winter': 'Winter',
// Pause Menu
'pause.title': 'PAUSED',
'pause.resume': '▶ Resume',
'pause.save': '💾 Save Game',
'pause.settings': '⚙️ Settings',
'pause.quit': '🚪 Quit to Menu',
'pause.hint': 'Press ESC to resume',
// Messages
'msg.demo_end': 'Demo Ended! Thanks for playing.',
'msg.freezing': '❄️ Freezing!',
'msg.overheating': '🔥 Overheating!'
},
'de': {
// UI
'ui.inventory': 'Inventar',
'ui.crafting': 'Handwerk',
'ui.health': 'Gesundheit',
'ui.hunger': 'Hunger',
'ui.oxygen': 'Sauerstoff',
'ui.day': 'Tag',
'ui.season': 'Jahreszeit',
'ui.hp': 'LP',
'ui.hun': 'HUN',
'ui.h2o': 'H2O',
'ui.xp': 'EP',
'ui.lv': 'ST',
// Items
'item.wood': 'Holz',
'item.stone': 'Stein',
'item.seeds': 'Samen',
'item.wheat': 'Weizen',
'item.corn': 'Mais',
// Actions
'action.plant': 'Pflanzen',
'action.harvest': 'Ernten',
'action.craft': 'Herstellen',
'action.build': 'Bauen',
// Seasons
'season.spring': 'Frühling',
'season.summer': 'Sommer',
'season.autumn': 'Herbst',
'season.winter': 'Winter'
'season.winter': 'Winter',
// Pause Menu
'pause.title': 'PAUSIERT',
'pause.resume': '▶ Fortsetzen',
'pause.save': '💾 Spiel speichern',
'pause.settings': '⚙️ Einstellungen',
'pause.quit': '🚪 Zum Menü',
'pause.hint': 'ESC drücken zum Fortsetzen',
// Messages
'msg.demo_end': 'Demo beendet! Danke fürs Spielen.',
'msg.freezing': '❄️ Du erfrierst!',
'msg.overheating': '🔥 Überhitzung!'
},
'it': {
// UI
'ui.inventory': 'Inventario',
'ui.crafting': 'Artigianato',
'ui.health': 'Salute',
'ui.hunger': 'Fame',
'ui.oxygen': 'Ossigeno',
'ui.day': 'Giorno',
'ui.season': 'Stagione',
'ui.hp': 'PS',
'ui.hun': 'FAM',
'ui.h2o': 'H2O',
'ui.xp': 'ESP',
'ui.lv': 'LIV',
// Items
'item.wood': 'Legno',
'item.stone': 'Pietra',
'item.seeds': 'Semi',
'item.wheat': 'Grano',
'item.corn': 'Mais',
// Actions
'action.plant': 'Pianta',
'action.harvest': 'Raccogli',
'action.craft': 'Crea',
'action.build': 'Costruisci',
// Seasons
'season.spring': 'Primavera',
'season.summer': 'Estate',
'season.autumn': 'Autunno',
'season.winter': 'Inverno'
'season.winter': 'Inverno',
// Pause Menu
'pause.title': 'IN PAUSA',
'pause.resume': '▶ Riprendi',
'pause.save': '💾 Salva gioco',
'pause.settings': '⚙️ Impostazioni',
'pause.quit': '🚪 Esci al menu',
'pause.hint': 'Premi ESC per riprendere',
// Messages
'msg.demo_end': 'Demo terminata! Grazie per aver giocato.',
'msg.freezing': '❄️ Stai congelando!',
'msg.overheating': '🔥 Surriscaldamento!'
},
'cn': {
// UI
'ui.inventory': '库存',
'ui.crafting': '制作',
'ui.health': '健康',
'ui.hunger': '饥饿',
'ui.oxygen': '氧气',
'ui.day': '天数',
'ui.season': '季节',
'ui.hp': '生命',
'ui.hun': '饥饿',
'ui.h2o': '水',
'ui.xp': '经验',
'ui.lv': '等级',
// Items
'item.wood': '木材',
'item.stone': '石头',
'item.seeds': '种子',
'item.wheat': '小麦',
'item.corn': '玉米',
// Actions
'action.plant': '种植',
'action.harvest': '收获',
'action.craft': '制作',
'action.build': '建造',
// Seasons
'season.spring': '春天',
'season.summer': '夏天',
'season.autumn': '秋天',
'season.winter': '冬天'
'season.winter': '冬天',
// Pause Menu
'pause.title': '暂停',
'pause.resume': '▶ 继续',
'pause.save': '💾 保存游戏',
'pause.settings': '⚙️ 设置',
'pause.quit': '🚪 退出到菜单',
'pause.hint': '按ESC继续',
// Messages
'msg.demo_end': '演示结束!感谢游玩。',
'msg.freezing': '❄️ 你在冻僵!',
'msg.overheating': '🔥 过热!'
}
};
}

View File

@@ -0,0 +1,154 @@
class StaminaSystem {
constructor(scene) {
this.scene = scene;
// Stamina properties
this.maxStamina = 100;
this.currentStamina = 100;
this.regenRate = 5; // Stamina per second
this.regenDelay = 2000; // Wait 2s after use before regen
this.lastUseTime = 0;
// Stamina costs
this.costs = {
'till': 5,
'plant': 3,
'harvest': 4,
'build': 10,
'attack': 8,
'sprint': 2 // per second
};
console.log('⚡ StaminaSystem: Initialized');
}
// Use stamina for action
useStamina(action) {
const cost = this.costs[action] || 0;
if (this.currentStamina < cost) {
console.log(`⚡ Not enough stamina! (${this.currentStamina}/${cost})`);
return false; // Not enough stamina
}
this.currentStamina -= cost;
this.lastUseTime = Date.now();
// Update UI
this.updateUI();
console.log(`⚡ Used ${cost} stamina (${action}). Remaining: ${this.currentStamina}`);
return true;
}
// Restore stamina (from food)
restoreStamina(amount) {
this.currentStamina = Math.min(this.maxStamina, this.currentStamina + amount);
this.updateUI();
console.log(`⚡ Restored ${amount} stamina. Current: ${this.currentStamina}`);
}
// Auto-regenerate stamina
update(delta) {
// Check if enough time has passed since last use
const timeSinceUse = Date.now() - this.lastUseTime;
if (timeSinceUse > this.regenDelay && this.currentStamina < this.maxStamina) {
// Regenerate stamina
const regenAmount = (this.regenRate * delta) / 1000;
this.currentStamina = Math.min(this.maxStamina, this.currentStamina + regenAmount);
// Update UI
this.updateUI();
}
}
// Update stamina bar in UI
updateUI() {
const uiScene = this.scene.scene.get('UIScene');
if (!uiScene) return;
// Update stamina bar (if exists)
if (uiScene.staminaBar) {
const percentage = this.currentStamina / this.maxStamina;
uiScene.staminaBar.clear();
// Background
uiScene.staminaBar.fillStyle(0x000000, 0.5);
uiScene.staminaBar.fillRect(20, 120, 200, 20);
// Stamina fill (yellow)
uiScene.staminaBar.fillStyle(0xffff00, 1.0);
uiScene.staminaBar.fillRect(20, 120, 200 * percentage, 20);
// Border
uiScene.staminaBar.lineStyle(2, 0xffffff, 1.0);
uiScene.staminaBar.strokeRect(20, 120, 200, 20);
}
// Update stamina text
if (uiScene.staminaText) {
uiScene.staminaText.setText(`${Math.floor(this.currentStamina)}/${this.maxStamina}`);
}
}
// Create stamina UI
createUI() {
const uiScene = this.scene.scene.get('UIScene');
if (!uiScene) return;
// Stamina bar (below health)
uiScene.staminaBar = uiScene.add.graphics();
uiScene.staminaBar.setScrollFactor(0);
uiScene.staminaBar.setDepth(1000);
// Stamina text
uiScene.staminaText = uiScene.add.text(
20,
105,
`${this.currentStamina}/${this.maxStamina}`,
{
fontSize: '14px',
color: '#ffff00',
fontStyle: 'bold'
}
);
uiScene.staminaText.setScrollFactor(0);
uiScene.staminaText.setDepth(1001);
// Initial update
this.updateUI();
console.log('⚡ Stamina UI created');
}
// Check if player has enough stamina
hasStamina(action) {
const cost = this.costs[action] || 0;
return this.currentStamina >= cost;
}
// Get stamina percentage (0-1)
getPercentage() {
return this.currentStamina / this.maxStamina;
}
// Save/Load
getSaveData() {
return {
currentStamina: this.currentStamina,
maxStamina: this.maxStamina
};
}
loadSaveData(data) {
if (data.currentStamina !== undefined) {
this.currentStamina = data.currentStamina;
}
if (data.maxStamina !== undefined) {
this.maxStamina = data.maxStamina;
}
this.updateUI();
}
}