Customer Music Player

free plugin/tool

Created an ingame music player for my game Starguard! Wanted to share the code (assisted by Grok) so ya'll have a template/idea how to do it too. You'll have to adapt the code to your specific situation. Any questions, concerns, need help? Happy to assist.

Starguard Music Player

# res://Scripts/UI/wave/waveUIMenuMusic.gd
#
# WAVE UI MUSIC PLAYER — BATTLE-ONLY JUKEBOX
# ------------------------------------------------------------
# • Instanced under WaveUIMenuMusic (child of waveUI)
# • Hardcoded playlist (6 tracks) — random pick on ready
# • OptionButton for track selection (names shown)
# • MM:SS timer display
# • Pause / Play / Loop toggle
# • Stops on game over via EventBus.battle_music_silence_requested
# • AudioStreamPlayer2D follows camera naturally
#
# STARLOG
# Stardate 2026.047.XXXX → In-battle jukebox v1.0 online
#   • Hardcoded 6 tracks, random start on ready
#   • OptionButton dropdown with track names
#   • Real-time MM:SS labels
#   • Pause/play/loop fully wired
#   • Silence routed through EventBus on game over
#   • Captain: "Variety is the spice of life — let the spores jam."

extends Control

 var debug: bool = false

# ──────────────────────────────────────────────────────────────
# NODE REFERENCES
# ──────────────────────────────────────────────────────────────

 var music_player: AudioStreamPlayer2D = $MusicPlayerAudio
 var pause_button: Button = $SwapPanel/musicButtons/pauseMusic
 var play_button: Button = $SwapPanel/musicButtons/playMusic
 var song_choice: OptionButton = $SwapPanel/musicButtons/songChoiceBox
 var minutes_label: Label = $SwapPanel/musicButtons/minutesLabel
 var seconds_label: Label = $SwapPanel/musicButtons/secondsLabel
 var loop_button: CheckButton = $SwapPanel/musicButtons/loopButton
 var title_label: Label = $SwapPanel/TitleLabel  # or wherever current track name goes

# ──────────────────────────────────────────────────────────────
# PLAYLIST — Hardcoded for now (drag .wav files in editor if needed)
# ──────────────────────────────────────────────────────────────

var tracks: Array[AudioStream] = [
preload("res://Music/mainMenu/AS00237 Traverse Pixelated Stars.wav"),
preload("res://Music/mainMenu/AS00204 Defy Stellar Winds.wav"),
preload("res://Music/mainMenu/AS00210 Harness Cosmic Tides.wav"),
preload("res://Music/wave/AS00208 Ignite Star Forge.wav"),
preload("res://Music/wave/AS00217 Ignite Black Hole.wav"),
preload("res://Music/wave/AS00227 Ignite Supernova Heart.wav")
]

var current_track_index: int = 0
var is_looping: bool = false

# ──────────────────────────────────────────────────────────────
# READY — Populate UI, pick random track, connect signals
# ──────────────────────────────────────────────────────────────

func _ready() -> void:
# Populate OptionButton with track names
song_choice.clear()
for i in tracks.size():
var track_name = tracks[i].resource_path.get_file().get_basename()
song_choice.add_item(track_name, i)

# Connect buttons
#pause_button.pressed.connect(_on_pause_music_pressed)
#play_button.pressed.connect(_on_play_music_pressed)
#song_choice.item_selected.connect(_on_song_choice_box_item_selected)
#loop_button.toggled.connect(_on_loop_button_toggled)

# Connect to music finished signal
music_player.finished.connect(_on_music_finished)

# Connect to game over silence request
EventBus.battle_music_silence_requested.connect(_on_silence_requested)

# Pick random track and start playing
if not tracks.is_empty():
current_track_index = randi() % tracks.size()
_play_track(current_track_index)
song_choice.select(current_track_index)
if debug:
print("[MusicPlayer] Battle jukebox ready — random track: ", _get_current_track_name())
else:
if debug:
print("[MusicPlayer] No tracks loaded — jukebox offline.")

# Initial UI update
_update_ui()

# ──────────────────────────────────────────────────────────────
# PROCESS — Update timer display
# ──────────────────────────────────────────────────────────────

func _process(delta: float) -> void:
if music_player.playing:
var pos = music_player.get_playback_position()
var total = music_player.stream.get_length() if music_player.stream else 0.0

var minutes = int(pos / 60)
var seconds = int(pos) % 60

minutes_label.text = "%02d" % minutes
seconds_label.text = "%02d" % seconds

# Optional: show total time too
# title_label.text = "%s (%02d:%02d)" % [_get_current_track_name(), int(total/60), int(total)%60]
else:
minutes_label.text = "00"
seconds_label.text = "00"

# ──────────────────────────────────────────────────────────────
# BUTTON HANDLERS
# ──────────────────────────────────────────────────────────────

func _on_pause_music_pressed() -> void:
if music_player.playing:
music_player.stream_paused = true
pause_button.text = "Paused"
play_button.text = "Resume"
if debug:
print("[MusicPlayer] Paused at ", music_player.get_playback_position())
else:
music_player.stream_paused = false
pause_button.text = "Pause"
play_button.text = "Play"
if debug:
print("[MusicPlayer] Resumed")

func _on_play_music_pressed() -> void:
if not music_player.playing:
if music_player.stream_paused:
music_player.stream_paused = false
else:
music_player.play()
pause_button.text = "Pause"
play_button.text = "Play"
if debug:
print("[MusicPlayer] Playing / Resuming")

func _on_song_choice_box_item_selected(index: int) -> void:
current_track_index = index
_play_track(index)
if debug:
print("[MusicPlayer] Switched to: ", _get_current_track_name())

func _on_loop_button_toggled(toggled_on: bool) -> void:
is_looping = toggled_on
if debug:
print("[MusicPlayer] Loop ", "enabled" if toggled_on else "disabled")

# ──────────────────────────────────────────────────────────────
# INTERNAL HELPERS
# ──────────────────────────────────────────────────────────────

func _play_track(index: int) -> void:
if index < 0 or index >= tracks.size():
return
music_player.stream = tracks[index]
music_player.play()
_update_ui()

func _update_ui() -> void:
if song_choice:
song_choice.select(current_track_index)

if title_label:
title_label.text = _get_current_track_name()

func _get_current_track_name() -> String:
if music_player.stream:
return music_player.stream.resource_path.get_file().get_basename()
return "No Track"

func _on_music_finished() -> void:
if is_looping:
music_player.play()
else:
current_track_index = (current_track_index + 1) % tracks.size()
_play_track(current_track_index)
song_choice.select(current_track_index)
if debug:
print("[MusicPlayer] Track finished — ", "looping" if is_looping else "next track")

# ──────────────────────────────────────────────────────────────
# GAME OVER SILENCE (via EventBus)
# ──────────────────────────────────────────────────────────────

func _on_silence_requested() -> void:
music_player.stop()
if debug:
print("[MusicPlayer] Battle music silenced — game over / chrono jump")

Posted Feb 16, 2026, 8:28 PM UTC

02
Loading comments…