diff options
author | Nemrav <50055236+Nemrav@users.noreply.github.com> | 2024-08-06 01:48:36 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-06 01:48:36 +0200 |
commit | 82b16bcca7c74607a8885b882ec36f5202e7ef70 (patch) | |
tree | 0a9bd4f52c01315c3b38ce641a78c33bd8562be2 /game/src/Game | |
parent | fde15e554dc9ed458a838683c69d10262764db12 (diff) | |
parent | 9506f4160f0bd351f0853e6e8263ea927d9ec771 (diff) |
Merge pull request #243 from Nemrav/music
Music and sound effects
Diffstat (limited to 'game/src/Game')
-rw-r--r-- | game/src/Game/Autoload/SoundManager.gd | 20 | ||||
-rw-r--r-- | game/src/Game/GameSession/GameSession.gd | 2 | ||||
-rw-r--r-- | game/src/Game/GameStart.gd | 26 | ||||
-rw-r--r-- | game/src/Game/MusicConductor/MusicConductor.gd | 82 | ||||
-rw-r--r-- | game/src/Game/MusicConductor/SongInfo.gd | 11 | ||||
-rw-r--r-- | game/src/Game/Theme/StyleBoxWithSound.gd | 2 |
6 files changed, 130 insertions, 13 deletions
diff --git a/game/src/Game/Autoload/SoundManager.gd b/game/src/Game/Autoload/SoundManager.gd index 35c715c..01562f8 100644 --- a/game/src/Game/Autoload/SoundManager.gd +++ b/game/src/Game/Autoload/SoundManager.gd @@ -18,7 +18,7 @@ func _ready() -> void: "ogg", "wav", "mp3": _loaded_sound[fname.get_basename()] = load(_audio_directory_path.path_join(fname)) # SND-10 -func play_stream(sound : AudioStream, bus_type : String) -> void: +func play_stream(sound : AudioStream, bus_type : String, volume : float = 1.0) -> void: var player : AudioStreamPlayer = _bus_to_stream_player.get(bus_type) if player == null: player = AudioStreamPlayer.new() @@ -28,6 +28,7 @@ func play_stream(sound : AudioStream, bus_type : String) -> void: add_child(player) player.play() var poly_playback : AudioStreamPlaybackPolyphonic = player.get_stream_playback() + player.volume_db = linear_to_db(volume) poly_playback.play_stream(sound) func play(sound : String, bus_type : String) -> void: @@ -35,8 +36,21 @@ func play(sound : String, bus_type : String) -> void: # REQUIREMENTS: # * SND-7 -func play_effect_stream(sound : AudioStream) -> void: - play_stream(sound, "SFX") +func play_effect_stream(sound : AudioStream, volume : float = 1.0) -> void: + play_stream(sound, "SFX", volume) func play_effect(sound : String) -> void: play(sound, "SFX") + +func play_effect_compat(sfx : String, fallback : AudioStream=null) -> void: + var sound:AudioStreamWAV = SoundSingleton.get_sound_stream(sfx) + var volume:float = SoundSingleton.get_sound_base_volume(sfx) + + if sound != null: + play_effect_stream(sound,volume) + elif fallback != null: + push_warning("Failed to find sound %s, playing fallback instead" % sfx) + play_effect_stream(fallback) + else: + push_warning("Failed to find sound %s" % sfx) + diff --git a/game/src/Game/GameSession/GameSession.gd b/game/src/Game/GameSession/GameSession.gd index 0158b3a..30e6c1c 100644 --- a/game/src/Game/GameSession/GameSession.gd +++ b/game/src/Game/GameSession/GameSession.gd @@ -10,6 +10,8 @@ func _ready() -> void: _model_manager.generate_units() _model_manager.generate_buildings() + MusicConductor.generate_playlist() + MusicConductor.select_next_song() func _process(_delta : float) -> void: GameSingleton.try_tick() diff --git a/game/src/Game/GameStart.gd b/game/src/Game/GameStart.gd index 6074df8..3c046a0 100644 --- a/game/src/Game/GameStart.gd +++ b/game/src/Game/GameStart.gd @@ -105,8 +105,32 @@ func _setup_compatibility_mode_paths() -> void: _compatibility_path_list.push_back(actual_base_path + "/mod/" + mod_name) func _load_compatibility_mode() -> void: - if GameSingleton.load_defines_compatibility_mode(_compatibility_path_list) != OK: + if GameSingleton.set_compatibility_mode_roots(_compatibility_path_list) != OK: + push_error("Errors setting game roots!") + + setup_title_theme() + + if GameSingleton.load_defines_compatibility_mode() != OK: push_error("Errors loading game defines!") + + SoundSingleton.load_sounds() + SoundSingleton.load_music() + MusicConductor.add_compat_songs() + +func setup_title_theme() -> void: + SoundSingleton.load_title_theme() + + MusicConductor.setup_compat_song(SoundSingleton.title_theme) + + var song_paths = MusicConductor.get_all_song_paths() + var title_index = song_paths.find(SoundSingleton.title_theme) + if title_index != -1: + MusicConductor.call_deferred("start_song_by_index",title_index) + if len(MusicConductor._available_songs) <= 0: + push_error("No song available to play") + else: + MusicConductor.call_deferred("start_current_song") + # REQUIREMENTS # * FS-333, FS-334, FS-335, FS-341 diff --git a/game/src/Game/MusicConductor/MusicConductor.gd b/game/src/Game/MusicConductor/MusicConductor.gd index b4b660a..7103aff 100644 --- a/game/src/Game/MusicConductor/MusicConductor.gd +++ b/game/src/Game/MusicConductor/MusicConductor.gd @@ -17,6 +17,12 @@ var _selected_track := 0 var _available_songs : Array[SongInfo] = [] var _auto_play_next_song : bool = true +var playlist: Array[int] = [] +var playlist_index:int = 0 +var preferred_playlist_len: int = 7 +var last_played: int = -1 + + ## True if music player should be visible. ## Used to keep keep consistency between scene changes var is_music_player_visible : bool = true @@ -28,6 +34,12 @@ func get_all_song_names() -> PackedStringArray: for si : SongInfo in _available_songs: songNames.append(si.song_name) return songNames + +func get_all_song_paths() -> PackedStringArray: + var songPaths : PackedStringArray = [] + for si : SongInfo in _available_songs: + songPaths.append(si.song_path) + return songPaths func get_current_song_index() -> int: return _selected_track @@ -67,24 +79,82 @@ func start_song_by_index(id: int) -> void: # REQUIREMENTS # * SS-69 func select_next_song() -> void: - _selected_track = (_selected_track + 1) % len(_available_songs) + #_selected_track = (_selected_track + 1) % len(_available_songs) + if playlist_index >= preferred_playlist_len or playlist_index >= len(playlist): + generate_playlist() + playlist_index = 0 + _selected_track = playlist[playlist_index] + playlist_index += 1 + last_played = playlist_index start_current_song() func select_previous_song() -> void: _selected_track = (len(_available_songs) - 1) if (_selected_track == 0) else (_selected_track - 1) start_current_song() -# REQUIREMENTS -# * SND-2, SND-3 -func _ready() -> void: +func setup_compat_song(file_name) -> void: + var song = SongInfo.new() + var stream = SoundSingleton.get_song(file_name) + + var metadata = MusicMetadata.new() + metadata.set_from_stream(stream) + var title = metadata.title + if title == "": + #use the file name without the extension if there's no metadata + title = file_name.split(".")[0] + song.init_stream(file_name,title,stream) + _available_songs.append(song) + +func add_compat_songs() -> void: + for file_name : String in SoundSingleton.song_list: + setup_compat_song(file_name) + +func add_ootb_music() -> void: var dir := DirAccess.open(music_directory) for fname : String in dir.get_files(): if fname.ends_with(".import"): fname = fname.get_basename() if fname.get_basename() == first_song_name: _selected_track = _available_songs.size() - _available_songs.append(SongInfo.new(music_directory, fname)) - start_current_song() + var song = SongInfo.new() + song.init_file_path(music_directory, fname) + _available_songs.append(song) + +func generate_playlist() -> void: + var song_names = MusicConductor.get_all_song_paths() + var possible_indices = range(len(song_names)-1) + + var title_index = song_names.find(SoundSingleton.title_theme) + possible_indices.remove_at(title_index) + + var actual_playlist_len = min(preferred_playlist_len,len(possible_indices)) + + #if the playlist size is too large or small, make it the same size as what we + #need to support + if len(playlist) != actual_playlist_len: + playlist.resize(actual_playlist_len) + playlist.fill(0) + + #The song we just played can be in the playlist, just not the first one + if last_played != -1: + possible_indices.remove_at(last_played) + + #essentially shuffle-bag randomness, picking from a list of song indices + for i in range(actual_playlist_len): + var ind = randi_range(0,len(possible_indices)-1) + #add back the last song we just played as an option + if i==2: + possible_indices.append(last_played) + + playlist[i] = possible_indices[ind] + possible_indices.remove_at(ind) + +# REQUIREMENTS +# * SND-2, SND-3 +func _ready() -> void: + add_ootb_music() + #don't start the current song for compat mode, do that from + #GameStart so we can wait until the music is loaded func set_startup_music(play : bool) -> void: if not _has_startup_happened: diff --git a/game/src/Game/MusicConductor/SongInfo.gd b/game/src/Game/MusicConductor/SongInfo.gd index abcf120..527f618 100644 --- a/game/src/Game/MusicConductor/SongInfo.gd +++ b/game/src/Game/MusicConductor/SongInfo.gd @@ -3,9 +3,16 @@ class_name SongInfo var song_path : String = "" var song_name : String = "" -var song_stream : Resource +var song_stream : AudioStream -func _init(dirname:String, fname:String) -> void: +#Initialize from a file path +func init_file_path(dirname : String, fname : String) -> void: song_path = dirname.path_join(fname) song_name = fname.get_basename().replace("_", " ") song_stream = load(song_path) + +#Initialize from an audio stream +func init_stream(dirpath : String, name : String, stream : AudioStream) -> void: + song_path = dirpath + song_name = name + song_stream = stream diff --git a/game/src/Game/Theme/StyleBoxWithSound.gd b/game/src/Game/Theme/StyleBoxWithSound.gd index 8c29b34..75a181a 100644 --- a/game/src/Game/Theme/StyleBoxWithSound.gd +++ b/game/src/Game/Theme/StyleBoxWithSound.gd @@ -29,6 +29,6 @@ func _draw(to_canvas_item : RID, rect : Rect2) -> void: # Is there any other reason aside from release sounds (might be useful for toggles?) # This should be fast enough to not cause draw issues if sound != null: - SoundManager.play_effect_stream(sound) + SoundManager.play_effect_compat("click",sound) if style_box != null: style_box.draw(to_canvas_item, rect) |