[SOLVED] Removing ParticleEmitter after Initial Explosion

I’m using ParticleEmitter to cause an explosion when a grenade goes off. It explodes just fine, but afterward it spews particles forever.

How can I detach the ParticleEmitter from the rootNode when the initial explosion is finished?

package com.myGame.JmeEffects;
import com.jme3.app.Application;
import com.jme3.app.state.BaseAppState;
import com.jme3.asset.AssetManager;
import com.jme3.effect.ParticleEmitter;
import com.jme3.effect.ParticleMesh;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Vector3f;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Node;

public class NitroState extends BaseAppState {
    private final AssetManager assetManager;
    private final Node nitroNode;
    private final String effectName;
    private final Vector3f gravity;
    private final float limitationTime=3f;
    private float counter=0.0f;
    private final ColorRGBA colorRGBA1;
    private final ColorRGBA colorRGBA2;
    private ViewPort viewPort;
    private MotionEffect motionEffect;
    public NitroState(AssetManager assetManager, Node nitroNode,Vector3f gravity, String effectName,ColorRGBA colorRGBA1,ColorRGBA colorRGBA2){
        this.assetManager=assetManager;
        this.nitroNode=nitroNode;
        this.gravity=gravity;
        this.effectName=effectName;
        this.colorRGBA1=colorRGBA1;
        this.colorRGBA2=colorRGBA2;
    }

    public void setViewPort(ViewPort viewPort) {
        this.viewPort = viewPort;
//        motionEffect=new MotionEffect(assetManager,viewPort);
//        motionEffect.add();
    }

    private ParticleEmitter advancedEffects(){
        ParticleEmitter rocksEffect = new ParticleEmitter(effectName, ParticleMesh.Type.Triangle, 5000);
        rocksEffect.setParticlesPerSec(FastMath.pow(5,5));
        Material fireMat = new Material(assetManager, "Common/MatDefs/Misc/Particle.j3md");
        fireMat.setTexture("Texture", assetManager.loadTexture("RocketLeauge/assets/Textures/Fire.png"));
        fireMat.setTexture("GlowMap", assetManager.loadTexture("RocketLeauge/assets/Textures/Fire.png"));
//        fireMat.selectTechnique("Glow",getApplication().getRenderManager());
//        fireMat.setColor("GlowColor",ColorRGBA.Blue);
        rocksEffect.setMaterial(fireMat);
        rocksEffect.getParticleInfluencer().setInitialVelocity(gravity.mult(3.5f));
        rocksEffect.getParticleInfluencer().setVelocityVariation(0.3f);
        rocksEffect.setImagesX(1);
        rocksEffect.setImagesY(1);
        rocksEffect.setStartColor(colorRGBA1);
        rocksEffect.setEndColor(colorRGBA2);
        rocksEffect.setStartSize(0.25f);
        rocksEffect.setEndSize(0.05f);
        rocksEffect.setGravity(gravity);
        rocksEffect.setLowLife(0.5f);
        rocksEffect.setHighLife(1f);
        rocksEffect.center();
        return rocksEffect;
    }


    @Override
    protected void initialize(Application app) {

        nitroNode.attachChild(advancedEffects());
//        motionEffect.run();
    }

    @Override
    protected void cleanup(Application app) {

    }

    @Override
    protected void onEnable() {

    }

    @Override
    protected void onDisable() {

    }

    @Override
    public void update(float tpf) {
        counter+=tpf;
        if(counter>limitationTime){
            nitroNode.detachChild(nitroNode.getChild(effectName));
            getStateManager().detach(this);
//            motionEffect.removeProcessorEffect();
            counter=0.0f;
        }
    }
}

main part :

            nitroNode.detachChild(nitroNode.getChild(effectName));

though also for clean code its better to use no more than 3~5 parameters in the constructor , & the other parts are passed as setters , but i have done this for simplicity in implementation.

But that might cutoff particles before they completely disappear.

They disappear after a momentum of time you adjust that in your AppState or your Entity .

That part here .

Okay here is the point , you can create 2 particle emitter instances with the same method but with different names :

Then , you remove each one accordingly with different time intervals , you will got something like a FlameThrower weapon emerging fire where the latter particles only disappear before the former do , you can manage this by the delay of the update method of your appState.

A ParticleEmitter as also a spatial. So you can add a custom control that just removes it from its parent after a period of time or some other criteria.

No muss, no fuss.

1 Like

Try this:

  1. Set your explosion’s number of particles per second to zero.
  2. Make the explosion occur using emitAllParticles().
  3. Check your explosion’s number of visible particles. If equals to zero, remove your explosion from the scene.
2 Likes

I’ve tried using fireEffect.getNumVisibleParticles() to detect the number of particles, but it seems to be throwing a NullPointerException.

EDIT: nvrmd, I got it.

do initialize the particle emitter instance before attaching the state/control onto the game loop stack.

Thanks for the help! :+1:

Oh, and while the subject is up, does anybody know how to make the particles explode in all directions? Thanks again.

Use gravity , also you know that all particles are Spatials so all bullet physics concepts are applied on it .

Example :

You can use maths functions with gravity to create a Linear emitting with different angles & call the setGravity() inside the void update(tpf) of your control & pass to it the x args in an array form & get the z if you want to have the effects projected into the screen , x & y only if you want a parallel view .

Sorry about the sound & the assets (they suck):

I always had trouble doing this with the stock ParticleEmitter class. For some reason, a high velocity variation does not also negate the initial velocity, and the result is just a random vecloity that always goes in the same positive or negative direction for each axis.

If you are using version 3.3 of the engine, then you may also want to consider using the newer particle system called ParticleMonkey thats opensource and available on the jmonkey store. I have found the new particle system much better for accurately controlling a particles location and behavior after being emitted.

Edit:
And in regards to your initial question: I unfortunately didn’t have time to read all of the other replies to know if you’ve found a good solution.

But in my case, I made a class that I call “AfterEffectCustom” that works as a contol for storing a list of ParticleEmitters that get passed into a new instance of the control whenever a spell (or grenade explosion in your case) is finished, and then it detaches them after a set amount of time. And most importantly it also has some code to shrink and / or fade out the transparency of the particle emitter, so the particles do not disappear abruptly.

2 Likes