ソースを参照

cleaned up sound module

tags/v0.7.0^2
Shaun 4年前
コミット
a41e8dc794
3個のファイルの変更174行の追加122行の削除
  1. +11
    -6
      src/client/js/components/sound.js
  2. +129
    -101
      src/client/js/sound/sound.js
  3. +34
    -15
      src/server/components/sound.js

+ 11
- 6
src/client/js/components/sound.js ファイルの表示

@@ -10,9 +10,12 @@ define([
volume: 0,

init: function () {
const { obj: { zoneId, x, y, width, height, area }, sound, volume, minDistance, fadeInOut, defaultMusic } = this;
const {
sound, volume, music, defaultMusic,
obj: { zoneId, x, y, width, height, area }
} = this;

soundManager.addSoundFromConfig({
const config = {
scope: zoneId,
file: sound,
volume,
@@ -21,10 +24,12 @@ define([
w: width,
h: height,
area,
minDistance,
fadeInOut,
defaultMusic
});
music,
defaultMusic,
loop: true
};

soundManager.addSound(config);
}
};
});

+ 129
- 101
src/client/js/sound/sound.js ファイルの表示

@@ -12,6 +12,9 @@ define([
globals
) {
const globalScopes = ['ui'];
const minDistance = 10;
const globalVolume = 0.3;
const fadeDuration = 3000;

return {
sounds: [],
@@ -26,7 +29,12 @@ define([

Object.entries(loadSounds).forEach(([ scope, soundList ]) => {
soundList.forEach(({ name: soundName, file }) => {
this.addOtherSound(scope, soundName, file);
this.addSound({
name: soundName,
file,
scope: 'ui',
autoLoad: true
});
});
});

@@ -58,105 +66,128 @@ define([
soundEntry.sound.play();
},

update: function (playerX, playerY) {
this.sounds.forEach((s, i) => {
const { x, y, w, area, sound, minDistance, fadeInOut } = s;
playSoundHelper: function (soundEntry, volume = 1) {
const { sound, music } = soundEntry;

if (!sound) {
const { file, loop } = soundEntry;

soundEntry.sound = this.loadSound(file, loop, true, volume);

return;
}

let volume = 0;
volume *= globalVolume;

if (sound.playing()) {
if (music)
sound.fade(sound.volume(), volume, fadeDuration);
else
sound.volume(volume);
} else {
sound.volume(0);
sound.play();

if (music)
sound.fade(0, volume, fadeDuration);
else
sound.volume(volume);
}
},

stopSoundHelper: function (soundEntry) {
const { sound, music } = soundEntry;

if (!sound || !sound.playing())
return;

if (music)
sound.fade(sound.volume(), 0, fadeDuration);
else
sound.volume(0);
},

if (!w) {
updateSounds: function (playerX, playerY) {
this.sounds.forEach(s => {
const { x, y, area, music, scope } = s;

if (music || scope === 'ui')
return;

let distance = 0;

if (!area) {
let dx = Math.abs(x - playerX);
if (dx >= minDistance) {
if (sound)
sound.volume(0);
return;
}
let dy = Math.abs(y - playerY);
if (dy >= minDistance) {
if (sound)
sound.volume(0);
return;
}

let dist = minDistance - Math.max(dx, dy);
dist = (dist * dist) / Math.pow(minDistance, 2);
volume = 0.3 * dist;
} else if (physics.isInPolygon(playerX, playerY, area))
volume = 0.3;
else {
let distance = physics.distanceToPolygon([playerX, playerY], area);
if (distance >= minDistance) {
if (sound) {
if (fadeInOut) {
sound.fade(sound.volume(), 0, 3000);

//Start the default audio if default audio is before us in the list and playing
const defaultAudio = this.sounds.find(f => f.defaultMusic);
const defaultAudioBefore = this.sounds.findIndex(f => f === defaultAudio) < i;
if (defaultAudioBefore && defaultAudio.sound)
defaultAudio.sound.fade(defaultAudio.sound.volume(), 0.3 * defaultAudio.volume, 3000);
} else
sound.volume(0);
}
return;
}

let dist = minDistance - distance;
dist = (dist * dist) / Math.pow(minDistance, 2);
volume = 0.3 * dist;
distance = Math.max(dx, dy);
} else if (!physics.isInPolygon(playerX, playerY, area))
distance = physics.distanceToPolygon([playerX, playerY], area);
if (distance > minDistance) {
this.stopSoundHelper(s);

return;
}

if (!sound) {
const file = s.file.includes('server') ? s.file : `audio/${s.file}`;
//eslint-disable-next-line no-undef
s.sound = new Howl({
src: [file],
autoplay: true,
loop: true,
volume: 0
});
//Exponential fall-off
const volume = s.volume * (1 - (Math.pow(distance, 2) / Math.pow(minDistance, 2)));
this.playSoundHelper(s, volume);
});
},

if (this.muted)
s.sound.mute(true);
}
updateMusic: function (playerX, playerY) {
const sounds = this.sounds;

const areaMusic = sounds.filter(s => s.music && s.area);
const currentMusic = areaMusic.find(s => physics.isInPolygon(playerX, playerY, s.area));
const defaultMusic = sounds.find(s => s.music && s.defaultMusic);

if (this.muted)
if (!currentMusic) {
this.playSoundHelper(defaultMusic);

const activeMusic = sounds.filter(s => s !== defaultMusic && s.sound && s.sound.playing());
activeMusic.forEach(s => this.stopSoundHelper(s));
} else {
this.stopSoundHelper(defaultMusic);
this.playSoundHelper(currentMusic);
}

this.sounds.forEach(s => {
const { x, y, area, music, scope } = s;

if (music || scope === 'ui')
return;

if (s.defaultMusic) {
//Only play if no other music is playing
const musicPlaying = this.sounds.some(f => f.sound && f.fadeInOut && f.sound.playing());
if (musicPlaying)
volume = 0;
else
volume = 1;
} else if (s.fadeInOut) {
//Stop the default audio if default audio is before us in the list and playing
const defaultAudio = this.sounds.find(f => f.defaultMusic);
const defaultAudioBefore = this.sounds.findIndex(f => f === defaultAudio) < i;
if (defaultAudioBefore && defaultAudio.sound && defaultAudio.sound.playing())
defaultAudio.sound.fade(defaultAudio.sound.volume(), 0, 3000);
}
let distance = 0;

const oldVolume = s.sound.volume();
const newVolume = volume * s.volume;
const volumeChanged = newVolume !== oldVolume;
if (!area) {
let dx = Math.abs(x - playerX);
let dy = Math.abs(y - playerY);
distance = Math.max(dx, dy);
} else if (!physics.isInPolygon(playerX, playerY, area))
distance = physics.distanceToPolygon([playerX, playerY], area);
if (distance > minDistance) {
this.stopSoundHelper(s);

if (volumeChanged) {
if (fadeInOut)
s.sound.fade(oldVolume, newVolume, 3000);
else
s.sound.volume(newVolume);
return;
}

//Exponential fall-off
const volume = s.volume * (1 - (Math.pow(distance, 2) / Math.pow(minDistance, 2)));
this.playSoundHelper(s, volume);
});
},

addSound: function (scope, file, volume, x, y, w, h, area) {
this.addSoundFromConfig({ scope, file, volume, x, y, w, h, area });
update: function (playerX, playerY) {
this.updateSounds(playerX, playerY);
this.updateMusic(playerX, playerY);
},

addSoundFromConfig: function ({ scope, file, volume, x, y, w, h, area, minDistance, fadeInOut, defaultMusic }) {
addSound: function (
{ name: soundName, scope, file, volume = 1, x, y, w, h, area, music, defaultMusic, autoLoad, loop }
) {
if (!area && w) {
area = [
[x, y],
@@ -166,39 +197,37 @@ define([
];
}

const sound = {
let sound = null;
if (autoLoad)
sound = this.loadSound(file, loop);

const soundEntry = {
name: soundName,
sound,
scope,
file,
loop,
x,
y,
w,
h,
volume,
area,
sound: null,
scope,
minDistance,
fadeInOut,
music,
defaultMusic
};

this.sounds.push(sound);
this.sounds.push(soundEntry);
},

addOtherSound: function (scope, soundName, file) {
loadSound: function (file, loop = false, autoplay = false, volume = 1) {
//eslint-disable-next-line no-undef
const sound = new Howl({
src: [file],
volume: 1
volume,
loop,
autoplay
});

const soundEntry = {
name: soundName,
file,
sound,
scope: 'ui'
};

this.sounds.push(soundEntry);
return sound;
},

onToggleAudio: function (isAudioOn) {
@@ -215,7 +244,6 @@ define([
return;
const { player: { x, y } } = window;

this.update(x, y);
}
};


+ 34
- 15
src/server/components/sound.js ファイルの表示

@@ -1,22 +1,41 @@
const serializeProps = [
'sound',
'defaultMusic',
'volume',
'music'
];

module.exports = {
type: 'sound',

sound: null,
volume: 0,
minDistance: 10,
fadeInOut: false,
defaultMusic: false,
simplified: null,

buildSimplified: function () {
const s = Object.fromEntries(
serializeProps
.map(p => {
if (!this.has(p))
return null;

return [p, this[p]];
})
.filter(p => !!p)
);

s.type = 'sound';

let file = s.sound;
if (!file.includes('server'))
file = 'audio/' + file;
s.sound = file;

this.simplified = s;
},

simplify: function () {
const { sound, volume, minDistance, fadeInOut, defaultMusic } = this;

return {
type: 'sound',
sound,
volume,
minDistance,
fadeInOut,
defaultMusic
};
if (!this.simplified)
this.buildSimplified();

return this.simplified;
}
};

読み込み中…
キャンセル
保存