141 lines
4.6 KiB
GDScript
141 lines
4.6 KiB
GDScript
extends Node2D
|
||
|
||
## Строгий headless-тест механик Этапа 1.
|
||
## Сцена: основной пол 800x40 (центр x=0), страховочный пол ниже (y=1000).
|
||
## Лиса стартует на (0,300).
|
||
|
||
var fox: CharacterBody2D
|
||
var phase: int = 0
|
||
var pt: float = 0.0 # время внутри фазы
|
||
var ground_y: float = 0.0
|
||
var min_y: float = 99999.0
|
||
var results: Array = []
|
||
|
||
# служебные флаги
|
||
var pressed_jump: bool = false
|
||
var airborne_at: float = -1.0
|
||
var left_ledge: bool = false
|
||
|
||
func _ready() -> void:
|
||
fox = $FoxInstance
|
||
|
||
func _reset_phase() -> void:
|
||
pt = 0.0
|
||
min_y = 99999.0
|
||
pressed_jump = false
|
||
left_ledge = false
|
||
airborne_at = -1.0
|
||
|
||
func _physics_process(delta: float) -> void:
|
||
pt += delta
|
||
|
||
match phase:
|
||
0: # ждём приземления
|
||
if fox.is_on_floor() and pt > 0.2:
|
||
ground_y = fox.position.y
|
||
results.append("landing: y=%.1f [OK]" % ground_y)
|
||
phase = 1
|
||
_reset_phase()
|
||
|
||
1: # ДЛИННЫЙ прыжок (держим кнопку)
|
||
if pt < 0.02:
|
||
Input.action_press("jump")
|
||
min_y = minf(min_y, fox.position.y)
|
||
if pt > 1.4:
|
||
Input.action_release("jump")
|
||
results.append("long jump rise: %.1f px (теория v^2/2g = 103.3)" % (ground_y - min_y))
|
||
phase = 2
|
||
_reset_phase()
|
||
|
||
2: # ждём приземления
|
||
if fox.is_on_floor() and pt > 0.3:
|
||
phase = 3
|
||
_reset_phase()
|
||
|
||
3: # КОРОТКИЙ прыжок (отпускаем через 0.05с)
|
||
if pt < 0.02:
|
||
Input.action_press("jump")
|
||
if pt > 0.05 and not pressed_jump:
|
||
Input.action_release("jump")
|
||
pressed_jump = true
|
||
min_y = minf(min_y, fox.position.y)
|
||
if pt > 1.2:
|
||
Input.action_release("jump")
|
||
results.append("short jump rise: %.1f px (должен быть заметно меньше длинного)" % (ground_y - min_y))
|
||
phase = 4
|
||
_reset_phase()
|
||
|
||
4: # ждём приземления
|
||
if fox.is_on_floor() and pt > 0.3:
|
||
phase = 5
|
||
_reset_phase()
|
||
|
||
5: # COYOTE TIME: бежим вправо, после схода прыгаем через ~0.05с
|
||
Input.action_press("move_right")
|
||
Input.action_press("run")
|
||
if not fox.is_on_floor() and not left_ledge:
|
||
left_ledge = true
|
||
airborne_at = 0.0
|
||
if left_ledge:
|
||
airborne_at += delta
|
||
if airborne_at >= 0.05 and not pressed_jump:
|
||
Input.action_press("jump")
|
||
pressed_jump = true
|
||
results.append("coyote: jump нажат через %.3fс после схода" % airborne_at)
|
||
phase = 6
|
||
_reset_phase()
|
||
if pt > 3.0:
|
||
results.append("coyote: FAIL — не дошёл до края")
|
||
phase = 8
|
||
_reset_phase()
|
||
|
||
6: # проверяем результат coyote-прыжка
|
||
if pt > 0.12:
|
||
var ok := fox.velocity.y < -100.0
|
||
results.append("coyote jump: %s (vel.y=%.0f)" % ["PASS" if ok else "FAIL", fox.velocity.y])
|
||
Input.action_release("jump")
|
||
phase = 7
|
||
_reset_phase()
|
||
|
||
7: # JUMP BUFFER (детерминированно): один телепорт в воздух, затем jump за ~0.07с до земли
|
||
Input.action_release("move_left")
|
||
Input.action_release("move_right")
|
||
Input.action_release("run")
|
||
if not fox.has_meta("tp"):
|
||
fox.set_meta("tp", true)
|
||
fox.position = Vector2(0.0, ground_y - 120.0)
|
||
fox.velocity = Vector2.ZERO
|
||
results.append("buffer: лиса телепортирована на y=%.1f, ждём падения" % fox.position.y)
|
||
elif not pressed_jump:
|
||
var dist: float = maxf(ground_y - fox.position.y, 0.0)
|
||
var v: float = maxf(fox.velocity.y, 0.0)
|
||
var ttl: float = (-v + sqrt(v * v + 2.0 * 980.0 * dist)) / 980.0
|
||
if dist > 0.0 and ttl <= 0.07:
|
||
Input.action_press("jump")
|
||
pressed_jump = true
|
||
results.append("buffer: jump нажат за %.3fс до земли (y=%.1f, vel.y=%.0f)" % [ttl, fox.position.y, v])
|
||
if pressed_jump:
|
||
if fox.velocity.y < -100.0:
|
||
results.append("buffer jump: PASS (vel.y=%.0f — прыжок сработал при касании)" % fox.velocity.y)
|
||
Input.action_release("jump")
|
||
phase = 8
|
||
_reset_phase()
|
||
elif pt > 3.0:
|
||
results.append("buffer jump: FAIL (vel.y=%.0f, on_floor=%s)" % [fox.velocity.y, fox.is_on_floor()])
|
||
Input.action_release("jump")
|
||
phase = 8
|
||
_reset_phase()
|
||
|
||
8:
|
||
Input.action_release("move_left")
|
||
Input.action_release("move_right")
|
||
Input.action_release("run")
|
||
Input.action_release("jump")
|
||
if pt > 0.3:
|
||
print("")
|
||
print("========== RESULTS: STAGE 1 PHYSICS ==========")
|
||
for r in results:
|
||
print(" * ", r)
|
||
print("==============================================")
|
||
get_tree().quit(0)
|