use crate::{ config::CELLS_TO_METRES, sim::{ cell::{cell::Cell, materials::MaterialForm}, cell_manager::manager::CellManager, lib::ray::AwDda, particle_manager::particle::Particle, }, }; pub mod particle; pub struct ParticleManager { pub particles: Vec, } const PARTICLE_GRAVITY: f32 = 9.81 * CELLS_TO_METRES; impl ParticleManager { pub fn tick(&mut self, world: &mut CellManager, delta_time: f32) { puffin::profile_function!(); let mut i = 0; 'outer: while i < self.particles.len() { let p = &mut self.particles[i]; p.life -= delta_time; if p.life <= 0.0 { self.particles.swap_remove(i); continue 'outer; } p.velocity.y += PARTICLE_GRAVITY * delta_time; let dt_velocity = p.velocity * delta_time; let mut dda = AwDda::new(p.position, p.position + dt_velocity); if let Some(mut prev) = dda.next() { if let Some(cell) = world.get_cell_from_game_position(prev.x, prev.y) && [ MaterialForm::Solid, MaterialForm::Powder, MaterialForm::Liquid, ] .contains(&cell.material.def().form) { // the particle is already inside a collider, we should just kill it self.particles.swap_remove(i); continue 'outer; } for next in dda { if let Some(cell) = world.get_cell_from_game_position(next.x, next.y) && [ MaterialForm::Solid, MaterialForm::Powder, MaterialForm::Liquid, ] .contains(&cell.material.def().form) { // write ourselves to the board world.set_cell_from_game_position( prev.x, prev.y, Cell::from_material(p.material), false, ); self.particles.swap_remove(i); continue 'outer; } prev = next; } } // no collision, just move p.position += dt_velocity; i += 1; } } pub fn new() -> Self { ParticleManager { particles: Vec::new(), } } }