kurhlaa

Update tween END value

Recommended Posts

Hello!

I try to use a tween and I need to set it's end value dynamically, and new value can't be precalculated - it is just a new integer.

I try this code in labs.phaser.io:

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

var tween;
var game = new Phaser.Game(config);

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

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

    tween = this.tweens.add({
        targets: image,
        duration: 100,
        paused: true
    });

    setTimeout(function() {
        // NewX can't bet precalculated
        var NewX = 500;

        tween.updateTo('x', NewX, true);
        tween.play();
    }, 1000);
}

function update() {}

 

.. but nothing happens, box is not moving after 1s. How do I make it to move to the NewX position?

Share this post


Link to post
Share on other sites

@prob, can you show an example with updateTo ? Given lab's sample has calculation functions inside tween definition. In my case I do not have anything to calculate. During the game I just get a number and need to move there an object, for example in 100ms, or 10px per frame.

In my code example I use setTimeout to simulate an action which happens later. Maybe you know how to achieve a movement to the location in other way?

Share this post


Link to post
Share on other sites

@kurhlaa the tween class has delay capabilities you can tap into.  I would give a look over the API to see how you can naturally leverage Phaser to do related tasks.

https://photonstorm.github.io/phaser3-docs/Phaser.Tweens.html

https://photonstorm.github.io/phaser3-docs/Phaser.Tweens.Timeline.html

And don't forget searching on Phaser labs for examples (e.g. http://labs.phaser.io/view.html?src=src/tweens\delay.js)

Share this post


Link to post
Share on other sites

@blackhawx, thanks for links, I've tried searching and tween.updateTo should do what I need. But why this code sample doesn't work?

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

var tween;
var game = new Phaser.Game(config);

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

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

    tween = this.tweens.add({
        targets: image,
        //x: 100,
        duration: 1000,
        paused: true,
    });

    setTimeout(function() {
        tween.updateTo('x', 500, true);
        tween.play();
    }, 1000);
}

function update() {}

 

.. I create a paused tween, because there is no need to run it in the beginning. Then after some time I update an 'x' value, call tween.play() and expect the box to move to the new location (x = 500). But the box is not moving. What am I missing? You can copy this code to the labs.phaser.io to play

Share this post


Link to post
Share on other sites
Quote

What am I missing?

You are missing the native way to handle delays with tweens in Phaser 3.  The following is a simpler and native approach to take:


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

var tween;
var game = new Phaser.Game(config);

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

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

  tween = this.tweens.add({
      targets: image,
      x: 500,
      duration: 1000,
      delay: 1000
  });
}

function update() {}

 

 

Share this post


Link to post
Share on other sites

@blackhawx, the question is not about a delay :) my timeout is just to simulate an action which happens later. How will you set a "delay" if you don't know when user will press the button? Why 1000 and not 13729 ? And I need exactly this - move an object when a needed event happens, immediately. There shouldn't be a delay inside a tween itself.

 

The question is how to move an object to the needed position.

Share this post


Link to post
Share on other sites

so to understand you correctly, you want to wait until an input event it triggered, (i.e. a user presses down on their mouse, then wait x number of seconds before tween begins) correct?

If that was the case, this request is still easy to implement.  If you look at this following example in labs:

http://labs.phaser.io/edit.html?src=src/tweens\update to.js

and after the paused:true, property, simply add delay:1000 and run the code.  The tween won't run until the input is triggered and the delay is met.

 

 

 

Share this post


Link to post
Share on other sites

Back to the original question and regardless of the timeout thing, which is off topic (and I'll handle at the end), I've been having the same problem and think I found the solution (or workaround).

Short answer: updateTo doesn't work for finished tweens (Is it a bug or the intended behavior? Please tell if you know).

What I wanted was a way to reuse tweens, because in my game I make heavy use of them, and it seems dumb to be recreating a tween that is applied over the same object and same properties. So when I saw updateTo() I was very happy. But it doesn't work the way I expected, It seems to work only if the tween is playing.

Here is the relevant part of my code:


var nextAngleChangeTime = 3000;
var curAngle = 0;

//...

function create(){
    //...
    direction = { angle: curAngle };
    directionTween = scn.tweens.add({
        targets: dirObj,
        angle: curAngle,
        duration: 2000,
        repeat: 0,
    });

}

function update(time, delta) {
    if (time > nextAngleChangeTime) {
        nextAngleChangeTime = time + 3000;
        curAngle += Math.PI/2 - Math.random()*Math.PI;

        directionTween.updateTo('angle', curAngle, true);
        directionTween.restart();
        console.log('New target Angle:', curAngle);
    }
    console.log('tweened angle:', direction.angle);
    //...
}

 

But this didn't work at all. The currAngle changed every 3 seconds, but the direction.angle remained as at the end of the first 2 seconds tween. 

After more than a day struggling with this and diving into the source code and not understanding anything, I realized the example on the labs was acting on a tween only while it was playing. And decided to give it a try. So instead of calling updateTo and then restarting the tween I did the oposite. I restart the tween and then update the end value just once (in my case it is going to be the same during the whole tween duration)

function update(time, delta) {
    if (time > nextAngleChangeTime) {
        nextAngleChangeTime = time + 3000;
        curAngle += Math.PI/2 - Math.random()*Math.PI;

        //directionTween.updateTo('angle', curAngle, true);
        directionTween.restart();
        console.log('New target Angle:', curAngle);
    }
    if(curAngle !== direction.angle) {
        directionTween.updateTo('angle', curAngle, true);
    }
    console.log('tweened angle:', direction.angle);
    //...
}

This worked nicely.
Notice that I update the value on the next frame after restarting the tween. If I do it on the same one it doesn't work, who knows why? (Not a rhetoric question 😜)

I don't like the contrived solution, but I need to randomly and smoothly change the angle of the movement every few seconds and I think this is much better than destroying the old twen and creating a new one, specially when I have a lot of sprites with this behavior on the screen.

P.D.: @jb-uy. The way I showed here is one Phaser friendly way to simulate setTimeOut (well, setInterval actually but you can see the pattern) Another way is with events. See this, for instance. As for why it's a bad idea to use setTimeOut, it's game engines 101. Your code should always be executed in sync with the update loop, setTimeOut can't guarantee it will happen so, and what you change on that callback can be overriden by the engine before the next update step, or you can change something that the engine doesn't expect to change outside the update loop and crash the game, for example. 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.