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:
@@ -0,0 +1,98 @@
|
||||
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()
|
||||
Reference in New Issue
Block a user