Crates.io | hecs-component-provider |
lib.rs | hecs-component-provider |
version | 0.2.0 |
source | src |
created_at | 2021-09-22 00:04:07.948075 |
updated_at | 2022-08-20 12:21:31.209484 |
description | Easily define behavior for sets of components when using the hecs ECS library. |
homepage | |
repository | https://github.com/t-mw/hecs-component-provider |
max_upload_size | |
id | 454660 |
size | 20,223 |
Easily define behavior for sets of components when using the hecs ECS library.
use hecs_component_provider::{
default_trait_impl, gen_tuple_query_component_providers,
ComponentProvider, ComponentProviderMut
};
struct Position(f32, f32);
struct Velocity(f32, f32);
struct Enemy { shot_count: i32 };
// implement a behavior for all entities that provide the required components
#[default_trait_impl]
trait ApplyVelocity: ComponentProviderMut<Position> + ComponentProvider<Velocity> {
fn apply_velocity(&mut self, dt: f32) {
let &Velocity(vx, vy) = self.get();
let position: &mut Position = self.get_mut();
position.0 += vx * dt;
position.1 += vy * dt;
}
}
let mut world = hecs::World::new();
world.spawn((Position(1.0, 2.0), Velocity(0.7, 0.8)));
// prepare a query that returns entities with the components required for the behavior
gen_tuple_query_component_providers!(
MovableQuery,
(&mut Position, &Velocity)
);
let dt = 0.1;
for (_, mut entity) in world.query_mut::<MovableQuery>() {
// apply the behavior to the entity
entity.apply_velocity(dt);
let position = entity.0;
assert_eq!(position.0, 1.07);
assert_eq!(position.1, 2.08);
}
// behaviors can depend on one another
#[default_trait_impl]
trait EnemyBehaviors: ApplyVelocity + ComponentProviderMut<Enemy> {
fn shoot_and_move(&mut self, dt: f32) {
self.shoot();
self.apply_velocity(dt);
}
fn shoot(&mut self) {
let enemy: &mut Enemy = self.get_mut();
enemy.shot_count += 1;
}
}
world.spawn((Enemy { shot_count: 0 }, Position(2.0, 3.0), Velocity(-0.7, -0.8)));
// queries can be prepared using structs instead of tuples
#[derive(hecs::Query, ComponentProvider)]
struct EnemyQuery<'a> {
enemy: &'a mut Enemy,
position: &'a mut Position,
velocity: &'a Velocity,
}
let dt = 0.1;
for (_, mut entity) in world.query_mut::<EnemyQuery>() {
// apply the behavior to the entity
entity.shoot_and_move(dt);
assert_eq!(entity.enemy.shot_count, 1);
assert_eq!(entity.position.0, 1.93);
assert_eq!(entity.position.1, 2.92);
}