Files
mtgodot-poc/project/bgm_test.gd
T
shenandshen c93894313a fix: 装备属性面板避让逻辑 + 多项功能更新
- item_tooltip_view.gd: 新增 avoid_rect 属性,tooltip 与装备窗口重叠时自动推到左侧
- inventory_ui.gd: 悬停装备时传入窗口矩形作为避让区域
- 包含其他累积的功能开发和测试文件
2026-09-21 16:38:59 -07:00

180 lines
7.5 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# bgm_test —— §9.1 地图 BGM 选曲 + §9.2 前后台音量存/恢复的 headless 自检。
# godot --headless --path project --script bgm_test.gd
# exit 0 = pass。
extends SceneTree
const BgmDirector = preload("res://bgm_director.gd")
const Audio = preload("res://audio.gd")
const AppLifecycle = preload("res://app_lifecycle.gd")
const MusicInfo = preload("res://musicinfo.gd")
const DEFAULT_VOL := 1.0 / 5.0 * 0.1 # 0.02
# 假 M2Client:只发 §9.1 关心的两个信号。
class FakeClient extends Node:
signal bgm_changed(name: String, volume: float)
signal world_reset()
# 假 Audio:记录 play_bgm / stop_bgm 调用与音量,够 director 断言用。
class FakeAudio extends Node:
var master_bgm := 0.6
var master_sfx := 0.9
var _bgm_name := ""
var played: Array[String] = []
var stopped := 0
func play_bgm(name: String, _fade := 1.2) -> void:
if name == _bgm_name:
return
_bgm_name = name
played.append(name)
func stop_bgm(_fade := 1.0) -> void:
_bgm_name = ""
stopped += 1
func set_music_volume(v: float) -> void:
master_bgm = clampf(v, 0.0, 1.0)
func set_sound_volume(v: float) -> void:
master_sfx = clampf(v, 0.0, 1.0)
var _fail := 0
func _ck(c: bool, m: String) -> void:
if not c:
_fail += 1
printerr("FAIL: " + m)
func _init() -> void:
_test_select_server_volume()
_test_select_default_volume()
_test_select_empty_falls_back()
_test_world_reset_reruns()
_test_musicinfo_lastplay_roundtrip()
_test_background_save_restore()
_test_window_focus_save_restore()
if _fail == 0:
print("PASS: bgm_test (§9.1 map BGM select + §9.2 volume save/restore)")
quit(0)
else:
printerr("%d check(s) failed" % _fail)
quit(1)
func _mk_director() -> Array:
var client := FakeClient.new()
var audio := FakeAudio.new()
var bd := BgmDirector.new()
get_root().add_child(client)
get_root().add_child(audio)
get_root().add_child(bd)
bd.bind(client, audio)
return [client, audio, bd]
# §9.1:服务端给了名字 + 音量 -> 用服务端音量并播放该曲。
func _test_select_server_volume() -> void:
var t := _mk_director()
var client: FakeClient = t[0]
var audio: FakeAudio = t[1]
client.bgm_changed.emit("pvp_bgm.mp3", 0.5)
_ck(audio.played == ["pvp_bgm.mp3"], "server name played, got %s" % [audio.played])
_ck(is_equal_approx(audio.master_bgm, 0.5), "server volume applied, got %f" % audio.master_bgm)
_ck(audio.stopped == 0, "no stop_bgm on server-provided track")
t[0].free(); t[1].free(); t[2].free()
# §9.1:服务端给了名字但音量 <0GC_MAIN_CHARACTER3_BGM,未收 BGM4-> 默认 0.02。
func _test_select_default_volume() -> void:
var t := _mk_director()
var client: FakeClient = t[0]
var audio: FakeAudio = t[1]
client.bgm_changed.emit("field_a.mp3", -1.0)
_ck(audio.played == ["field_a.mp3"], "name played on unspecified volume, got %s" % [audio.played])
_ck(is_equal_approx(audio.master_bgm, DEFAULT_VOL), "default 0.02 applied, got %f" % audio.master_bgm)
t[0].free(); t[1].free(); t[2].free()
# §9.1:服务端名为空 -> 回落 musicInfo.fieldMusicMETIN2THEMA = "M2BG.mp3")。
func _test_select_empty_falls_back() -> void:
var t := _mk_director()
var client: FakeClient = t[0]
var audio: FakeAudio = t[1]
client.bgm_changed.emit("", -1.0)
_ck(audio.played == [String(MusicInfo.fieldMusic)],
"empty name falls back to fieldMusic, got %s" % [audio.played])
_ck(String(MusicInfo.fieldMusic) == "M2BG.mp3", "METIN2THEMA constant is M2BG.mp3")
_ck(is_equal_approx(audio.master_bgm, DEFAULT_VOL), "default 0.02 on fallback, got %f" % audio.master_bgm)
t[0].free(); t[1].free(); t[2].free()
# §9.1 / §1.3:换图(world_reset)重跑选曲逻辑。
func _test_world_reset_reruns() -> void:
var t := _mk_director()
var client: FakeClient = t[0]
var audio: FakeAudio = t[1]
var bd: BgmDirector = t[2]
_ck(client.world_reset.is_connected(bd._on_world_reset), "director connected to world_reset")
client.bgm_changed.emit("map_a.mp3", 0.4)
# warpworld_reset 先到(旧曲目仍在 store 里),随后新图的 BGM 包。
client.world_reset.emit()
_ck(audio.played == ["map_a.mp3"], "world_reset keeps current track, got %s" % [audio.played])
client.bgm_changed.emit("map_b.mp3", 0.2)
_ck(audio.played == ["map_a.mp3", "map_b.mp3"], "new map BGM played, got %s" % [audio.played])
_ck(is_equal_approx(audio.master_bgm, 0.2), "new map volume applied, got %f" % audio.master_bgm)
t[0].free(); t[1].free(); t[2].free()
# §9.1musicInfo.SaveLastPlayFieldMusic / LoadLastPlayFieldMusic 往返。
func _test_musicinfo_lastplay_roundtrip() -> void:
MusicInfo.save_last_play_field_music("last_field.mp3")
_ck(MusicInfo.load_last_play_field_music() == "last_field.mp3",
"lastplay.inf roundtrip, got %s" % MusicInfo.load_last_play_field_music())
# §9.2:后台保存音量 + 静音,前台恢复;_bgm_name 不变,同一首继续播。
func _test_background_save_restore() -> void:
var client := FakeClient.new()
var audio := Audio.new()
var life := AppLifecycle.new()
get_root().add_child(audio)
audio.setup("res://__no_assets__") # 无资源,play_bgm 只置名不出声
get_root().add_child(life)
life.pause_tree_on_background = false # 别把测试树暂停了
life.background_max_fps = 0
life.bind(null, audio)
audio.master_bgm = 0.6
audio.master_sfx = 0.9
# 模拟「某首战场曲目正在播放」(headless 无资源,不实际解码)。
audio._bgm_name = "M2BG.mp3"
var name_before := audio._bgm_name
_ck(name_before == "M2BG.mp3", "bgm name set before background, got %s" % name_before)
life._enter_background()
_ck(is_equal_approx(audio.master_bgm, 0.0), "music muted in background, got %f" % audio.master_bgm)
_ck(is_equal_approx(audio.master_sfx, 0.0), "sound muted in background, got %f" % audio.master_sfx)
_ck(audio._volume_saved, "save_volume ran (backup taken)")
_ck(is_equal_approx(audio._backup_music_volume, 0.6), "backup music volume, got %f" % audio._backup_music_volume)
_ck(is_equal_approx(audio._backup_sound_volume, 0.9), "backup sound volume, got %f" % audio._backup_sound_volume)
_ck(audio._bgm_name == name_before, "_bgm_name unchanged in background, got %s" % audio._bgm_name)
life._exit_background()
_ck(is_equal_approx(audio.master_bgm, 0.6), "music volume restored, got %f" % audio.master_bgm)
_ck(is_equal_approx(audio.master_sfx, 0.9), "sound volume restored, got %f" % audio.master_sfx)
_ck(audio._bgm_name == name_before, "_bgm_name still unchanged after restore, got %s" % audio._bgm_name)
_ck(not audio._volume_saved, "backup flag cleared after restore")
client.free(); life.free(); audio.free()
# §9.2 / Windows WM_ACTIVATEAPP:桌面失焦和重新获得焦点与后台一样保存、静音、恢复。
func _test_window_focus_save_restore() -> void:
var audio := Audio.new()
var life := AppLifecycle.new()
get_root().add_child(audio)
audio.setup("res://__no_assets__")
get_root().add_child(life)
life.pause_tree_on_background = false
life.background_max_fps = 0
life.bind(null, audio)
audio.master_bgm = 0.55
audio.master_sfx = 0.75
life._notification(Node.NOTIFICATION_WM_WINDOW_FOCUS_OUT)
_ck(is_equal_approx(audio.master_bgm, 0.0), "window focus-out mutes music, got %f" % audio.master_bgm)
_ck(is_equal_approx(audio.master_sfx, 0.0), "window focus-out mutes sound, got %f" % audio.master_sfx)
life._notification(Node.NOTIFICATION_WM_WINDOW_FOCUS_IN)
_ck(is_equal_approx(audio.master_bgm, 0.55), "window focus-in restores music, got %f" % audio.master_bgm)
_ck(is_equal_approx(audio.master_sfx, 0.75), "window focus-in restores sound, got %f" % audio.master_sfx)
life.free(); audio.free()