4 releases

0.1.4 Oct 1, 2023
0.1.3 Sep 10, 2023
0.1.2 Sep 3, 2023
0.1.1 Sep 3, 2023

#568 in Game dev

23 downloads per month

BSD-2-Clause

110KB
3K SLoC

Mewo ECS

Version Badge Docs Badge License Badge Downloads Badge

What is Mewo?

I've always wanted to create my own game engine, and this is the manifestation of those dreams. Mewo isn't a full game engine though. Rather, it is a fast, minimal, multithread-able Entity Component System. (mewo_ecs has exactly one dependency!)

Interested in how it works? Here's a really boring walkthrough.

Getting Started

See the docs for a guide to pretty much everything Mewo has to offer.

Examples

Terminal Flappy Bird


lib.rs:

Mewo

Driving the Car

//  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();

Defining Components

Components are pieces of data that are attached to entities. There are two types of components: CheapComponent and UniqueComponent.

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

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

CheapComponent is for components that are cheap to copy. UniqueComponent is for components that either don't implement copy or shouldn't be copied too often.

Defining Resources

Resources are pieces of data that just exist and can be accessed with some value.

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

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

Here, PlayerEntity is a single resource which can be accessed using PlayerEntity::single_resource(). There is only one PlayerEntity.

However, there can be multiple of Window. You can access each window later using literally any value.

Systems

Systems are just functions that take a galaxy.

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

Spawning an Entity

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

This creates an entity, however, this entity is not accessible until the next update.

Queries

//  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() {
    //  ...
}

Getting a Specific Entity

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();

Once again, both inserted and removed components don't show until the next update.

Spawning a Resource

//  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));

Resources that are created are instantly available unlike with components.

Accessing a Resource

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

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

Removing Stuff

galaxy.remove_entity(entity);

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

Events

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

galaxy.insert_event(KeyEvent { key });

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

Similar to components, inserted events don't appear until the next update.

Game Over

galaxy.set_exit();

Dependencies

~0.4–5.5MB
~16K SLoC