use crate::{
entity::Lifetime,
physics::{Position, Velocity},
};
use specs_blit::{
specs::{
Component, DenseVecStorage, Entities, Join, LazyUpdate, NullStorage, Read, ReadStorage,
System,
},
Sprite, SpriteRef,
};
type Vec2 = vek::Vec2<f64>;
#[derive(Component, Debug, Default)]
#[storage(NullStorage)]
pub struct Particle;
#[derive(Component, Debug)]
pub struct ParticleEmitter {
amount: u8,
lifetime: f64,
dispersion: f64,
sprite: SpriteRef,
offset: Vec2,
}
impl ParticleEmitter {
pub fn new(lifetime: f64, sprite: SpriteRef) -> Self {
Self {
amount: 1,
dispersion: 0.5,
lifetime,
sprite,
offset: Vec2::new(0.0, 0.0),
}
}
pub fn with_offset(mut self, offset: Vec2) -> Self {
self.offset = offset;
self
}
pub fn with_dispersion(mut self, dispersion: f64) -> Self {
self.dispersion = dispersion;
self
}
pub fn with_amount(mut self, amount: u8) -> Self {
self.amount = amount;
self
}
}
pub struct ParticleEmitterSystem;
impl<'a> System<'a> for ParticleEmitterSystem {
type SystemData = (
Entities<'a>,
ReadStorage<'a, ParticleEmitter>,
ReadStorage<'a, Position>,
Read<'a, LazyUpdate>,
);
fn run(&mut self, (entities, emitter, pos, updater): Self::SystemData) {
for (emitter, pos) in (&emitter, &pos).join() {
for _ in 0..emitter.amount {
let particle = entities.create();
updater.insert(particle, Particle);
updater.insert(particle, Lifetime::new(emitter.lifetime));
updater.insert(particle, pos.add_offset(emitter.offset));
updater.insert(particle, Velocity::from_random_range(emitter.dispersion));
updater.insert(particle, Sprite::new(emitter.sprite.clone()));
}
}
}
}