MusicPlayer component
August 16, 2025 at 06:01 PM
August 16, 2025 at 06:01 PM
15 views
0 replies

August 16, 2025 at 06:01 PM
I did not write it, i used AI to make it.
I think nobody really wants to spend time to make MusicPlayer for a game, so i figured that i can just ask cursor to make it and share it :)
So, how to make it work.
Create script and call it MusicPlayer and copy this Script in it:
import cave
import os
class MusicPlayer(cave.Component):
STATE_KEY = "music_player_state"
VOLUME_STEP = 0.05
def __init__(self):
super().__init__()
self.folder = "Source/Content/Audio/Music"
self.playlist = []
self.index = -1
self.track = None
self.volume = 0.6
self.muted = False
def start(self, scene):
# Build playlist from .asset files β strip " (UID).asset" β use asset name like "song.ogg"
try:
dir_path = cave.getGamePath(self.folder)
asset_files = [f for f in os.listdir(dir_path) if f.lower().endswith(".asset")]
names = []
for f in asset_files:
base = f.rsplit(" (", 1)[0]
if base.lower().endswith(".ogg"):
names.append(base)
self.playlist = sorted(names)
except Exception:
self.playlist = []
# Restore state (index/progress/volume/muted)
state = cave.getGlobalDict().get(self.STATE_KEY, {})
if isinstance(state, dict):
self.volume = float(state.get("volume", self.volume))
self.muted = bool(state.get("muted", self.muted))
if isinstance(state, dict) and "index" in state and self.playlist:
self.index = max(0, min(int(state.get("index", 0)), len(self.playlist) - 1))
progress = float(state.get("progress", 0.0) or 0.0)
self._play_current(progress)
else:
self.index = -1
self._play_next()
def update(self):
events = cave.getEvents()
# Volume down/up with [ and ]
if events.pressed(cave.event.KEY_LEFTBRACKET):
self.volume = max(0.0, round(self.volume - self.VOLUME_STEP, 2))
self.muted = False
self._apply_volume()
if events.pressed(cave.event.KEY_RIGHTBRACKET):
self.volume = min(1.0, round(self.volume + self.VOLUME_STEP, 2))
self.muted = False
self._apply_volume()
# Mute toggle with M
if events.pressed(cave.event.KEY_M):
self.muted = not self.muted
self._apply_volume()
# Track navigation: < previous, > next
if events.pressed(cave.event.KEY_LESS):
self._play_prev()
if events.pressed(cave.event.KEY_GREATER):
self._play_next()
# Auto-advance
if self.playlist and (self.track is None or not self.track.isPlaying()):
self._play_next()
def end(self, scene):
if self.track:
cave.getGlobalDict()[self.STATE_KEY] = {
"index": self.index,
"progress": self.track.getProgress(),
"volume": self.volume,
"muted": self.muted,
}
def _apply_volume(self):
if not self.track:
return
vol = 0.0 if self.muted else self.volume
try:
self.track.setVolume(vol)
except Exception:
try:
self.track.volume = vol
except Exception:
pass
def _play_current(self, resume_progress=0.0):
if not self.playlist:
self.track = None
return
if self.index < 0 or self.index >= len(self.playlist):
self.index = 0
name = self.playlist[self.index] # asset name only, e.g. "track.ogg"
if self.track:
try:
self.track.stop()
except Exception:
pass
self.track = cave.playSound(name, self.volume if not self.muted else 0.0, 0, False)
self._apply_volume()
if resume_progress > 0.0:
try:
dur = self.track.getDuration()
if dur > 0:
self.track.setProgress(min(resume_progress, max(0.0, dur - 0.01)))
except Exception:
pass
def _play_next(self):
if not self.playlist:
self.track = None
return
self.index = (self.index + 1) % len(self.playlist)
self._play_current(0.0)
def _play_prev(self):
if not self.playlist:
self.track = None
return
self.index = (self.index - 1 + len(self.playlist)) % len(self.playlist)
self._play_current(0.0)
# Safety alias in case the editor cached an old typo
_play_curren = _play_current
In Scene Graph create Empty and call it MusicManager and add MusicPlayer component to it.
In Asset Browser: In Content create Audio folder and in side Audio folder create Music folder
Content/Audio/Music
And inside Music folder just import .ogg assets.
Press [ ] for volume
Press M to mute
Press , . to change songs