From 533da47f2cc03a8b60a7c6c0bb5a938a7e523a03 Mon Sep 17 00:00:00 2001 From: Kai Stevenson Date: Thu, 20 Aug 2026 23:20:21 -0700 Subject: particles --- src/sim/cell_sim/chunk.rs | 5 +- src/sim/mod.rs | 6 +-- src/sim/particle_sim/mod.rs | 101 +++++++++++++++++++++++++++++++++++++++ src/sim/particle_sim/particle.rs | 21 ++++++++ 4 files changed, 125 insertions(+), 8 deletions(-) create mode 100644 src/sim/particle_sim/mod.rs create mode 100644 src/sim/particle_sim/particle.rs (limited to 'src/sim') diff --git a/src/sim/cell_sim/chunk.rs b/src/sim/cell_sim/chunk.rs index 85d2c09..3fe5056 100644 --- a/src/sim/cell_sim/chunk.rs +++ b/src/sim/cell_sim/chunk.rs @@ -1,10 +1,7 @@ use crate::{ config::{CELLS_IN_CHUNK, CHUNK_SIZE}, sim::{ - cell::{ - cell::Cell, - materials::{MaterialForm, MaterialId}, - }, + cell::{cell::Cell, materials::MaterialForm}, lib::marching_squares::Marchable, }, }; diff --git a/src/sim/mod.rs b/src/sim/mod.rs index c73a373..d9e358b 100644 --- a/src/sim/mod.rs +++ b/src/sim/mod.rs @@ -1,11 +1,9 @@ -use crate::{ - config::CHUNK_SIZE, - sim::{cell::materials::MaterialId, cell_sim::world::World, rb_sim::RbSimManager}, -}; +use crate::sim::{cell::materials::MaterialId, cell_sim::world::World, rb_sim::RbSimManager}; pub mod cell; pub mod cell_sim; pub mod lib; +pub mod particle_sim; pub mod rb_sim; pub fn write_rb_entity_to_world( diff --git a/src/sim/particle_sim/mod.rs b/src/sim/particle_sim/mod.rs new file mode 100644 index 0000000..8bad61d --- /dev/null +++ b/src/sim/particle_sim/mod.rs @@ -0,0 +1,101 @@ +use glam::{IVec2, Vec2}; + +use crate::{ + config::PIXELS_TO_METRES, + sim::{ + cell::{cell::Cell, materials::MaterialId}, + cell_sim::world::World, + 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; + + // Amanatides and Woo's fast Voxel Traversal + { + let mut cur = IVec2::new(p.position.x.round() as i32, p.position.y.round() as i32); + // direction we step for each component on each iteration + let step_sign = + IVec2::new(dt_velocity.x.signum() as i32, dt_velocity.y.signum() as i32); + let delta = Vec2::new(1.0 / dt_velocity.x.abs(), 1.0 / dt_velocity.y.abs()); + + let frac = Vec2::new( + if step_sign.x > 0 { + (cur.x as f32 + 0.5) - p.position.x + } else { + p.position.x - (cur.x as f32 - 0.5) + }, + if step_sign.y > 0 { + (cur.y as f32 + 0.5) - p.position.y + } else { + p.position.y - (cur.y as f32 - 0.5) + }, + ); + let mut t_max = frac * delta; + + let mut prev = cur; + if let Some(cell) = world.get_cell_from_game_position(prev.x, prev.y) + && cell.material != MaterialId::Void + { + // already occupied, die + self.particles.swap_remove(i); + continue 'outer; + } + while t_max.min_element() <= 1.0 { + if t_max.x < t_max.y { + cur.x += step_sign.x; + t_max.x += delta.x; + } else { + cur.y += step_sign.y; + t_max.y += delta.y; + } + if let Some(cell) = world.get_cell_from_game_position(cur.x, cur.y) + && cell.material != MaterialId::Void + { + // 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 = cur; + } + } + + // no collision, just move + p.position = p.position + dt_velocity; + i += 1; + } + } + + pub fn new() -> Self { + ParticleManager { + particles: Vec::new(), + } + } +} diff --git a/src/sim/particle_sim/particle.rs b/src/sim/particle_sim/particle.rs new file mode 100644 index 0000000..cc7dd28 --- /dev/null +++ b/src/sim/particle_sim/particle.rs @@ -0,0 +1,21 @@ +use glam::Vec2; + +use crate::sim::cell::materials::MaterialId; + +pub struct Particle { + pub position: Vec2, + pub velocity: Vec2, + pub material: MaterialId, + pub life: f32, +} + +impl Particle { + pub fn new(position: Vec2, velocity: Vec2, material: MaterialId, life: f32) -> Self { + Particle { + position, + velocity, + material, + life, + } + } +} -- cgit v1.3.1