class WorldEventSystem { constructor(scene) { this.scene = scene; this.activeEvents = []; this.bats = []; this.owl = null; } /* * BATS: Visual effect for evening/night */ spawnBatSwarm() { console.log('🦇 Bat Swarm Incoming!'); const count = 10 + Math.floor(Math.random() * 10); for (let i = 0; i < count; i++) { // Start right-side of screen, random height const sx = this.scene.scale.width + 50 + Math.random() * 200; const sy = Math.random() * (this.scene.scale.height / 2); // Top half const bat = this.scene.add.sprite(sx, sy, 'bat'); bat.setDepth(2000); // Above most things bat.setScrollFactor(0); // Screen space (UI layer) or World space? // Better world space if we want them to feel like part of the world, but screen space is easier for "effect". // Let's stick to Screen Space for "Ambience". // Random speed const speed = 150 + Math.random() * 100; this.bats.push({ sprite: bat, speed: speed }); } } /* * NIGHT OWL: Delivers a gift */ spawnNightOwl() { if (this.owl) return; // Only one at a time console.log('🦉 Night Owl Arriving!'); // Spawn top-left const sx = -50; const sy = 100; const owl = this.scene.add.sprite(sx, sy, 'owl'); owl.setDepth(2000); owl.setScrollFactor(0); // Screen space for delivery this.owl = { sprite: owl, state: 'ARRIVING', // ARRIVING, DELIVERING, LEAVING timer: 0, targetX: this.scene.scale.width / 2, targetY: this.scene.scale.height / 3 }; if (this.scene.soundManager) { // Play owl hoot sound (placeholder or generic) // this.scene.soundManager.playHoot(); } this.scene.events.emit('show-floating-text', { x: this.scene.player.sprite.x, y: this.scene.player.sprite.y - 120, text: '🦉 Hoot Hoot!', color: '#FFA500' }); } update(delta) { // 1. Bats for (let i = this.bats.length - 1; i >= 0; i--) { const b = this.bats[i]; b.sprite.x -= b.speed * (delta / 1000); // Fly left b.sprite.y += (Math.sin(b.sprite.x * 0.02) * 2); // Wobbly flight if (b.sprite.x < -50) { b.sprite.destroy(); this.bats.splice(i, 1); } } // 2. Owl if (this.owl) { const o = this.owl; const speed = 200 * (delta / 1000); if (o.state === 'ARRIVING') { const dx = o.targetX - o.sprite.x; const dy = o.targetY - o.sprite.y; const dist = Math.sqrt(dx * dx + dy * dy); if (dist < 10) { o.state = 'DELIVERING'; o.timer = 0; this.dropGift(); } else { o.sprite.x += (dx / dist) * speed; o.sprite.y += (dy / dist) * speed; } } else if (o.state === 'DELIVERING') { o.timer += delta; if (o.timer > 1000) { // Hover for 1s o.state = 'LEAVING'; } } else if (o.state === 'LEAVING') { o.sprite.x += speed; // Fly right o.sprite.y -= speed * 0.5; // Fly up if (o.sprite.x > this.scene.scale.width + 50) { o.sprite.destroy(); this.owl = null; } } } } dropGift() { console.log('🎁 Owl dropped a gift!'); const p = this.scene.player; // Spawn loot at player pos (World Space) if (this.scene.interactionSystem) { // Random gift: Gold or maybe a rare item const r = Math.random(); let item = 'flower_red'; let count = 1; if (r < 0.3) { item = 'coin_gold'; count = 10; } else if (r < 0.6) { item = 'seeds_corn'; count = 5; } else if (r < 0.9) { item = 'item_scrap'; count = 3; } else { item = 'artefact_old'; count = 1; } // Rare! this.scene.interactionSystem.spawnLoot(p.gridX, p.gridY, item, count); } } }