.gif)
class_name NumberPopup extends Node2D
'''
Node2D
-> Label
-> AnimationPlayer
Have an animation that makes it scale up really fast,
then turn transparent and scale down
If you are going to spawn a lot, create a manager with a pool of numbers!
'''
@export var speed: float = 100
@export var friction: float = 15
var shift_direction: Vector2 = Vector2.ZERO
@onready var label: Label = $Label
@onready var animation_player: AnimationPlayer = $AnimationPlayer
func popup(damage: String, popup_direction: Vector2 = Vector2.ZERO) -> void:
label.text = str(damage)
animation_player.play("number_popup")
shift_direction += popup_direction
func _process(delta: float) -> void:
global_position += speed * shift_direction * delta
speed = max(speed - friction * delta, 0)
extends Node
const SOUND_FOLDER_PATH: String = "res://assets/audio/sounds/"
const SAVE_FILE_PATH: String = "user://audio_settings.cfg"
const POOL_SIZE: int = 12
var sounds_dictionary: Dictionary = {}
var supported_audio_files: Array[String] = [".wav", ".ogg", ".mp3"]
var sounds_bus_idx: int
var music_bus_idx: int
var sound_volume: float = 1.0
var music_volume: float = 1.0
var player_pool: Array[AudioStreamPlayer] = []
func _ready() -> void:
sounds_bus_idx = AudioServer.get_bus_index("sounds")
music_bus_idx = AudioServer.get_bus_index("music")
# Pre-populate the object pool for performance.
create_player_pool()
load_sound_paths_dictionary()
load_volumes()
func create_player_pool() -> void:
for i in range(POOL_SIZE):
var stream_player := AudioStreamPlayer.new()
# Add the player to this node. It will stay in the scene tree.
add_child(stream_player)
# The player is now part of the pool.
player_pool.append(stream_player)
func get_available_player() -> AudioStreamPlayer:
for player in player_pool:
if not player.is_playing():
return player
return null # All players are busy
func play_sound(sound_name: String, pitch_scale: float = -1.0) -> void:
if not sounds_dictionary.has(sound_name):
push_warning("Sound not found in dictionary: %s" % sound_name)
return
# Fetch an available player from the pool.
var player = get_available_player()
# If no player is available, we can't play the sound.
if not player:
push_warning("Audio player pool is full. Consider increasing POOL_SIZE.")
return
# Configure and play the sound.
player.stream = sounds_dictionary[sound_name]
player.bus = "sounds"
if pitch_scale == -1.0:
player.pitch_scale = randf_range(0.9, 1.1)
else:
player.pitch_scale = pitch_scale
player.play()
func set_sound_volume(volume_linear: float) -> void:
sound_volume = clampf(volume_linear, 0.0, 1.0)
var volume_db = linear_to_db(sound_volume) if sound_volume > 0 else -80.0
AudioServer.set_bus_volume_db(sounds_bus_idx, volume_db)
save_volumes()
func set_music_volume(volume_linear: float) -> void:
music_volume = clampf(volume_linear, 0.0, 1.0)
var volume_db = linear_to_db(music_volume) if music_volume > 0 else -80.0
AudioServer.set_bus_volume_db(music_bus_idx, volume_db)
save_volumes()
func save_volumes() -> void:
var config := ConfigFile.new()
config.set_value("audio", "sound_volume", sound_volume)
config.set_value("audio", "music_volume", music_volume)
config.save(SAVE_FILE_PATH)
func load_volumes() -> void:
var config := ConfigFile.new()
if config.load(SAVE_FILE_PATH) == OK:
var loaded_sound_vol = config.get_value("audio", "sound_volume", sound_volume)
var loaded_music_vol = config.get_value("audio", "music_volume", music_volume)
set_sound_volume(loaded_sound_vol)
set_music_volume(loaded_music_vol)
else:
print("No audio settings file found. Creating one with default values.")
save_volumes()
func load_sound_paths_dictionary() -> void:
var dir := DirAccess.open(SOUND_FOLDER_PATH)
if not dir:
push_error("Could not open sound assets folder: %s" % SOUND_FOLDER_PATH)
return
dir.list_dir_begin()
var file_name := dir.get_next()
while file_name != "":
if dir.current_is_dir() or not is_supported_audio_file(file_name):
file_name = dir.get_next()
continue
if OS.has_feature("editor") and file_name.ends_with(".import"):
file_name = dir.get_next()
continue
var sound_name_key = file_name.get_basename()
var sound_path = "%s/%s" % [SOUND_FOLDER_PATH, file_name]
sounds_dictionary[sound_name_key] = load(sound_path)
file_name = dir.get_next()
func is_supported_audio_file(file_name: String) -> bool:
for ext in supported_audio_files:
if file_name.ends_with(ext):
return true
return false
extends Node
"""
How it works:
First we (automatically) load all the sounds placed inside res://assets/audio/sounds/ and place them inside the sounds_dictionary,
using the sound name as the dictionary key.
Then, from anywhere in the game, we can call play_sound(sound_name) and it
will play :)
"""
var sound_folder_path: String = "res://assets/audio/sounds/"
var sounds_dictionary: Dictionary = {}
var supported_audio_files: Array = [".wav", ".ogg", ".mp3"]
func _ready() -> void:
load_sound_paths_dictionary()
func play_sound(sound_name: String, pitch_scale: float = -1) -> void:
if !sounds_dictionary.has(sound_name):
print("Sound not present in sounds dictionary: " + sound_name)
return
var sound_stream: AudioStream = sounds_dictionary[sound_name]
if sound_stream:
var stream_player: AudioStreamPlayer = AudioStreamPlayer.new()
stream_player.stream = sound_stream
stream_player.bus = "sound"
stream_player.finished.connect(stream_player.queue_free)
randomize()
if pitch_scale == -1:
pitch_scale = randf_range(0.9, 1.1)
stream_player.pitch_scale = pitch_scale # Randomize pitch so it's not always the same!
add_child(stream_player)
stream_player.play()
func load_sound_paths_dictionary() -> void:
var directory: DirAccess = DirAccess.open(sound_folder_path)
if directory:
directory.list_dir_begin()
var file_name = directory.get_next()
while file_name != "":
if directory.current_is_dir():
pass # If you want recursive file loading, do it here. I think
else: # it's a bit overkill :)
for file_type in supported_audio_files:
#print(file_name)
if file_name.contains(file_type):
if OS.has_feature("editor"):
if file_name.contains(".import"):
continue
else:
if file_name.ends_with(".import"):
file_name = file_name.trim_suffix(".import")
var sound_file_path: String = sound_folder_path + "/" + file_name
var new_audio_stream = load(sound_file_path)
if new_audio_stream is AudioStream:
sounds_dictionary[file_name.trim_suffix(file_type)] = new_audio_stream
# print("Successfully loaded sound: " + sound_file_path)
file_name = directory.get_next()
else:
print("An error occurred when trying to access the sounds path: " + sound_folder_path)
Creative Trio – Free CCO Stylized Low Poly 3D Models, Game Assets, VR Assets, Roblox