用途
Bevy Roguelike 是一个“类型路由”(thin router)技能,面向 Bevy 0.20 的 Roguelike 游戏开发。它本身不承担具体领域实现,而是把随机种子、房间生成、永久死亡标记等需求路由到对应的 Bevy 子技能。资料说明:当需要处理 run seeds、房间生成和 permadeath 标记时加载本技能。
主要能力与 ECS 结构
资料规定了几条 ECS 组织原则:
- Component 以纯数据形式保存该类型的每实体标记,本文件不命名新的引擎类型。
- Resource 通过 bevy-data-resources 保存整局范围的计数器(分数、波次索引、种子)。
- 系统在 Update 或来自 bevy-master 的固定时间步读取这些组件;当后续系统必须看到前一个系统的结果时,用 .chain() 排序。
- 玩法模式切换走 bevy-state-machines,不要自行发明类型插件。
路由目标包括:bevy-procedural-generation(种子与生成)、bevy-turn-system(回合制时的回合顺序)、bevy-inventory-system(局内战利品)、bevy-rpg-stats(局内属性)。
使用方式(资料中的代码示例)
依赖声明为 bevy = "0.20" 与 rand = "0.9"。
随机种子是一个资源,房间是实体,StdRng 在系统内部构建,使种子保留在资源上:
use rand::rngs::StdRng;
use rand::{Rng, SeedableRng};
#[derive(Resource)]
struct RunSeed(u64);
#[derive(Component)]
struct Room {
x: i32,
y: i32,
}
fn carve(mut commands: Commands, seed: Res<RunSeed>) {
let mut rng = StdRng::seed_from_u64(seed.0);
for _ in 0..8 {
commands.spawn(Room {
x: rng.random_range(-6..6),
y: rng.random_range(-6..6),
});
}
}
fn install_run(app: &mut App) {
app.insert_resource(RunSeed(0x5EED))
.add_systems(Startup, carve);
}
永久死亡是角色上的标记加一个整局资源,由一个系统同时写入两者:
#[derive(Component)]
struct Actor {
hp: i32,
}
#[derive(Resource)]
struct RunOver(bool);
fn permadeath(mut actors: Query<&mut Actor>, mut over: ResMut<RunOver>) {
for mut actor in &mut actors {
if actor.hp > 0 {
continue;
}
actor.hp = 0;
over.0 = true;
}
}
回合能量累积在资源上,行动消耗它;两个系统都写 TurnClock,因此需要链式排序:
#[derive(Resource)]
struct TurnClock {
energy: f32,
}
fn charge(time: Res<Time>, mut clock: ResMut<TurnClock>) {
clock.energy = (clock.energy + time.delta_secs()).min(1.0);
}
#[derive(Component)]
struct Actor {
hp: i32,
}
fn spend(mut clock: ResMut<TurnClock>, mut actors: Query<&mut Actor>) {
if clock.energy < 1.0 {
return;
}
clock.energy = 0.0;
for mut actor in &mut actors {
if actor.hp > 0 {
actor.hp -= 1;
}
}
}
fn install_turns(app: &mut App) {
app.insert_resource(TurnClock { energy: 0.0 })
.add_systems(Update, (charge, spend).chain());
}
地面战利品是实体,角色可按网格距离拾取:
#[derive(Component)]
struct Loot {
value: u32,
}
#[derive(Component)]
struct GridPos {
x: i32,
y: i32,
}
#[derive(Component)]
struct Actor;
#[derive(Resource)]
struct RunSeed(u64);
fn pickup(
mut commands: Commands,
actors: Query<&GridPos, With<Actor>>,
loot: Query<(Entity, &GridPos, &Loot)>,
mut wallet: ResMut<RunSeed>,
) {
for actor in &actors {
for (entity, pos, item) in &loot {
if actor.x == pos.x && actor.y == pos.y {
wallet.0 = wallet.0.wrapping_add(u64::from(item.value));
commands.entity(entity).despawn();
}
}
}
}
资料特别说明:pickup 中的 RunSeed 只是占位计数器,使示例保持在单一资源内;金币钱包应属于 bevy-economy-system。permadeath 与 spend 都写 Actor,两者同时运行时需要链式排序。
适用场景
适用于 Bevy 0.20 的 Roguelike 项目,尤其是需要可复现的随机种子、房间生成、永久死亡、回合制能量与网格拾取等基础结构时。噪声与更大的地图路由到 bevy-procedural-generation;物品栏堆叠路由到 bevy-inventory-system。
限制与禁止事项
资料明确列出若干 NEVER 规则:
- 不要在文档 URL 中固定 /0.20.0/,链接应保持在 latest,0.20 目标只在正文中说明一次。
- 不要从两个无序系统可变查询同一组件,因为调度默认并行运行系统,除非用 .chain() 排序。
- 不要在此发明物理、导航、网络或 XR crate,本技能只命名有文档的 Bevy crate 与模块。
- 不要每帧用新种子重建 StdRng,run seed 应保留在 RunSeed 上以保证房间布局可复现。
- 不要让 permadeath 与 spend 在未 .chain() 的情况下同时写 Actor。
- 不发明类型 API,Bevy 代码保持惯用 ECS 并只使用有文档的 Bevy API。
关于 Bevy 版本、依赖版本与官方文档链接,资料给出:库固定在 bevy-master 上保持 0.20.0,官方页面保持在无版本号的 latest 分支。官方文档涵盖 Assets、Examples、ECS(Component、systems、Query、Startup、Update、.chain())、Plugins(Plugin、DefaultPlugins、MinimalPlugins、add_plugins)。前置技能为 bevy-master 与 bevy-ecs-composition;互补技能包括 godot-genre-roguelike、bevy-procedural-generation、bevy-turn-system、bevy-inventory-system、bevy-rpg-stats。本路由不拥有第二套实现,下游消费者为 None。