flame-engine / forge2d

A Dart port of Box2D
BSD 3-Clause "New" or "Revised" License
181 stars 26 forks source link

bug: Particles are never destroyed #70

Open gkjpettet opened 2 years ago

gkjpettet commented 2 years ago

As far as I can see, particles in a particle system are never destroyed.

In the original LiquidFun library, particles expired after a certain time period:

https://google.github.io/liquidfun/Programmers-Guide/html/md__chapter11__particles.html

Looking through the particle system in Forge2D however, I can't see anyway that a particle is ever removed automatically from the particle system. The only time a particle is removed from the system's internal list is if it is a "zombie" by having it's flags property set to have the zombie flag. However, I can't see any code that ever does this.

Am I missing something here?

spydon commented 2 years ago

If I remembered correctly they disappeared after some time in the Dart example in the repository, have you tried that one? The particles have barely been touched in Forge2D, so there is probably some work to be done there, I can see some TODOs in the code.

gkjpettet commented 2 years ago

Hmm, looking through the source of the examples it would appear that the lifetime of a particle is managed through Flame and its components rather than through the Forge2D library. Since I'm trying to port Forge2D to Xojo, I'll need to figure out a way to incorporate lifetimes into particles just in the physics engine alone. I'm guessing Flame does it by checking a timer in every particle step?

spydon commented 2 years ago

I meant this example: https://github.com/flame-engine/forge2d/blob/main/packages/forge2d/example/web/particles.dart But it looks like the destroyAutomatically is for something else than what you are looking for? Definitely think we should introduce some settable lifetime on the particles.

gkjpettet commented 2 years ago

Yeah I don't think the particles are getting destroyed in that example.

Since I'm writing a port (not in Dart), what I've done (and it seems to work fine) is the following:

  1. Added two properties to class Particle:
double _age = 0.0; // seconds
double lifespan = 0.5; // seconds
  1. Added a new method to Particle called preSolve() that is called from ParticleSystem.solve():
void preSolve(double dt) {
  _age +=dt;

  if (_age > lifespan) {
    // The particle has expired. Set it to be a zombie and it'll get
    // removed after the `solve()` step in `ParticleSystem`.
    flags |= ParticleType.zombieParticle;
  }
}
  1. In ParticleSystem.solve() we need to call each particle's preSolve() method. You can replace the short for loop (lines 501-503):
for (final particle in _particles) {
  // Tell this particle we are beginning the `solve` step. 
  // This will determine if the particle has expired.
  particle.PreSolve(step.dt);
  allParticleFlags |= particle.flags;
}

This seems to happily purge the particles after they have aged past their maximum lifespan.

spydon commented 2 years ago

Great, thanks for the code! I'll put this into Forge2D when I have time (if you don't have the time to make the PR that is). :)

alestiago commented 1 year ago

Is someone still looking into this? 👀

erickzanardo commented 1 year ago

Is someone still looking into this? 👀

I don't believe so! Would you like to work on this? We can assign you to it