use ::bracket_lib::prelude::*; use ::specs::prelude::*; use crate::components::{ParticleLifetime, Position, Renderable}; pub fn update_particles(ecs: &mut World, ctx: &BTerm) { let mut dead_particles: Vec = Vec::new(); { // Age out particles let mut particles = ecs.write_storage::(); let entities = ecs.entities(); for (entity, mut particle) in (&entities, &mut particles).join() { if let Some(animation) = &mut particle.animation { animation.timer += ctx.frame_time_ms; if animation.timer > animation.step_time && animation.current_step < animation.path.len() - 2 { animation.current_step += 1; if let Some(pos) = ecs.write_storage::().get_mut(entity) { pos.x = animation.path[animation.current_step].x; pos.y = animation.path[animation.current_step].y; } } } particle.lifetime_ms -= ctx.frame_time_ms; if particle.lifetime_ms < 0.0 { dead_particles.push(entity); } } } for dead in dead_particles.iter() { ecs.delete_entity(*dead).expect("Particle will not die."); } } struct ParticleRequest { x: i32, y: i32, fg: RGB, bg: RGB, glyph: FontCharType, lifetime: f32, } #[derive(Default)] pub struct ParticleBuilder { requests: Vec, } impl ParticleBuilder { pub fn new() -> ParticleBuilder { ParticleBuilder::default() } pub fn request( &mut self, x: i32, y: i32, fg: RGB, bg: RGB, glyph: FontCharType, lifetime: f32, ) { self.requests.push(ParticleRequest { x, y, fg, bg, glyph, lifetime, }) } } pub struct ParticleSpawnSystem {} impl<'a> System<'a> for ParticleSpawnSystem { #[allow(clippy::type_complexity)] type SystemData = ( Entities<'a>, WriteStorage<'a, Position>, WriteStorage<'a, Renderable>, WriteStorage<'a, ParticleLifetime>, WriteExpect<'a, ParticleBuilder>, ); fn run(&mut self, data: Self::SystemData) { let (entities, mut positions, mut renderables, mut particles, mut particle_builder) = data; for new_particle in particle_builder.requests.iter() { let p = entities.create(); positions .insert( p, Position { x: new_particle.x, y: new_particle.y, }, ) .expect("Failed to insert Position of new particle"); renderables .insert( p, Renderable { fg: new_particle.fg, bg: new_particle.bg, glyph: new_particle.glyph, render_order: 0, }, ) .expect("Failed to insert Renderable of new particle"); particles .insert( p, ParticleLifetime { lifetime_ms: new_particle.lifetime, animation: None, }, ) .expect("Failed to insert Lifetime of new particle"); } particle_builder.requests.clear(); } }