MusicPlayer component

August 16, 2025 at 06:01 PM
15 views 0 replies
David
CornDuck
User
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

Join the Discussion

Please login or create an account to reply to this post.