138 lines
4.4 KiB
JavaScript
138 lines
4.4 KiB
JavaScript
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);
|
|
}
|
|
}
|
|
}
|