Files
Bullosseum/tests/ragdoll_throw_test.gd
2026-06-10 18:56:17 +03:00

84 lines
2.4 KiB
GDScript

extends SceneTree
## Ragdoll throw visual test — triggers ragdoll on the matador and captures a
## frame strip so you can inspect the throw arc and settling.
##
## Run (needs a display for real screenshots):
## godot --script tests/ragdoll_throw_test.gd
##
## Outputs: tests/output/ragdoll_throw/frame_00..09.png
## Each frame is 0.2 s apart → strip covers 2 s of flight and tumble.
const OUTPUT_DIR := "res://tests/output/ragdoll_throw"
const BULL_SPEED := 22.0 # simulate a solid charge
const TRACKED_BONES: Array[StringName] = [&"chest", &"head", &"COG"]
func _init() -> void:
_run.call_deferred()
func _run() -> void:
DirAccess.make_dir_recursive_absolute(OUTPUT_DIR)
var scene_res := load("res://scene.tscn")
if not scene_res:
push_error("ragdoll_throw_test: failed to load scene.tscn")
quit(1)
return
var scene: Node = scene_res.instantiate()
root.add_child(scene)
# Let physics and AI settle
await create_timer(0.8).timeout
var matadors := get_nodes_in_group(&"matador")
if matadors.is_empty():
push_error("ragdoll_throw_test: no matadors in scene")
quit(1)
return
var mat := matadors[0] as Node3D
var spawn := mat.global_position
print("matador spawn: %s" % spawn)
# Throw toward +Z with a realistic charge speed
mat.call(&"_enter_ragdoll", Vector3(0.0, 0.0, 1.0), BULL_SPEED)
print("ragdoll triggered bull_speed=%.1f" % BULL_SPEED)
# Strip: 10 frames every 0.2 s
for i: int in range(10):
await create_timer(0.2).timeout
var t := (i + 1) * 0.2
var img: Image = root.get_viewport().get_texture().get_image()
if img:
img.save_png(OUTPUT_DIR + "/frame_%02d.png" % i)
var sim: Node = _find_class_recursive(mat, "PhysicalBoneSimulator3D")
var bone_info := ""
if sim:
for bone_name: StringName in TRACKED_BONES:
for child: Node in sim.get_children():
if child is PhysicalBone3D and \
(child as PhysicalBone3D).bone_name == bone_name:
var bp: Vector3 = (child as PhysicalBone3D).global_position
var dist: float = bp.distance_to(spawn)
bone_info += " %s y=%.2f dist=%.2f" % [bone_name, bp.y, dist]
print("t=%.1fs frame %02d%s" % [t, i, bone_info])
print("\nStrip saved → %s" % OUTPUT_DIR)
quit(0)
func _find_class_recursive(node: Node, class_name_str: String) -> Node:
if node.get_class() == class_name_str:
return node
for child: Node in node.get_children():
var r := _find_class_recursive(child, class_name_str)
if r:
return r
return null