Initial commit: Fighting_Rthythm_game project setup
This commit is contained in:
40
tests/test_jump_height.gd
Normal file
40
tests/test_jump_height.gd
Normal file
@@ -0,0 +1,40 @@
|
||||
extends SceneTree
|
||||
|
||||
const ORIGINAL_JUMP_INTENSITY := 430.0
|
||||
const GRAVITY := 1200.0
|
||||
|
||||
var failures: Array[String] = []
|
||||
|
||||
|
||||
func _init() -> void:
|
||||
var scene: PackedScene = load("res://scenes/characters/player.tscn")
|
||||
if scene == null:
|
||||
push_error("Could not load player.tscn")
|
||||
quit(1)
|
||||
return
|
||||
|
||||
var player: Node = scene.instantiate()
|
||||
var jump_intensity: float = float(player.get("jump_intensity"))
|
||||
var expected_height: float = _jump_height(ORIGINAL_JUMP_INTENSITY) * 0.5
|
||||
var actual_height: float = _jump_height(jump_intensity)
|
||||
|
||||
if absf(actual_height - expected_height) > 0.01:
|
||||
failures.append("jump height expected %.3f, got %.3f from jump_intensity %.3f" % [
|
||||
expected_height,
|
||||
actual_height,
|
||||
jump_intensity,
|
||||
])
|
||||
|
||||
player.free()
|
||||
|
||||
if failures.is_empty():
|
||||
print("PASS jump height")
|
||||
quit(0)
|
||||
else:
|
||||
for failure: String in failures:
|
||||
push_error(failure)
|
||||
quit(1)
|
||||
|
||||
|
||||
func _jump_height(jump_intensity: float) -> float:
|
||||
return jump_intensity * jump_intensity / (2.0 * GRAVITY)
|
||||
1
tests/test_jump_height.gd.uid
Normal file
1
tests/test_jump_height.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://14lstjosx718
|
||||
56
tests/test_player_scale.gd
Normal file
56
tests/test_player_scale.gd
Normal file
@@ -0,0 +1,56 @@
|
||||
extends SceneTree
|
||||
|
||||
var failures: Array[String] = []
|
||||
|
||||
|
||||
func _init() -> void:
|
||||
var scene: PackedScene = load("res://scenes/characters/player.tscn")
|
||||
if scene == null:
|
||||
push_error("Could not load player.tscn")
|
||||
quit(1)
|
||||
return
|
||||
|
||||
var player: Node = scene.instantiate()
|
||||
var sprite: Sprite2D = player.get_node("CharacterSprite") as Sprite2D
|
||||
var collision: CollisionShape2D = player.get_node("CollisionShape2D") as CollisionShape2D
|
||||
var camera: Camera2D = player.get_node("Camera2D") as Camera2D
|
||||
var animation_player: AnimationPlayer = player.get_node("AnimationPlayer") as AnimationPlayer
|
||||
|
||||
_expect_vector((player as Node2D).scale, Vector2(4, 4), "Player root scale")
|
||||
_expect_vector(sprite.scale, Vector2.ONE, "CharacterSprite local scale should keep anchor")
|
||||
_expect_vector(sprite.offset, Vector2(-24, -40), "CharacterSprite visible foot offset")
|
||||
_expect_vector(collision.scale, Vector2.ONE, "CollisionShape2D local scale should keep anchor")
|
||||
_expect_vector(collision.position, Vector2(0, -18), "CollisionShape2D local position should keep anchor")
|
||||
_expect_vector(camera.position, Vector2(0, -37.5), "Camera2D position should compensate player scale")
|
||||
_expect_vector(camera.scale, Vector2(0.25, 0.25), "Camera2D scale should compensate player scale")
|
||||
_expect_animation_offset(animation_player, "idle", Vector2(-24, -40))
|
||||
_expect_animation_offset(animation_player, "jump", Vector2(-24, -44))
|
||||
_expect_animation_offset(animation_player, "挥砍", Vector2(-40, -48))
|
||||
|
||||
player.free()
|
||||
|
||||
if failures.is_empty():
|
||||
print("PASS player scale")
|
||||
quit(0)
|
||||
else:
|
||||
for failure: String in failures:
|
||||
push_error(failure)
|
||||
quit(1)
|
||||
|
||||
|
||||
func _expect_vector(actual: Vector2, expected: Vector2, label: String) -> void:
|
||||
if not actual.is_equal_approx(expected):
|
||||
failures.append("%s: expected %s, got %s" % [label, expected, actual])
|
||||
|
||||
|
||||
func _expect_animation_offset(animation_player: AnimationPlayer, animation_name: String, expected: Vector2) -> void:
|
||||
var animation: Animation = animation_player.get_animation(animation_name)
|
||||
if animation == null:
|
||||
failures.append("Missing animation: %s" % animation_name)
|
||||
return
|
||||
for track_index: int in range(animation.get_track_count()):
|
||||
if animation.track_get_path(track_index) == NodePath("CharacterSprite:offset"):
|
||||
var actual: Vector2 = animation.track_get_key_value(track_index, 0)
|
||||
_expect_vector(actual, expected, "%s CharacterSprite offset" % animation_name)
|
||||
return
|
||||
failures.append("Missing CharacterSprite offset track: %s" % animation_name)
|
||||
1
tests/test_player_scale.gd.uid
Normal file
1
tests/test_player_scale.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://di3givapw00bd
|
||||
41
tests/test_rhythm_conductor.gd
Normal file
41
tests/test_rhythm_conductor.gd
Normal file
@@ -0,0 +1,41 @@
|
||||
extends SceneTree
|
||||
|
||||
var failures: Array[String] = []
|
||||
|
||||
|
||||
func _init() -> void:
|
||||
var conductor_script: Script = load("res://scenes/rhythm/rhythm_conductor.gd")
|
||||
if conductor_script == null:
|
||||
push_error("Could not load rhythm_conductor.gd")
|
||||
quit(1)
|
||||
return
|
||||
var conductor: Node = conductor_script.new()
|
||||
conductor.set("bpm", 120.0)
|
||||
conductor.set("perfect_window", 0.060)
|
||||
conductor.set("good_window", 0.120)
|
||||
conductor.set("bad_window", 0.200)
|
||||
conductor.set("beat_offset", 0.0)
|
||||
conductor.call("_ready")
|
||||
|
||||
_expect_rating(conductor, 1.000, "perfect", "exact beat")
|
||||
_expect_rating(conductor, 1.055, "perfect", "55ms from beat")
|
||||
_expect_rating(conductor, 1.095, "good", "95ms from beat")
|
||||
_expect_rating(conductor, 1.170, "bad", "170ms from beat")
|
||||
_expect_rating(conductor, 1.240, "miss", "240ms from beat")
|
||||
|
||||
conductor.free()
|
||||
|
||||
if failures.is_empty():
|
||||
print("PASS rhythm conductor")
|
||||
quit(0)
|
||||
else:
|
||||
for failure: String in failures:
|
||||
push_error(failure)
|
||||
quit(1)
|
||||
|
||||
|
||||
func _expect_rating(conductor: Node, time_seconds: float, expected: String, label: String) -> void:
|
||||
var rating: Dictionary = conductor.call("get_rating_for_time", time_seconds)
|
||||
var actual: String = str(rating.get("label", ""))
|
||||
if actual != expected:
|
||||
failures.append("%s: expected %s, got %s" % [label, expected, actual])
|
||||
1
tests/test_rhythm_conductor.gd.uid
Normal file
1
tests/test_rhythm_conductor.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cwovjddnrsl2o
|
||||
42
tests/test_rhythm_scene.gd
Normal file
42
tests/test_rhythm_scene.gd
Normal file
@@ -0,0 +1,42 @@
|
||||
extends SceneTree
|
||||
|
||||
var failures: Array[String] = []
|
||||
|
||||
|
||||
func _init() -> void:
|
||||
var scene: PackedScene = load("res://scenes/main/main.tscn")
|
||||
if scene == null:
|
||||
push_error("Could not load main.tscn")
|
||||
quit(1)
|
||||
return
|
||||
|
||||
var main: Node = scene.instantiate()
|
||||
if main.get_script() == null:
|
||||
failures.append("Main script failed to load")
|
||||
var required_nodes := [
|
||||
"RhythmConductor",
|
||||
"RhythmFeedback",
|
||||
"Player",
|
||||
]
|
||||
for node_name: String in required_nodes:
|
||||
if not main.has_node(node_name):
|
||||
failures.append("Missing required node: %s" % node_name)
|
||||
|
||||
if main.has_node("RhythmConductor"):
|
||||
var conductor: Node = main.get_node("RhythmConductor")
|
||||
if not conductor.has_method("judge_action"):
|
||||
failures.append("RhythmConductor missing judge_action")
|
||||
if not conductor is AudioStreamPlayer:
|
||||
failures.append("RhythmConductor should be an AudioStreamPlayer")
|
||||
elif (conductor as AudioStreamPlayer).stream == null:
|
||||
failures.append("RhythmConductor should have a music stream")
|
||||
|
||||
main.free()
|
||||
|
||||
if failures.is_empty():
|
||||
print("PASS rhythm scene")
|
||||
quit(0)
|
||||
else:
|
||||
for failure: String in failures:
|
||||
push_error(failure)
|
||||
quit(1)
|
||||
1
tests/test_rhythm_scene.gd.uid
Normal file
1
tests/test_rhythm_scene.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bmrcfsd34i24n
|
||||
41
tests/test_rhythm_ui.gd
Normal file
41
tests/test_rhythm_ui.gd
Normal file
@@ -0,0 +1,41 @@
|
||||
extends SceneTree
|
||||
|
||||
var failures: Array[String] = []
|
||||
|
||||
|
||||
func _init() -> void:
|
||||
var scene: PackedScene = load("res://scenes/main/main.tscn")
|
||||
if scene == null:
|
||||
push_error("Could not load main.tscn")
|
||||
quit(1)
|
||||
return
|
||||
|
||||
var main: Node = scene.instantiate()
|
||||
var required_nodes := [
|
||||
"RhythmFeedback/RhythmTrack",
|
||||
"RhythmFeedback/RhythmTrack/LeftRod",
|
||||
"RhythmFeedback/RhythmTrack/RightRod",
|
||||
"RhythmFeedback/RhythmTrack/CenterBase",
|
||||
"RhythmFeedback/RhythmTrack/CenterFlash",
|
||||
"RhythmFeedback/RhythmTrack/LeftMover",
|
||||
"RhythmFeedback/RhythmTrack/RightMover",
|
||||
"RhythmFeedback/RhythmTrack/BlueBallLeft1",
|
||||
"RhythmFeedback/RhythmTrack/BlueBallRight1",
|
||||
"RhythmFeedback/JudgementLabel",
|
||||
]
|
||||
for node_path: String in required_nodes:
|
||||
if not main.has_node(node_path):
|
||||
failures.append("Missing rhythm UI node: %s" % node_path)
|
||||
|
||||
if main.has_method("_update_rhythm_track") == false:
|
||||
failures.append("Main script missing _update_rhythm_track")
|
||||
|
||||
main.free()
|
||||
|
||||
if failures.is_empty():
|
||||
print("PASS rhythm ui")
|
||||
quit(0)
|
||||
else:
|
||||
for failure: String in failures:
|
||||
push_error(failure)
|
||||
quit(1)
|
||||
1
tests/test_rhythm_ui.gd.uid
Normal file
1
tests/test_rhythm_ui.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://b52hcjno3t4to
|
||||
60
tests/test_rhythm_ui_layout.gd
Normal file
60
tests/test_rhythm_ui_layout.gd
Normal file
@@ -0,0 +1,60 @@
|
||||
extends SceneTree
|
||||
|
||||
var failures: Array[String] = []
|
||||
|
||||
|
||||
func _init() -> void:
|
||||
_run.call_deferred()
|
||||
|
||||
|
||||
func _run() -> void:
|
||||
var scene: PackedScene = load("res://scenes/main/main.tscn")
|
||||
if scene == null:
|
||||
push_error("Could not load main.tscn")
|
||||
quit(1)
|
||||
return
|
||||
|
||||
var main: Node = scene.instantiate()
|
||||
var initial_left_mover: Control = main.get_node("RhythmFeedback/RhythmTrack/LeftMover")
|
||||
var initial_right_mover: Control = main.get_node("RhythmFeedback/RhythmTrack/RightMover")
|
||||
var initial_center_base: Control = main.get_node("RhythmFeedback/RhythmTrack/CenterBase")
|
||||
var initial_center_flash: Control = main.get_node("RhythmFeedback/RhythmTrack/CenterFlash")
|
||||
var expected_left_start := _control_center(initial_left_mover)
|
||||
var expected_right_start := _control_center(initial_right_mover)
|
||||
var expected_track_center := _control_center(initial_center_base)
|
||||
var expected_mover_size := initial_left_mover.size
|
||||
var expected_center_flash_size := initial_center_flash.size
|
||||
|
||||
root.add_child(main)
|
||||
await process_frame
|
||||
|
||||
_expect_vector("left_mover_start", main.get("left_mover_start"), expected_left_start)
|
||||
_expect_vector("right_mover_start", main.get("right_mover_start"), expected_right_start)
|
||||
_expect_vector("track_center", main.get("track_center"), expected_track_center)
|
||||
_expect_vector("mover_size", main.get("mover_size"), expected_mover_size)
|
||||
_expect_vector("center_flash_size", main.get("center_flash_size"), expected_center_flash_size)
|
||||
|
||||
main.free()
|
||||
|
||||
if failures.is_empty():
|
||||
print("PASS rhythm ui layout")
|
||||
quit(0)
|
||||
else:
|
||||
for failure: String in failures:
|
||||
push_error(failure)
|
||||
quit(1)
|
||||
|
||||
|
||||
func _control_center(control: Control) -> Vector2:
|
||||
return Vector2(
|
||||
(control.offset_left + control.offset_right) * 0.5,
|
||||
(control.offset_top + control.offset_bottom) * 0.5
|
||||
)
|
||||
|
||||
|
||||
func _expect_vector(label: String, actual: Variant, expected: Vector2) -> void:
|
||||
if not actual is Vector2:
|
||||
failures.append("%s should be cached as Vector2, got %s" % [label, typeof(actual)])
|
||||
return
|
||||
if not (actual as Vector2).is_equal_approx(expected):
|
||||
failures.append("%s should match scene layout: expected %s got %s" % [label, expected, actual])
|
||||
1
tests/test_rhythm_ui_layout.gd.uid
Normal file
1
tests/test_rhythm_ui_layout.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bnkjqsfttot3m
|
||||
Reference in New Issue
Block a user