Files
hello-godot/tests/ground_test.gd
T

167 lines
4.7 KiB
GDScript

extends SceneTree
## 地面单位回归测试(时间驱动):
## A) 独立堡垒:随地面滚动(~120px/s)、有开火产出敌弹
## B) Game 集成:堡垒击杀 +300、船击杀 +800
## C) 碰撞规则:玩家机体叠在堡垒上不掉命;玩家子弹真实命中堡垒
## 运行:godot --headless -s tests/ground_test.gd
const GLOBAL_TIMEOUT := 25.0
var _phase := 0
var _step := 0
var _phase_time := 0.0
var _time := 0.0
var _fortress: EnemyFortress
var _ship: EnemyShip
var _game: Game
var _bullets: Node2D
var _start_y := 0.0
var _bullet_time := 0.0
var _score_before := 0
var _lives_before := 3
var _fails: Array[String] = []
func _initialize() -> void:
_bullets = Node2D.new()
_bullets.add_to_group("enemy_bullets")
root.add_child(_bullets)
_fortress = EnemyFortress.new()
_fortress.setup(270.0, 200.0, 1.0)
root.add_child(_fortress)
_start_y = 200.0
print("[ground_test] phase A: standalone fortress")
func _fail(msg: String) -> void:
_fails.append(msg)
print("[FAIL] " + msg)
func _next_phase() -> void:
_phase += 1
_step = 0
_phase_time = 0.0
func _restart_step() -> void:
_step += 1
_phase_time = 0.0
func _finish() -> bool:
if _fails.is_empty():
print("[ground_test] PASS")
else:
print("[ground_test] FAIL: %d issue(s)" % _fails.size())
quit(0 if _fails.is_empty() else 1)
return true
## 清场(敌机+敌弹),保证后续断言确定性
func _clear_field() -> void:
for enemy in _game._enemies.get_children():
(enemy as Node).queue_free()
for bullet in _game._enemy_bullets.get_children():
bullet.queue_free()
func _process(delta: float) -> bool:
_time += delta
if _time > GLOBAL_TIMEOUT:
_fail("global timeout in phase %d" % _phase)
return _finish()
_phase_time += delta
match _phase:
0:
if _bullets.get_child_count() > 0:
_bullet_time += delta
if _phase_time >= 4.0:
var moved := _fortress.position.y - _start_y
if moved < 380.0 or moved > 620.0:
_fail("fortress scroll wrong: moved %.0f px in 4s (expect ~480)" % moved)
elif _bullet_time < 0.3:
_fail("fortress fired too little: %.2fs" % _bullet_time)
else:
print("[ground_test] fortress scroll+fire ok (moved %.0f px, bullet %.1fs)" % [moved, _bullet_time])
_fortress.apply_damage(999)
_next_phase()
1:
if not is_instance_valid(_fortress):
_next_phase()
elif _phase_time > 2.0:
_fail("fortress not freed after kill")
_next_phase()
2:
if _game == null:
_game = (load("res://scenes/game.tscn") as PackedScene).instantiate()
root.add_child(_game)
elif _game._enemies != null:
_ship = EnemyShip.new()
_ship.setup(270.0, 300.0, 1.0)
_game._enemies.add_child(_ship)
var f2 := EnemyFortress.new()
f2.setup(150.0, 300.0, 1.0)
_game._enemies.add_child(f2)
_score_before = _game.score
f2.apply_damage(999)
_next_phase()
3:
if _phase_time >= 0.6:
if _game.score != _score_before + 300:
_fail("fortress score: %d -> %d (expected +300)" % [_score_before, _game.score])
else:
print("[ground_test] fortress kill +300 ok")
_score_before = _game.score
_ship.apply_damage(999)
_next_phase()
4:
if _phase_time >= 0.6:
if _game.score != _score_before + 800:
_fail("ship score: %d -> %d (expected +800)" % [_score_before, _game.score])
else:
print("[ground_test] ship kill +800 ok")
_next_phase()
5:
match _step:
0:
_clear_field()
_lives_before = _game.lives
var f3 := EnemyFortress.new()
f3.setup(_game.player.global_position.x, _game.player.global_position.y, 1.0)
_game._enemies.add_child(f3)
_restart_step()
1:
if _phase_time >= 0.8:
if _game.lives != _lives_before or not _game.player.active:
_fail("ramming fortress hurt player: lives %d->%d active=%s" % [
_lives_before, _game.lives, str(_game.player.active)])
else:
print("[ground_test] player overlaps fortress unharmed ok")
_next_phase()
6:
match _step:
0:
_clear_field()
var f4 := EnemyFortress.new()
f4.setup(270.0, 300.0, 1.0)
_game._enemies.add_child(f4)
var bullet := PlayerBullet.new()
bullet.direction = Vector2.UP
(_game.get_node("PlayerBullets") as Node2D).add_child(bullet)
bullet.position = Vector2(270.0, 430.0)
_restart_step()
1:
if _phase_time >= 0.7:
if _game._enemies.get_child_count() == 0:
_fail("fortress missing before bullet-hit check")
else:
var target := _game._enemies.get_child(0) as EnemyFortress
if target.hp != 3:
_fail("player bullet did not hit fortress: hp=%d expected 3" % target.hp)
else:
print("[ground_test] player bullet hits fortress ok")
return _finish()
return false