182 lines
4.8 KiB
JavaScript
182 lines
4.8 KiB
JavaScript
/**
|
|
* AudioTriggerSystem.js
|
|
* Spatial audio triggers - play sound once when player enters area
|
|
*/
|
|
|
|
class AudioTriggerSystem {
|
|
constructor(scene) {
|
|
this.scene = scene;
|
|
|
|
// Active triggers
|
|
this.triggers = new Map();
|
|
|
|
// Triggered history (to prevent re-triggering)
|
|
this.triggered = new Set();
|
|
|
|
console.log('🔊 AudioTriggerSystem initialized');
|
|
}
|
|
|
|
/**
|
|
* Add a spatial audio trigger
|
|
* @param {number} x - Grid X position
|
|
* @param {number} y - Grid Y position
|
|
* @param {string} audioKey - Audio file key
|
|
* @param {object} options - Additional options
|
|
*/
|
|
addTrigger(x, y, audioKey, options = {}) {
|
|
const triggerId = `${x},${y}`;
|
|
|
|
const trigger = {
|
|
x,
|
|
y,
|
|
audioKey,
|
|
radius: options.radius || 0, // 0 = exact tile only
|
|
volume: options.volume || 1.0,
|
|
oneTime: options.oneTime !== false, // Default true
|
|
delay: options.delay || 0, // Delay before playing (ms)
|
|
callback: options.callback || null, // Optional callback after playing
|
|
visualDebug: options.visualDebug || false
|
|
};
|
|
|
|
this.triggers.set(triggerId, trigger);
|
|
|
|
// Add visual debug marker if enabled
|
|
if (trigger.visualDebug && this.scene.add) {
|
|
const worldX = x * 48 + 24;
|
|
const worldY = y * 48 + 24;
|
|
|
|
const circle = this.scene.add.circle(worldX, worldY, 20, 0x00ff00, 0.3);
|
|
circle.setDepth(1000);
|
|
|
|
const text = this.scene.add.text(worldX, worldY - 30, '🔊', {
|
|
fontSize: '20px',
|
|
color: '#00ff00'
|
|
});
|
|
text.setOrigin(0.5);
|
|
text.setDepth(1001);
|
|
}
|
|
|
|
console.log(`✅ Audio trigger added at (${x}, ${y}): ${audioKey}`);
|
|
|
|
return triggerId;
|
|
}
|
|
|
|
/**
|
|
* Remove a trigger
|
|
*/
|
|
removeTrigger(triggerId) {
|
|
this.triggers.delete(triggerId);
|
|
this.triggered.delete(triggerId);
|
|
}
|
|
|
|
/**
|
|
* Reset trigger (allow re-triggering)
|
|
*/
|
|
resetTrigger(triggerId) {
|
|
this.triggered.delete(triggerId);
|
|
}
|
|
|
|
/**
|
|
* Reset all triggers
|
|
*/
|
|
resetAll() {
|
|
this.triggered.clear();
|
|
}
|
|
|
|
/**
|
|
* Check if player is in trigger zone
|
|
*/
|
|
checkTrigger(playerX, playerY) {
|
|
const playerGridX = Math.floor(playerX / 48);
|
|
const playerGridY = Math.floor(playerY / 48);
|
|
|
|
this.triggers.forEach((trigger, triggerId) => {
|
|
// Skip if already triggered and it's one-time only
|
|
if (trigger.oneTime && this.triggered.has(triggerId)) {
|
|
return;
|
|
}
|
|
|
|
// Check distance
|
|
const dx = Math.abs(playerGridX - trigger.x);
|
|
const dy = Math.abs(playerGridY - trigger.y);
|
|
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
|
|
if (distance <= trigger.radius) {
|
|
// TRIGGER!
|
|
this.activateTrigger(trigger, triggerId);
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Activate a trigger (play audio)
|
|
*/
|
|
activateTrigger(trigger, triggerId) {
|
|
console.log(`🔊 TRIGGER ACTIVATED: ${triggerId} (${trigger.audioKey})`);
|
|
|
|
// Mark as triggered
|
|
this.triggered.add(triggerId);
|
|
|
|
// Play audio after delay
|
|
if (trigger.delay > 0) {
|
|
this.scene.time.delayedCall(trigger.delay, () => {
|
|
this.playAudio(trigger);
|
|
});
|
|
} else {
|
|
this.playAudio(trigger);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Play audio for trigger
|
|
*/
|
|
playAudio(trigger) {
|
|
// Check if audio exists
|
|
if (!this.scene.cache.audio.exists(trigger.audioKey)) {
|
|
console.warn(`⚠️ Audio not found: ${trigger.audioKey}`);
|
|
return;
|
|
}
|
|
|
|
// Play sound
|
|
const sound = this.scene.sound.add(trigger.audioKey, {
|
|
volume: trigger.volume
|
|
});
|
|
|
|
sound.play();
|
|
|
|
// Visual feedback (optional)
|
|
if (trigger.visualDebug) {
|
|
const worldX = trigger.x * 48 + 24;
|
|
const worldY = trigger.y * 48 + 24;
|
|
|
|
const flash = this.scene.add.circle(worldX, worldY, 30, 0xffff00, 0.8);
|
|
flash.setDepth(1002);
|
|
|
|
this.scene.tweens.add({
|
|
targets: flash,
|
|
alpha: 0,
|
|
scale: 2,
|
|
duration: 500,
|
|
ease: 'Quad.Out',
|
|
onComplete: () => flash.destroy()
|
|
});
|
|
}
|
|
|
|
// Callback
|
|
if (trigger.callback) {
|
|
trigger.callback();
|
|
}
|
|
|
|
console.log(`✅ Audio played: ${trigger.audioKey}`);
|
|
}
|
|
|
|
/**
|
|
* Update - called every frame
|
|
*/
|
|
update(playerX, playerY) {
|
|
if (this.triggers.size === 0) return;
|
|
|
|
this.checkTrigger(playerX, playerY);
|
|
}
|
|
}
|