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
This commit is contained in:
2026-10-28 15:05:29 +05:00
co-authored by Claude Sonnet 5.5
parent af462364c0
commit 556d3af615
14 changed files with 329 additions and 2 deletions
+51
View File
@@ -0,0 +1,51 @@
extends Node
# Подтягивание на уступы: тонкая полка и сплошной блок, коллизия «коробка» и «меш», ходьба и спринт, высоты 1,2–2,7 м.
# Запуск: godot --headless --path . res://tools/test/mantle_test.tscn -- --client (ожидание: везде «ДА»)
var root3d: Node3D
var p
# kind: "thin" (полка 0.6 м, под ней пусто) или "block" (сплошной блок от пола); shape: "box" или "mesh"
func build(kind: String, shape: String, h: float) -> 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)
var fl := CollisionShape3D.new(); var fb := BoxShape3D.new(); fb.size = Vector3(60, 1, 60); fl.shape = fb; fl.position = Vector3(0, -0.5, 0); sb.add_child(fl)
var size := Vector3(10, 0.6, 12) if kind == "thin" else Vector3(10, h, 12)
var cy := h - 0.3 if kind == "thin" else h * 0.5
var cs := CollisionShape3D.new()
if shape == "box":
var b := BoxShape3D.new(); b.size = size; cs.shape = b
else:
var m := BoxMesh.new(); m.size = size; cs.shape = m.create_trimesh_shape()
cs.position = Vector3(0, cy, -8 - size.z * 0.5) # передняя грань на z=-8
sb.add_child(cs)
func trial(kind: String, shape: String, h: float, sprint: bool) -> String:
await build(kind, shape, h)
p = (load("res://player/player.tscn") as PackedScene).instantiate()
root3d.add_child(p)
p.global_position = Vector3(0, 1.17, 0)
await get_tree().physics_frame
Input.action_press("move_forward")
if sprint: Input.action_press("sprint")
var f := 0; var jumped := false; var ok := false
while f < 420:
await get_tree().physics_frame; f += 1
var dz: float = p.global_position.z + 8.0 # до грани
if not jumped and dz < (-1.0 if not sprint else 0.0) + 2.4 and p.is_on_floor() and f > 30:
jumped = true; Input.action_press("jump")
if jumped and p.is_on_floor() and p.global_position.z < -8.2 and absf(p.global_position.y - (h + 1.16)) < 0.35:
ok = true; break
for a in ["move_forward","sprint","jump"]: Input.action_release(a)
var res := "ДА " if ok else "нет"
p.queue_free()
return res
func _ready() -> void:
print("высота уступа: 1.2 1.6 2.0 2.4 2.7")
for kind in ["thin", "block"]:
for shape in ["box", "mesh"]:
for sprint in [false, true]:
var row := "%-5s %-4s %-6s " % [kind, shape, "спринт" if sprint else "ходьба"]
for h in [1.2, 1.6, 2.0, 2.4, 2.7]:
row += await trial(kind, shape, h, sprint) + " "
print(row)
get_tree().quit()