Fix crashes, remove Gronk, add Water/Wind anims, fix Tiled paths, clean plants assets

This commit is contained in:
2026-01-14 01:15:55 +01:00
parent cbecdc3ac7
commit 4ef1adc413
480 changed files with 34600 additions and 545 deletions

View File

@@ -6,6 +6,13 @@ class ErrorHandler {
return false;
};
window.addEventListener('unhandledrejection', (event) => {
// IGNORE AUDIO DECODING ERRORS (Phaser/Electron issue)
const msg = event.reason ? String(event.reason) : '';
if (msg.includes('Unable to decode audio data') || msg.includes('EncodingError') || msg.includes(':0:0')) {
console.warn('🔇 Ignored Critical Audio Error (Game continues):', msg);
event.preventDefault();
return;
}
ErrorHandler.showError('Unhandled Promise Rejection', '', 0, 0, event.reason);
});
console.log('🛡️ Global Error Handler Initialized');

View File

@@ -227,9 +227,64 @@ class GameScene extends Phaser.Scene {
map.layers.forEach(layer => {
if (layer.type === 'tilelayer') {
const createdLayer = map.createLayer(layer.name, tileset, 0, 0);
// Set Depth based on layer name or order
if (layer.name === 'Objects') createdLayer.setDepth(10); // Above ground
if (layer.name === 'Collision') createdLayer.setVisible(false); // Hide collision usually
if (layer.name === 'Objects') createdLayer.setDepth(10);
if (layer.name === 'Collision') {
createdLayer.setVisible(false);
this.collisionLayer = createdLayer;
this.collisionLayer.setCollisionByExclusion([-1]);
console.log('🚧 Collision Layer Set!');
}
// 💧 DYNAMIC TILED EFFECTS (Shine)
// Check for custom properties from Tiled
const layerProps = layer.properties || [];
const getProp = (n) => {
if (Array.isArray(layerProps)) {
const p = layerProps.find(x => x.name === n);
return p ? p.value : undefined;
}
return layerProps[n];
};
const shineIntensity = getProp('shine_intensity');
const isWind = getProp('isWind');
// Apply Shine if prop exists OR if name is Water/Voda
if (shineIntensity !== undefined || layer.name === 'Water' || layer.name === 'Voda') {
const intensity = shineIntensity !== undefined ? parseFloat(shineIntensity) : 5;
// Validate intensity
if (!isNaN(intensity) && intensity > 0 && createdLayer.postFX) {
console.log(`💧 Applying Shine to layer '${layer.name}' (Intensity: ${intensity})`);
const shine = createdLayer.postFX.addShine(1, 0.2, intensity);
// Animate shine speed for 'glimmer' effect
this.tweens.add({
targets: shine,
speed: 0.5,
duration: 2000,
yoyo: true,
repeat: -1
});
}
}
// 🌬️ WIND (Wobble Effect)
if (isWind) {
console.log(`🌬️ Applying Wind to '${layer.name}'`);
this.tweens.add({
targets: createdLayer,
x: createdLayer.x + 3,
skewX: 0.015,
duration: 2000 + Math.random() * 500,
ease: 'Sine.easeInOut',
yoyo: true,
repeat: -1
});
}
}
});
}
@@ -238,6 +293,20 @@ class GameScene extends Phaser.Scene {
try {
// 🎵 MUSIC PROP
const mapMusic = map.properties && map.properties.find(p => p.name === 'music')?.value;
// 🌲 FOREST AMBIENT (Safe Play)
try {
// Verify cache existence first to avoid decode errors propagating
if (this.cache.audio.exists('forest_ambient')) {
this.sound.play('forest_ambient', { loop: true, volume: 0.3 });
console.log('🌲 Playing Forest Ambient');
} else {
console.warn('⚠️ Forest Ambient skipped (Not in cache/Load failed)');
}
} catch (e) {
console.warn('❌ Audio play CRASH prevented:', e);
}
if (mapMusic) {
console.log(`🎵 Map Triggered Music: ${mapMusic}`);
// Use sound manager or direct play (SoundManager preferred but let's check safety)
@@ -266,6 +335,15 @@ class GameScene extends Phaser.Scene {
}
});
}
// 🎭 ACTORS LAYER (NPCs including Gronk)
const actorsLayer = map.getObjectLayer('Actors') || map.getObjectLayer('Objects');
if (actorsLayer && actorsLayer.objects) {
console.log(`🎭 Found ${actorsLayer.objects.length} Actors`);
actorsLayer.objects.forEach(obj => {
// Gronk disabled per user request
});
}
} catch (err) {
console.warn('⚠️ Error parsing object layers:', err);
}
@@ -429,11 +507,11 @@ class GameScene extends Phaser.Scene {
// Odstrani // če želiš sadovnjak
/*
console.log('🍎 Ustvarjam sadovnjak...');
const orchardX = 35; // Lokacija sadovnjaka
const orchardY = 60;
const orchardSize = 10; // 10x10 območje
// 1. Očisti območje (odstrani obstoječe drevese)
for (let x = orchardX; x < orchardX + orchardSize; x++) {
for (let y = orchardY; y < orchardY + orchardSize; y++) {
@@ -442,7 +520,7 @@ class GameScene extends Phaser.Scene {
if (this.terrainSystem.decorationsMap.has(key)) {
this.terrainSystem.removeDecoration(x, y);
}
// Spremeni teren v travo
if (this.terrainSystem.tiles[y] && this.terrainSystem.tiles[y][x]) {
this.terrainSystem.tiles[y][x].type = 'grass';
@@ -454,12 +532,12 @@ class GameScene extends Phaser.Scene {
}
}
}
// 2. Dodaj SADIKE (tree_sapling) - bodo rasle v sadna drevesa!
const fruitTreeTypes = ['tree_apple', 'tree_orange', 'tree_cherry'];
let treeCount = 0;
const saplingPositions = []; // Shrani pozicije za ograje
for (let x = orchardX + 1; x < orchardX + orchardSize - 1; x += 2) {
for (let y = orchardY + 1; y < orchardY + orchardSize - 1; y += 2) {
if (x >= 0 && x < 100 && y >= 0 && y < 100) {
@@ -470,7 +548,7 @@ class GameScene extends Phaser.Scene {
}
}
}
// 3. Dodaj LESENO OGRAJO okoli vsakega drevesa (3x3 kvadrat)
saplingPositions.forEach(pos => {
// Ograja okoli drevesa (3x3)
@@ -488,14 +566,14 @@ class GameScene extends Phaser.Scene {
// Desna stran
{ x: pos.x + 1, y: pos.y }
];
fencePositions.forEach(fPos => {
if (fPos.x >= 0 && fPos.x < 100 && fPos.y >= 0 && fPos.y < 100) {
this.buildSystem.placeSingleFence(fPos.x, fPos.y, 'fence_horizontal', false);
}
});
});
// 4. Dodaj ZUNANJO OGRAJO okoli celega sadovnjaka
this.buildSystem.placeFenceRectangle(
orchardX - 1,
@@ -505,7 +583,7 @@ class GameScene extends Phaser.Scene {
'fence_post',
false
);
// 5. Dodaj cvetje med ograjami
for (let x = orchardX; x < orchardX + orchardSize; x++) {
for (let y = orchardY; y < orchardY + orchardSize; y++) {
@@ -517,21 +595,21 @@ class GameScene extends Phaser.Scene {
}
}
}
// 6. RAST DREVES - Sadike bodo rasle v sadna drevesa!
// Nastavi timer za rast (vsako drevo raste po 30 sekundah)
saplingPositions.forEach((pos, index) => {
this.time.delayedCall(30000 + (index * 2000), () => {
const key = `${pos.x},${pos.y}`;
// Odstrani sadiko
if (this.terrainSystem.decorationsMap.has(key)) {
this.terrainSystem.removeDecoration(pos.x, pos.y);
}
// Dodaj SADNO DREVO
this.terrainSystem.addDecoration(pos.x, pos.y, pos.type);
// Animacija rasti
if (this.terrainSystem.visibleDecorations.has(key)) {
const sprite = this.terrainSystem.visibleDecorations.get(key);
@@ -544,11 +622,11 @@ class GameScene extends Phaser.Scene {
ease: 'Bounce.out'
});
}
console.log(`🌳 Drevo zraslo: ${pos.type} na (${pos.x}, ${pos.y})`);
});
});
console.log(`✅ Sadovnjak ustvarjen na (${orchardX}, ${orchardY}) - ${treeCount} sadik (bodo rasle v 30s)`);
*/
// ========================================================
@@ -706,6 +784,9 @@ class GameScene extends Phaser.Scene {
// ALL NPCs REMOVED - Solo farming mode
console.log('🌾 Solo farming mode - no NPCs');
// Gronk logic removed from create() fallback
// FPS Monitor (Performance)
// FPS Monitor - DISABLED (Using UnifiedStatsPanel instead)
// console.log('📊 Initializing FPS Monitor...');
@@ -801,7 +882,7 @@ class GameScene extends Phaser.Scene {
console.log('💡 Initializing Lighting & Shadow System... (DISABLED FOR DEBUG)');
/*
this.lightingSystem = new LightingSystem(this);
// Create player shadow
if (this.player) {
this.lightingSystem.createShadow(this.player, 12, 30, 15);
@@ -2453,17 +2534,17 @@ class GameScene extends Phaser.Scene {
/*
if (!this.player || this.npcs.length > 50) return;
const playerPos = this.player.getPosition();
const angle = Math.random() * Math.PI * 2;
const distance = Phaser.Math.Between(15, 25);
const spawnX = Math.floor(playerPos.x + Math.cos(angle) * distance);
const spawnY = Math.floor(playerPos.y + Math.sin(angle) * distance);
if (spawnX < 0 || spawnX >= 100 || spawnY < 0 || spawnY >= 100) return;
if (Phaser.Math.Distance.Between(spawnX, spawnY, 20, 20) < 15) return;
const tile = this.terrainSystem.getTile(spawnX, spawnY);
if (tile && tile.type !== 'water') {
console.log(`🌑 Night Spawn: Zombie at ${spawnX},${spawnY}`);
@@ -2720,11 +2801,47 @@ class GameScene extends Phaser.Scene {
if (bird.x < -100) {
bird.x = width + 100;
bird.y = 100 + Math.random() * 200;
}
});
}
setupGronk() { }
// 🧛‍♂️ GRONK SPAWN METHOD (Advanced Wander AI)
if(this.gronk.aiState === 'IDLE') {
const rand = Math.random();
if (rand < 0.3) { // 30% Vape
this.gronk.aiState = 'VAPE';
this.gronk.anims.play('gronk_vape');
emitVape();
this.gronk.nextDecisionTime = time + 3000;
setTimeout(() => { if (this.gronk && this.gronk.active) this.gronk.aiState = 'IDLE'; }, 2500);
} else { // 70% Wander
const angle = Math.random() * Math.PI * 2;
const dist = 30 + Math.random() * wanderRadius; // Min 30px move
const tx = this.gronk.homePos.x + Math.cos(angle) * dist;
const ty = this.gronk.homePos.y + Math.sin(angle) * dist;
this.gronk.moveTarget = new Phaser.Math.Vector2(tx, ty);
this.physics.moveToObject(this.gronk, this.gronk.moveTarget, moveSpeed);
this.gronk.aiState = 'MOVE';
this.gronk.nextDecisionTime = time + 5000; // Timeout
}
} else if (this.gronk.aiState === 'MOVE') {
const dist = Phaser.Math.Distance.Between(this.gronk.x, this.gronk.y, this.gronk.moveTarget.x, this.gronk.moveTarget.y);
if (dist < 10) {
this.gronk.body.reset(this.gronk.x, this.gronk.y);
this.gronk.aiState = 'IDLE';
this.gronk.nextDecisionTime = time + 1000 + Math.random() * 2000;
} else if (time >= this.gronk.nextDecisionTime) { // Stuck/Timeout
this.gronk.body.reset(this.gronk.x, this.gronk.y);
this.gronk.aiState = 'IDLE';
this.gronk.nextDecisionTime = time + 1000;
}
}
}
});
}
}

View File

@@ -97,7 +97,7 @@ class PreloadScene extends Phaser.Scene {
// Trees
this.load.image('tileset_Tree_Apple', 'assets/references/trees/apple/apple_tree.png');
this.load.image('tileset_Tree_Cherry', 'assets/references/trees/cherry/cherry_tree.png');
this.load.image('tileset_Tree_Dead', 'assets/references/trees/dead/dead_tree.png');
this.load.image('tileset_Tree_Dead', 'assets/maps/tilesets/Tree_Dead.png');
// Buildings
this.load.image('tileset_House_Gothic', 'assets/references/buildings/kai_house/04_gothic_house.png');
@@ -143,6 +143,16 @@ class PreloadScene extends Phaser.Scene {
this.loadAudioSafe('kai_voice_4', basePath + 'kai/kai_04.mp3');
this.loadAudioSafe('kai_voice_5', basePath + 'kai/kai_05.mp3');
// 🎵 AMBIENT
this.loadAudioSafe('forest_ambient', 'assets/audio/music/forest_ambient.mp3');
// 🧛‍♂️ GRONK FULL SPRITESHEET (Custom Animation Set)
// 🧛‍♂️ GRONK PRO SPRITESHEET (Custom Animation Set - Cleaned & Centered)
this.load.spritesheet('gronk_pro_sheet', 'assets/characters/gronk_pro_sheet.png', {
frameWidth: 128,
frameHeight: 128
});
// Ana voices
this.loadAudioSafe('ana_voice_1', basePath + 'ana/ana_01.mp3');
this.loadAudioSafe('ana_voice_2', basePath + 'ana/ana_02.mp3');
@@ -240,6 +250,42 @@ class PreloadScene extends Phaser.Scene {
frameRate: 1
});
// 🧛‍♂️ GRONK ANIMATIONS
// Down
this.anims.create({
key: 'gronk_walk_down',
frames: this.anims.generateFrameNumbers('gronk_pro_sheet', { start: 0, end: 3 }),
frameRate: 8,
repeat: -1
});
// Right
this.anims.create({
key: 'gronk_walk_right',
frames: this.anims.generateFrameNumbers('gronk_pro_sheet', { start: 4, end: 7 }),
frameRate: 8,
repeat: -1
});
// Up
this.anims.create({
key: 'gronk_walk_up',
frames: this.anims.generateFrameNumbers('gronk_pro_sheet', { start: 8, end: 11 }),
frameRate: 8,
repeat: -1
});
// Vape (Special)
this.anims.create({
key: 'gronk_vape',
frames: this.anims.generateFrameNumbers('gronk_pro_sheet', { start: 12, end: 15 }),
frameRate: 8,
repeat: 0 // Play once
});
// Idle
this.anims.create({
key: 'gronk_idle', // Default idle (Down)
frameRate: 2,
repeat: -1
});
console.log('🎞️ Animations created!');
}