the game
1import type { KAPLAYCtx } from "kaplay";
2
3// Sound effects and music system
4export function setupSoundSystem(k: KAPLAYCtx) {
5 // Available music tracks
6 const musicTracks = [
7 "pixel-song-3.mp3",
8 "pixel-song-18.mp3",
9 "pixel-song-19.mp3",
10 "pixel-song-21.mp3",
11 ];
12
13 // Sound effects
14 const soundEffects = {
15 coin: [
16 "coin-1.wav",
17 "coin-2.wav",
18 "coin-3.wav",
19 "coin-4.wav",
20 "coin-5.wav",
21 ],
22 explosion: ["pixel-explosion.mp3"],
23 jump: ["coin-1.wav"],
24 hit: ["ouch.mp3"],
25 heal: ["coin-3.wav"],
26 death: ["large-underwater-explosion.mp3"],
27 levelUp: ["smb_powerup.wav"],
28 windup: ["windup.mp3"],
29 };
30
31 // Keep track of last played music to avoid repeats
32 let lastPlayedMusic = "";
33 let currentMusic: any = null;
34 let musicVolume = 0.8; // Increased from 0.5 to 0.8
35 let sfxVolume = 0.7;
36 let musicEnabled = true;
37 let sfxEnabled = true;
38
39 // Preload all sounds
40 function preloadSounds() {
41 // Preload music
42 musicTracks.forEach((track) => {
43 k.loadSound(track, `music/${track}`);
44 });
45
46 // Preload sound effects
47 Object.values(soundEffects)
48 .flat()
49 .forEach((sfx) => {
50 k.loadSound(sfx, `sfx/${sfx}`);
51 });
52 }
53
54 // Play a random music track (avoiding the last played one)
55 function playRandomMusic() {
56 if (!musicEnabled) return;
57
58 // Stop current music if playing
59 if (currentMusic) {
60 currentMusic.stop();
61 }
62
63 // Filter out the last played track to avoid repeats
64 const availableTracks = musicTracks.filter(
65 (track) => track !== lastPlayedMusic,
66 );
67
68 // Select a random track from available tracks
69 const randomIndex = Math.floor(Math.random() * availableTracks.length);
70 const selectedTrack = availableTracks[randomIndex];
71
72 // Update last played track
73 lastPlayedMusic = selectedTrack;
74
75 // Play the selected track
76 currentMusic = k.play(selectedTrack, {
77 volume: musicVolume,
78 loop: true,
79 });
80
81 return currentMusic;
82 }
83
84 // Play a sound effect
85 function playSfx(type: keyof typeof soundEffects, options: any = {}) {
86 if (!sfxEnabled) return;
87
88 const sounds = soundEffects[type];
89 if (!sounds || sounds.length === 0) return;
90
91 // Select a random sound from the category
92 const randomIndex = Math.floor(Math.random() * sounds.length);
93 const selectedSound = sounds[randomIndex];
94 // Play the sound with options
95 return k.play(selectedSound, {
96 volume: options.volume ?? sfxVolume,
97 ...options,
98 });
99 }
100
101 // Play a specific sound file directly
102 function playSound(soundName: string, options: any = {}) {
103 if (!sfxEnabled) return;
104
105 return k.play(soundName, {
106 volume: options.volume ?? sfxVolume,
107 ...options,
108 });
109 }
110
111 // Toggle music on/off
112 function toggleMusic() {
113 musicEnabled = !musicEnabled;
114
115 if (musicEnabled) {
116 playRandomMusic();
117 } else if (currentMusic) {
118 currentMusic.stop();
119 currentMusic = null;
120 }
121
122 return musicEnabled;
123 }
124
125 // Toggle sound effects on/off
126 function toggleSfx() {
127 sfxEnabled = !sfxEnabled;
128 return sfxEnabled;
129 }
130
131 // Set music volume
132 function setMusicVolume(volume: number) {
133 musicVolume = Math.max(0, Math.min(1, volume));
134 if (currentMusic) {
135 currentMusic.volume(musicVolume);
136 }
137 return musicVolume;
138 }
139
140 // Set sound effects volume
141 function setSfxVolume(volume: number) {
142 sfxVolume = Math.max(0, Math.min(1, volume));
143 return sfxVolume;
144 }
145
146 // Check if a sound is currently playing
147 function isMusicPlaying() {
148 return currentMusic !== null;
149 }
150
151 // Stop current music
152 function stopMusic() {
153 if (currentMusic) {
154 currentMusic.stop();
155 currentMusic = null;
156 }
157 }
158
159 // Get current music track name
160 function getCurrentMusic() {
161 return lastPlayedMusic;
162 }
163
164 return {
165 preloadSounds,
166 playRandomMusic,
167 playSfx,
168 playSound,
169 toggleMusic,
170 toggleSfx,
171 setMusicVolume,
172 setSfxVolume,
173 isMusicPlaying,
174 stopMusic,
175 getCurrentMusic,
176 };
177}
178
179export default setupSoundSystem;