address review: reserve room for unprocessed particles before each exploder burst

This commit is contained in:
Dylan M. Taylor
2026-11-03 21:38:55 +00:00
parent 8e52aee9cc
commit 7715b6aabb
2 changed files with 23 additions and 4 deletions
+8 -4
View File
@@ -499,18 +499,22 @@ impl Pg {
// Particle Exploder: affected particles larger than the new radius burst into smaller
// ones that fly apart (each new particle bursts no further).
if self.pex_radius > 0.0 {
let mut out = Vec::with_capacity(st.parts.len());
for q in std::mem::take(&mut st.parts) {
let total = st.parts.len();
let mut out = Vec::with_capacity(total);
for (i, q) in std::mem::take(&mut st.parts).into_iter().enumerate() {
let n = ((q.r / self.pex_radius).powi(2).round() as u32).clamp(2, 16);
// The particles after this one are all kept, so a burst fits only if they and its
// children still fit the budget.
let unprocessed = total - i - 1;
if q.src == SRC_PARTICLE_EXPLODER
|| q.ch != 0
|| q.r <= self.pex_radius * 1.01
|| self.pex_affects.weight(&q) <= 0.5
|| out.len() > MAX_PG_PARTICLES
|| out.len() + unprocessed + n as usize > MAX_PG_PARTICLES
{
out.push(q);
continue;
}
let n = ((q.r / self.pex_radius).powi(2).round() as u32).clamp(2, 16);
for k in 0..n {
let id = st.next_id;
st.next_id = st.next_id.wrapping_add(1);
+15
View File
@@ -281,6 +281,21 @@ fn particle_exploder_bursts_big_particles() {
assert!(s.parts.is_empty());
}
/// Bursts count the particles still waiting to be processed, so a grid near the particle budget
/// cannot end the frame over it.
#[test]
fn particle_exploder_stays_within_the_particle_budget() {
let st = Pg { pex_radius: 2.0, pex_dispersion: 30.0, ..bare(1) };
let mut s = PgState::default();
for _ in 0..MAX_PG_PARTICLES - 20 {
s.parts.push(PgParticle::new([50.0, 50.0], [0.0; 2], [1.0; 4], 6.0, 0, SRC_GRID));
}
st.step(&mut s);
assert!(s.parts.len() <= MAX_PG_PARTICLES, "{}", s.parts.len());
// Room was left for the first bursts: 20 spare slots hold two bursts of 9 - 1 new each.
assert!(s.parts.len() > MAX_PG_PARTICLES - 20);
}
#[test]
fn text_particles_draw_characters() {
let grid = |text: &str| {