posodobitev
This commit is contained in:
@@ -41,12 +41,31 @@ class GameScene extends Phaser.Scene {
|
||||
this.expansionSystem = new ExpansionSystem(this);
|
||||
this.blueprintSystem = new BlueprintSystem(this);
|
||||
|
||||
// Farm Stats Tracking for UI
|
||||
this.farmStats = {
|
||||
cropsPlanted: 0,
|
||||
totalHarvested: 0,
|
||||
goldEarned: 0,
|
||||
daysFarmed: 0
|
||||
};
|
||||
|
||||
// PARALLAX BACKGROUND - Clouds & Birds
|
||||
this.createParallaxBackground();
|
||||
|
||||
// Inicializiraj terrain sistem - 100x100 mapa
|
||||
console.log('🌍 Initializing terrain...');
|
||||
try {
|
||||
this.terrainSystem = new TerrainSystem(this, 100, 100);
|
||||
this.terrainSystem.generate();
|
||||
|
||||
// Initialize Farming System
|
||||
this.farmingSystem = new FarmingSystem(this);
|
||||
console.log('🌾 Farming system initialized!');
|
||||
|
||||
// Initialize Build System
|
||||
this.buildSystem = new BuildSystem(this);
|
||||
console.log('🏗️ Build system initialized!');
|
||||
|
||||
// Terrain offset
|
||||
this.terrainOffsetX = width / 2;
|
||||
this.terrainOffsetY = 100;
|
||||
@@ -176,6 +195,24 @@ class GameScene extends Phaser.Scene {
|
||||
console.log('🧟⚒️ Initializing Zombie Worker System...');
|
||||
this.zombieWorkerSystem = new ZombieWorkerSystem(this);
|
||||
|
||||
// SPAWN STARTER ZOMBIE WORKER (8x8 Farm)
|
||||
console.log('🧟 Spawning STARTER Zombie Worker...');
|
||||
const starterZombieX = 48; // Inside 8x8 farm (center is 50,50, farm is 46-54)
|
||||
const starterZombieY = 48;
|
||||
const starterZombie = new NPC(this, starterZombieX, starterZombieY, this.terrainOffsetX, this.terrainOffsetY, 'zombie');
|
||||
// Auto-tame the starter zombie
|
||||
starterZombie.isTamed = true; // Use isTamed (not just tamed)
|
||||
starterZombie.state = 'IDLE';
|
||||
if (starterZombie.showEmote) {
|
||||
starterZombie.showEmote('👋'); // Friendly wave
|
||||
}
|
||||
this.npcs.push(starterZombie);
|
||||
// Assign to farming work
|
||||
if (this.zombieWorkerSystem) {
|
||||
this.zombieWorkerSystem.assignWork(starterZombie, 'FARM', 5); // Farming work, 5 tile radius
|
||||
}
|
||||
console.log('✅ Starter zombie worker spawned and assigned to farming!');
|
||||
|
||||
// GRAVE SYSTEM
|
||||
console.log('🪦 Initializing Grave System...');
|
||||
this.graveSystem = new GraveSystem(this);
|
||||
@@ -495,24 +532,34 @@ class GameScene extends Phaser.Scene {
|
||||
|
||||
// Build Mode Keys
|
||||
this.input.keyboard.on('keydown-B', () => {
|
||||
if (this.buildingSystem) this.buildingSystem.toggleBuildMode();
|
||||
if (this.buildSystem) this.buildSystem.toggleBuildMode();
|
||||
});
|
||||
|
||||
this.input.keyboard.on('keydown-ONE', () => {
|
||||
if (this.buildingSystem && this.buildingSystem.isBuildMode) this.buildingSystem.selectBuilding('fence');
|
||||
if (this.buildSystem && this.buildSystem.buildMode) this.buildSystem.selectBuilding('fence_post');
|
||||
else if (this.scene.get('UIScene')) this.scene.get('UIScene').selectSlot(0);
|
||||
});
|
||||
|
||||
this.input.keyboard.on('keydown-TWO', () => {
|
||||
if (this.buildingSystem && this.buildingSystem.isBuildMode) this.buildingSystem.selectBuilding('wall');
|
||||
if (this.buildSystem && this.buildSystem.buildMode) this.buildSystem.selectBuilding('fence_horizontal');
|
||||
else if (this.scene.get('UIScene')) this.scene.get('UIScene').selectSlot(1);
|
||||
});
|
||||
|
||||
this.input.keyboard.on('keydown-THREE', () => {
|
||||
if (this.buildingSystem && this.buildingSystem.isBuildMode) this.buildingSystem.selectBuilding('house');
|
||||
if (this.buildSystem && this.buildSystem.buildMode) this.buildSystem.selectBuilding('fence_vertical');
|
||||
else if (this.scene.get('UIScene')) this.scene.get('UIScene').selectSlot(2);
|
||||
});
|
||||
|
||||
this.input.keyboard.on('keydown-FOUR', () => {
|
||||
if (this.buildSystem && this.buildSystem.buildMode) this.buildSystem.selectBuilding('fence_corner');
|
||||
else if (this.scene.get('UIScene')) this.scene.get('UIScene').selectSlot(3);
|
||||
});
|
||||
|
||||
this.input.keyboard.on('keydown-FIVE', () => {
|
||||
if (this.buildSystem && this.buildSystem.buildMode) this.buildSystem.selectBuilding('barn');
|
||||
else if (this.scene.get('UIScene')) this.scene.get('UIScene').selectSlot(4);
|
||||
});
|
||||
|
||||
// Soft Reset (F4)
|
||||
this.input.keyboard.on('keydown-F4', () => window.location.reload());
|
||||
|
||||
@@ -530,6 +577,7 @@ class GameScene extends Phaser.Scene {
|
||||
if (this.lootSystem) this.lootSystem.update(delta);
|
||||
if (this.interactionSystem) this.interactionSystem.update(delta);
|
||||
if (this.farmingSystem) this.farmingSystem.update(delta);
|
||||
if (this.buildSystem) this.buildSystem.update(delta);
|
||||
if (this.questSystem) this.questSystem.update(delta);
|
||||
if (this.multiplayerSystem) this.multiplayerSystem.update(delta);
|
||||
|
||||
@@ -816,6 +864,9 @@ class GameScene extends Phaser.Scene {
|
||||
window.Antigravity.Update(this, delta);
|
||||
}
|
||||
|
||||
// Parallax background update
|
||||
this.updateParallax(delta);
|
||||
|
||||
// Terrain system update (za water animacijo)
|
||||
if (this.terrainSystem && this.terrainSystem.update) {
|
||||
this.terrainSystem.update(Date.now(), delta);
|
||||
@@ -823,4 +874,69 @@ class GameScene extends Phaser.Scene {
|
||||
console.warn('⚠️ TerrainSystem.update not available!');
|
||||
}
|
||||
}
|
||||
|
||||
createParallaxBackground() {
|
||||
const width = this.cameras.main.width;
|
||||
const height = this.cameras.main.height;
|
||||
|
||||
// Parallax container
|
||||
this.parallaxContainer = this.add.container(0, 0);
|
||||
this.parallaxContainer.setDepth(-1000); // Always behind everything
|
||||
|
||||
this.clouds = [];
|
||||
this.birds = [];
|
||||
|
||||
// Create 5 clouds
|
||||
for (let i = 0; i < 5; i++) {
|
||||
const cloud = this.add.text(
|
||||
Math.random() * width * 2,
|
||||
Math.random() * height * 0.5,
|
||||
'☁️',
|
||||
{ fontSize: `${30 + Math.random() * 20}px` }
|
||||
);
|
||||
cloud.speed = 0.3 + Math.random() * 0.2; // 0.3-0.5x speed
|
||||
this.parallaxContainer.add(cloud);
|
||||
this.clouds.push(cloud);
|
||||
}
|
||||
|
||||
// Create 3 birds
|
||||
for (let i = 0; i < 3; i++) {
|
||||
const bird = this.add.text(
|
||||
Math.random() * width * 2,
|
||||
100 + Math.random() * 200,
|
||||
'🐦',
|
||||
{ fontSize: '20px' }
|
||||
);
|
||||
bird.speed = 0.5 + Math.random() * 0.3; // 0.5-0.8x speed
|
||||
this.parallaxContainer.add(bird);
|
||||
this.birds.push(bird);
|
||||
}
|
||||
|
||||
console.log('☁️ Parallax background created!');
|
||||
}
|
||||
|
||||
updateParallax(delta) {
|
||||
if (!this.parallaxContainer) return;
|
||||
|
||||
const width = this.cameras.main.width;
|
||||
|
||||
// Update clouds
|
||||
this.clouds.forEach(cloud => {
|
||||
cloud.x -= cloud.speed * (delta / 16);
|
||||
if (cloud.x < -100) {
|
||||
cloud.x = width + 100;
|
||||
cloud.y = Math.random() * this.cameras.main.height * 0.5;
|
||||
}
|
||||
});
|
||||
|
||||
// Update birds
|
||||
this.birds.forEach(bird => {
|
||||
bird.x -= bird.speed * (delta / 16);
|
||||
bird.y += Math.sin(Date.now() / 1000 + bird.x) * 0.5; // Flutter effect
|
||||
if (bird.x < -100) {
|
||||
bird.x = width + 100;
|
||||
bird.y = 100 + Math.random() * 200;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,12 +78,44 @@ class PreloadScene extends Phaser.Scene {
|
||||
this.load.image('fence_full', 'assets/fence_full.png');
|
||||
this.load.image('wall_damaged', 'assets/wall_damaged.png');
|
||||
|
||||
|
||||
// Voxel stil asset-i (2.5D)
|
||||
this.load.image('tree_voxel_green', 'assets/tree_voxel_green.png');
|
||||
this.load.image('tree_voxel_blue', 'assets/tree_voxel_blue.png');
|
||||
this.load.image('tree_voxel_dead', 'assets/tree_voxel_dead.png');
|
||||
this.load.image('rock_voxel', 'assets/rock_voxel.png');
|
||||
|
||||
// NEW ISOMETRIC 2.5D ASSETS (Stardew Valley style)
|
||||
// Buildings & Structures
|
||||
this.load.image('barn_isometric', 'assets/barn_isometric.png');
|
||||
this.load.image('farmhouse_isometric', 'assets/farmhouse_isometric.png');
|
||||
this.load.image('fence_isometric', 'assets/fence_isometric.png');
|
||||
this.load.image('bridge_isometric', 'assets/bridge_isometric.png');
|
||||
this.load.image('blacksmith_workshop', 'assets/blacksmith_workshop.png');
|
||||
this.load.image('ruins_building', 'assets/ruins_building.png');
|
||||
|
||||
// Farm & Crops
|
||||
this.load.image('soil_tilled', 'assets/soil_tilled.png');
|
||||
this.load.image('carrots_stages', 'assets/carrots_stages.png');
|
||||
this.load.image('flowers_pink_isometric', 'assets/flowers_pink_isometric.png');
|
||||
|
||||
// Characters - SPRITESHEETS (6 frames @ 64x64 each)
|
||||
this.load.spritesheet('player_dreadlocks', 'assets/player_dreadlocks.png', {
|
||||
frameWidth: 64,
|
||||
frameHeight: 64
|
||||
});
|
||||
this.load.spritesheet('zombie_worker', 'assets/zombie_worker.png', {
|
||||
frameWidth: 64,
|
||||
frameHeight: 64
|
||||
});
|
||||
this.load.image('grave_zombie', 'assets/grave_zombie.png');
|
||||
|
||||
// Fence pieces (separate parts)
|
||||
this.load.image('fence_post', 'assets/fence_post.png');
|
||||
this.load.image('fence_horizontal', 'assets/fence_horizontal.png');
|
||||
this.load.image('fence_vertical', 'assets/fence_vertical.png');
|
||||
this.load.image('fence_corner', 'assets/fence_corner.png');
|
||||
|
||||
// Wait for load completion then process transparency
|
||||
this.load.once('complete', () => {
|
||||
this.processAllTransparency();
|
||||
@@ -98,6 +130,7 @@ class PreloadScene extends Phaser.Scene {
|
||||
createAnimations() {
|
||||
if (this.anims.exists('player_walk_anim')) return;
|
||||
|
||||
// Old animations
|
||||
this.anims.create({
|
||||
key: 'player_walk_anim',
|
||||
frames: this.anims.generateFrameNumbers('player_walk', { start: 0, end: 5 }),
|
||||
@@ -111,6 +144,22 @@ class PreloadScene extends Phaser.Scene {
|
||||
frameRate: 8,
|
||||
repeat: -1
|
||||
});
|
||||
|
||||
// NEW: Isometric character animations (6 frames)
|
||||
this.anims.create({
|
||||
key: 'player_dreadlocks_walk',
|
||||
frames: this.anims.generateFrameNumbers('player_dreadlocks', { start: 0, end: 5 }),
|
||||
frameRate: 10,
|
||||
repeat: -1
|
||||
});
|
||||
|
||||
this.anims.create({
|
||||
key: 'zombie_worker_walk',
|
||||
frames: this.anims.generateFrameNumbers('zombie_worker', { start: 0, end: 5 }),
|
||||
frameRate: 8,
|
||||
repeat: -1
|
||||
});
|
||||
|
||||
console.log('🎞️ Animations created!');
|
||||
}
|
||||
|
||||
@@ -162,13 +211,58 @@ class PreloadScene extends Phaser.Scene {
|
||||
'tree_voxel_green',
|
||||
'tree_voxel_blue',
|
||||
'tree_voxel_dead',
|
||||
'rock_voxel'
|
||||
'rock_voxel',
|
||||
|
||||
// NEW ISOMETRIC 2.5D ASSETS - Remove transparency
|
||||
'barn_isometric',
|
||||
'farmhouse_isometric',
|
||||
'fence_isometric',
|
||||
'bridge_isometric',
|
||||
'blacksmith_workshop',
|
||||
'ruins_building',
|
||||
'soil_tilled',
|
||||
'carrots_stages',
|
||||
'flowers_pink_isometric',
|
||||
// NOTE: player_dreadlocks and zombie_worker are SPRITESHEETS - don't process!
|
||||
'grave_zombie',
|
||||
|
||||
// NEW FENCE PIECES
|
||||
'fence_post',
|
||||
'fence_horizontal',
|
||||
'fence_vertical',
|
||||
'fence_corner',
|
||||
|
||||
// ANIMALS & NPCs
|
||||
'chicken',
|
||||
'cow',
|
||||
'cow_mutant',
|
||||
'elf',
|
||||
'troll',
|
||||
'villager',
|
||||
'npc_merchant',
|
||||
'npc_zombie',
|
||||
|
||||
// STRUCTURES
|
||||
'structure_house',
|
||||
'wall_damaged',
|
||||
'city_wall',
|
||||
|
||||
// MISC OBJECTS
|
||||
'wheat_sprite',
|
||||
'grass_sprite',
|
||||
'leaf_sprite',
|
||||
'stone_sprite'
|
||||
];
|
||||
|
||||
spritesToProcess.forEach(spriteKey => {
|
||||
this.processSpriteTransparency(spriteKey);
|
||||
});
|
||||
|
||||
// ULTRA AGGRESSIVE: Fence Post only
|
||||
if (this.textures.exists('fence_post')) {
|
||||
this.ultraRemoveBackground('fence_post');
|
||||
}
|
||||
|
||||
console.log('✅ All sprites transparency processed!');
|
||||
}
|
||||
|
||||
@@ -191,21 +285,45 @@ class PreloadScene extends Phaser.Scene {
|
||||
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||
const data = imageData.data;
|
||||
|
||||
// Remove backgrounds
|
||||
// Remove backgrounds - IMPROVED CHECKBOARD DETECTION
|
||||
for (let i = 0; i < data.length; i += 4) {
|
||||
const r = data[i];
|
||||
const g = data[i + 1];
|
||||
const b = data[i + 2];
|
||||
|
||||
// Remove white/light gray backgrounds (Checkerboard & White)
|
||||
// Target grays: R,G,B should be similar and high value.
|
||||
if (r > 150 && g > 150 && b > 150) {
|
||||
// Check if it's grayscale (checkerboard is usually perfect gray)
|
||||
if (Math.abs(r - g) < 30 && Math.abs(g - b) < 30) {
|
||||
data[i + 3] = 0;
|
||||
// Remove ALL grayscale colors (checkboard pattern)
|
||||
// Checkboard has both light (204,204,204) and dark (153,153,153) squares
|
||||
const isGrayscale = Math.abs(r - g) < 15 && Math.abs(g - b) < 15 && Math.abs(r - b) < 15;
|
||||
|
||||
if (isGrayscale) {
|
||||
// ULTRA-AGGRESSIVE: Remove ALL grays from 100-240
|
||||
const isAnyGray = r >= 100 && r <= 240;
|
||||
|
||||
if (isAnyGray) {
|
||||
data[i + 3] = 0; // Make transparent
|
||||
}
|
||||
}
|
||||
|
||||
// AGGRESSIVE: Remove ALL light backgrounds (AI-generated sprites)
|
||||
const brightness = (r + g + b) / 3;
|
||||
const isVeryLight = brightness > 170 && Math.abs(r - g) < 50 && Math.abs(g - b) < 50;
|
||||
|
||||
if (isVeryLight) {
|
||||
data[i + 3] = 0; // Make transparent
|
||||
}
|
||||
|
||||
// ULTRA AGGRESSIVE: Remove PURE WHITE backgrounds
|
||||
const isWhite = r > 240 && g > 240 && b > 240;
|
||||
if (isWhite) {
|
||||
data[i + 3] = 0; // Make transparent
|
||||
}
|
||||
|
||||
// ULTRA AGGRESSIVE: Remove OFF-WHITE backgrounds (cream, beige)
|
||||
const isOffWhite = brightness > 230 && Math.abs(r - g) < 20 && Math.abs(g - b) < 20;
|
||||
if (isOffWhite) {
|
||||
data[i + 3] = 0; // Make transparent
|
||||
}
|
||||
|
||||
// Special: Remove brown/tan backgrounds (merchant sprite)
|
||||
if (spriteKey === 'merchant_sprite') {
|
||||
// Brown detection: R > G > B, warm tones
|
||||
@@ -360,4 +478,42 @@ class PreloadScene extends Phaser.Scene {
|
||||
startGame();
|
||||
});
|
||||
}
|
||||
|
||||
ultraRemoveBackground(spriteKey) {
|
||||
if (!this.textures.exists(spriteKey)) return;
|
||||
|
||||
const texture = this.textures.get(spriteKey);
|
||||
const source = texture.getSourceImage();
|
||||
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = source.width;
|
||||
canvas.height = source.height;
|
||||
const ctx = canvas.getContext('2d', { willReadFrequently: true });
|
||||
|
||||
ctx.drawImage(source, 0, 0);
|
||||
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||
const data = imageData.data;
|
||||
|
||||
// Remove EVERYTHING except brown wood colors
|
||||
for (let i = 0; i < data.length; i += 4) {
|
||||
const r = data[i];
|
||||
const g = data[i + 1];
|
||||
const b = data[i + 2];
|
||||
|
||||
// Keep only brown/wood colors: R > G > B and R is dominant
|
||||
const isBrown = r > g && g > b && r > 80 && r < 200;
|
||||
|
||||
if (!isBrown) {
|
||||
data[i + 3] = 0; // Make transparent
|
||||
}
|
||||
}
|
||||
|
||||
ctx.putImageData(imageData, 0, 0);
|
||||
|
||||
// Remove old texture and create new one from canvas
|
||||
this.textures.remove(spriteKey);
|
||||
this.textures.addCanvas(spriteKey, canvas);
|
||||
|
||||
console.log(`🔥 ULTRA removed background from ${spriteKey}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,17 +11,60 @@ class StoryScene extends Phaser.Scene {
|
||||
const bg = this.add.rectangle(0, 0, width, height, 0x0a0a0a);
|
||||
bg.setOrigin(0);
|
||||
|
||||
// Title
|
||||
// GLOW EFFECT for title (multiple Text objects)
|
||||
const titleGlow1 = this.add.text(width / 2, 80, 'NOVAFARMA', {
|
||||
fontSize: '72px',
|
||||
fontFamily: 'Courier New',
|
||||
color: '#00ff41',
|
||||
fontStyle: 'bold'
|
||||
});
|
||||
titleGlow1.setOrigin(0.5);
|
||||
titleGlow1.setAlpha(0.3);
|
||||
titleGlow1.setScale(1.05);
|
||||
|
||||
const titleGlow2 = this.add.text(width / 2, 80, 'NOVAFARMA', {
|
||||
fontSize: '72px',
|
||||
fontFamily: 'Courier New',
|
||||
color: '#00ff41',
|
||||
fontStyle: 'bold'
|
||||
});
|
||||
titleGlow2.setOrigin(0.5);
|
||||
titleGlow2.setAlpha(0.5);
|
||||
titleGlow2.setScale(1.02);
|
||||
|
||||
// Main title
|
||||
const title = this.add.text(width / 2, 80, 'NOVAFARMA', {
|
||||
fontSize: '72px',
|
||||
fontFamily: 'Courier New',
|
||||
color: '#00ff41',
|
||||
fontStyle: 'bold',
|
||||
stroke: '#000000',
|
||||
strokeThickness: 6
|
||||
stroke: '#003311',
|
||||
strokeThickness: 8
|
||||
});
|
||||
title.setOrigin(0.5);
|
||||
|
||||
// Pulsing glow animation
|
||||
this.tweens.add({
|
||||
targets: [titleGlow1, titleGlow2],
|
||||
scaleX: 1.08,
|
||||
scaleY: 1.08,
|
||||
alpha: 0.6,
|
||||
duration: 2000,
|
||||
yoyo: true,
|
||||
repeat: -1,
|
||||
ease: 'Sine.easeInOut'
|
||||
});
|
||||
|
||||
// Subtle title bounce
|
||||
this.tweens.add({
|
||||
targets: title,
|
||||
y: 75,
|
||||
duration: 3000,
|
||||
yoyo: true,
|
||||
repeat: -1,
|
||||
ease: 'Sine.easeInOut'
|
||||
});
|
||||
|
||||
// Subtitle
|
||||
const subtitle = this.add.text(width / 2, 150, '2084 - Survival Farm', {
|
||||
fontSize: '20px',
|
||||
|
||||
@@ -91,6 +91,8 @@ class UIScene extends Phaser.Scene {
|
||||
}
|
||||
|
||||
this.createOxygenBar();
|
||||
this.createZombieStatsPanel();
|
||||
this.createFarmStatsPanel();
|
||||
}
|
||||
|
||||
// ... (rest of class) ...
|
||||
@@ -318,6 +320,8 @@ class UIScene extends Phaser.Scene {
|
||||
// Re-create UI elements at new positions
|
||||
this.createClock();
|
||||
this.createGoldDisplay();
|
||||
this.createResourcesDisplay();
|
||||
this.createTimeControlPanel();
|
||||
this.createInventoryBar();
|
||||
this.createInventoryBar();
|
||||
this.createDebugInfo();
|
||||
@@ -580,6 +584,62 @@ class UIScene extends Phaser.Scene {
|
||||
this.clockText.setOrigin(0.5, 0.5);
|
||||
}
|
||||
|
||||
createResourcesDisplay() {
|
||||
const startX = this.scale.width - 160;
|
||||
const startY = 110; // Below gold display
|
||||
const spacing = 35;
|
||||
|
||||
// Container
|
||||
this.resourcesContainer = this.add.container(0, 0);
|
||||
this.resourcesContainer.setDepth(1000);
|
||||
|
||||
// Resources to display
|
||||
const resources = [
|
||||
{ key: 'wood', label: '🪵', color: '#8B4513' },
|
||||
{ key: 'stone', label: '🪨', color: '#808080' },
|
||||
{ key: 'iron', label: '⚙️', color: '#C0C0C0' }
|
||||
];
|
||||
|
||||
this.resourceTexts = {};
|
||||
|
||||
resources.forEach((res, i) => {
|
||||
const y = startY + (i * spacing);
|
||||
|
||||
// Background
|
||||
const bg = this.add.graphics();
|
||||
bg.fillStyle(0x1a1a1a, 0.7);
|
||||
bg.fillRect(startX, y, 140, 28);
|
||||
bg.lineStyle(2, parseInt(res.color.replace('#', '0x')), 0.6);
|
||||
bg.strokeRect(startX, y, 140, 28);
|
||||
this.resourcesContainer.add(bg);
|
||||
|
||||
// Icon/Label
|
||||
const icon = this.add.text(startX + 10, y + 14, res.label, {
|
||||
fontSize: '18px'
|
||||
}).setOrigin(0, 0.5);
|
||||
this.resourcesContainer.add(icon);
|
||||
|
||||
// Count text
|
||||
const text = this.add.text(startX + 40, y + 14, `${res.key.toUpperCase()}: 0`, {
|
||||
fontSize: '14px',
|
||||
fontFamily: 'Courier New',
|
||||
fill: res.color,
|
||||
fontStyle: 'bold'
|
||||
}).setOrigin(0, 0.5);
|
||||
this.resourcesContainer.add(text);
|
||||
|
||||
this.resourceTexts[res.key] = text;
|
||||
});
|
||||
}
|
||||
|
||||
updateResourceDisplay(resource, amount) {
|
||||
if (!this.resourceTexts) return;
|
||||
const text = this.resourceTexts[resource];
|
||||
if (text) {
|
||||
text.setText(`${resource.toUpperCase()}: ${amount}`);
|
||||
}
|
||||
}
|
||||
|
||||
createGoldDisplay() {
|
||||
if (this.goldBg) this.goldBg.destroy();
|
||||
if (this.goldText) this.goldText.destroy();
|
||||
@@ -660,7 +720,141 @@ class UIScene extends Phaser.Scene {
|
||||
this.setBarValue(this.hungerBar, stats.hunger);
|
||||
this.setBarValue(this.thirstBar, stats.thirst);
|
||||
}
|
||||
|
||||
// Update Zombie Stats Panel (starter zombie worker)
|
||||
if (this.gameScene.npcs && this.gameScene.npcs.length > 0) {
|
||||
const zombieWorker = this.gameScene.npcs.find(npc => npc.type === 'zombie' && npc.isTamed);
|
||||
if (zombieWorker) {
|
||||
this.updateZombieStats(zombieWorker);
|
||||
}
|
||||
}
|
||||
|
||||
// Update Farm Stats Panel
|
||||
if (this.gameScene.farmStats) {
|
||||
this.updateFarmStats(this.gameScene.farmStats);
|
||||
}
|
||||
|
||||
// Update Clock Display (HH:MM format)
|
||||
if (this.clockText && this.gameScene.timeSystem) {
|
||||
const ts = this.gameScene.timeSystem;
|
||||
const hour = Math.floor(ts.hour);
|
||||
const minute = Math.floor((ts.hour - hour) * 60);
|
||||
const hourStr = hour.toString().padStart(2, '0');
|
||||
const minStr = minute.toString().padStart(2, '0');
|
||||
|
||||
// Day/Night indicator
|
||||
const isNight = hour < 6 || hour >= 18;
|
||||
const period = isNight ? '🌙' : '☀️';
|
||||
|
||||
this.clockText.setText(`Day ${ts.day} - ${hourStr}:${minStr} ${period}`);
|
||||
}
|
||||
|
||||
// Update Resources Display
|
||||
if (this.resourceTexts && this.gameScene.inventorySystem) {
|
||||
const inv = this.gameScene.inventorySystem;
|
||||
this.updateResourceDisplay('wood', inv.getItemCount('wood'));
|
||||
this.updateResourceDisplay('stone', inv.getItemCount('stone'));
|
||||
this.updateResourceDisplay('iron', inv.getItemCount('iron'));
|
||||
}
|
||||
}
|
||||
|
||||
createTimeControlPanel() {
|
||||
const x = this.scale.width - 170;
|
||||
const y = 250; // Below resources
|
||||
|
||||
this.timeControlContainer = this.add.container(x, y);
|
||||
this.timeControlContainer.setDepth(1000);
|
||||
|
||||
// Background
|
||||
const bg = this.add.graphics();
|
||||
bg.fillStyle(0x1a1a2a, 0.8);
|
||||
bg.fillRect(0, 0, 150, 100);
|
||||
bg.lineStyle(2, 0x4a90e2, 0.8);
|
||||
bg.strokeRect(0, 0, 150, 100);
|
||||
this.timeControlContainer.add(bg);
|
||||
|
||||
// Title
|
||||
const title = this.add.text(75, 15, 'TIME SPEED', {
|
||||
fontSize: '12px',
|
||||
fontFamily: 'Courier New',
|
||||
fill: '#ffffff',
|
||||
fontStyle: 'bold'
|
||||
}).setOrigin(0.5, 0.5);
|
||||
this.timeControlContainer.add(title);
|
||||
|
||||
// Speed buttons
|
||||
const speeds = [
|
||||
{ label: '1x', value: 1.0, y: 40 },
|
||||
{ label: '2x', value: 2.0, y: 60 },
|
||||
{ label: '5x', value: 5.0, y: 80 }
|
||||
];
|
||||
|
||||
this.timeSpeedButtons = [];
|
||||
|
||||
speeds.forEach((speed, i) => {
|
||||
const btn = this.add.text(75, speed.y, speed.label, {
|
||||
fontSize: '14px',
|
||||
fontFamily: 'Courier New',
|
||||
fill: '#4a90e2',
|
||||
fontStyle: 'bold',
|
||||
backgroundColor: '#1a1a2a',
|
||||
padding: { x: 20, y: 5 }
|
||||
}).setOrigin(0.5, 0.5);
|
||||
|
||||
btn.setInteractive({ useHandCursor: true });
|
||||
btn.on('pointerdown', () => {
|
||||
this.setTimeSpeed(speed.value);
|
||||
this.highlightSpeedButton(i);
|
||||
});
|
||||
|
||||
this.timeControlContainer.add(btn);
|
||||
this.timeSpeedButtons.push(btn);
|
||||
});
|
||||
|
||||
this.highlightSpeedButton(0);
|
||||
|
||||
// Pause button
|
||||
const pauseBtn = this.add.text(10, 15, '⏸️', { fontSize: '18px' }).setOrigin(0, 0.5);
|
||||
pauseBtn.setInteractive({ useHandCursor: true });
|
||||
pauseBtn.on('pointerdown', () => this.toggleTimePause());
|
||||
this.timeControlContainer.add(pauseBtn);
|
||||
this.pauseBtn = pauseBtn;
|
||||
}
|
||||
|
||||
setTimeSpeed(speed) {
|
||||
if (this.gameScene && this.gameScene.timeSystem) {
|
||||
this.gameScene.timeSystem.timeScale = speed;
|
||||
console.log(`⏱️ Time speed: ${speed}x`);
|
||||
}
|
||||
}
|
||||
|
||||
highlightSpeedButton(index) {
|
||||
this.timeSpeedButtons.forEach((btn, i) => {
|
||||
if (i === index) {
|
||||
btn.setStyle({ fill: '#ffff00', backgroundColor: '#2a4a6a' });
|
||||
} else {
|
||||
btn.setStyle({ fill: '#4a90e2', backgroundColor: '#1a1a2a' });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
toggleTimePause() {
|
||||
if (!this.gameScene || !this.gameScene.timeSystem) return;
|
||||
|
||||
const ts = this.gameScene.timeSystem;
|
||||
|
||||
if (ts.timeScale === 0) {
|
||||
ts.timeScale = this.lastTimeScale || 1.0;
|
||||
this.pauseBtn.setText('▶️');
|
||||
console.log('▶️ Time resumed');
|
||||
} else {
|
||||
this.lastTimeScale = ts.timeScale;
|
||||
ts.timeScale = 0;
|
||||
this.pauseBtn.setText('⏸️');
|
||||
console.log('⏸️ Time paused');
|
||||
}
|
||||
}
|
||||
|
||||
toggleBuildMenu(isVisible) {
|
||||
if (!this.buildMenuContainer) {
|
||||
this.createBuildMenuInfo();
|
||||
@@ -1897,4 +2091,166 @@ class UIScene extends Phaser.Scene {
|
||||
this.scene.start('StoryScene');
|
||||
}
|
||||
}
|
||||
|
||||
// ========== NEW: ZOMBIE & FARM STATS PANELS ==========
|
||||
|
||||
createZombieStatsPanel() {
|
||||
const panelWidth = 220;
|
||||
const panelHeight = 140;
|
||||
const x = 20;
|
||||
const y = 120; // Below player stats
|
||||
|
||||
// Container
|
||||
this.zombieStatsContainer = this.add.container(x, y);
|
||||
this.zombieStatsContainer.setDepth(1000);
|
||||
|
||||
// Background
|
||||
const bg = this.add.graphics();
|
||||
bg.fillStyle(0x1a1a2e, 0.9);
|
||||
bg.fillRect(0, 0, panelWidth, panelHeight);
|
||||
bg.lineStyle(2, 0x8a2be2, 0.8); // Purple border
|
||||
bg.strokeRect(0, 0, panelWidth, panelHeight);
|
||||
this.zombieStatsContainer.add(bg);
|
||||
|
||||
// Title
|
||||
const title = this.add.text(panelWidth / 2, 15, '🧟 ZOMBIE WORKER', {
|
||||
fontSize: '14px',
|
||||
fontFamily: 'Courier New',
|
||||
fill: '#8a2be2',
|
||||
fontStyle: 'bold'
|
||||
}).setOrigin(0.5);
|
||||
this.zombieStatsContainer.add(title);
|
||||
|
||||
// Stats Text
|
||||
this.zombieNameText = this.add.text(10, 35, 'Name: Worker #1', {
|
||||
fontSize: '12px',
|
||||
fill: '#ffffff'
|
||||
});
|
||||
this.zombieStatsContainer.add(this.zombieNameText);
|
||||
|
||||
this.zombieTaskText = this.add.text(10, 55, 'Task: IDLE', {
|
||||
fontSize: '12px',
|
||||
fill: '#ffff00'
|
||||
});
|
||||
this.zombieStatsContainer.add(this.zombieTaskText);
|
||||
|
||||
this.zombieLevelText = this.add.text(10, 75, 'Level: 1 (0/100 XP)', {
|
||||
fontSize: '12px',
|
||||
fill: '#00ff00'
|
||||
});
|
||||
this.zombieStatsContainer.add(this.zombieLevelText);
|
||||
|
||||
// Energy Bar
|
||||
const energyLabel = this.add.text(10, 95, 'ENERGY:', { fontSize: '11px', fill: '#aaaaaa' });
|
||||
this.zombieStatsContainer.add(energyLabel);
|
||||
|
||||
this.zombieEnergyBar = this.drawMiniBar(10, 110, panelWidth - 20, 15, 0x00aaff, 100);
|
||||
this.zombieStatsContainer.add(this.zombieEnergyBar.bg);
|
||||
this.zombieStatsContainer.add(this.zombieEnergyBar.fill);
|
||||
|
||||
// Initially visible
|
||||
this.zombieStatsContainer.setVisible(true);
|
||||
}
|
||||
|
||||
createFarmStatsPanel() {
|
||||
const panelWidth = 220;
|
||||
const panelHeight = 120;
|
||||
const x = 20;
|
||||
const y = 280; // Below zombie stats
|
||||
|
||||
// Container
|
||||
this.farmStatsContainer = this.add.container(x, y);
|
||||
this.farmStatsContainer.setDepth(1000);
|
||||
|
||||
// Background
|
||||
const bg = this.add.graphics();
|
||||
bg.fillStyle(0x1a2e1a, 0.9);
|
||||
bg.fillRect(0, 0, panelWidth, panelHeight);
|
||||
bg.lineStyle(2, 0x00ff00, 0.8); // Green border
|
||||
bg.strokeRect(0, 0, panelWidth, panelHeight);
|
||||
this.farmStatsContainer.add(bg);
|
||||
|
||||
// Title
|
||||
const title = this.add.text(panelWidth / 2, 15, '🌾 FARM STATS', {
|
||||
fontSize: '14px',
|
||||
fontFamily: 'Courier New',
|
||||
fill: '#00ff00',
|
||||
fontStyle: 'bold'
|
||||
}).setOrigin(0.5);
|
||||
this.farmStatsContainer.add(title);
|
||||
|
||||
// Stats
|
||||
this.farmCropsPlantedText = this.add.text(10, 40, 'Crops Planted: 0', {
|
||||
fontSize: '12px',
|
||||
fill: '#ffffff'
|
||||
});
|
||||
this.farmStatsContainer.add(this.farmCropsPlantedText);
|
||||
|
||||
this.farmCropsHarvestedText = this.add.text(10, 60, 'Total Harvested: 0', {
|
||||
fontSize: '12px',
|
||||
fill: '#ffff00'
|
||||
});
|
||||
this.farmStatsContainer.add(this.farmCropsHarvestedText);
|
||||
|
||||
this.farmGoldEarnedText = this.add.text(10, 80, 'Gold Earned: 0g', {
|
||||
fontSize: '12px',
|
||||
fill: '#ffd700'
|
||||
});
|
||||
this.farmStatsContainer.add(this.farmGoldEarnedText);
|
||||
|
||||
this.farmDaysText = this.add.text(10, 100, 'Days Farmed: 0', {
|
||||
fontSize: '12px',
|
||||
fill: '#aaaaaa'
|
||||
});
|
||||
this.farmStatsContainer.add(this.farmDaysText);
|
||||
}
|
||||
|
||||
drawMiniBar(x, y, width, height, color, initialPercent = 100) {
|
||||
// Background
|
||||
const bg = this.add.graphics();
|
||||
bg.fillStyle(0x000000, 0.5);
|
||||
bg.fillRect(x, y, width, height);
|
||||
bg.lineStyle(1, 0xffffff, 0.3);
|
||||
bg.strokeRect(x, y, width, height);
|
||||
|
||||
// Fill
|
||||
const fill = this.add.graphics();
|
||||
fill.fillStyle(color, 1);
|
||||
const maxWidth = width - 4;
|
||||
const currentWidth = (maxWidth * initialPercent) / 100;
|
||||
fill.fillRect(x + 2, y + 2, currentWidth, height - 4);
|
||||
|
||||
return { bg, fill, x, y, width, height, color };
|
||||
}
|
||||
|
||||
setMiniBarValue(bar, percent) {
|
||||
percent = Phaser.Math.Clamp(percent, 0, 100);
|
||||
bar.fill.clear();
|
||||
bar.fill.fillStyle(bar.color, 1);
|
||||
const maxWidth = bar.width - 4;
|
||||
const currentWidth = (maxWidth * percent) / 100;
|
||||
bar.fill.fillRect(bar.x + 2, bar.y + 2, currentWidth, bar.height - 4);
|
||||
}
|
||||
|
||||
// Update methods (call from update())
|
||||
updateZombieStats(zombie) {
|
||||
if (!zombie || !this.zombieStatsContainer) return;
|
||||
|
||||
this.zombieStatsContainer.setVisible(true);
|
||||
if (this.zombieNameText) this.zombieNameText.setText(`Name: ${zombie.name || 'Worker #1'}`);
|
||||
if (this.zombieTaskText) this.zombieTaskText.setText(`Task: ${zombie.task || 'IDLE'}`);
|
||||
if (this.zombieLevelText) this.zombieLevelText.setText(`Level: ${zombie.level || 1} (${zombie.xp || 0}/100 XP)`);
|
||||
|
||||
const energy = zombie.energy !== undefined ? zombie.energy : 100;
|
||||
if (this.zombieEnergyBar) this.setMiniBarValue(this.zombieEnergyBar, energy);
|
||||
}
|
||||
|
||||
updateFarmStats(stats) {
|
||||
if (!stats || !this.farmStatsContainer) return;
|
||||
|
||||
if (this.farmCropsPlantedText) this.farmCropsPlantedText.setText(`Crops Planted: ${stats.cropsPlanted || 0}`);
|
||||
if (this.farmCropsHarvestedText) this.farmCropsHarvestedText.setText(`Total Harvested: ${stats.totalHarvested || 0}`);
|
||||
if (this.farmGoldEarnedText) this.farmGoldEarnedText.setText(`Gold Earned: ${stats.goldEarned || 0}g`);
|
||||
if (this.farmDaysText) this.farmDaysText.setText(`Days Farmed: ${stats.daysFarmed || 0}`);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user