9个版本 (5个破坏性更新)
0.6.0 | 2024年5月19日 |
---|---|
0.5.0 | 2024年4月7日 |
0.4.2 | 2024年3月25日 |
0.3.0 | 2024年2月14日 |
0.1.0 |
|
#173 in 游戏开发
每月下载量 26
340KB
7K SLoC
Evenio
evenio
是一个基于原型的 实体组件系统 框架,用于构建事件驱动的程序。它旨在提供一组小巧但功能强大的特性,易于使用且效率高。
特性
- 除了常见的实体、组件和系统之外,
evenio
引入了事件作为一等公民。而不是限制系统按固定顺序每帧/更新运行一次,系统被泛化为事件处理器。整个程序的流程控制由处理器之间的事件流定义。 - 世界的结构变化(如实体销毁、组件添加/删除等)由事件中介,允许处理器钩入其发生。
- 目标事件使处理器能够根据查询有效地过滤事件。
- 组件类型、事件类型和处理器与代数索引相关联,允许它们动态地添加和删除。
- 与 Rayon 并行执行查询。
- 世界数据没有
Send
或Sync
要求。 no_std
支持。
有关完整介绍,请阅读 教程书籍 📚。
示例
以下是我们在 evenio
中创建简单游戏循环的方式
use evenio::prelude::*;
// Define position and velocity components.
#[derive(Component)]
struct Position {
x: f32,
y: f32,
}
#[derive(Component)]
struct Velocity {
x: f32,
y: f32,
}
// Events can carry data, but for this example we only need a unit struct.
#[derive(GlobalEvent)]
struct Tick;
pub fn main() {
// Create a new `World` to store all our data.
let mut world = World::new();
// Spawn a new entity and add the `Position` and `Velocity` components to it.
// We'll store the entity's ID in a variable for later use.
let e = world.spawn();
world.insert(e, Position { x: 0.0, y: 0.0 });
world.insert(e, Velocity { x: 1.0, y: 0.4 });
// Add our event handler to the world.
world.add_handler(update_positions);
// Run our fake "game loop" by sending the `Tick` event every update.
for _ in 0..50 {
world.send(Tick);
}
// Get the `Position` component from the entity we added earlier.
let pos = world.get::<Position>(e).unwrap();
println!("Final position of the entity: ({}, {})", pos.x, pos.y);
}
// The `Receiver<Tick>` parameter tells our handler to listen for the `Tick` event.
fn update_positions(_: Receiver<Tick>, entities: Fetcher<(&mut Position, &Velocity)>) {
// Loop over all entities with both the `Position` and `Velocity` components, and update their positions.
for (pos, vel) in entities {
pos.x += vel.x;
pos.y += vel.y;
}
}
功能标志
std
(默认启用):启用对标准库的支持。没有这个,evenio
仅依赖于core
和alloc
。rayon
:为Fetcher
添加并行迭代器支持。使用 Rayon 库。
依赖
~1.8–3MB
~53K SLoC