use glam::{IVec2, Vec2}; use crate::{ config::PIXELS_TO_METRES, sim::{ cell::{ cell::Cell, materials::{MaterialForm, MaterialId}, }, cell_sim::world::World, lib::ray::AwDda, particle_sim::particle::Particle, }, }; pub mod particle; pub struct ParticleManager { pub particles: Vec, } const PARTICLE_GRAVITY: f32 = 9.81 * PIXELS_TO_METRES; impl ParticleManager { pub fn particle_tick(&mut self, world: &mut World, delta_time: f32) { 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 + p.velocity * delta_time); if let Some(prev) = dda.next() { if let Some(cell) = world.get_cell_from_game_position(prev.x, prev.y) && [MaterialForm::Solid, MaterialForm::Powder] .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 cell in dda.map(|p| world.get_cell_from_game_position(p.x, p.y)) { if let Some(cell) = cell && [MaterialForm::Solid, MaterialForm::Powder] .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; } } } // no collision, just move p.position = p.position + dt_velocity; i += 1; } } pub fn new() -> Self { ParticleManager { particles: Vec::new(), } } }