Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/jomy10/kiwi-ecs

A performant, small and versatile entity component system written in Rust
https://github.com/jomy10/kiwi-ecs

ecs entity-component-system game-development gamedev rust

Last synced: 3 months ago
JSON representation

A performant, small and versatile entity component system written in Rust

Awesome Lists containing this project

README

        


kiwi ecs


A performant, zero-dependency ECS library with a nice API written in Rust.

# Usage
```toml
# Cargo.toml

[dependecies]
kiwi-ecs = "1.3"
```

```rust
// lib.rs
use kiwi_ecs::*;
```

## The world

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

Components are defined as follows:

```rust
#[derive(Component)]
struct Position {
x: u32,
y: u32
}
```

## Flags

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
#[flags]
enum Flags {
Player,
Enemy,
Ground,
}
```

## Entities

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

## Systems

There are two ways to define systems.

### The first is using the `system` macro:

```rust
// immutable system
#[system(pos: Position)]
fn print_positions(world: &World) {
println!("{:?}", pos);
}

// mutable system
#[system(pos: Position, vel: Vel)]
fn move_entities(world: &mut World) {
pos.x += vel.x;
pos.y += vel.y
}

// query entity ids as well
#[system(id: EntityId, pos: Position)]
/// prints all entities ids having the position component
fn print_entity_ids(world: &World) {
println!("{id}");
}

pub fn main() {
let mut world = World::new();

//--snip

// Call the systems
print_positions(&world);
move_entities(&mut world);
print_entity_ids(&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.

### The second is using the `query` and `query_mut` macros:

```rust
pub fn main() {
let mut world = World::new();

//--snip

let query_result = query!(world, Position);
let query_result = query_mut!(world, Position, Velocity);
let query_result = query!(world, EntityId, Position);

// You can now loop over the components
query_result.for_each(|components| {
// ...
});
}
```

### Flags in queries

You can further filter queries using flags:

```rust
#[system(id: EntityId, pos: Position)]
fn on_player(world: &World) {
if world.has_flag(id, Flags::Player) {
// ...
}
}

let query_result = query!(world, EntityId, Position)
.filter(|(id, _pos)| world.has_flag(*id, Flags::Player));
```

### Feature flags

#### try

The try feature of this crate enables returning early from a system.

To enable it:

```toml
# Cargo.toml

[dependencies]
kiwi-ecs = { version = "*", features = ["try"] }
```

##### Usage

Mark a system which returns a `Result` of ok type `()` with `try`:

```rust
#[system(try, id: EntityId, pos: Position)]
fn a_system_with_a_fallible_condition(world: &World) -> Result<(), String> {
let mesh = get_mesh(id)?; // fallible function
render(mesh, pos)?;
}
```

Next to returning an `Err`, you can also use
`return std::ops::ControlFlow::Continue(())` to skip the current entity
and continue to the next or `return std::ops::ControlFlow::Break(())` to
break from the function without an error.

# Contributing

Contributors are always welcome. If you find any bugs, feel free to open an issue. If you feel like it, PRs are also appreciated!

# License

Licensed under the MIT license.