WIP: Camera controls, WebGL setup, Procedural grass attempt (Black screen debug)

This commit is contained in:
2026-01-18 05:35:23 +01:00
parent 91eb68a65f
commit de089e5b01
16 changed files with 353 additions and 2912 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 481 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 727 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

After

Width:  |  Height:  |  Size: 727 KiB

View File

@@ -35,17 +35,27 @@
align-items: center;
width: 100vw;
height: 100vh;
image-rendering: -moz-crisp-edges;
image-rendering: -webkit-crisp-edges;
image-rendering: pixelated;
image-rendering: crisp-edges;
/* SMOOTH FILMSKI RENDERING (no pixelation!) */
image-rendering: auto;
/* Browser default - SMOOTH */
background: #000;
/* Black by default (intro) */
}
/* GRASS BACKGROUND - only when GameScene active */
#game-container.game-active {
background-image: url('assets/slike/teren/grass_noir.png');
background-repeat: repeat;
background-size: 128px 128px;
/* 512px * 0.25 = 128px */
background-position: 0 0;
image-rendering: auto;
/* SMOOTH LINEAR filtering */
}
canvas {
image-rendering: -moz-crisp-edges;
image-rendering: -webkit-crisp-edges;
image-rendering: pixelated;
image-rendering: crisp-edges;
/* SMOOTH FILMSKI RENDERING for Phaser sprites */
image-rendering: auto;
}
</style>
</head>
@@ -281,7 +291,7 @@
<script src="src/systems/MasterGameSystemsManager.js"></script> <!-- 🎮 Master Coordinator -->
<!-- 🧪 TEST SCENE -->
<!-- <script src="src/AssetManifest.js"></script> DISABLED: File removed -->
<!-- 🧪 TEST SCENE -->
<script src="src/scenes/AssetTestScene.js"></script> <!-- 🖼️ Asset Gallery -->
<script src="src/systems/WaterPhysicsSystem.js"></script> <!-- 🌊 Water Physics -->
<script src="src/systems/WaterRipplesSystem.js"></script> <!-- 💧 Water Ripples -->

View File

@@ -108,12 +108,16 @@ class Player {
}
createSprite() {
// KRVAVA ŽETEV: Use new protagonist sprite
let texKey = 'player_protagonist';
// Priority: kai_main (real sprite) > player_style32 > fallback
let texKey = 'kai_main';
// Fallback to generated sprite if not loaded
if (!this.scene.textures.exists(texKey)) {
console.warn('⚠️ player_protagonist sprite not found! Generating fallback...');
texKey = 'player_style32';
}
// Fallback to generated pink square if nothing loaded
if (!this.scene.textures.exists(texKey)) {
console.warn('⚠️ No Kai sprite found! Generating pink fallback...');
TextureGenerator.createPlayerSprite(this.scene, 'player_fallback');
texKey = 'player_fallback';
}
@@ -134,7 +138,7 @@ class Player {
// Scale based on sprite type
if (texKey === 'player_protagonist') {
this.sprite.setScale(0.5); // 256x256 frames scaled to 128x128 display size
this.sprite.setScale(0.25); // 0.25 scale for correct size
} else {
this.sprite.setScale(0.5); // Fallback sprite
}

View File

@@ -47,19 +47,19 @@ ErrorHandler.init();
// Phaser Game Configuration
const config = {
type: Phaser.CANVAS, // Canvas renderer za pixel-perfect ostrino
type: Phaser.WEBGL, // WEBGL renderer (Canvas has issues in Electron!)
width: 1024, // Larger viewport for better view
height: 768, // 4:3 aspect ratio
parent: 'game-container',
backgroundColor: '#000000', // Black background (not gray!)
pixelArt: false, // 🎨 SMOOTH 2D (was: true)
antialias: true, // 🎨 SMOOTH edges (was: false)
roundPixels: false, // 🎨 SMOOTH positioning (was: true)
backgroundColor: '#000000', // Black background
pixelArt: false, // 🎨 SMOOTH FILMSKI LOOK (LINEAR filtering)
antialias: true, // 🎨 SMOOTH edges (mehki prehodi)
roundPixels: false, // 🎨 FLUID positioning (no kockanje)
render: {
pixelArt: false, // 🎨 SMOOTH 2D
antialias: true, // 🎨 SMOOTH edges
roundPixels: false, // 🎨 SMOOTH positioning
transparent: false,
pixelArt: false, // 🎨 LINEAR filtering (gladko)
antialias: true, // 🎨 Smooth transitions
roundPixels: false, // 🎨 Sub-pixel precision
transparent: true, // Allow HTML background to show through
clearBeforeRender: true,
powerPreference: 'high-performance',
premultipliedAlpha: true,

View File

@@ -38,7 +38,7 @@ class BootScene extends Phaser.Scene {
create() {
console.log('✅ BootScene: Complete!');
console.log('🎨 Pixel Art Mode: pixelArt=true, roundPixels=true (NEAREST filtering)');
console.log('🎨 SMOOTH Rendering Mode: pixelArt=FALSE, roundPixels=FALSE (LINEAR filtering - filmski look)');
window.gameState.currentScene = 'BootScene';
// Global Constants for Sprites

File diff suppressed because it is too large Load Diff

View File

@@ -34,18 +34,16 @@ class IntroScene extends Phaser.Scene {
this.load.image('intro_ana_barbershop', dreamyPath + 'ana_barbershop_dreads_dreamy.png');
this.load.image('intro_birthday_cake', dreamyPath + 'birthday_cake_rd_dreamy.png');
this.load.image('intro_virus', introPath + 'virus_xnoir_microscope.png');
this.load.image('intro_chaos', dreamyPath + 'chaos_streets_apocalypse_dreamy.png');
this.load.image('intro_zombies', dreamyPath + 'zombie_silhouettes_panic_dreamy.png');
this.load.image('intro_parents_ghosts', dreamyPath + 'parents_transparent_ghosts_dreamy.png');
this.load.image('intro_ana_taken', introPath + 'ana_taken_military.png');
this.load.image('intro_kai_alone', introPath + 'kai_alone_basement.png');
this.load.image('intro_kai_young', introPath + 'kai_young_timelapse.png');
this.load.image('intro_kai_adult', introPath + 'kai_adult_35_timelapse.png');
this.load.image('intro_kai_elder', introPath + 'kai_elder_50_timelapse.png');
this.load.image('intro_ana_memory', introPath + 'ana_memory_flash_purple.png');
this.load.image('intro_bedroom', introPath + 'kai_bedroom_wakeup.png');
this.load.image('intro_gronk', introPath + 'gronk_doorway_silhouette.png');
this.load.image('intro_twins_childhood', introPath + 'kai_ana_twins_childhood.png');
// REMOVED STORY ASSETS TO PREVENT 404
// this.load.image('intro_kai_alone', introPath + 'kai_alone_basement.png');
// Missing assets commented out to clean console errors
// this.load.image('intro_ana_memory', introPath + 'ana_memory_flash_purple.png');
// this.load.image('intro_bedroom', introPath + 'kai_bedroom_wakeup.png'); // This was not in the instruction, but it's likely a missing asset too.
// this.load.image('intro_gronk_doorway', introPath + 'gronk_doorway_silhouette.png');
// this.load.image('intro_kai_twins', introPath + 'kai_ana_twins_childhood.png');
// this.load.image('intro_kai_basement', introPath + 'kai_alone_basement.png'); // This seems to be a duplicate of intro_kai_alone, but with a different key.
console.log('✅ IntroScene assets skipped (clean console check)');
// 🎵 AMBIENT MUSIC
this.loadAudioSafe('noir_ambience', 'assets/audio/ambient/noir_ambience.mp3');

View File

@@ -57,76 +57,29 @@ class PreloadScene extends Phaser.Scene {
// Load Manifest Images
// Since we are using script tags in index.html, window.AssetManifest is already available!
if (window.AssetManifest) {
const manifest = window.AssetManifest;
// REMOVED MANIFEST CHECK - FORCE LOAD ASSETS
console.log('📦 FORCE LOADING ASSETS (No Manifest Check)...');
console.log(`📦 Loading Asset Manifest (Phased)...`);
// 🎨 TILESET IMAGES
console.log('🔍 LOADING REFERENCE GRASS: assets/slike/teren/grass_tile.png');
this.load.image('trava_osnova', 'assets/slike/teren/grass_tile.png');
this.load.image('tileset_grass', 'assets/slike/teren/grass_tile.png'); // Duplicate for safety
// Iterate over phases (farm, basement_mine, etc.)
if (manifest.phases) {
Object.keys(manifest.phases).forEach(phaseName => {
console.log(`Phase: ${phaseName} - ${manifest.phases[phaseName].length} items`);
manifest.phases[phaseName].forEach(img => {
this.loadImageSafe(img.key, img.path);
});
});
}
this.load.image('tileset_dirt', 'assets/slike/teren/dirt.png');
this.load.image('tileset_water', 'assets/slike/teren/water.png');
this.load.image('tileset_stone', 'assets/slike/teren/stone.png');
// Iterate over spritesheets
if (manifest.spritesheets) {
manifest.spritesheets.forEach(sheet => {
this.load.spritesheet(sheet.key, sheet.path, sheet.frameConfig);
});
}
// Legacy Keys
this.load.image('tileset_Terrain_Grass', 'assets/slike/teren/grass_tile.png');
this.load.image('tileset_Terrain_Dirt', 'assets/slike/teren/dirt.png');
this.load.image('tileset_Terrain_Water', 'assets/slike/teren/water.png');
console.log('✅ AssetManifest Queue Complete');
console.log('✅ All Tilesets Preloaded!');
// 🗺️ TILESET IMAGES (For Tiled maps - Faza1_Finalna.tmx)
console.log('🎨 Preloading All Tileset Images...');
// Terrain - UPDATED FOR STYLE 32 (Flat2DTerrainSystem keys)
console.log('🔍 ATTEMPTING LOAD: assets/slike/teren/grass_tile.png');
this.load.image('trava_osnova', 'assets/slike/teren/grass_tile.png');
// Legacy/Map keys
this.load.image('tileset_grass', 'assets/slike/teren/grass_tile.png'); // Keep for map compatibility
// Intro Assets (Verified paths in assets/slike/zgodba)
// 'ana_memory_flash' not found, using 'intro_twin_photo' as placeholder
this.load.image('intro_ana_memory', 'assets/slike/zgodba/assets_references_intro_twin_photo.png');
// 'kai_bedroom_wakeup' not found, using 'intro_cellar' placeholder for now
this.load.image('intro_bedroom_wakeup', 'assets/slike/zgodba/assets_references_intro_cellar_ruins.png');
this.load.image('tileset_dirt', 'assets/slike/teren/dirt.png');
this.load.image('tileset_water', 'assets/slike/teren/water.png');
// this.load.image('tileset_farmland', 'assets/slike/teren/farmland.png'); // DISABLED: Not found in teren
this.load.image('tileset_stone', 'assets/slike/teren/stone.png');
// Legacy Keys (Keep for Tiled Map compatibility if needed)
this.load.image('tileset_Terrain_Grass', 'assets/slike/teren/grass_tile.png');
this.load.image('tileset_Terrain_Dirt', 'assets/slike/teren/dirt.png');
this.load.image('tileset_Terrain_Water', 'assets/slike/teren/water.png');
// Fences (Commented out if not in teren/okolje yet, likely in ZA_PREGLED)
// this.load.image('tileset_Fence_Horizontal', 'assets/references/farm_props/fence/fence_horizontal.png');
// this.load.image('tileset_Fence_Vertical', 'assets/references/farm_props/fence/fence_vertical.png');
// this.load.image('tileset_Fence_Corner', 'assets/references/farm_props/fence/fence_corner.png');
// Trees (Commented out legacy paths)
// 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/maps/tilesets/Tree_Dead.png');
// Buildings
// this.load.image('tileset_House_Gothic', 'assets/references/buildings/kai_house/04_gothic_house.png');
console.log('✅ All Tilesets Preloaded!');
// MAP (Tiled JSON)
this.load.tilemapTiledJSON('NovaFarma', 'assets/maps/NovaFarma.json');
console.log('🗺️ Preloading NovaFarma.json map...');
} else {
console.error('❌ Critical: window.AssetManifest not found! Check index.html imports.');
}
// MAP (Tiled JSON)
// Found at: assets/maps/NovaFarma.json
this.load.tilemapTiledJSON('NovaFarma', 'assets/maps/NovaFarma.json');
console.log('🗺️ Preloading NovaFarma.json map...');
}
loadImageSafe(key, path) {
@@ -145,7 +98,7 @@ class PreloadScene extends Phaser.Scene {
// this.load.audio('background_music', 'assets/audio/bg_noir.mp3');
// 🧛‍♂️ GRONK SPRITESHEET (Verified)
// 🧛‍♂️ GRONK (Verified Path: assets/slike/liki/gronk_pro_sheet.png)
this.load.spritesheet('gronk_pro_sheet', 'assets/slike/liki/gronk_pro_sheet.png', {
frameWidth: 128,
frameHeight: 128
@@ -597,8 +550,8 @@ class PreloadScene extends Phaser.Scene {
// ✅ Starting INTRO SEQUENCE (NEW! Jan 10, 2026)
this.time.delayedCall(500, () => {
console.log('🎬 Starting IntroScene (Cinematic Intro)...');
this.scene.start('IntroScene'); // ← NEW INTRO SEQUENCE
console.log('🎬 Starting GameScene (DEMO MODE - SKIP INTRO)...');
this.scene.start('GameScene'); // ← NEW INTRO SEQUENCE
});
}
});
@@ -607,15 +560,15 @@ class PreloadScene extends Phaser.Scene {
create() {
console.log('🎵 Starting Background Music Loop...');
try {
if (!this.sound.get('background_music')) {
this.sound.play('background_music', { loop: true, volume: 0.5 });
} else if (!this.sound.get('background_music').isPlaying) {
this.sound.get('background_music').play();
}
} catch (e) {
console.warn('🎵 Audio Playback Failed (Autoplay policy?):', e);
}
// try {
// if (!this.sound.get('background_music')) {
// this.sound.play('background_music', { loop: true, volume: 0.5 });
// } else if (!this.sound.get('background_music').isPlaying) {
// this.sound.get('background_music').play();
// }
// } catch (e) {
// console.warn('🎵 Audio Playback Failed (Autoplay policy?):', e);
// }
// The actual scene start logic has been moved to the 'load.on(complete)' callback
// to ensure all assets are fully loaded and the loading bar has faded out.

View File

@@ -2240,7 +2240,7 @@ class UIScene extends Phaser.Scene {
// Background - FARM THEME
const bg = this.add.graphics();
bg.fillStyle(0x4a3520, 0.9); // Brown wood
bg.fillStyle(0x4a3520, 0.7); // Brown wood (70% alpha for noir)
bg.fillRect(0, 0, panelWidth, panelHeight);
bg.lineStyle(3, 0x8B4513, 0.8); // Saddle brown
bg.strokeRect(0, 0, panelWidth, panelHeight);
@@ -2298,7 +2298,7 @@ class UIScene extends Phaser.Scene {
// Background - FARM THEME
const bg = this.add.graphics();
bg.fillStyle(0x2a4a2a, 0.9); // Dark green
bg.fillStyle(0x2a4a2a, 0.7); // Dark green (70% alpha for noir)
bg.fillRect(0, 0, panelWidth, panelHeight);
bg.lineStyle(3, 0x90EE90, 0.8); // Light green border
bg.strokeRect(0, 0, panelWidth, panelHeight);

View File

@@ -115,7 +115,7 @@ export class AudioLoader {
// Common sound keys that systems expect
const fallbackKeys = [
'background_music',
// 'background_music',
'music_chill_lofi',
'mayor_anthem',
'zombie_satisfied',

View File

@@ -125,9 +125,11 @@ export class CinematicVoiceSystem {
return new Promise((resolve) => {
utterance.onend = () => {
// Restore music volume
/*
if (this.scene.sound && this.scene.sound.get('background_music')) {
this.duckMusic(1.0, 800); // Restore to 100% over 800ms
}
*/
resolve();
};
});
@@ -251,6 +253,7 @@ export class CinematicVoiceSystem {
* Duck/restore background music volume
*/
duckMusic(targetVolume, duration) {
/*
const music = this.scene.sound.get('background_music');
if (!music) return;
@@ -260,6 +263,7 @@ export class CinematicVoiceSystem {
duration: duration,
ease: 'Sine.easeInOut'
});
*/
}
/**

View File

@@ -144,7 +144,7 @@ export class DrugEconomySystem {
applyMarijuanaAudio(config) {
// Change music to chill variant
const currentMusic = this.scene.sound.get('background_music');
const currentMusic = null; // this.scene.sound.get('background_music');
if (currentMusic) {
// Fade out current
this.scene.tweens.add({
@@ -189,7 +189,7 @@ export class DrugEconomySystem {
duration: 2000,
onComplete: () => {
chillMusic.stop();
this.scene.sound.play('background_music', { loop: true, volume: 0.5 });
// this.scene.sound.play('background_music', { loop: true, volume: 0.5 });
}
});
}

View File

@@ -308,9 +308,9 @@ export class ElectionSystem {
}
// Change music to ordered/military theme
if (this.scene.sound && this.scene.sound.get('background_music')) {
this.scene.sound.get('background_music').stop();
}
// if (this.scene.sound && this.scene.sound.get('background_music')) {
// this.scene.sound.get('background_music').stop();
// }
this.scene.sound.play('mayor_anthem', { loop: true, volume: 0.5 });
// Unlock new features

View File

@@ -16,3 +16,85 @@
[2026-01-16T22:32:55.980Z] CLICK: <CANVAS> "CANVAS" at (575, 456)
[2026-01-16T22:32:56.453Z] CLICK: <CANVAS> "CANVAS" at (575, 457)
[2026-01-16T22:32:56.994Z] CLICK: <CANVAS> "CANVAS" at (576, 458)
[2026-01-17T10:24:35.121Z] CLICK: <CANVAS> "CANVAS" at (579, 460)
[2026-01-17T10:36:14.716Z] CLICK: <CANVAS> "CANVAS" at (908, 487)
[2026-01-17T10:36:33.704Z] CLICK: <CANVAS> "CANVAS" at (748, 393)
[2026-01-17T10:39:00.310Z] CLICK: <CANVAS> "CANVAS" at (913, 580)
[2026-01-17T10:39:11.508Z] CLICK: <CANVAS> "CANVAS" at (915, 567)
[2026-01-17T10:42:30.481Z] CLICK: <CANVAS> "CANVAS" at (900, 486)
[2026-01-17T10:42:38.107Z] CLICK: <CANVAS> "CANVAS" at (857, 434)
[2026-01-17T10:43:47.956Z] CLICK: <CANVAS> "CANVAS" at (956, 208)
[2026-01-17T10:54:13.790Z] CLICK: <CANVAS> "CANVAS" at (804, 508)
[2026-01-17T10:54:16.355Z] CLICK: <CANVAS> "CANVAS" at (804, 499)
[2026-01-17T10:57:29.275Z] CLICK: <CANVAS> "CANVAS" at (752, 393)
[2026-01-17T11:03:23.237Z] CLICK: <CANVAS> "CANVAS" at (672, 273)
[2026-01-17T11:06:00.593Z] CLICK: <CANVAS> "CANVAS" at (751, 387)
[2026-01-17T11:06:10.184Z] CLICK: <CANVAS> "CANVAS" at (871, 182)
[2026-01-17T11:16:59.532Z] CLICK: <CANVAS> "CANVAS" at (781, 354)
[2026-01-17T11:17:00.652Z] CLICK: <CANVAS> "CANVAS" at (702, 440)
[2026-01-17T11:17:00.867Z] CLICK: <CANVAS> "CANVAS" at (701, 440)
[2026-01-17T11:17:01.883Z] CLICK: <CANVAS> "CANVAS" at (750, 467)
[2026-01-17T11:17:02.763Z] CLICK: <CANVAS> "CANVAS" at (679, 470)
[2026-01-17T11:17:03.597Z] CLICK: <CANVAS> "CANVAS" at (680, 469)
[2026-01-17T11:21:58.998Z] CLICK: <CANVAS> "CANVAS" at (605, 332)
[2026-01-17T11:22:11.989Z] CLICK: <CANVAS> "CANVAS" at (696, 192)
[2026-01-17T11:27:05.930Z] ERROR: Uncaught SyntaxError: Missing catch or finally after try at file:///Users/davidkotnik/repos/novafarma/src/scenes/GameScene.js:366
[2026-01-17T11:27:09.191Z] CLICK: <DIV> "DIV" at (765, 394)
[2026-01-17T11:27:11.166Z] CLICK: <BUTTON> "BUTTON" at (479, 455)
[2026-01-17T11:27:11.398Z] ERROR: Uncaught SyntaxError: Missing catch or finally after try at file:///Users/davidkotnik/repos/novafarma/src/scenes/GameScene.js:366
[2026-01-17T11:27:12.151Z] CLICK: <BUTTON> "BUTTON" at (629, 456)
[2026-01-17T11:30:19.856Z] ERROR: Uncaught SyntaxError: Missing catch or finally after try at file:///Users/davidkotnik/repos/novafarma/src/scenes/GameScene.js:560
[2026-01-17T11:30:20.920Z] CLICK: <BUTTON> "BUTTON" at (502, 457)
[2026-01-17T11:30:21.154Z] ERROR: Uncaught SyntaxError: Missing catch or finally after try at file:///Users/davidkotnik/repos/novafarma/src/scenes/GameScene.js:560
[2026-01-17T11:30:23.707Z] CLICK: <DIV> "error-overlay" at (785, 391)
[2026-01-17T11:45:56.635Z] CLICK: <BUTTON> "BUTTON" at (516, 446)
[2026-01-17T11:45:56.884Z] ERROR: Uncaught SyntaxError: Identifier 'spawnPoint' has already been declared at file:///Users/davidkotnik/repos/novafarma/src/scenes/GameScene.js:262
[2026-01-17T11:45:57.768Z] CLICK: <BUTTON> "BUTTON" at (466, 428)
[2026-01-17T11:45:58.001Z] ERROR: Uncaught SyntaxError: Identifier 'spawnPoint' has already been declared at file:///Users/davidkotnik/repos/novafarma/src/scenes/GameScene.js:262
[2026-01-17T11:45:59.385Z] CLICK: <DIV> "DIV" at (725, 397)
[2026-01-17T11:55:11.186Z] CLICK: <BUTTON> "BUTTON" at (485, 445)
[2026-01-17T11:55:11.434Z] ERROR: Uncaught SyntaxError: Identifier 'spawnPoint' has already been declared at file:///Users/davidkotnik/repos/novafarma/src/scenes/GameScene.js:262
[2026-01-17T11:55:12.616Z] CLICK: <BUTTON> "BUTTON" at (465, 439)
[2026-01-17T11:55:12.830Z] ERROR: Uncaught SyntaxError: Identifier 'spawnPoint' has already been declared at file:///Users/davidkotnik/repos/novafarma/src/scenes/GameScene.js:262
[2026-01-17T11:55:14.561Z] ERROR: Uncaught SyntaxError: Identifier 'spawnPoint' has already been declared at file:///Users/davidkotnik/repos/novafarma/src/scenes/GameScene.js:262
[2026-01-17T11:55:18.034Z] CLICK: <DIV> "DIV" at (784, 383)
[2026-01-17T11:59:37.275Z] CLICK: <BUTTON> "BUTTON" at (490, 455)
[2026-01-17T11:59:37.506Z] ERROR: Uncaught SyntaxError: Identifier 'spawnPoint' has already been declared at file:///Users/davidkotnik/repos/novafarma/src/scenes/GameScene.js:262
[2026-01-17T11:59:38.026Z] CLICK: <BUTTON> "BUTTON" at (495, 453)
[2026-01-17T11:59:38.258Z] ERROR: Uncaught SyntaxError: Identifier 'spawnPoint' has already been declared at file:///Users/davidkotnik/repos/novafarma/src/scenes/GameScene.js:262
[2026-01-17T12:03:57.336Z] CLICK: <BUTTON> "BUTTON" at (481, 431)
[2026-01-17T12:03:57.574Z] ERROR: Uncaught SyntaxError: Identifier 'spawnPoint' has already been declared at file:///Users/davidkotnik/repos/novafarma/src/scenes/GameScene.js:262
[2026-01-17T12:03:58.262Z] CLICK: <BUTTON> "BUTTON" at (498, 448)
[2026-01-17T12:03:58.513Z] ERROR: Uncaught SyntaxError: Identifier 'spawnPoint' has already been declared at file:///Users/davidkotnik/repos/novafarma/src/scenes/GameScene.js:262
[2026-01-17T23:16:02.945Z] CLICK: <BUTTON> "BUTTON" at (529, 475)
[2026-01-17T23:16:03.208Z] ERROR: Uncaught SyntaxError: Identifier 'spawnPoint' has already been declared at file:///Users/davidkotnik/repos/novafarma/src/scenes/GameScene.js:262
[2026-01-17T23:16:14.426Z] CLICK: <DIV> "error-overlay" at (787, 383)
[2026-01-17T23:20:29.984Z] ERROR: Uncaught SyntaxError: Identifier 'spawnPoint' has already been declared at file:///Users/davidkotnik/repos/novafarma/src/scenes/GameScene.js:262
[2026-01-17T23:20:33.110Z] CLICK: <BUTTON> "BUTTON" at (505, 427)
[2026-01-17T23:20:33.344Z] ERROR: Uncaught SyntaxError: Identifier 'spawnPoint' has already been declared at file:///Users/davidkotnik/repos/novafarma/src/scenes/GameScene.js:262
[2026-01-17T23:20:54.992Z] ERROR: Uncaught SyntaxError: Identifier 'spawnPoint' has already been declared at file:///Users/davidkotnik/repos/novafarma/src/scenes/GameScene.js:262
[2026-01-17T23:21:01.475Z] CLICK: <DIV> "DIV" at (693, 391)
[2026-01-17T23:26:19.741Z] CLICK: <DIV> "error-overlay" at (830, 594)
[2026-01-18T03:13:42.954Z] CLICK: <CANVAS> "CANVAS" at (926, 561)
[2026-01-18T03:51:45.932Z] CLICK: <CANVAS> "CANVAS" at (728, 474)
[2026-01-18T03:51:52.937Z] CLICK: <CANVAS> "CANVAS" at (526, 231)
[2026-01-18T03:54:15.247Z] CLICK: <CANVAS> "CANVAS" at (671, 443)
[2026-01-18T04:00:22.297Z] CLICK: <CANVAS> "CANVAS" at (828, 439)
[2026-01-18T04:09:12.192Z] ERROR: Uncaught SyntaxError: Unexpected token '{' at file:///Users/davidkotnik/repos/novafarma/src/scenes/GameScene.js:12
[2026-01-18T04:09:14.290Z] CLICK: <BUTTON> "BUTTON" at (454, 441)
[2026-01-18T04:09:14.528Z] ERROR: Uncaught SyntaxError: Unexpected token '{' at file:///Users/davidkotnik/repos/novafarma/src/scenes/GameScene.js:12
[2026-01-18T04:09:16.300Z] CLICK: <DIV> "DIV" at (553, 320)
[2026-01-18T04:09:16.949Z] CLICK: <STRONG> "STRONG" at (387, 280)
[2026-01-18T04:09:18.427Z] CLICK: <DIV> "DIV" at (782, 384)
[2026-01-18T04:11:43.897Z] CLICK: <BUTTON> "BUTTON" at (502, 462)
[2026-01-18T04:16:06.619Z] CLICK: <CANVAS> "CANVAS" at (646, 279)
[2026-01-18T04:17:46.019Z] CLICK: <CANVAS> "CANVAS" at (653, 239)
[2026-01-18T04:18:36.517Z] CLICK: <CANVAS> "CANVAS" at (738, 407)
[2026-01-18T04:18:37.684Z] CLICK: <CANVAS> "CANVAS" at (577, 274)
[2026-01-18T04:18:38.400Z] CLICK: <CANVAS> "CANVAS" at (572, 272)
[2026-01-18T04:18:41.734Z] CLICK: <CANVAS> "CANVAS" at (607, 315)
[2026-01-18T04:22:12.641Z] CLICK: <CANVAS> "CANVAS" at (667, 402)
[2026-01-18T04:23:07.307Z] CLICK: <CANVAS> "CANVAS" at (667, 385)
[2026-01-18T04:23:13.882Z] CLICK: <CANVAS> "CANVAS" at (683, 396)
[2026-01-18T04:26:59.179Z] ERROR: Uncaught SyntaxError: Unexpected token '{' at file:///Users/davidkotnik/repos/novafarma/src/scenes/GameScene.js:62
[2026-01-18T04:27:03.450Z] CLICK: <DIV> "DIV" at (583, 395)