Jump to content

Using Tween to animate the recoil of a cannon: stop working after few shots


Nodragem
 Share

Recommended Posts

Hello,

I have a cannon that shoots bullets when I press space.

I use the following code to add some  recoil animation to my cannon when shooting (note, by default this.scale.x = 1):

    public launch(ball:Phaser.Sprite) {        
        ball.reset(this.x + this.cannonTip.x, 
                    this.y + this.cannonTip.y);
        ball.body.rotation = this.rotation;
        ball.lifespan = 1500; // FIXME: why?
        ball.body.velocity.x = this.cannonTip.x * State.MISSILE_SPEED;
        ball.body.velocity.y = this.cannonTip.y * State.MISSILE_SPEED;
        this.game.add.tween(this.scale).to(
            {x:0.98}, 20, Phaser.Easing.Elastic.In, true, 0, 1, true
        );
    }

When I run it in the browser, it works perfectly fine if I don't shoot like crazy.

However, if I shoot several times very quickly, the cannon will stop to animate. I can try to shoot slowly, it will not animate anymore.

 

My guess is that if you shot at intervals <20ms, you are starting a new tween on top of the one that is running. The previous tween is stopped but does not reset the scale.x, so that the next tween starts with a scale.x smaller than 1.

Apply this several times and the new tweens end up starting at scale.x = 0.98, with the target scale.x = 0.98. In other words, you can't see any recoil anymore.

So my question would be, how to cleanly add a new tween on a property while the previous tween on that property is not complete yet?

Link to comment
Share on other sites

I found a solution, but I don't know if this is the best (I post it in case that can help others).

I basically keep a reference to the current tween (this._cannon_tween) applied on scale.x, if this reference is not empty at the time I shot, I stop the tween and reset scale.x:

   public launch(ball:Phaser.Sprite) {        
        ball.reset(this.x + this.cannonTip.x, 
                    this.y + this.cannonTip.y);
        ball.body.rotation = this.rotation;
        ball.lifespan = 1500; // FIXME: why?
        ball.body.velocity.x = this.cannonTip.x * State.MISSILE_SPEED;
        ball.body.velocity.y = this.cannonTip.y * State.MISSILE_SPEED;
        
        if(this._cannon_tween !== undefined){
            this._cannon_tween.stop();
            this.scale.x = 1;
        }
        
        this._cannon_tween = this.game.add.tween(this.scale).to(
            {x:0.98}, 20, Phaser.Easing.Elastic.In, true, 0, 1, true
        );
    }

 

Link to comment
Share on other sites

You are correct that you need to make sure you have the starting properties you want before adding a new tween.

As for checking for an existing tween object and disposing of it, this is only necessary if Phasers tween library lacks an override system for newly added tweens which target the same object as an existing tween in the tween manager. From a quick look at the docs, it seems that's the case.

A slightly cleaner way to write it would be to use the removeFrom method. So instead of the undefined check do this:

game.tweens.removeFrom(this)

https://phaser.io/docs/2.4.4/Phaser.TweenManager.html#removeFrom

That may avoid the necessity for holding a reference to that tween if you don't need to do anything special with it.

Edited by lloydevans
It seems the input parameter for removeFrom is Phaser.Group. So I assume the .scale (PIXI.Point) won't work.
Link to comment
Share on other sites

Thank you for your reply :) 

I am not sure if this is what you meant, but to replace:

        if(this._cannon_tween !== undefined){
            this._cannon_tween.stop();
            this.scale.x = 1;
        }

with:

this.game.tweens.removeFrom(this.scale);

Does not work.

The input parameters is accepted (object, array of objects or group), but the scale.x is not resetted to 1, so that `scale.x` converges to 0.98 after few quick shots.

 

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...