手册:弹幕子弹系统

概述

弹幕系统 是一种通过专用执行动作 “发射弹幕子弹 (FireBarrageBullet)” 发射极轻量级子弹的系统,这些子弹仅具备最低限度的功能。

该系统可同时发射数百发子弹,但其功能高度受限:无法为子弹本身分配视觉脚本,也无法对其进行动画处理。

弹幕子弹的碰撞只能通过专用条件 “与弹幕子弹碰撞 (CollideWithBarrageBullet)” 检测,无法使用常规的攻击碰撞检测或墙壁碰撞检测。

如需实现复杂行为的子弹,请改用常规的 “发射子弹” 动作。

使用“发射弹幕子弹”可实现的功能

  • 全向连发霰弹 中选择发射类型。
  • 指定发射原点。
  • 指定发射目标。
  • 直线曲线转向分裂追踪 中选择发射后行为。
  • 指定子弹精灵图。
  • 子弹会根据移动方向自动旋转,以 0度(向右) 为前进方向。
  • 指定子弹速度,包括发射后的加速度与减速度。
  • 指定碰撞箱大小及碰撞层级。
  • 指定子弹攻击力与属性(但伤害处理不会自动执行,需手动设置)。

创建“弹幕图案”的示例

“花朵图案”

使用 全向 + 曲线 子弹同时生成多发子弹。通过设置相反的曲线角度(例如一个子弹设为 +0.3度,另一个设为 –0.3度),可形成清晰的花朵状图案。

添加旋转后,图案将变为类似洗衣机的旋转效果。

“网格图案”

使用多个 连发 + 直线 子弹,并调整发射原点偏移量。添加转向或分裂行为可产生有趣的变体。

“玩家追踪”

将玩家设为目标。通过添加偏移量,可生成故意偏离玩家的子弹(“偏移瞄准”子弹);若再添加追踪行为,则可生成预测式“提前量”子弹。

弹幕与脚本

弹幕系统生成的子弹无法附加脚本。

所有行为需通过 检测碰撞的对象脚本 实现,使用 “与弹幕子弹碰撞” 条件。

使用“与弹幕子弹碰撞”可实现的功能

  • 检测对象 HitArea 与弹幕子弹碰撞箱的接触。当 HitArea2D 层遮罩弹幕子弹层级 匹配时触发检测。
  • 接触时移除弹幕子弹(适用于炸弹或玩家伤害)。
  • 弹幕子弹被移除时,可按指定概率将其转换为其他对象或 Godot 场景(主要用于炸弹)。
  • 将接触的弹幕子弹的 攻击力属性 存储到指定变量中。

使用“与弹幕子弹碰撞”的实际示例

“炸弹”

创建一个 HitArea 层遮罩与弹幕子弹层匹配的游戏对象,其范围等同于炸弹的攻击范围。(此设置稍复杂,但无法使用 AttackArea 进行碰撞检测

使用视觉脚本,使 HitArea 仅在爆炸时机激活,随后消失。爆炸后,设置 “与弹幕子弹碰撞” 条件并启用“移除接触的弹幕子弹”选项。

  • 当炸弹移除弹幕子弹并生成得分道具时
    指定掉落物品。由于此转换过程的处理开销等同于普通游戏对象生成,一次性生成大量物品易导致性能下降。建议将掉落率设为较低值,如 10%
  • 当炸弹同时对敌人造成伤害时
    只需如常设置 AttackArea2D 和攻击力,同时执行标准伤害处理。

“擦弹”

创建专用的游戏对象处理 擦弹,并将其设为子节点。

  • 擦弹对象设置
    设置一个比父对象更大的 HitArea。使用视觉脚本,配置在触发 “与弹幕子弹碰撞” 时播放擦弹动画或粒子效果并增加分数的行为。

“弹幕伤害/属性处理”

由于无法使用标准伤害系统,需手动设置伤害处理。

存储:

  • 弹幕伤害变量 A
  • 弹幕属性变量 B
  • 应用简单伤害
    在伤害处理状态中,设置如 “HP 减少变量 A 的值” 的逻辑。
  • 应用属性相关效果
    使用过渡链接条件如 “若变量 B 等于指定值” 分支处理相应行为。

使用 GDScript 生成弹幕

你可以通过将定义子弹移动和行为的类传递给 弹幕管理器 API 来生成弹幕。

示例:
一个以 36度间隔 向所有方向发射子弹的弹幕,每个子弹在发射后 5秒 消失。

# 创建子弹命令列表(5秒后消失)
var vanish_command = BarrageBulletVanishCommand.new()
var wait_command = BarrageBulletWaitCommand.new()
wait_command.wait_time = 5

# 将命令列表分配给子弹动作数据
var bullet_action_data = BarrageActionData.new()
bullet_action_data.command_list = [wait_command, vanish_command]

# 创建子弹数据
var bullet_data = BarrageBulletData.new()
bullet_data.action_list = [bullet_action_data]
bullet_data.image_path = "res://〇〇.png"
bullet_data.speed = 100

# 创建向所有方向发射的弹幕数据
# 发射命令
var fire_command = BarrageBulletFireCommand.new()
fire_command.bullet_data = bullet_data

# 方向数据
var direction_data = BarrageBulletDirectionData.new()
direction_data.direction_type = 3 # 参考之前发射的角度(BulletML 中的 SEQUENCE)
direction_data.angle = 36         # 子弹之间的角度间隔

# 将方向数据分配给发射命令
fire_command.fire_direction_data = direction_data

# 创建传递给重复命令的动作数据
var repeat_command_action = BarrageActionData.new()
repeat_command_action.command_list = [fire_command]

# 创建运行 10 次的重复命令
var repeat_command = BarrageBulletRepeatCommand.new()
repeat_command.action_data = repeat_command_action
repeat_command.repeat_num = 10

# 创建弹幕发射命令列表
var barrage_command_list = [repeat_command]

# 传递给管理器的动作数据
var action_data = BarrageActionData.new()
action_data.command_list = barrage_command_list

# 将数据传递给弹幕管理器
BarragesManager.fire_barrage([action_data])