Godot Version
Godot_v4.3-stable_mono_win64
Question
So basically, I am coding a game where you can play ultimate tic tac toe and simple tic tac toe, But when I start the game, the music works, but as soon as I click the SettingsButton, the song restarts itself again, any reason why? I have been troubleshooting this for about an hour now and cant seem to find why, please help.
Here is a video to show exactly whats happening
here is settingspopup.gd (where the settingspopup is)
extends Popup
# Member variables for controls
var volume_slider: HSlider
var sfx_mute: CheckButton
var save_button: Button
var close_button: Button
var color_rect: ColorRect
var vbox_container: VBoxContainer
var vibes_player: AudioStreamPlayer
func _ready():
vbox_container = get_node("VBoxContainer")
volume_slider = vbox_container.get_node("Volume_Slider")
sfx_mute = vbox_container.get_node("SFXMute")
save_button = vbox_container.get_node("Save_Button")
close_button = vbox_container.get_node("Close_Button")
color_rect = get_node("ColorRect")
color_rect.show()
color_rect.color = Color(0.3, 0.3, 0.3, 1) # Set to a darker gray
color_rect.size = Vector2(100, 150) # Adjust the size as needed
# Set the size of the popup
size = Vector2(300, 150) # Adjusted for better visibility
popup()
# Adjust size flags
vbox_container.size_flags_horizontal = Control.SIZE_EXPAND_FILL
vbox_container.size_flags_vertical = Control.SIZE_EXPAND_FILL
# Initialize controls based on config settings
initialize_controls()
# Call the method to connect signals
_connect_signals()
func initialize_controls():
load_mute_state()
# Adjust this path based on your scene hierarchy
vibes_player = get_node("/root/Control/VibesPlayer") # Adjust the path based on your hierarchy
if vibes_player: # Ensure it's not null
vibes_player.stream = load("res://vibes.ogg") # Ensure this path is correct
if not vibes_player.playing:
vibes_player.play() # Start playing music
func _on_CloseButton_pressed():
hide()
print("Popup closed")
# Function to mute/unmute SFX AudioStreamPlayers
func update_sfx_mute_state(is_muted: bool):
var sfx_manager = get_node("/root/SFXManager")
if sfx_manager:
sfx_manager.set_mute_state(is_muted) # Update global mute state
else:
print("SFXManager is not found!")
# Call this when the user toggles the SFX mute state in the settings menu
func _on_SFXMute_pressed():
var is_muted = sfx_mute.is_pressed() # Corrected here
update_sfx_mute_state(is_muted) # Update global state
# Load the mute state from the config file
func load_mute_state():
var config = ConfigFile.new()
if config.load("user://settings.cfg") == OK:
var is_muted = config.get_value("audio", "sfx_mute", false)
sfx_mute.set_pressed(is_muted) # Set the button state based on the config
update_sfx_mute_state(is_muted) # Apply the mute state
# Function to save the mute state in settings.cfg
func save_mute_state(is_muted: bool):
var config = ConfigFile.new()
config.load("user://settings.cfg")
config.set_value("audio", "sfx_mute", is_muted) # Save the mute state
config.save("user://settings.cfg") # Write to disk
func _connect_signals():
if not volume_slider.is_connected("value_changed", Callable(self, "_on_Volume_Slider_value_changed")):
volume_slider.connect("value_changed", Callable(self, "_on_Volume_Slider_value_changed"))
if not sfx_mute.is_connected("pressed", Callable(self, "_on_SFXMute_pressed")):
sfx_mute.connect("pressed", Callable(self, "_on_SFXMute_pressed"))
if not save_button.is_connected("pressed", Callable(self, "_on_SaveButton_pressed")):
save_button.connect("pressed", Callable(self, "_on_SaveButton_pressed"))
if not close_button.is_connected("pressed", Callable(self, "_on_CloseButton_pressed")):
close_button.connect("pressed", Callable(self, "_on_CloseButton_pressed"))
# Function to handle volume slider value change
func _on_Volume_Slider_value_changed(value: float):
if vibes_player: # Ensure it's not null
# Map the slider value back to dB for the vibes_player
vibes_player.volume_db = value / 100 * 60 - 60 # Convert 0-100 to -60 to 0 dB
if sfx_mute.is_pressed() and value > 0:
sfx_mute.set_pressed(false) # Unmute if volume is adjusted above 0
# Function to handle save button pressed
func _on_SaveButton_pressed():
print("Save button pressed")
var volume_value = volume_slider.value
var is_muted = sfx_mute.is_pressed() # Corrected here
save_mute_state(is_muted) # Save the mute state
print("Volume:", volume_value)
print("SFX Mute:", is_muted)
Ui.gd (The main scene with the music)
extends Control
var credits_popup: Popup = null
var settings_popup: Popup = null
var button_click_player: AudioStreamPlayer = null # Reference to the AudioStreamPlayer
var music_player: AudioStreamPlayer = null # Reference to the AudioStreamPlayer for music
# Function ready
func _ready():
# Initialize the music player
music_player = get_node("VibesPlayer") # Adjust this path based on your scene hierarchy
# Start playing the background music if not already playing
if music_player:
if not music_player.is_playing(): # Check if the music is already playing
music_player.play() # Start playing the music
# Initialize AudioStreamPlayer reference and set the sound stream
button_click_player = $ButtonClickPlayer
button_click_player.stream = load("res://sounds/click.ogg")
if $SubscribeLabel:
$SubscribeLabel.connect("gui_input", Callable(self, "_on_SubscribeLabel_clicked"))
if $DiscordLabel:
$DiscordLabel.connect("gui_input", Callable(self, "_on_DiscordLabel_clicked"))
func _on_SettingsButton_pressed():
_play_button_click_sound() # Play the button click sound
print("Settings Button Clicked!") # Log button click to the console
# Load and instance the SettingsPopup.tscn
if settings_popup == null: # Check if the popup is not created
var packed_scene = preload("res://settingspopup.tscn") # Preload the scene
settings_popup = packed_scene.instantiate() # Instantiate the scene
get_tree().current_scene.add_child(settings_popup) # Add to the current scene
settings_popup.popup_centered() # Show it centered on the screen
else:
if settings_popup.is_visible():
settings_popup.hide() # Hide the popup if it's visible
else:
settings_popup.popup_centered() # Show it centered on the screen
# Function to play button click sound
func _play_button_click_sound():
button_click_player.play() # Play the button click sound
func _on_Button_pressed():
_play_button_click_sound() # Play the button click sound
print("Credits Button Clicked!") # Log button click to the console
if credits_popup == null: # Check if the popup is not created
credits_popup = Popup.new() # Create a new popup
# Create a RichTextLabel for credits with clickable links
var rich_text_label = RichTextLabel.new()
rich_text_label.bbcode_enabled = true # Enable BBCode for clickable links
rich_text_label.text = "Game by [url=https://youtube.com/@monkagaming420]MonkaGaming420YT[/url]/Anthony\n" + \
"Song name at home page: [url=https://www.youtube.com/watch?v=x-ObUKegl6g]Vibes - David Renda[/url]\n" + \
"Click sound effect: [url=https://freesound.org/people/Breviceps/sounds/448081]Tic Toc UI Click[/url]\n" + \
"Simple Tic Tac Toe picture credits: [url=https://projectbook.code.brettchalupa.com/games/img/ttt.webp]https://projectbook.code.brettchalupa.com/games/img/ttt.webp[/url]\n" + \
"Super Tic Tac Toe credits: [url=https://upload.wikimedia.org/wikipedia/commons/7/7d/Super_tic-tac-toe_rules_example.png]https://upload.wikimedia.org/wikipedia/commons/7/7d/Super_tic-tac-toe_rules_example.png[/url]\n" # BBCode for clickable links
# Set minimum size for the label
rich_text_label.custom_minimum_size = Vector2(200, 100)
credits_popup.add_child(rich_text_label) # Add the label to the popup
# Connect the link click event to open the URL
rich_text_label.connect("meta_clicked", Callable(self, "_on_link_clicked"))
# Connect the close functionality
credits_popup.connect("popup_hide", Callable(self, "_on_CreditsPopup_closed"))
# Add the popup to the current scene
get_tree().current_scene.add_child(credits_popup) # Adding to the current scene
# Position the popup in the center of the screen after it's been added to the tree
credits_popup.popup_centered() # Show it centered on the screen
else:
# If popup is already created, just show or hide it
if credits_popup.is_visible():
credits_popup.hide() # Hide the popup if it's visible
else:
credits_popup.popup_centered() # Show it centered on the screen
# Function to handle link clicks
func _on_link_clicked(meta: String):
print("Clicked link: ", meta) # Print the clicked link
OS.shell_open(meta) # Open the link in the default browser
func _on_PlayButton_pressed():
print("Play Button sound trigger")
_play_button_click_sound() # Play the button click sound
# Add a slight delay if necessary
await get_tree().create_timer(0.15).timeout
print("Play Button Pressed")
get_tree().change_scene_to_file("res://ultimate_or_simple.tscn")
func _on_SaveButton_pressed():
_play_button_click_sound() # Play the button click sound for the save button
# Save settings logic can be modified here if you still want to save other settings
print("Settings Saved.")
func _on_DiscordLabel_clicked(event: InputEvent):
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
print("Discord Label Clicked!") # Print message when Discord label is clicked
OS.shell_open("https://discord.gg/hX9JeZD7Rx") # Open Discord in default browser
# Function to handle when the SubscribeLabel is clicked
func _on_SubscribeLabel_clicked(event: InputEvent):
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
print("Subscribe Label Clicked!") # Print message when Subscribe label is clicked
OS.shell_open("https://www.youtube.com/@monkagaming420") # Open YouTube channel in the default browser
I dont know if this has anything to do with it but SFXManager.gd
extends Node
# Function to mute/unmute SFX
func set_mute_state(is_muted: bool):
var bus_index = AudioServer.get_bus_index("custombuslayout") # Get the index of your custom bus
if is_muted:
AudioServer.set_bus_volume_db(bus_index, -80) # Mute the bus
else:
AudioServer.set_bus_volume_db(bus_index, 0) # Unmute the bus
# Optional: Save the mute state to a config file
var config = ConfigFile.new()
config.set_value("audio", "sfx_muted", is_muted)
config.save("user://settings.cfg")
# Log the mute state change
var mute_status = "muted" if is_muted else "unmuted"
print("SFX is " + mute_status)
# Function to load mute state from config on startup
func load_mute_state():
var config = ConfigFile.new()
var err = config.load("user://settings.cfg")
if err == OK:
var is_muted = config.get_value("audio", "sfx_muted", false) # Default to false (not muted)
set_mute_state(is_muted)
else:
print("No settings file found, using default audio settings.")
func _ready():
load_mute_state() # Load the saved mute state when the game starts
Here is settingspopup SceneTree
UI.GD SceneTree
Here is all the Scripts if u need them, let me know if u want specific scripts.
Here are all the Scenes
Singleton/Autoloads
Audio Buses:

Sorry if this seems confusing, but, Let me know if u need any scripts or SceneTrees