5f6258e3d4
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
155 lines
4.5 KiB
GDScript
155 lines
4.5 KiB
GDScript
extends SceneTree
|
|
## 炸弹系统回归测试(时间驱动):
|
|
## 初始 2 枚 → 引爆清敌清弹-1 → 用尽 → 空仓无效 → Boss 击破 +1
|
|
## → B 道具拾取 +1 → 上限 5
|
|
## 输入映射层:fire 含 J、bomb 含 K
|
|
## 运行:godot --headless -s tests/bomb_test.gd
|
|
|
|
const GLOBAL_TIMEOUT := 25.0
|
|
|
|
var _phase := 0
|
|
var _phase_time := 0.0
|
|
var _time := 0.0
|
|
var _game: Game
|
|
var _fails: Array[String] = []
|
|
|
|
|
|
func _initialize() -> void:
|
|
_game = (load("res://scenes/game.tscn") as PackedScene).instantiate()
|
|
root.add_child(_game)
|
|
print("[bomb_test] game instantiated")
|
|
|
|
|
|
func _fail(msg: String) -> void:
|
|
_fails.append(msg)
|
|
print("[FAIL] " + msg)
|
|
|
|
|
|
func _next_phase() -> void:
|
|
_phase += 1
|
|
_phase_time = 0.0
|
|
|
|
|
|
func _finish() -> bool:
|
|
if _fails.is_empty():
|
|
print("[bomb_test] PASS")
|
|
else:
|
|
print("[bomb_test] FAIL: %d issue(s)" % _fails.size())
|
|
quit(0 if _fails.is_empty() else 1)
|
|
return true
|
|
|
|
|
|
## 输入映射检查(真实按键输入无法无头模拟,检查映射配置本身)
|
|
func _check_input_maps() -> void:
|
|
var fire_ok := false
|
|
if InputMap.has_action("fire"):
|
|
for event in InputMap.action_get_events("fire"):
|
|
if event is InputEventKey and (event as InputEventKey).physical_keycode == 74:
|
|
fire_ok = true
|
|
if not fire_ok:
|
|
_fail("fire action missing J key")
|
|
var bomb_ok := false
|
|
if InputMap.has_action("bomb"):
|
|
for event in InputMap.action_get_events("bomb"):
|
|
if event is InputEventKey and (event as InputEventKey).physical_keycode == 75:
|
|
bomb_ok = true
|
|
if not bomb_ok:
|
|
_fail("bomb action missing K key")
|
|
|
|
|
|
func _process(delta: float) -> bool:
|
|
_time += delta
|
|
if _time > GLOBAL_TIMEOUT:
|
|
_fail("global timeout in phase %d" % _phase)
|
|
return _finish()
|
|
if _game._enemies == null:
|
|
return false
|
|
|
|
_phase_time += delta
|
|
match _phase:
|
|
0:
|
|
_check_input_maps()
|
|
if _game.player.bombs != 2:
|
|
_fail("initial bombs=%d expected 2" % _game.player.bombs)
|
|
# 场上放 3 架敌机 + 2 发敌弹
|
|
for i in 3:
|
|
var enemy := EnemySmall.new()
|
|
enemy.setup(150.0 + 120.0 * i, 300.0 + 60.0 * i, 100.0)
|
|
_game._enemies.add_child(enemy)
|
|
for i in 2:
|
|
var bullet := EnemyBullet.new()
|
|
bullet.position = Vector2(120.0 + 200.0 * i, 400.0)
|
|
_game._enemy_bullets.add_child(bullet)
|
|
_game.player.use_bomb()
|
|
_next_phase()
|
|
1:
|
|
# 首波 spawner 敌机 0.8s 后才出现,检查点在 0.5s 安全
|
|
if _phase_time >= 0.5:
|
|
var enemies_left := _game._enemies.get_child_count()
|
|
var bullets_left := _game._enemy_bullets.get_child_count()
|
|
if enemies_left != 0:
|
|
_fail("bomb left enemies: %d" % enemies_left)
|
|
if bullets_left != 0:
|
|
_fail("bomb left enemy bullets: %d" % bullets_left)
|
|
if _game.player.bombs != 1:
|
|
_fail("bombs=%d expected 1" % _game.player.bombs)
|
|
else:
|
|
print("[bomb_test] detonate ok: enemies/bullets cleared, bombs 2->1, score=%d" % _game.score)
|
|
_next_phase()
|
|
2:
|
|
_game.player.use_bomb()
|
|
_next_phase()
|
|
3:
|
|
if _phase_time >= 0.3:
|
|
if _game.player.bombs != 0:
|
|
_fail("second bomb not consumed: %d" % _game.player.bombs)
|
|
_game.player.use_bomb() # 空仓
|
|
_next_phase()
|
|
4:
|
|
if _phase_time >= 0.3:
|
|
if _game.player.bombs != 0:
|
|
_fail("empty stock still fired: %d" % _game.player.bombs)
|
|
else:
|
|
print("[bomb_test] stock drain + empty guard ok")
|
|
var boss := _game.spawn_boss(1.0)
|
|
boss.apply_damage(99999)
|
|
_next_phase()
|
|
5:
|
|
if _phase_time >= 1.0:
|
|
if _game.player.bombs != 1:
|
|
_fail("boss kill did not grant bomb: %d" % _game.player.bombs)
|
|
else:
|
|
print("[bomb_test] boss kill +1 bomb ok")
|
|
# B 道具拾取链路:1 → 2,再补到 5 验证上限
|
|
_collect_bomb_pickup()
|
|
_next_phase()
|
|
6:
|
|
if _phase_time >= 0.5:
|
|
if _game.player.bombs != 2:
|
|
_fail("B pickup did not add bomb: %d" % _game.player.bombs)
|
|
else:
|
|
print("[bomb_test] B pickup +1 ok")
|
|
_collect_bomb_pickup()
|
|
_collect_bomb_pickup()
|
|
_collect_bomb_pickup()
|
|
_collect_bomb_pickup()
|
|
_next_phase()
|
|
7:
|
|
if _phase_time >= 0.5:
|
|
if _game.player.bombs != 5:
|
|
_fail("bomb cap broken: %d expected 5" % _game.player.bombs)
|
|
else:
|
|
print("[bomb_test] bomb cap at 5 ok")
|
|
return _finish()
|
|
return false
|
|
|
|
|
|
func _collect_bomb_pickup() -> void:
|
|
var powerups := _game.get_node_or_null("Powerups") as Node2D
|
|
var pickup := Powerup.new()
|
|
pickup.kind = Powerup.Kind.BOMB
|
|
pickup.position = _game.player.global_position
|
|
powerups.add_child(pickup)
|
|
# 直接触发玩家拾取路径(与 area_entered 信号同一入口)
|
|
_game.player._collect_powerup(pickup)
|