47 lines
1.7 KiB
JavaScript
47 lines
1.7 KiB
JavaScript
import BaseEffectSource from "./base-effect-source.mjs";
|
|
import PointEffectSourceMixin from "./point-effect-source.mjs";
|
|
|
|
/**
|
|
* A specialized subclass of the BaseEffectSource which describes a point-based source of sound.
|
|
* @extends {BaseEffectSource}
|
|
* @mixes {PointEffectSource}
|
|
*/
|
|
export default class PointSoundSource extends PointEffectSourceMixin(BaseEffectSource) {
|
|
|
|
/** @override */
|
|
static sourceType = "sound";
|
|
|
|
/** @override */
|
|
get effectsCollection() {
|
|
return canvas.sounds.sources;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
/** @inheritDoc */
|
|
_getPolygonConfiguration() {
|
|
return Object.assign(super._getPolygonConfiguration(), {useThreshold: true});
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
/**
|
|
* Get the effective volume at which an AmbientSound source should be played for a certain listener.
|
|
* @param {Point} listener
|
|
* @param {object} [options]
|
|
* @param {boolean} [options.easing]
|
|
* @returns {number}
|
|
*/
|
|
getVolumeMultiplier(listener, {easing=true}={}) {
|
|
if ( !listener ) return 0; // No listener = 0
|
|
const {x, y, radius} = this.data;
|
|
const distance = Math.hypot(listener.x - x, listener.y - y);
|
|
if ( distance === 0 ) return 1;
|
|
if ( distance > radius ) return 0; // Distance outside of radius = 0
|
|
if ( !this.shape?.contains(listener.x, listener.y) ) return 0; // Point outside of shape = 0
|
|
if ( !easing ) return 1; // No easing = 1
|
|
const dv = Math.clamp(distance, 0, radius) / radius;
|
|
return (Math.cos(Math.PI * dv) + 1) * 0.5; // Cosine easing [0, 1]
|
|
}
|
|
}
|