#ecs #gamedev #game-engine #game

mewo

mewo - 简单、轻量级的ECS

4个版本

0.1.4 2023年10月1日
0.1.3 2023年9月10日
0.1.2 2023年9月3日
0.1.1 2023年9月3日

#1223 in 游戏开发

每月 22次下载

BSD-2-Clause

110KB
3K SLoC

Mewo ECS

Version Badge Docs Badge License Badge Downloads Badge

什么是Mewo?

我一直想创建自己的游戏引擎,这就是梦想的实现。然而,Mewo不是一个完整的游戏引擎。相反,它是一个快速、轻量级、可多线程的实体组件系统。(mewo_ecs只有一个依赖项!)

想了解它是如何工作的?这里有一个非常无聊的演示

入门

查看文档,了解Mewo提供的几乎所有内容。

示例

终端Flappy Bird


lib.rs:

Mewo

驾驶汽车

//  For single threaded use cases.
//  let galaxy = Galaxy::new();
let galaxy = Arc::new(RwLock::new(Galaxy::new()));

{
    let mut galaxy = galaxy.write();
    
    //  Initialize Game.
    some_init_system(&galaxy);

    galaxy.update();
}

//  Although you can do this, you should prefer the built-in runner functions.
//
//  //  Game Loop
//  loop {
//      let galaxy = galaxy.write();
//      system_one(&galaxy);
//      system_two(&galaxy);
//      if galaxy.update().is_none() {
//          //  Game Over
//          return;
//      }
//  }

run_spawn(Arc::clone(&galaxy)).join().unwrap();

定义组件

组件是附加到实体上的数据片段。有两种类型的组件:CheapComponentUniqueComponent

#[derive(Clone, Copy, CheapComponent)]
struct A;

#[derive(Clone, UniqueComponent)]
struct B;

CheapComponent 用于复制成本低的组件。 UniqueComponent 用于不实现复制或不应频繁复制的组件。

定义资源

资源是仅存在并可使用某些值访问的数据片段。

#[derive(SingleResource)]
struct PlayerEntity(Entity);

#[derive(Resource)]
struct Window(...);

在这里,PlayerEntity 是一个单一的资源,可以使用 PlayerEntity::single_resource() 访问。只有一个 PlayerEntity

然而,可以有多个 Window。您可以稍后使用任何值访问每个窗口。

系统

系统只是接受一个星系(galaxy)的函数。

fn my_system(galaxy: &Galaxy) {
    todo!();
}

创建实体

let player = galaxy
    .insert_entity()
    .insert(Player)
    .insert(SomeComponent)
    .insert(OtherComponent)
    .get_entity();

这创建了一个实体,但是,这个实体在下一个更新之前不可访问。

查询

//  With Entity
for (entity, (player, health, other)) in g.query::<(&Player, &mut Health, Option<&Other>)>().eiter() {
    //  ...
}

//  Without Entity
for (player, health, other) in g.query::<(&Player, &mut Health, Option<&Other>)>().iter() {
    //  ...
}

获取特定实体

let entity_getter = galaxy.get_entity(entity).unwrap();

entity_getter
    .insert(SomeComponent)
    .insert(OtherComponent)
    .remove(SomeOtherComponent);

//  I don't see when you would use this.
let entity = entity_getter.get_entity();

同样,插入和删除的组件在下一个更新之前不会显示。

创建资源

//  For single resources.
galaxy.insert_resource(PlayerEntity::single_resource(), PlayerEntity(player));

//  For (generic) resources.
//  This associates the new window with the string `"My Window"`.
galaxy.insert_resource("My Window", Window(window));

与组件不同,创建的资源立即可用。

访问资源

galaxy
    .get_resource::<PlayerEntity, _>(PlayerEntity::single_resource())
    .unwrap()

galaxy
    .get_resource::<Window, _>("My Window")
    .unwrap()

移除内容

galaxy.remove_entity(entity);

galaxy.remove_resource::<Window, _>("My Window");
galaxy.remove_resource::<PlayerEntity, _>(PlayerEntity::single_resource());

事件

#[derive(Event)]
struct KeyEvent {
    pub key: Key,
}

galaxy.insert_event(KeyEvent { key });

for event in galaxy.get_events() {
    todo!()
}

与组件类似,插入的事件在下一个更新之前不会出现。

游戏结束

galaxy.set_exit();

依赖项

~0.4–5.5MB
~16K SLoC