add audio options, improve sfx handling code

This commit is contained in:
Omsi 2020-06-14 22:01:26 -07:00
parent 78f6351dea
commit c7c04e664e
17 changed files with 115 additions and 46 deletions

BIN
audio/Fix Infinity.wav Normal file

Binary file not shown.

BIN
audio/Tab changed deep.wav Normal file

Binary file not shown.

View File

@ -369,6 +369,7 @@
<script type="text/javascript" src="javascripts/components/modals/modal-start-eternity-challenge.js"></script> <script type="text/javascript" src="javascripts/components/modals/modal-start-eternity-challenge.js"></script>
<script type="text/javascript" src="javascripts/components/modals/options/modal-options.js"></script> <script type="text/javascript" src="javascripts/components/modals/options/modal-options.js"></script>
<script type="text/javascript" src="javascripts/components/modals/options/modal-news-options.js"></script> <script type="text/javascript" src="javascripts/components/modals/options/modal-news-options.js"></script>
<script type="text/javascript" src="javascripts/components/modals/options/modal-audio-options.js"></script>
<script type="text/javascript" src="javascripts/components/modals/options/modal-animation-options.js"></script> <script type="text/javascript" src="javascripts/components/modals/options/modal-animation-options.js"></script>
<script type="text/javascript" src="javascripts/components/modals/options/modal-confirmation-options.js"></script> <script type="text/javascript" src="javascripts/components/modals/options/modal-confirmation-options.js"></script>
<script type="text/javascript" src="javascripts/components/modals/options/modal-info-display-options.js"></script> <script type="text/javascript" src="javascripts/components/modals/options/modal-info-display-options.js"></script>

View File

@ -0,0 +1,59 @@
"use strict";
Vue.component("modal-audio-options", {
data() {
return {
dimensionBoost: 0,
antimatterGalaxy: 0,
glyphMoved: 0,
tabChanged: 0,
achievementUnlocked: 0,
breakInfinity: 0,
fixInfinity: 0
};
},
computed: {
sounds() {
return GameDatabase.sounds;
}
},
methods: {
update() {
const sounds = Object.keys(this.$data);
const options = player.options.audio;
for (const sound of sounds) {
this[sound] = options[sound];
}
},
updateOption(sound) {
const name = `${sound.name.camelize()}`;
player.options.audio[name] = (player.options.audio[name] + 1) % this.getLabels(sound.options).length;
},
getText(name) {
return `${name}: `;
},
getLabels(options) {
if (options) {
const labels = options.distinct();
labels.unshift("Off");
return labels;
}
return ["Off", "On"];
},
getButtonText(sound) {
const labelIndex = this[`${sound.name.camelize()}`];
return `${sound.name}: ${this.getLabels(sound.options)[labelIndex]}`;
}
},
template: `
<modal-options @close="emitClose">
<primary-button
v-for="(sound, index) in sounds"
:key="index"
@click="updateOption(sound)"
class="o-primary-btn--option"
>
{{ getButtonText(sound) }}
</primary-button>
</modal-options>`
});

View File

@ -119,6 +119,10 @@ Vue.component("options-visual-tab", {
class="o-primary-btn--option" class="o-primary-btn--option"
onclick="Modal.infoDisplayOptions.show()" onclick="Modal.infoDisplayOptions.show()"
>Open Info Display Options</options-button> >Open Info Display Options</options-button>
<options-button
class="o-primary-btn--option"
onclick="Modal.audioOptions.show();"
>Open Audio Options</options-button>
</div> </div>
<p onclick="Modal.shortcuts.show()" class="c-options-tab__shortcuts-link"> <p onclick="Modal.shortcuts.show()" class="c-options-tab__shortcuts-link">
Press <kbd>?</kbd> to open shortcut list. Press <kbd>?</kbd> to open shortcut list.

View File

@ -54,6 +54,7 @@ class ChallengeConfirmationModal extends Modal {
Modal.h2p = new Modal("modal-h2p"); Modal.h2p = new Modal("modal-h2p");
Modal.shortcuts = new Modal("modal-shortcuts"); Modal.shortcuts = new Modal("modal-shortcuts");
Modal.newsOptions = new Modal("modal-news-options"); Modal.newsOptions = new Modal("modal-news-options");
Modal.audioOptions = new Modal("modal-audio-options");
Modal.animationOptions = new Modal("modal-animation-options"); Modal.animationOptions = new Modal("modal-animation-options");
Modal.confirmationOptions = new Modal("modal-confirmation-options"); Modal.confirmationOptions = new Modal("modal-confirmation-options");
Modal.infoDisplayOptions = new Modal("modal-info-display-options"); Modal.infoDisplayOptions = new Modal("modal-info-display-options");

View File

@ -97,7 +97,12 @@ function safeCall(fn) {
} }
String.prototype.capitalize = function() { String.prototype.capitalize = function() {
return this.toLowerCase().replace(/^\w/, c => c.toUpperCase()); return this.toLowerCase().replace(/^\w/u, c => c.toUpperCase());
};
String.prototype.camelize = function() {
// eslint-disable-next-line no-unused-vars
return this.toLowerCase().replace(/[^a-zA-Z0-9]+(.)/gu, (x, char) => char.toUpperCase());
}; };
String.prototype.splice = function(start, delCount, newSubStr) { String.prototype.splice = function(start, delCount, newSubStr) {

View File

@ -506,6 +506,15 @@ let player = {
AIChance: 0, AIChance: 0,
speed: 1 speed: 1
}, },
audio: {
dimensionBoost: 0,
antimatterGalaxy: 0,
glyphMoved: 0,
tabChanged: 0,
achievementUnlocked: 0,
breakInfinity: 0,
fixInfinity: 0
},
notation: "Mixed scientific", notation: "Mixed scientific",
retryChallenge: false, retryChallenge: false,
retryCelestial: false, retryCelestial: false,

View File

@ -541,6 +541,7 @@ const Glyphs = {
this.updateRealityGlyphEffects(); this.updateRealityGlyphEffects();
this.updateGlyphCountForV(); this.updateGlyphCountForV();
EventHub.dispatch(GAME_EVENT.GLYPHS_CHANGED); EventHub.dispatch(GAME_EVENT.GLYPHS_CHANGED);
EventHub.dispatch(GAME_EVENT.GLYPHS_MOVED);
this.validate(); this.validate();
}, },
unequipAll() { unequipAll() {
@ -554,6 +555,7 @@ const Glyphs = {
this.updateRealityGlyphEffects(); this.updateRealityGlyphEffects();
this.updateGlyphCountForV(); this.updateGlyphCountForV();
EventHub.dispatch(GAME_EVENT.GLYPHS_CHANGED); EventHub.dispatch(GAME_EVENT.GLYPHS_CHANGED);
EventHub.dispatch(GAME_EVENT.GLYPHS_MOVED);
}, },
unequip(activeIndex, requestedInventoryIndex) { unequip(activeIndex, requestedInventoryIndex) {
if (this.active[activeIndex] === null) return; if (this.active[activeIndex] === null) return;
@ -565,6 +567,7 @@ const Glyphs = {
this.updateRealityGlyphEffects(); this.updateRealityGlyphEffects();
this.updateGlyphCountForV(); this.updateGlyphCountForV();
EventHub.dispatch(GAME_EVENT.GLYPHS_CHANGED); EventHub.dispatch(GAME_EVENT.GLYPHS_CHANGED);
EventHub.dispatch(GAME_EVENT.GLYPHS_MOVED);
}, },
updateRealityGlyphEffects() { updateRealityGlyphEffects() {
// There should only be one reality glyph; this picks one pseudo-randomly if multiple are cheated/glitched in // There should only be one reality glyph; this picks one pseudo-randomly if multiple are cheated/glitched in
@ -591,6 +594,7 @@ const Glyphs = {
this.inventory[targetSlot] = glyph; this.inventory[targetSlot] = glyph;
glyph.idx = targetSlot; glyph.idx = targetSlot;
EventHub.dispatch(GAME_EVENT.GLYPHS_CHANGED); EventHub.dispatch(GAME_EVENT.GLYPHS_CHANGED);
EventHub.dispatch(GAME_EVENT.GLYPHS_MOVED);
} else { } else {
throw new Error("Attempted glyph move into non-empty slot"); throw new Error("Attempted glyph move into non-empty slot");
} }
@ -606,6 +610,7 @@ const Glyphs = {
glyphB.idx = swapGlyph; glyphB.idx = swapGlyph;
this.validate(); this.validate();
EventHub.dispatch(GAME_EVENT.GLYPHS_CHANGED); EventHub.dispatch(GAME_EVENT.GLYPHS_CHANGED);
EventHub.dispatch(GAME_EVENT.GLYPHS_MOVED);
}, },
addToInventory(glyph, requestedInventoryIndex) { addToInventory(glyph, requestedInventoryIndex) {
this.validate(); this.validate();

View File

@ -2,39 +2,32 @@
GameDatabase.sounds = [ GameDatabase.sounds = [
{ {
id: 1, name: "Dimension Boost",
fileName: "dimension_boost", checkEvent: GAME_EVENT.DIMBOOST_AFTER
checkRequirement: () => true,
checkEvent: GameEvent.DIMBOOST_AFTER
}, },
{ {
id: 2, name: "Antimatter Galaxy",
fileName: "galaxy", checkEvent: GAME_EVENT.GALAXY_RESET_AFTER
checkRequirement: () => true,
checkEvent: GameEvent.GALAXY_RESET_AFTER
}, },
{ {
id: 3, name: "Glyph moved",
fileName: "glyphs_changed", checkEvent: GAME_EVENT.GLYPHS_MOVED
checkRequirement: () => true,
checkEvent: GameEvent.GLYPHS_CHANGED
}, },
{ {
id: 4, name: "Tab changed",
fileName: "tab_change", options: ["Clicky", "Deep"],
checkRequirement: () => true, checkEvent: GAME_EVENT.TAB_CHANGED
checkEvent: GameEvent.TAB_CHANGED
}, },
{ {
id: 5, name: "Achievement unlocked",
fileName: "achievement_unlocked", checkEvent: GAME_EVENT.ACHIEVEMENT_UNLOCKED
checkRequirement: () => true,
checkEvent: GameEvent.ACHIEVEMENT_UNLOCKED
}, },
{ {
id: 6, name: "Break Infinity",
fileName: "break_infinity", checkEvent: GAME_EVENT.BREAK_INFINITY
checkRequirement: () => true, },
checkEvent: GameEvent.BREAK_INFINITY {
name: "Fix Infinity",
checkEvent: GAME_EVENT.FIX_INFINITY
}, },
]; ];

View File

@ -1,40 +1,32 @@
"use strict"; "use strict";
class SoundEffectState { class SoundEffectState extends GameMechanicState {
constructor(config) { constructor(config) {
if (!config) throw new Error("Must specify config for SoundEffectState"); super(config);
this.config = config; this.registerEvents(config.checkEvent, args => this.tryPlay(args));
} }
static createIndex(gameData) { tryPlay() {
this.index = mapGameData(gameData, config => new this(config)); const option = player.options.audio[this.config.name.camelize()];
} if (option === 0) return;
const path = this.config.options
play() { ? `audio/${this.config.name} ${this.config.options[option - 1].toLowerCase()}.wav`
const sound = new Audio(`audio/${this.config.fileName}.wav`); : `audio/${this.config.name}.wav`;
const sound = new Audio(path);
sound.volume = 0.5; sound.volume = 0.5;
sound.play(); sound.play();
} }
} }
SoundEffectState.createIndex(GameDatabase.sounds);
/** /**
* @param {number} id * @param {number} id
* @returns {SoundEffectState} * @returns {SoundEffectState}
*/ */
const SoundEffect = id => SoundEffectState.index[id]; const SoundEffect = SoundEffectState.createAccessor(GameDatabase.sounds);
const SoundEffects = { const SoundEffects = {
/** /**
* @type {SoundEffectState[]} * @type {SoundEffectState[]}
*/ */
all: SoundEffectState.index.compact() all: SoundEffect.index.compact()
}; };
EventHub.registerStateCollectionEvents(
SoundEffects.all,
sound => sound.config.checkEvent,
// eslint-disable-next-line max-params
sound => sound.play()
);