-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a /sounds demo page with new vanilla sounds
- Loading branch information
1 parent
45b719e
commit 63281dc
Showing
3 changed files
with
195 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
--- | ||
import Layout from '../layouts/Layout.astro' | ||
import '../styles/index.css' | ||
const sounds = ['startGame', 'startTurn', 'endTurn', 'selectCard', 'cardToHand', 'playCard'] | ||
--- | ||
|
||
<script> | ||
import sounds from '../sounds.js' | ||
import {beep, playCoin, playWhoosh} from '../sounds2.js' | ||
|
||
const buttons = document.querySelectorAll('menu.sounds button') | ||
buttons.forEach((button) => { | ||
button.addEventListener('click', (event) => { | ||
const sound = event.currentTarget.dataset.sound | ||
console.log('playing', sound) | ||
sounds[sound]() | ||
}) | ||
}) | ||
|
||
document.querySelectorAll('[data-sfx]').forEach((el) => { | ||
el.addEventListener('click', () => { | ||
const {sfx, coin} = el.dataset | ||
if (sfx === 'whoosh') { | ||
playWhoosh(0.6) | ||
} else if (coin) { | ||
playCoin(coin) | ||
} else { | ||
beep(sfx, sfx * 2, 0.3) | ||
} | ||
}) | ||
}) | ||
</script> | ||
|
||
<Layout title="Slay the Web"> | ||
<div class="Container"> | ||
<h1>Sounds</h1> | ||
<p>Play any of the sound effects used in the game.</p> | ||
|
||
<menu> | ||
<button type="button" data-sfx="220">220</button> | ||
<button type="button" data-sfx="440">440</button> | ||
<button type="button" data-sfx="880">880</button> | ||
<button type="button" data-sfx data-coin="minor">Coin minor</button> | ||
<button type="button" data-sfx data-coin="major">Coin major</button> | ||
<button type="button" data-sfx data-coin="pentatonic">Coin penta</button> | ||
<button type="button" data-sfx="whoosh">Whoosh</button> | ||
</menu> | ||
|
||
<menu class="sounds"> | ||
{ | ||
sounds.map((s) => ( | ||
<button type="button" data-sound={s}> | ||
{s} | ||
</button> | ||
)) | ||
} | ||
</menu> | ||
</div> | ||
</Layout> | ||
|
||
<style> | ||
h1 + p { | ||
margin-left: 0.8em; | ||
margin-bottom: 2rem; | ||
} | ||
menu { | ||
margin: 0 0 1rem; | ||
display: flex; | ||
flex-flow: column wrap; | ||
gap: 0.5em; | ||
max-width: 14em; | ||
} | ||
button { | ||
margin: 0; | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
const audioContext = new (window.AudioContext || window.webkitAudioContext)() | ||
|
||
/** | ||
* Plays a beep sound using web audio api | ||
* AudioContext > Oscillator -> Gain | ||
*/ | ||
export function beep( | ||
startFrequency = 440, | ||
endFrequency = 880, | ||
duration = 0.5, | ||
waveform = 'square', | ||
volume = 0.1, | ||
) { | ||
const oscillator = audioContext.createOscillator() | ||
oscillator.type = waveform // 'square', 'sawtooth', 'triangle', or 'sine' | ||
oscillator.frequency.setValueAtTime(startFrequency, audioContext.currentTime) | ||
if (endFrequency && duration > 0) { | ||
oscillator.frequency.exponentialRampToValueAtTime(endFrequency, audioContext.currentTime + duration) | ||
} | ||
|
||
// Adding a simple gain envelope for a more "blippy" sound | ||
const gainNode = audioContext.createGain() | ||
gainNode.gain.setValueAtTime(0, audioContext.currentTime) | ||
gainNode.gain.linearRampToValueAtTime(volume, audioContext.currentTime + 0.01) // Quick ramp up | ||
gainNode.gain.exponentialRampToValueAtTime(0.001, audioContext.currentTime + duration) // And down | ||
|
||
oscillator.connect(gainNode) | ||
gainNode.connect(audioContext.destination) | ||
|
||
oscillator.start() | ||
oscillator.stop(audioContext.currentTime + duration) | ||
} | ||
|
||
const majorScale = [523.25, 587.33, 659.25, 698.46, 783.99, 880.0, 987.77, 1046.5] // C5, D5, E5, F5, G5, A5, B5, C6 | ||
const minorScale = [440.0, 523.25, 587.33, 659.25, 698.46, 783.99, 880.0, 987.77] // A4, C5, D5, E5, F5, G5, A5, B5 | ||
const pentatonicScale = [523.25, 659.25, 783.99, 880.0, 1046.5] // C5, E5, G5, A5, C6 | ||
|
||
/** | ||
* Plays a coin/reward high pitched sound | ||
*/ | ||
export function playCoin(type, volume = 0.5) { | ||
const scales = [majorScale, minorScale, pentatonicScale] | ||
let selectedScale = scales[Math.floor(Math.random() * scales.length)] | ||
if (type === 'major') selectedScale = majorScale | ||
if (type === 'minor') selectedScale = minorScale | ||
if (type === 'pentatonic') selectedScale = pentatonicScale | ||
|
||
selectedScale.forEach((note, index) => { | ||
setTimeout(() => { | ||
beep(note, note, 0.1, 'triangle', volume) | ||
}, index * 100) | ||
}) | ||
} | ||
|
||
export function playWhoosh(duration = 1, startFreq = 200, endFreq = 800, volume = 0.2) { | ||
const audioContext = new (window.AudioContext || window.webkitAudioContext)() | ||
|
||
// Sine wave oscillator | ||
const oscillator = audioContext.createOscillator() | ||
oscillator.type = 'sine' | ||
oscillator.frequency.setValueAtTime(startFreq, audioContext.currentTime) | ||
oscillator.frequency.exponentialRampToValueAtTime(endFreq, audioContext.currentTime + duration) | ||
|
||
// Gain envelope for smooth fade-in and fade-out | ||
const gainNode = audioContext.createGain() | ||
gainNode.gain.setValueAtTime(0, audioContext.currentTime) | ||
gainNode.gain.linearRampToValueAtTime(volume, audioContext.currentTime + duration * 0.2) | ||
gainNode.gain.linearRampToValueAtTime(0, audioContext.currentTime + duration) | ||
|
||
oscillator.connect(gainNode) | ||
gainNode.connect(audioContext.destination) | ||
|
||
oscillator.start() | ||
oscillator.stop(audioContext.currentTime + duration) | ||
} |