Search code examples
javalibgdx

Particle acting very fast libgdx java


I am using a particle effect that goes to where you click and doesn't stop. When I click somewhere the particle goes accordingly. However when I click again the particle starts going through its effect faster and faster and I am completely stumped as to why. I am assuming it is within the SpellParent class because it happens with all spells and all spells as of right now are generally the same as the parent. Here is the parent spell class

   public SpellParent(Player player, float x, float y, float scalar){
    this.player = player;
    this.position = new Vector2(player.getHandPosition().x, player.getHandPosition().y);
    this.destination = new Vector2(x, y);
    this.isAlive = true;
    this.gridPosition = new Vector2();
    particle = new ParticleEffect();
    emitter = new ParticleEmitter();
    emitter.setName("asshole");

}
@Override
public void update() {
    particle.update(Gdx.graphics.getDeltaTime());
    if(particle.isComplete())
        particle.reset();
    particle.setPosition(position.x, position.y);
    //particle.getEmitters().first().setPosition(position.x, position.y);
    if(position.x >= destination.x - 1 && position.x <= destination.x + 1)
        reachedX = true;
    if(position.y >= destination.y - 1 && position.y <= destination.y + 1)
        reachedY = true;
    if(!reachedX){
        if(position.x < destination.x){
            velocity.x = 1f;
        }
        else if(position.x > destination.x){
            velocity.x = -1f;
        }

    }
    if(!reachedY){
        if(position.y < destination.y){
            velocity.y = 1f;
        }
        else if(position.y > destination.y){
            velocity.y = -1f;
        }
    }
    if(reachedX && reachedY){
        startBehavior();
    }else if(reachedY){
        velocity.y = 0;
    }else if(reachedX){
        velocity.x = 0;
    }
    position.x += velocity.x;
    position.y += velocity.y;

    gridPosition.x = position.x / MapGrid.CELL_SIZE;
    gridPosition.y = position.y / MapGrid.CELL_SIZE;
}

@Override
public void render(SpriteBatch batch) {
    //if(isAlive)
    //emitter.draw(batch);
        particle.draw(batch);
        batch.draw(TextureTuples.dirt, position.x, position.y, 10, 10);
}

and here is the input listener to see how it is called

    @Override
public boolean keyDown(int keycode) {
    if(keycode == Keys.NUM_1){
         referenceSpell = new FlameSpell(player, tmp.x, tmp.y, .2f);
    }
    if(keycode == Keys.NUM_2){
         referenceSpell = new HealthRingSpell(player, tmp.x, tmp.y, .2f);
    }

    public boolean touchDown(int screenX, int screenY, int pointer, int button) {
    tmp.x = screenX;
    tmp.y = screenY;
    tmp.z = 0;
    cam.unproject(tmp);
    stage.addSpell(referenceSpell);
    stageSpells.add(referenceSpell);
    grid.checkAndDestroy(new Vector2(tmp.x, tmp.y));
    return false;
}

Just to clarify here is an example. My health ring spell is a ring of blue that goes from a small ring to a big ring, therefor pulsates in size. However if I click again it starts doing its size change faster and faster and faster. With the flame spell that shoots right its x velocity will go very fast on multiple clicks. Any help is extremely appreciated


Solution

  • Well, instead of using the old particle you create a new one. new FlameSpell/HelthRingSpell. Better use a pool for this. (Take a look here)

    Moreover do not add the spell to the stage at every touch. (2 times added = 2x faster because it get doubled update call) So sure if you hit 10 times it is 10x faster. If you update both stages the spell is updated twice. So in that case one new spell get 2x updated. Pushing again its 4x updated again is 6x updated and so on. If i get that right.

    But i am not sure if the Stage meight check if the reference is already in the Stage.

    But in General, if you added the referenceSpell to the stage, there is no need to add it again after calling a new spell if you set the reference to a new spell. So everything is just fine as it is, just dont readd on touchDown. Simply add the referenceSpell on startup and set the reference to the spells on keyDown as you do.

    @Override
    public boolean keyDown(int keycode) {
        if (keycode == Keys.NUM_1) {
            referenceSpell = new FlameSpell(player, tmp.x, tmp.y, .2f);
        }
        if (keycode == Keys.NUM_2) {
            referenceSpell = new HealthRingSpell(player, tmp.x, tmp.y, .2f);
        }
    }
    
    public boolean touchDown(int screenX, int screenY, int pointer, int button) {
        tmp.x = screenX;
        tmp.y = screenY;
        tmp.z = 0;
        cam.unproject(tmp);
        //stage.addSpell(referenceSpell); //already added in ctor
        //stageSpells.add(referenceSpell);
        grid.checkAndDestroy(new Vector2(tmp.x, tmp.y));
        return false;
    }