This commit is contained in:
2025-12-13 01:29:24 +01:00
parent f6450cd3b8
commit c618f3d7fa
13 changed files with 1195 additions and 72 deletions

View File

@@ -41,8 +41,8 @@ ErrorHandler.init();
// Phaser Game Configuration
const config = {
type: Phaser.CANVAS, // Canvas renderer za pixel-perfect ostrino
width: 640, // Pixel Art Viewport
height: 360, // Pixel Art Viewport (16:9)
width: 1024, // Larger viewport for better view
height: 768, // 4:3 aspect ratio
parent: 'game-container',
backgroundColor: '#1a1a2e',
pixelArt: true,

View File

@@ -2185,54 +2185,54 @@ class UIScene extends Phaser.Scene {
createZombieStatsPanel() {
const panelWidth = 180;
const panelHeight = 130;
const x = 20;
const y = 120; // Below player stats
const x = this.scale.width - panelWidth - 20; // RIGHT SIDE
const y = 200; // Below minimap
// Container
this.zombieStatsContainer = this.add.container(x, y);
this.zombieStatsContainer.setDepth(1000);
// Background
// Background - FARM THEME
const bg = this.add.graphics();
bg.fillStyle(0x1a1a2e, 0.9);
bg.fillStyle(0x4a3520, 0.9); // Brown wood
bg.fillRect(0, 0, panelWidth, panelHeight);
bg.lineStyle(2, 0x8a2be2, 0.8); // Purple border
bg.lineStyle(3, 0x8B4513, 0.8); // Saddle brown
bg.strokeRect(0, 0, panelWidth, panelHeight);
this.zombieStatsContainer.add(bg);
// Title
const title = this.add.text(panelWidth / 2, 12, '🧟 ZOMBIE', {
fontSize: '12px',
fontFamily: 'Courier New',
fill: '#8a2be2',
const title = this.add.text(panelWidth / 2, 12, '🧟 WORKER', {
fontSize: '14px',
fontFamily: 'Arial',
fill: '#FFD700',
fontStyle: 'bold'
}).setOrigin(0.5);
this.zombieStatsContainer.add(title);
// Stats Text
this.zombieNameText = this.add.text(8, 30, 'Name: Worker #1', {
fontSize: '10px',
this.zombieNameText = this.add.text(8, 35, 'Name: Worker #1', {
fontSize: '11px',
fill: '#ffffff'
});
this.zombieStatsContainer.add(this.zombieNameText);
this.zombieTaskText = this.add.text(8, 48, 'Task: IDLE', {
fontSize: '10px',
fill: '#ffff00'
this.zombieTaskText = this.add.text(8, 53, 'Task: IDLE', {
fontSize: '11px',
fill: '#90EE90'
});
this.zombieStatsContainer.add(this.zombieTaskText);
this.zombieLevelText = this.add.text(8, 66, 'Level: 1 (0/100 XP)', {
fontSize: '10px',
fill: '#00ff00'
this.zombieLevelText = this.add.text(8, 71, 'Level: 1 (0/100 XP)', {
fontSize: '11px',
fill: '#FFD700'
});
this.zombieStatsContainer.add(this.zombieLevelText);
// Energy Bar
const energyLabel = this.add.text(8, 84, 'ENERGY:', { fontSize: '9px', fill: '#aaaaaa' });
const energyLabel = this.add.text(8, 89, 'ENERGY:', { fontSize: '10px', fill: '#cccccc' });
this.zombieStatsContainer.add(energyLabel);
this.zombieEnergyBar = this.drawMiniBar(8, 98, panelWidth - 16, 12, 0x00aaff, 100);
this.zombieEnergyBar = this.drawMiniBar(8, 103, panelWidth - 16, 12, 0x90EE90, 100);
this.zombieStatsContainer.add(this.zombieEnergyBar.bg);
this.zombieStatsContainer.add(this.zombieEnergyBar.fill);
@@ -2243,51 +2243,51 @@ class UIScene extends Phaser.Scene {
createFarmStatsPanel() {
const panelWidth = 180;
const panelHeight = 110;
const x = 20;
const y = 270; // Below zombie stats
const x = this.scale.width - panelWidth - 20; // RIGHT SIDE
const y = 350; // Below zombie stats
// Container
this.farmStatsContainer = this.add.container(x, y);
this.farmStatsContainer.setDepth(1000);
// Background
// Background - FARM THEME
const bg = this.add.graphics();
bg.fillStyle(0x1a2e1a, 0.9);
bg.fillStyle(0x2a4a2a, 0.9); // Dark green
bg.fillRect(0, 0, panelWidth, panelHeight);
bg.lineStyle(2, 0x00ff00, 0.8); // Green border
bg.lineStyle(3, 0x90EE90, 0.8); // Light green border
bg.strokeRect(0, 0, panelWidth, panelHeight);
this.farmStatsContainer.add(bg);
// Title
const title = this.add.text(panelWidth / 2, 12, '🌾 FARM', {
fontSize: '12px',
fontFamily: 'Courier New',
fill: '#00ff00',
fontSize: '14px',
fontFamily: 'Arial',
fill: '#90EE90',
fontStyle: 'bold'
}).setOrigin(0.5);
this.farmStatsContainer.add(title);
// Stats
this.farmCropsPlantedText = this.add.text(8, 32, 'Planted: 0', {
fontSize: '10px',
this.farmCropsPlantedText = this.add.text(8, 35, 'Planted: 0', {
fontSize: '11px',
fill: '#ffffff'
});
this.farmStatsContainer.add(this.farmCropsPlantedText);
this.farmCropsHarvestedText = this.add.text(8, 50, 'Harvested: 0', {
fontSize: '10px',
fill: '#ffff00'
this.farmCropsHarvestedText = this.add.text(8, 53, 'Harvested: 0', {
fontSize: '11px',
fill: '#FFD700'
});
this.farmStatsContainer.add(this.farmCropsHarvestedText);
this.farmGoldEarnedText = this.add.text(8, 68, 'Gold: 0g', {
fontSize: '10px',
fill: '#ffd700'
this.farmGoldEarnedText = this.add.text(8, 71, 'Gold: 0g', {
fontSize: '11px',
fill: '#FFD700'
});
this.farmStatsContainer.add(this.farmGoldEarnedText);
this.farmDaysText = this.add.text(8, 86, 'Days: 0', {
fontSize: '10px',
this.farmDaysText = this.add.text(8, 89, 'Days: 0', {
fontSize: '11px',
fill: '#aaaaaa'
});
this.farmStatsContainer.add(this.farmDaysText);
@@ -2490,47 +2490,50 @@ class UIScene extends Phaser.Scene {
// Equipment Preview
createEquipmentPreview() {
const previewX = 20;
const previewY = 150;
const previewY = 400; // MOVED LOWER (was 150)
// Background
// Background - SMALLER
this.equipmentBg = this.add.graphics();
this.equipmentBg.fillStyle(0x000000, 0.6);
this.equipmentBg.fillRoundedRect(previewX, previewY, 80, 80, 8);
this.equipmentBg.fillStyle(0x4a3520, 0.8); // Brown wood color
this.equipmentBg.fillRoundedRect(previewX, previewY, 60, 60, 8); // 60x60 (was 80x80)
this.equipmentBg.lineStyle(2, 0x8B4513, 1);
this.equipmentBg.strokeRoundedRect(previewX, previewY, 60, 60, 8);
this.equipmentBg.setScrollFactor(0);
this.equipmentBg.setDepth(1000);
// Label
// Label - SMALLER
this.equipmentLabel = this.add.text(
previewX + 40,
previewX + 30,
previewY - 5,
'EQUIPPED',
'TOOL',
{
font: 'bold 10px Arial',
fill: '#ffff00'
font: 'bold 9px Arial',
fill: '#FFD700'
}
);
this.equipmentLabel.setOrigin(0.5, 1);
this.equipmentLabel.setScrollFactor(0);
this.equipmentLabel.setDepth(1001);
// Icon sprite placeholder
this.equipmentIcon = this.add.rectangle(previewX + 40, previewY + 40, 32, 32, 0x888888);
// Icon sprite placeholder - SMALLER
this.equipmentIcon = this.add.rectangle(previewX + 30, previewY + 30, 24, 24, 0x888888);
this.equipmentIcon.setScrollFactor(0);
this.equipmentIcon.setDepth(1001);
// Tool name
// Tool name - HIDDEN (too much text)
this.equipmentName = this.add.text(
previewX + 40,
previewY + 75,
'None',
previewX + 30,
previewY + 50,
'',
{
font: 'bold 12px Arial',
font: 'bold 8px Arial',
fill: '#ffffff'
}
);
this.equipmentName.setOrigin(0.5, 0);
this.equipmentName.setScrollFactor(0);
this.equipmentName.setDepth(1001);
this.equipmentName.setVisible(false); // HIDDEN
console.log('🎮 Equipment preview created!');
}

View File

@@ -283,42 +283,53 @@ class AccessibilitySystem {
// EPILEPSY WARNING
showEpilepsyWarning(onContinue) {
const warning = this.scene.add.container(
this.scene.cameras.main.centerX,
this.scene.cameras.main.centerY
// 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(10000);
warning.setDepth(99999); // ALWAYS ON TOP
warning.setScrollFactor(0);
const bg = this.scene.add.rectangle(0, 0, 600, 400, 0x000000, 0.95);
// Dark background overlay
const bg = uiScene.add.rectangle(0, 0, 700, 500, 0x000000, 0.98);
bg.setStrokeStyle(4, 0xff0000);
const title = this.scene.add.text(0, -150, '⚠️ EPILEPSY WARNING', {
fontSize: '32px',
const title = uiScene.add.text(0, -180, '⚠️ EPILEPSY WARNING', {
fontSize: '36px',
color: '#ff0000',
fontStyle: 'bold'
fontStyle: 'bold',
stroke: '#000000',
strokeThickness: 4
}).setOrigin(0.5);
const text = this.scene.add.text(0, -50,
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: '18px',
fontSize: '20px',
color: '#ffffff',
align: 'center',
wordWrap: { width: 500 }
wordWrap: { width: 600 },
lineSpacing: 8
}
).setOrigin(0.5);
const enableBtn = this.scene.add.text(0, 100, '[ ENABLE PROTECTION ]', {
fontSize: '20px',
const enableBtn = uiScene.add.text(0, 120, '[ ENABLE PROTECTION ]', {
fontSize: '24px',
color: '#00ff00',
backgroundColor: '#003300',
padding: { x: 20, y: 10 }
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();
@@ -327,12 +338,16 @@ class AccessibilitySystem {
if (onContinue) onContinue();
});
const continueBtn = this.scene.add.text(0, 150, '[ CONTINUE WITHOUT ]', {
fontSize: '16px',
color: '#888888'
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();

View File

@@ -0,0 +1,359 @@
/**
* CENTRAL POPUP SYSTEM
* Displays important messages, quests, and dialogs in center of screen
* Always appears in front of player for easy reading
*/
class CentralPopupSystem {
constructor(scene) {
this.scene = scene;
this.enabled = true;
// Current popup
this.currentPopup = null;
this.popupQueue = [];
this.isShowing = false;
// Settings
this.settings = {
enabled: true,
autoClose: true,
autoCloseDelay: 5000, // 5 seconds
pauseGameOnPopup: true,
soundOnPopup: true
};
this.loadSettings();
console.log('✅ Central Popup System initialized');
}
/**
* Show popup in center of screen
*/
showPopup(config) {
const popup = {
title: config.title || 'Notification',
message: config.message || '',
type: config.type || 'info', // info, quest, warning, success, story
icon: config.icon || '📋',
buttons: config.buttons || [{ text: 'OK', action: 'close' }],
image: config.image || null,
autoClose: config.autoClose !== undefined ? config.autoClose : this.settings.autoClose,
onClose: config.onClose || null,
priority: config.priority || 'normal' // low, normal, high, critical
};
// Add to queue
this.popupQueue.push(popup);
// Show if not already showing
if (!this.isShowing) {
this.displayNextPopup();
}
}
/**
* Display next popup from queue
*/
displayNextPopup() {
if (this.popupQueue.length === 0) {
this.isShowing = false;
return;
}
this.isShowing = true;
const popup = this.popupQueue.shift();
// Get UIScene
const uiScene = this.scene.scene.get('UIScene');
if (!uiScene) return;
// Pause game if needed
if (this.settings.pauseGameOnPopup) {
this.scene.physics.pause();
}
// Create popup container
const centerX = uiScene.scale.width / 2;
const centerY = uiScene.scale.height / 2;
this.currentPopup = uiScene.add.container(centerX, centerY);
this.currentPopup.setDepth(10000); // Always on top
this.currentPopup.setScrollFactor(0);
// Popup size based on type
const width = popup.type === 'story' ? 600 : 500;
const height = popup.type === 'story' ? 400 : 300;
// Background overlay (darken screen)
const overlay = uiScene.add.rectangle(0, 0, uiScene.scale.width * 2, uiScene.scale.height * 2, 0x000000, 0.7);
overlay.setOrigin(0.5);
this.currentPopup.add(overlay);
// Main popup background
const bg = uiScene.add.graphics();
// Color based on type
let bgColor = 0x2a2a3e;
let borderColor = 0x4e4e6e;
if (popup.type === 'quest') {
bgColor = 0x3a2a1e;
borderColor = 0xFFD700;
} else if (popup.type === 'warning') {
bgColor = 0x3e2a2a;
borderColor = 0xff4444;
} else if (popup.type === 'success') {
bgColor = 0x2a3e2a;
borderColor = 0x44ff44;
} else if (popup.type === 'story') {
bgColor = 0x1a1a2e;
borderColor = 0x8888ff;
}
// Draw background with rounded corners
bg.fillStyle(bgColor, 0.95);
bg.fillRoundedRect(-width / 2, -height / 2, width, height, 16);
bg.lineStyle(4, borderColor, 1);
bg.strokeRoundedRect(-width / 2, -height / 2, width, height, 16);
this.currentPopup.add(bg);
// Icon
const iconText = uiScene.add.text(-width / 2 + 30, -height / 2 + 30, popup.icon, {
fontSize: '48px'
});
this.currentPopup.add(iconText);
// Title
const title = uiScene.add.text(0, -height / 2 + 50, popup.title, {
fontSize: '28px',
fontFamily: 'Arial',
fill: '#ffffff',
fontStyle: 'bold',
align: 'center'
}).setOrigin(0.5);
this.currentPopup.add(title);
// Separator line
const separator = uiScene.add.graphics();
separator.lineStyle(2, borderColor, 0.5);
separator.lineBetween(-width / 2 + 20, -height / 2 + 90, width / 2 - 20, -height / 2 + 90);
this.currentPopup.add(separator);
// Message
const message = uiScene.add.text(0, -height / 2 + 150, popup.message, {
fontSize: '18px',
fontFamily: 'Arial',
fill: '#dddddd',
align: 'center',
wordWrap: { width: width - 80 }
}).setOrigin(0.5, 0);
this.currentPopup.add(message);
// Image (if provided)
if (popup.image) {
const img = uiScene.add.image(0, -height / 2 + 120, popup.image);
img.setScale(0.5);
this.currentPopup.add(img);
}
// Buttons
const buttonY = height / 2 - 50;
const buttonSpacing = 150;
const buttonStartX = -(popup.buttons.length - 1) * buttonSpacing / 2;
popup.buttons.forEach((btn, index) => {
const btnX = buttonStartX + index * buttonSpacing;
// Button background
const btnBg = uiScene.add.graphics();
btnBg.fillStyle(0x4a4a6e, 1);
btnBg.fillRoundedRect(btnX - 60, buttonY - 20, 120, 40, 8);
btnBg.lineStyle(2, borderColor, 1);
btnBg.strokeRoundedRect(btnX - 60, buttonY - 20, 120, 40, 8);
btnBg.setInteractive(
new Phaser.Geom.Rectangle(btnX - 60, buttonY - 20, 120, 40),
Phaser.Geom.Rectangle.Contains
);
// Hover effect
btnBg.on('pointerover', () => {
btnBg.clear();
btnBg.fillStyle(0x6a6a8e, 1);
btnBg.fillRoundedRect(btnX - 60, buttonY - 20, 120, 40, 8);
btnBg.lineStyle(2, borderColor, 1);
btnBg.strokeRoundedRect(btnX - 60, buttonY - 20, 120, 40, 8);
});
btnBg.on('pointerout', () => {
btnBg.clear();
btnBg.fillStyle(0x4a4a6e, 1);
btnBg.fillRoundedRect(btnX - 60, buttonY - 20, 120, 40, 8);
btnBg.lineStyle(2, borderColor, 1);
btnBg.strokeRoundedRect(btnX - 60, buttonY - 20, 120, 40, 8);
});
// Click handler
btnBg.on('pointerdown', () => {
if (btn.action === 'close') {
this.closePopup(popup);
} else if (btn.callback) {
btn.callback();
this.closePopup(popup);
}
});
this.currentPopup.add(btnBg);
// Button text
const btnText = uiScene.add.text(btnX, buttonY, btn.text, {
fontSize: '18px',
fontFamily: 'Arial',
fill: '#ffffff',
fontStyle: 'bold'
}).setOrigin(0.5);
this.currentPopup.add(btnText);
});
// Auto-close timer
if (popup.autoClose && this.settings.autoClose) {
uiScene.time.delayedCall(this.settings.autoCloseDelay, () => {
this.closePopup(popup);
});
}
// Play sound
if (this.settings.soundOnPopup && this.scene.soundManager) {
this.scene.soundManager.beepPickup();
}
// Animate in
this.currentPopup.setScale(0.8);
this.currentPopup.setAlpha(0);
uiScene.tweens.add({
targets: this.currentPopup,
scale: 1,
alpha: 1,
duration: 300,
ease: 'Back.easeOut'
});
console.log(`📋 Popup shown: ${popup.title}`);
}
/**
* Close current popup
*/
closePopup(popup) {
if (!this.currentPopup) return;
const uiScene = this.scene.scene.get('UIScene');
if (!uiScene) return;
// Animate out
uiScene.tweens.add({
targets: this.currentPopup,
scale: 0.8,
alpha: 0,
duration: 200,
ease: 'Power2',
onComplete: () => {
this.currentPopup.destroy();
this.currentPopup = null;
// Resume game
if (this.settings.pauseGameOnPopup) {
this.scene.physics.resume();
}
// Call onClose callback
if (popup.onClose) {
popup.onClose();
}
// Show next popup
this.displayNextPopup();
}
});
}
/**
* Show quest popup
*/
showQuest(title, description, objectives) {
this.showPopup({
title: title,
message: description + '\n\nObjectives:\n' + objectives.map((obj, i) => `${i + 1}. ${obj}`).join('\n'),
type: 'quest',
icon: '📜',
buttons: [
{ text: 'Accept', action: 'close' },
{ text: 'Decline', action: 'close' }
],
autoClose: false
});
}
/**
* Show story popup
*/
showStory(title, text, image = null) {
this.showPopup({
title: title,
message: text,
type: 'story',
icon: '📖',
image: image,
buttons: [{ text: 'Continue', action: 'close' }],
autoClose: false
});
}
/**
* Show notification
*/
showNotification(message, type = 'info') {
const icons = {
'info': '',
'success': '✅',
'warning': '⚠️',
'error': '❌'
};
this.showPopup({
title: type.charAt(0).toUpperCase() + type.slice(1),
message: message,
type: type,
icon: icons[type] || '',
buttons: [{ text: 'OK', action: 'close' }],
autoClose: true
});
}
/**
* Save settings
*/
saveSettings() {
localStorage.setItem('novafarma_popup_settings', JSON.stringify(this.settings));
}
/**
* Load settings
*/
loadSettings() {
const saved = localStorage.getItem('novafarma_popup_settings');
if (saved) {
this.settings = { ...this.settings, ...JSON.parse(saved) };
}
}
/**
* Destroy system
*/
destroy() {
if (this.currentPopup) {
this.currentPopup.destroy();
}
this.popupQueue = [];
console.log('📋 Central Popup System destroyed');
}
}