SuperAPI AI 工具集

bevy-game-loop-waves

编程与开发

查看项目

更新于 10-16 06:08

技能介绍

用途

本技能用于在 Bevy 引擎中实现遭遇战的波次循环:当敌人以波次形式到达、并在清空后推进波次索引时加载。关键词包括 Bevy、waves、spawn、encounter、ECS。

主要能力

技能围绕 ECS 结构给出实现约定:

  • 组件:波次索引与剩余数量由使用者自行定义。
  • 资源:运行期全局表存放在资源中(参见 bevy-data-resources)。
  • 系统:在 Update 或固定时间步上修改这些组件;当伤害必须先于死亡结算时使用 .chain()。
  • 消息:一次性事实(命中、拾取、任务推进)通过 bevy-events-messaging 处理;波次推进本身是资源,而不是新的消息类型。

使用方式

示例依赖为 bevy = "0.20"。波次索引与生成预算合为一个资源,每个敌人是一个实体。生成与清空共享 WaveDirector,因此这两个系统被串联。

#[derive(Resource)]
struct WaveDirector {
    index: u32,
    budget: u32,
    intermission: f32,
}

#[derive(Component)]
struct Enemy;

fn boot(mut commands: Commands) {
    commands.insert_resource(WaveDirector {
        index: 1,
        budget: 4,
        intermission: 0.0,
    });
}

fn spawn_budget(mut commands: Commands, mut wave: ResMut<WaveDirector>) {
    if wave.intermission > 0.0 || wave.budget == 0 {
        return;
    }
    for _ in 0..wave.budget {
        commands.spawn(Enemy);
    }
    wave.budget = 0;
}

fn advance_on_clear(
    enemies: Query<(), With<Enemy>>,
    mut wave: ResMut<WaveDirector>,
    time: Res<Time>,
) {
    if !enemies.is_empty() {
        wave.intermission = 0.0;
        return;
    }
    wave.intermission += time.delta_secs();
    if wave.intermission < 2.0 {
        return;
    }
    wave.index += 1;
    wave.budget = 3 + wave.index;
    wave.intermission = 0.0;
}

fn install(app: &mut App) {
    app.add_systems(Startup, boot)
        .add_systems(Update, (spawn_budget, advance_on_clear).chain());
}

固定步适合对存活敌人的剩余时间进行计时。上面的清空系统留在 Update 上,只读取 Enemy。

#[derive(Component)]
struct Lifetime(f32);

fn age_enemies(
    mut commands: Commands,
    mut enemies: Query<(Entity, &mut Lifetime)>,
    time: Res<Time<Fixed>>,
) {
    for (entity, mut life) in &mut enemies {
        life.0 -= time.delta_secs();
        if life.0 <= 0.0 {
            commands.entity(entity).despawn();
        }
    }
}

fn install_lifetime(app: &mut App) {
    app.add_systems(FixedUpdate, age_enemies);
}

状态归属

部分 归属 谁可修改 调度
单个实体上的数据 Component 一个系统通过 Query Update 或 FixedMain
整个应用的一个值 Resource 一个系统 Startup 插入,随后由读取它的调度
生成 Commands 执行生成的系统 初始世界用 Startup;运行期生成用后续调度
不可竞争的顺序 .chain() 仅被串联的系统 同一调度
插件边界 Plugin build 注册系统与资源 应用运行之前

借用规则:两个系统若都可变查询同一组件,必须排序(.chain())或拆分,使只有一个写入。无关系统保持并行。

决策

如果你需要 这样做 不要
每实体数据 Component + Query 所有实体共享一个可变大对象
应用级配置或时钟 Resource 把值复制到每个实体
稳定的模拟步 FixedMain 与 Fixed 时钟 把模拟绑定到原始帧 Update
启动时生成 Startup 中的 Commands 从渲染系统生成
非共享状态的跨系统通知 bevy-events-messaging 中的消息或观察者槽位 在本文件中新造事件类型
文档集合之外的 API 阅读 Bevy 官方页面 编造的 crate 或 API

适用场景

  • 敌人按波次到达、清空后推进波次索引的遭遇战。
  • 需要把波次、生成器与遭遇数据构建为组件的场景。
  • 需要区分每实体数据、应用级资源与一次性消息的 ECS 设计。

限制与边界

  • 波次、生成器与遭遇数据由使用者自行构建为组件。
  • 敌人移动路由到 bevy-ai-navigation 与 bevy-character-movement。
  • 目标为 Bevy 0.20+。核心 ECS 类型包括 Component、Resource、Query、Commands、Startup、Update、Fixed / FixedMain(bevy::time)、.chain()、Plugin、DefaultPlugins、MinimalPlugins。消息与观察者属于归属槽位,其 API 见 bevy-events-messaging。除非 .chain() 对冲突系统排序,否则系统并行运行。
  • 不要在文档 URL 中固定 /0.20.0/;链接保持指向最新版本,0.20 目标只在正文中说明一次。
  • 不要从两个未排序的系统可变查询同一组件。
  • 不要在此处发明物理、导航、网络或 XR crate;本技能只命名有文档的 Bevy crate 与模块。
  • 不要使用编造的 API 或未命名的第三方 crate 作为选定求解器;Bevy 代码保持惯用 ECS,只使用有文档的 Bevy API。
  • 参考:bevy-master 的库固定为 0.20.0;官方页面保持在无版本站点上。

相关技能

前置:bevy-master(枢纽与调度)、bevy-ecs-composition(组件与系统)、bevy-ai-navigation(生成角色做什么)、bevy-data-resources(表与定义)、bevy-events-messaging(一次性事实)。

补充:bevy-state-machines(模式标志)。

下游/消费者:暂无。

主技能:bevy-master(Bevy 路由器)。