pub trait ParticleSystem {
type ParticleType: Particle + ?Sized;
type EmitterType: ParticleEmitter<ParticleType = Self::ParticleType> + ?Sized;
fn iter_particles(&self)
-> impl Iterator<Item = &Box<Self::ParticleType>>;
fn iter_particles_mut(
&mut self,
) -> impl Iterator<Item = &mut Box<Self::ParticleType>>;
fn iter_emitters(
&self,
) -> impl Iterator<Item = &Box<Self::EmitterType>>;
fn iter_emitters_mut(
&mut self,
) -> impl Iterator<Item = &mut Box<Self::EmitterType>>;
fn add_particle(&mut self, particle: Box<Self::ParticleType>);
fn add_emitter(&mut self, emitter: Box<Self::EmitterType>);
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<Self::ParticleType>> {
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<ParticleType = dyn Particle<Position = P>>>>,
}
impl<P> ParticleSystem for BaseParticleSystem<P> {
type ParticleType = dyn Particle<Position = P>;
type EmitterType = dyn ParticleEmitter<ParticleType = Self::ParticleType>;
fn iter_particles(
&self,
) -> impl Iterator<Item = &Box<Self::ParticleType>> {
self.particles.iter()
}
fn iter_particles_mut(
&mut self,
) -> impl Iterator<Item = &mut Box<Self::ParticleType>> {
self.particles.iter_mut()
}
fn iter_emitters(
&self,
) -> impl Iterator<Item = &Box<Self::EmitterType>> {
self.emitters.iter()
}
fn iter_emitters_mut(
&mut self,
) -> impl Iterator<Item = &mut Box<Self::EmitterType>> {
self.emitters.iter_mut()
}
fn add_particle(&mut self, particle: Box<Self::ParticleType>) {
self.particles.push(particle);
}
fn add_emitter(&mut self, emitter: Box<Self::EmitterType>) {
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 ParticleType: Particle + ?Sized;
fn update(&mut self, dt: f64) -> Vec<Box<Self::ParticleType>>;
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;
}