I'm trying to randomize the sounds that I play when clicking on a button, but I also wanted to skip the last played sound. For example, if Sfx4
will be played four times in a row it won't sound natural. I want to always play a new sound (within these 5 sounds of course). What I'm doing wrong? Give me some ideas on how to implement it if possible.
<template>
<button class="book__nav-btn" @click="playTurnSfx">
<slot> </slot>
</button>
</template>
<script setup>
import { ref, computed, onMounted } from 'vue';
import Sfx1 from '@/assets/sounds/page-turn-1.mp3?url';
import Sfx2 from '@/assets/sounds/page-turn-2.mp3?url';
import Sfx3 from '@/assets/sounds/page-turn-3.mp3?url';
import Sfx4 from '@/assets/sounds/page-turn-4.mp3?url';
import Sfx5 from '@/assets/sounds/page-turn-5.mp3?url';
const sounds = [Sfx1, Sfx2, Sfx3, Sfx4, Sfx5];
const lastPlayedIndex = ref(null);
let playableSounds = sounds.toSpliced(lastPlayedIndex.value, 1);
const randomIndex = computed(() => {
return Math.floor(Math.random() * playableSounds.length);
});
const playTurnSfx = () => {
const sound = new Audio(sounds[randomIndex.value]);
sound.volume = 0.1;
sound.play();
};
</script>
You can always keep track of what the latest value was, filter it out from the array (don't worry, the original array will not change, you will get a copy of the array via filter, but without the items that did not match your criteria) and randomize the result:
let sounds = ['a', 'b', 'c', 'd', 'e'];
let previous = -1;
function randomize() {
let randIndex = parseInt(Math.random() * (sounds.length - ((sounds.indexOf(previous) >= 0) ? 1 : 0)));
console.log(previous = sounds.filter(item => (item !== previous))[randIndex]);
}
<input type="button" value="randomize" onclick="randomize()">
EDIT
Looked into the try inside the second edit to the question and this is how I made it to work (I ignore the sound-playing, we need to fix the logic that determines which sound is to be played, so here it's safe to asume that playing sounds works):
const sounds = ['Sfx1', 'Sfx2', 'Sfx3', 'Sfx4', 'Sfx5'];
let previous = null;
const getRand = () => {
const filteredSounds = sounds.filter(item => item !== previous);
return filteredSounds[Math.floor(Math.random() * filteredSounds.length)];
};
const playSfx = () => {
//const sound = new Audio(sounds[randIndex]);
//sound.volume = 0.1;
//sound.play();
previous = getRand();
console.log(previous);
};
for (let i = 0; i < 20; i++) playSfx();
The logical mistake that you made while trying to apply this idea was to, after correctly filtering your array and getting a random index, you took the sound corresponding the index just randomized from the unfiltered array rather than the filtered array.
So, if previous
was Sfx2
, for example, then your filter resulted in an array like [Sfx1, Sfx3, Sfx4, Sfx5]
, but your initial array remained [Sfx1, Sfx2, Sfx3, Sfx4, Sfx5]
, so if you get a random integer between 0..3, which happens to be 1, then filteredSounds[1]
will be Sfx3
, which differs from previous
, which was Sfx2
in this scenario, whereas sounds[1]
is still Sfx2
, so you need to get the value at the randomized index of filteredSounds
rather than the unfiltered sounds
.