A performant, zero-dependency ECS library with a nice API written in Rust.
```toml
[dependecies] kiwi-ecs = "1.2" ```
rust
// lib.rs
use kiwi_ecs::*;
To start, create a new World
. This is the starting point of the ecs.
The program can have multiple independent worlds.
rust
pub fn main() {
let mut world = World::new();
}
Components are defined as follows:
```rust
struct Position { x: u32, y: u32 } ```
Unit structs can't be used as Components, this is where you would have to use a flag. Flags are represented as an enum:
```rust
enum Flags { Player, Enemy, Ground, } ```
To spawn a new entity with the given components:
rust
// spawn_entity macro accepts the world as the first parameter, and the
// components to add to the entity as the other parameters
let entity_id = spawn_entity!(world, Position { x: 0, y: 0 });
You can give an entity a flag using the set_flag
method:
rust
world.set_flag(entity_id, Flags::Player);
There are two ways to define systems.
system
macro:```rust // immutable system
fn print_positions(world: &World) { println!("{:?}", pos); }
// mutable system
fn move_entities(world: &mut World) { pos.x += vel.x; pos.y += vel.y }
// query entity ids as well
/// prints all entities ids having the position component fn printentityids(world: &World) { println!("{id}"); }
pub fn main() { let mut world = World::new();
//--snip
// Call the systems printpositions(&world); moveentities(&mut world); printentityids(&world); } ```
To create a mutable system, the function should contain world: &mut World
as its first argument,
for an immutable one, add world: &World
.
The function can contain any number of arguments you can pass to it when calling.
The function can return any type of Result<(), Any>
. If this function has the given result
return type, Ok(())
will be returned at the end of the system.
query
and query_mut
macros:```rust pub fn main() { let mut world = World::new();
//--snip
let queryresult = query!(world, Position); let queryresult = querymut!(world, Position, Velocity); let queryresult = query!(world, EntityId, Position);
// You can now loop over the components queryresult.foreach(|components| { // ... }); } ```
You can further filter queries using flags:
```rust
fn onplayer(world: &World) { if world.hasflag(id, Flags::Player) { // ... } }
let queryresult = query!(world, EntityId, Position) .filter(|(id, _pos)| world.hasflag(*id, Flags::Player)); ```
Contributors are always welcome. If you find any bugs, feel free to open an issue. If you feel like it, PRs are also appreciated!
Licensed under the MIT license.