Files
sijcdusmode/scripts/bullet_ring.gd
T
sijcdu 1b3d61793d Enemies no longer attack; add a fixed bullet-ring emitter and make lasers permanent obstacles
walker.gd lost its firing code entirely: monsters now only patrol and hurt on contact, so the only way past is footwork or the key throw + W warp. New bullet_ring prefab fires a set number of bullets evenly spread over a fixed arc on a timer, with directions derived only from its own exports, so every volley is identical and the pattern can be memorised; the level places one at cell (12,12) aimed upward with the 12 bullets spread over 180 degrees. laser.gd gained always_on, defaulting to true, so the five copied lasers are now static hazards that are always lit and damage anything overlapping them rather than blinking on and off. Bullets now stop when they spawn inside terrain.
2026-10-07 22:23:18 +08:00

77 lines
2.4 KiB
GDScript

extends Node2D
## 固定弹幕源:每隔一段时间以自己为中心,按**固定角度**围一圈发射子弹。
## 每一波的角度都算死(可选每波整体旋转),所以弹道可以背下来,
## 玩家靠走位找空隙,或者用「扔钥匙 + W 传送」直接穿过去。
const BULLET := preload("res://scenes/prefabs/enemies/bullet.tscn")
const BULLET_SCRIPT := preload("res://scripts/bullet.gd")
@export var enabled: bool = true
## 发射间隔(秒)
@export var interval: float = 2.0
## 开场后第一次发射前的延迟
@export var start_delay: float = 1.0
## 每波几颗
@export var count: int = 12
## 扇形张开角度:360 = 围一整圈
@export var arc_deg: float = 360.0
## 整圈的中心朝向(度):0=右 90=下 180=左 270=上
@export var base_angle_deg: float = 0.0
## 每发一波整体旋转多少度(0 = 弹道完全固定,可以背板)
@export var rotate_per_shot_deg: float = 0.0
@export var bullet_speed: float = 55.0
@export var bullet_color: Color = Color(1.0, 0.45, 0.85)
## 中心的圆点半径(只是给玩家一个视觉提示)
@export var core_radius: int = 4
var _timer: float = 0.0
var _angle: float = 0.0
func _ready() -> void:
add_to_group("emitter")
_timer = start_delay
_angle = base_angle_deg
var core := get_node_or_null("Core") as Sprite2D
if core != null:
core.texture = BULLET_SCRIPT.circle_texture(core_radius, bullet_color)
func _physics_process(delta: float) -> void:
if not enabled:
return
_timer -= delta
if _timer > 0.0:
return
_timer = maxf(interval, 0.05)
fire()
func fire() -> void:
var n: int = maxi(count, 1)
var base := deg_to_rad(_angle)
var full_circle := is_equal_approx(arc_deg, 360.0)
var step := deg_to_rad(arc_deg) / float(n) if full_circle else deg_to_rad(arc_deg)
for i in n:
var ang: float
if full_circle:
ang = base + step * float(i)
elif n <= 1:
ang = base
else:
ang = base + step * (float(i) / float(n - 1) - 0.5)
_spawn(ang)
if not is_zero_approx(rotate_per_shot_deg):
_angle = fmod(_angle + rotate_per_shot_deg, 360.0)
func _spawn(ang: float) -> void:
var bullet := BULLET.instantiate()
# 这两个属性必须在 add_child 之前设好,子弹的 _ready 会拿它们生成贴图
bullet.bullet_color = bullet_color
bullet.speed = bullet_speed
get_parent().add_child(bullet)
bullet.global_position = global_position
bullet.launch(Vector2(cos(ang), sin(ang)), bullet_speed)