feat: 场景与核心玩法脚本(双机型/波次/Boss/道具/炸弹/地面单位/浮游炮激光)

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
2026-08-31 00:31:29 +08:00
parent 024447fbda
commit 3c6f31b503
36 changed files with 1692 additions and 0 deletions
+73
View File
@@ -0,0 +1,73 @@
class_name EnemyBase
extends Area2D
## 敌机基类:血量、受击闪白、死亡结算与爆炸。
var hp := 1
var score_value := 100
var dead := false
var drops_powerup := false
## 激光命中判定的近似半径(水平覆盖 + 垂直截断)
var hit_radius := 16.0
func apply_damage(dmg: int) -> void:
if dead:
return
hp -= dmg
if hp <= 0:
dead = true
_die()
else:
_flash()
func _die() -> void:
_spawn_drop()
var game := get_tree().get_first_node_in_group("game") as Game
if game != null:
game.add_score(score_value)
game.spawn_explosion(global_position, 1.0)
queue_free()
## 死亡时按标记掉落道具(可能在物理信号回调中调用,需延迟入树)。
## forced 为 -1 时随机 P/B(各 50%)。
func _spawn_drop(forced := -1) -> void:
if not drops_powerup:
return
var container := get_tree().get_first_node_in_group("powerups")
if container == null:
return
var pickup := Powerup.new()
pickup.position = global_position
if forced >= 0:
pickup.kind = forced
else:
pickup.kind = Powerup.Kind.BOMB if randf() < 0.5 else Powerup.Kind.POWER
container.call_deferred("add_child", pickup)
func _flash() -> void:
modulate = Color(3.0, 3.0, 3.0)
create_tween().tween_property(self, "modulate", Color.WHITE, 0.12)
## 朝玩家方向的单位向量;玩家不存在或不活跃时朝正下方
func _aim_direction() -> Vector2:
var game := get_tree().get_first_node_in_group("game") as Game
if game != null and is_instance_valid(game.player) and game.player.active:
var to_player: Vector2 = game.player.global_position - global_position
if to_player.length() > 1.0:
return to_player.normalized()
return Vector2.DOWN
## 向敌方弹幕容器发射一发子弹
func _fire_bullet(velocity: Vector2, muzzle_offset := Vector2(0.0, 14.0)) -> void:
var container := get_tree().get_first_node_in_group("enemy_bullets")
if container == null:
return
var bullet := EnemyBullet.new()
bullet.velocity = velocity
container.add_child(bullet)
bullet.global_position = global_position + muzzle_offset