pub trait ParticleSystem {
type Position;
fn iter_particles(&self)
-> impl Iterator<Item = &Box<dyn Particle<Position = Self::Position>>>;
fn iter_particles_mut(
&mut self,
) -> impl Iterator<Item = &mut Box<dyn Particle<Position = Self::Position>>>;
fn iter_emitters(
&self,
) -> impl Iterator<Item = &Box<dyn ParticleEmitter<Position = Self::Position>>>;
fn iter_emitters_mut(
&mut self,
) -> impl Iterator<Item = &mut Box<dyn ParticleEmitter<Position = Self::Position>>>;
fn add_particle(&mut self, particle: Box<dyn Particle<Position = Self::Position>>);
fn add_emitter(&mut self, emitter: Box<dyn ParticleEmitter<Position = Self::Position>>);
fn update_particles(&mut self, dt: f64) {
for particle in self.iter_particles_mut() {
particle.update(dt);
}
}
fn update_emitters(&mut self, dt: f64) -> Vec<Box<dyn Particle<Position = Self::Position>>> {
self.iter_emitters_mut()
.flat_map(|emitter| emitter.update(dt))
.collect()
}
fn clean_particles(&mut self);
fn clean_emitters(&mut self);
fn update(&mut self, dt: f64) {
let new_particles = self.update_emitters(dt);
for new_particle in new_particles {
self.add_particle(new_particle);
}
self.update_particles(dt);
self.clean_particles();
self.clean_emitters();
}
fn draw(&self) {
for particle in self.iter_particles() {
particle.draw();
}
}
}
#[derive(Default)]
pub struct BaseParticleSystem<P> {
particles: Vec<Box<dyn Particle<Position = P>>>,
emitters: Vec<Box<dyn ParticleEmitter<Position = P>>>,
}
impl<P> ParticleSystem for BaseParticleSystem<P> {
type Position = P;
fn iter_particles(
&self,
) -> impl Iterator<Item = &Box<dyn Particle<Position = Self::Position>>> {
self.particles.iter()
}
fn iter_particles_mut(
&mut self,
) -> impl Iterator<Item = &mut Box<dyn Particle<Position = Self::Position>>> {
self.particles.iter_mut()
}
fn iter_emitters(
&self,
) -> impl Iterator<Item = &Box<dyn ParticleEmitter<Position = Self::Position>>> {
self.emitters.iter()
}
fn iter_emitters_mut(
&mut self,
) -> impl Iterator<Item = &mut Box<dyn ParticleEmitter<Position = Self::Position>>> {
self.emitters.iter_mut()
}
fn add_particle(&mut self, particle: Box<dyn Particle<Position = Self::Position>>) {
self.particles.push(particle);
}
fn add_emitter(&mut self, emitter: Box<dyn ParticleEmitter<Position = Self::Position>>) {
self.emitters.push(emitter);
}
fn clean_particles(&mut self) {
self.particles.retain(|particle| particle.is_alive());
}
fn clean_emitters(&mut self) {
self.emitters.retain(|emitter| emitter.is_alive());
}
}
pub trait ParticleEmitter {
type Position;
fn update(&mut self, dt: f64) -> Vec<Box<dyn Particle<Position = Self::Position>>>;
fn is_alive(&self) -> bool;
}
pub trait Particle {
type Position;
fn get_position(&self) -> Self::Position;
fn update(&mut self, dt: f64);
fn draw(&self);
fn is_alive(&self) -> bool;
}