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 |
#947 in Game dev
22 downloads per month
110KB
3K
SLoC
Mewo ECS
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
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–5MB
~17K SLoC