# BgmDirector —— 把 M2Client.bgm_changed 信号翻译成 Audio 的 BGM 播放。 # # 存在的理由:§9.1 的地图 BGM 消费点,从 net_world.gd 里拆出来,避免 W2(可见性) # 和 W4(音频)同时改 net_world.gd。地图 → 曲目解析和音量应用在这里(§9.1)。 # # 选曲逻辑对标 game.py:190(GameWindow.Open 内): # snd.SetMusicVolume(...); snd.SetSoundVolume(...) # 先应用音量 # name = net.GetFieldMusicFileName() # if name: snd.FadeInMusic("BGM/" + name) # elif musicInfo.fieldMusic: snd.FadeInMusic("BGM/" + musicInfo.fieldMusic) # 默认音量 gs_fieldMusic_volume = 1.0f/5.0f*0.1f = 0.02f(服务器未下发时)。 # # 用法: # var bd := preload("res://bgm_director.gd").new() # add_child(bd) # bd.bind(client, audio) extends Node const MusicInfo = preload("res://musicinfo.gd") # gs_fieldMusic_volume 默认值(PythonNetworkStreamPhaseLoading.cpp:299)。 const DEFAULT_FIELD_MUSIC_VOLUME := 1.0 / 5.0 * 0.1 # = 0.02 var _client: Node var _audio: Node # 服务器最近一次下发的 BGM(曲目 id 或路径)和音量(<0 表示未指定)。 var current_track := "" var current_volume := -1.0 func bind(client: Node, audio: Node) -> void: _client = client _audio = audio if _client and _client.has_signal("bgm_changed"): _client.bgm_changed.connect(_on_bgm_changed) # 换图(§1.3):world_reset 后重跑选曲逻辑。新图的 BGM 包到达前沿用当前曲目。 if _client and _client.has_signal("world_reset"): _client.world_reset.connect(_on_world_reset) func _on_bgm_changed(name: String, volume: float) -> void: # M2Client 已在 EntityStore 侧做音量保留(BGM3 只带名、BGM4 带名+音量), # 这里拿到的 volume 就是「有效音量」,<0 仅表示从未收到过 BGM4。 current_track = name current_volume = volume _select() func _on_world_reset() -> void: _select() # game.py:190 的三行选曲 + 先置音量。 func _select() -> void: if _audio == null: return # 1) 选曲:服务端名优先,否则回落 musicInfo.fieldMusic(METIN2THEMA = "M2BG.mp3")。 var track := current_track if track == "": track = String(MusicInfo.fieldMusic) # 2) 音量:服务端未指定(<0)用默认 0.02,否则用服务端值。 var vol := current_volume if current_volume >= 0.0 else DEFAULT_FIELD_MUSIC_VOLUME vol = clampf(vol, 0.0, 1.0) # 3) 先应用音量再淡入:Audio.play_bgm() 的淡入目标是 linear_to_db(master_bgm), # 对标 game.py 先 SetMusicVolume/SetSoundVolume 再 FadeInMusic。 # 声音(SFX)音量在参考里取自系统设置(systemSetting.GetSoundVolume), # 不随 BGM 包下发,这里不改 master_sfx。 if "master_bgm" in _audio: _audio.master_bgm = vol if _audio.has_method("set_music_volume"): _audio.set_music_volume(vol) if track == "": if _audio.has_method("stop_bgm"): _audio.stop_bgm() return if _audio.has_method("play_bgm"): _audio.play_bgm(track) # musicInfo.SaveLastPlayFieldMusic 语义:记录本次战场曲目。 MusicInfo.save_last_play_field_music(track)