Reusing a Timeline Tween for a Path Follower

I want to reuse the ballFlight timeline when the function shotPath is called a second time. Right now, the ball gets scaled by the timeline only on the first execution. I tried using ballFlight.resetTweens(), but no luck. I tried a lot of other things that were wrong as well. :slight_smile:

Is there a way?

ballpath = new Phaser.Curves.Path(883, 1444);
ball = this.add.follower(ballpath, 883, 1444, 'ball').setDepth(1);
var ballFlight = this.tweens.createTimeline();

function shotPath(finX, finY, curveWidth, curveHeight) {
   //Reset the curves.
    ballpath.curves.length = 0;
    ballpath.cacheLengths.length = 0;
    ballpath.quadraticBezierTo(finX, finY, curveWidth, curveHeight);

    //Set the scale of the ball as it travels.
    ballFlight.add({targets: ball, duration: 3500, scaleX: 4, scaleY: 4});
    ballFlight.add({targets: ball, duration: 1000, scaleX: 3, scaleY:  3});
    ballFlight.add({targets: ball, duration: 700, scaleX: 2, scaleY: 2});
    ballFlight.add({targets: ball, duration: 500, scaleX: 1.5, scaleY: 1.5});
    ballFlight.add({targets: ball, duration: 300, scaleX: .5, scaleY: .5});
    
    if (currentClosingTime - now < 0 && currentClosingTime - now  > -10) {

        ball.startFollow({
            positionOnPath: true,
            duration: 6000,
            repeat: 0,
            onComplete: shotCompleteHandler
        });
        ballFlight.play();

        function shotCompleteHandler () {
            graphicsResultBackdrop.setAlpha(.9);
            resultText.text = lastResult.text;
            resultText.setAlpha(1);
        }

    }
}

I’ve put the ballFlight Tweens out of the function and tried ballFlight.resetTweens(true) in the function to clear, but this doesn’t work. How do I reset things?

Here is an example that can be pasted:

var config = {
    type: Phaser.WEBGL,
    width: 800,
    height: 600,
    backgroundColor: '#2d2d2d',
    parent: 'phaser-example',
    scene: {
        preload: preload,
        create: create
    }
};

var game = new Phaser.Game(config);

function preload ()
{
    this.load.image('block', 'assets/sprites/block.png');
}

function create ()
{

    var image = this.add.image(100, 100, 'block').setInteractive();

    var timeline = this.tweens.createTimeline();

    timeline.add({
        targets: image,
        x: 600,
        ease: 'Power1',
        duration: 500
    });

    timeline.add({
        targets: image,
        y: 500,
        ease: 'Power1',
        duration: 500
    });

    timeline.add({
        targets: image,
        x: 100,
        ease: 'Power1',
        duration: 500
    });

    timeline.add({
        targets: image,
        y: 100,
        ease: 'Power1',
        duration: 500
    });


    image.on('pointerup', function (pointer) {

        timeline.play();

        timeline.destroy();

    });
}

Edit: Very frustrated. Spent over 8 hours trying to solve this and cannot figure it out. Is it possible? The only solution I can think of is to define thousands of timelines, and then iterate through each one every time it is called and update the public version every so often so it doesn’t stop working. Or just use Phaser 2 for now?

It works there: https://phaser.io/examples/v2/tweens/single-tween-reuse

I finally found a solution, but it’s not a very good one. The solution is to daisychain the tweens together with onComplete.

The documentation and examples don’t make clear the differences of timelines versus tweens, or why things are the way they are. I think a little bit of documenting the why would help. I still don’t know what .restart() won’t work on a timeline. To me it just seems logical that the Phaser 3 library would just be chaining individual tweens together as I am doing now, and offer all of the same methods as tweens have. I struggle with being developmentally disabled a lot, but I don’t think I’m wrong to be confused here.

function create ()
{
    var image = this.add.image(100, 100, 'block').setInteractive();

 ball1 = this.tweens.add({
        targets: image,
        x: 600,
        paused: true,
        onComplete: ball2func,
        duration: 300
    });

function ball2func(){ ball2.restart();}

  var ball2 = this.tweens.add({
            targets: image,
            y: 500,
            paused: true,
            duration: 300
     });



    image.on('pointerdown', () => {
        ball1.restart();
    });

}

Is this still the only way to do it (in 2021)?

1 Like

Same question here. timeline.play() doesn’t work again.
Is the timeline one-time play only? Do I have to create it again?

//EDIT:
the only way I was able to make timeline play again was to set loop: -1 and than in onLoop method pause the timeline. Next time, when I want to play it again I fire mytimeline.resume();

I think you can restart a stopped/completed timeline with just

this.tweens.makeActive(timeline);

It’s perfectly fine to create a new timeline as well. Tweens/timelines are cheap.