extends SceneTree ## 节奏点从两侧向中心的移动必须由音乐时钟连续驱动: ## 进度 = RhythmManager 当前拍内进度,不允许 beat_flash 期间瞬移到中心。 var failures: Array[String] = [] func _init() -> void: _run.call_deferred() func _run() -> void: root.size = Vector2i(1152, 648) var rhythm := root.get_node_or_null("RhythmManager") _expect(rhythm != null, "RhythmManager autoload should exist") if rhythm == null: _finish() return var scene: PackedScene = load("res://scenes/ui/rhythm_track.tscn") _expect(scene != null, "rhythm_track.tscn should load") if scene == null: _finish() return var track := scene.instantiate() as Control root.add_child(track) await process_frame var beat_time := float(rhythm.get("beat_time")) var left_mover := track.get_node("LeftMover") as Control var right_mover := track.get_node("RightMover") as Control var left_start := track.get("left_mover_start") as Vector2 var right_start := track.get("right_mover_start") as Vector2 var center := track.get("track_center") as Vector2 # 把音乐时钟冻结在拍内 37% 处,节奏点必须停在 37% 的插值位置。 rhythm.call("pause_clock") rhythm.set("_paused_song_position", beat_time * 0.37) # beat_flash 拉满:旧实现会在此瞬移到中心,新实现必须继续跟随时钟。 track.set("beat_flash", 1.0) track.call("_update_movers") _expect_mover_at(left_mover, left_start.lerp(center, 0.37), "left mover follows the musical clock at 37%") _expect_mover_at(right_mover, right_start.lerp(center, 0.37), "right mover follows the musical clock at 37%") # 时钟推进到 82%:节奏点连续前进,不回跳。 rhythm.set("_paused_song_position", beat_time * 0.82) track.call("_update_movers") _expect_mover_at(left_mover, left_start.lerp(center, 0.82), "left mover keeps gliding at 82%") _expect_mover_at(right_mover, right_start.lerp(center, 0.82), "right mover keeps gliding at 82%") # 拍点整数时刻(进度 0):节奏点回到两侧起点,开始下一拍收束。 rhythm.set("_paused_song_position", beat_time * 1.0) track.call("_update_movers") _expect_mover_at(left_mover, left_start, "left mover restarts from the edge on the beat") _expect_mover_at(right_mover, right_start, "right mover restarts from the edge on the beat") rhythm.call("resume_clock") track.free() _finish() func _expect_mover_at(mover: Control, expected_center: Vector2, label: String) -> void: var actual := Vector2( (mover.offset_left + mover.offset_right) * 0.5, (mover.offset_top + mover.offset_bottom) * 0.5 ) if actual.distance_to(expected_center) > 0.75: failures.append("%s: expected %s, got %s" % [label, expected_center, actual]) func _expect(condition: bool, label: String) -> void: if not condition: failures.append(label) func _finish() -> void: if failures.is_empty(): print("PASS rhythm mover smoothness") quit(0) else: for failure: String in failures: push_error(failure) quit(1)