Files
my-world/tools/test/measure_movement.gd
aibrashandClaude Sonnet 5.5 556d3af615 README: заметки для будущего меня; тестовые сцены в tools/test
- Договорённости с владельцем, замеры мувсета (стенами высоту не набрать), исправление
  подтягивания, конвейер Parkour и его грабли, ловушка с ресурсами, загружаемыми по строке
- tools/test: measure_movement, mantle_test, parkour_gaps, parkour_tour, parkour_check.txt

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WxZo3ekR5m1af437Qzqwc1
2026-10-28 15:05:29 +05:00

99 lines
5.1 KiB
GDScript
Raw Permalink 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.
extends Node
# Замеры мувсета ботом: дальность прыжка / двойного / рывка на спринте, бег по стене, прыжок от стены.
# Запуск: godot --headless --path . res://tools/test/measure_movement.tscn -- --client (~1 мин, печатает таблицу)
# Замеры мувсета: дальность прыжков, рывок, бег по стене, прыжок от стены
var root3d: Node3D
var p
func world(with_floor: bool, wall: bool) -> void:
if root3d: root3d.queue_free()
await get_tree().physics_frame
root3d = Node3D.new(); add_child(root3d)
var sb := StaticBody3D.new(); root3d.add_child(sb)
if with_floor:
var cs := CollisionShape3D.new(); var b := BoxShape3D.new(); b.size = Vector3(400, 1, 800); cs.shape = b; cs.position = Vector3(0, -0.5, -300); sb.add_child(cs)
if wall:
var cs2 := CollisionShape3D.new(); var b2 := BoxShape3D.new(); b2.size = Vector3(1, 400, 800); cs2.shape = b2; cs2.position = Vector3(-4.5, 0, -300); sb.add_child(cs2)
var cs3 := CollisionShape3D.new(); var b3 := BoxShape3D.new(); b3.size = Vector3(1, 400, 800); cs3.shape = b3; cs3.position = Vector3(4.5, 0, -300); sb.add_child(cs3)
func spawn(pos: Vector3, vel := Vector3.ZERO) -> void:
p = (load("res://player/player.tscn") as PackedScene).instantiate()
root3d.add_child(p)
p.global_position = pos
p.velocity = vel
func press(a: String) -> void: Input.action_press(a)
func release(a: String) -> void: Input.action_release(a)
func tap_dash() -> void:
var e := InputEventAction.new(); e.action = "dash"; e.pressed = true
Input.parse_input_event(e)
func release_all() -> void:
for a in ["move_forward","move_left","move_right","sprint","jump","crouch","dash"]: Input.action_release(a)
func frames(n: int) -> void:
for i in n: await get_tree().physics_frame
# прыжок с разбега по ровному полу: variant: single / dj / dash / djdash / dashdj
func jump_exp(variant: String) -> void:
await world(true, false)
spawn(Vector3(0, 1.17, 0))
await frames(5)
press("move_forward"); press("sprint")
await frames(60)
var z0: float = p.global_position.z
press("jump")
var maxy: float = 0.0; var f := 0; var did2 := false; var did3 := false; var lz := 0.0
while f < 400:
await get_tree().physics_frame; f += 1
maxy = maxf(maxy, p.global_position.y - 1.17)
if not did2 and p.velocity.y <= 0.0 and not p.is_on_floor():
did2 = true
if variant in ["dj", "djdash"]:
release("jump"); await get_tree().physics_frame; press("jump")
elif variant in ["dash", "dashdj"]:
tap_dash()
if did2 and not did3 and f > 40 and variant in ["djdash", "dashdj"]:
did3 = true
if variant == "djdash": tap_dash()
else: release("jump"); await get_tree().physics_frame; press("jump")
if f > 10 and p.is_on_floor():
lz = p.global_position.z; break
release_all()
print("прыжок %-7s: дальность %.1f м, высота %.2f м, время %.2f с" % [variant, z0 - lz, maxy, f / 60.0])
p.queue_free()
# бег по стене: летим вдоль левой стены со скоростью v, стена слева
func wall_exp(v: float, jump_after: float, then: String) -> void:
await world(false, true)
spawn(Vector3(-3.4, 100, 0), Vector3(0, 0, -v))
press("move_forward")
var z0: float = p.global_position.z
var f := 0; var run_f := 0; var started := false; var y_start := 0.0; var z_start := 0.0; var jumped := false; var x_max := -99.0; var z_j := 0.0; var y_j := 0.0
var landed_x := 0.0; var landed_z := 0.0; var t_j := 0
while f < 500:
await get_tree().physics_frame; f += 1
if p.is_wallrunning:
if not started: started = true; y_start = p.global_position.y; z_start = p.global_position.z
run_f += 1
if started and not jumped and (run_f / 60.0) >= jump_after:
jumped = true; z_j = p.global_position.z; y_j = p.global_position.y; t_j = f
release("move_forward"); press("move_forward")
press("jump"); await get_tree().physics_frame; release("jump")
if then == "dash": await frames(15); tap_dash()
if then == "dj": await frames(25); press("jump"); await get_tree().physics_frame; release("jump")
if jumped:
x_max = maxf(x_max, p.global_position.x)
if p.global_position.y < y_j - 3.0:
landed_x = p.global_position.x; landed_z = p.global_position.z; break
if not jumped and started and not p.is_wallrunning and f > 30:
break
release_all()
if jump_after < 0: pass
print("стена v=%.0f: бежали %.2f с, %.1f м вдоль, провал по y %.2f м; прыжок от стены (после %.1fс, затем %s): отлёт от стены до x=%.1f (стена x=-4), вперёд %.1f м, за %.2f с" % [v, run_f / 60.0, (z_start - (z_j if jumped else p.global_position.z)), y_start - (y_j if jumped else p.global_position.y), jump_after, then, x_max, z_j - landed_z, (f - t_j) / 60.0])
p.queue_free()
func _ready() -> void:
for v in ["single", "dj", "dash", "djdash", "dashdj"]:
await jump_exp(v)
await wall_exp(13.0, 99.0, "none")
await wall_exp(13.0, 0.5, "none")
await wall_exp(13.0, 0.5, "dash")
await wall_exp(13.0, 0.5, "dj")
get_tree().quit()