1
0
Fork 0
roguelike-game/src/particle_system.rs

133 lines
3.6 KiB
Rust

use ::rltk::{Rltk, RGB};
use ::specs::prelude::*;
use crate::components::{ParticleLifetime, Position, Renderable};
pub fn update_particles(ecs: &mut World, ctx: &Rltk) {
let mut dead_particles: Vec<Entity> = Vec::new();
{
// Age out particles
let mut particles = ecs.write_storage::<ParticleLifetime>();
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::<Position>().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: rltk::FontCharType,
lifetime: f32,
}
#[derive(Default)]
pub struct ParticleBuilder {
requests: Vec<ParticleRequest>,
}
impl ParticleBuilder {
pub fn new() -> ParticleBuilder {
ParticleBuilder::default()
}
pub fn request(
&mut self,
x: i32,
y: i32,
fg: RGB,
bg: RGB,
glyph: rltk::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();
}
}