2
0
Fork 0
mirror of https://github.com/photonstorm/phaser synced 2024-12-22 02:53:27 +00:00
phaser/v3/merge/tween/Tween.js

911 lines
35 KiB
JavaScript
Raw Normal View History

2013-10-01 12:54:29 +00:00
/**
* @author Richard Davey <rich@photonstorm.com>
2016-04-04 21:15:01 +00:00
* @copyright 2016 Photon Storm Ltd.
2013-10-01 12:54:29 +00:00
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
2013-08-28 23:09:12 +00:00
/**
* A Tween allows you to alter one or more properties of a target object over a defined period of time.
* This can be used for things such as alpha fading Sprites, scaling them or motion.
* Use `Tween.to` or `Tween.from` to set-up the tween values. You can create multiple tweens on the same object
* by calling Tween.to multiple times on the same Tween. Additional tweens specified in this way become "child" tweens and
* are played through in sequence. You can use Tween.timeScale and Tween.reverse to control the playback of this Tween and all of its children.
2013-08-28 23:09:12 +00:00
*
2013-10-01 12:54:29 +00:00
* @class Phaser.Tween
* @constructor
* @param {object} target - The target object, such as a Phaser.Sprite or Phaser.Sprite.scale.
* @param {Phaser.TweenManager} manager - The TweenManager responsible for looking after this Tween.
2013-08-28 23:09:12 +00:00
*/
Phaser.Tween = function (target, manager)
{
/**
* @property {Phaser.TweenManager} manager - Reference to the TweenManager responsible for updating this Tween.
*/
this.manager = manager;
2013-08-28 23:09:12 +00:00
2013-10-01 12:54:29 +00:00
/**
* @property {Phaser.Game} game - A reference to the currently running Game.
*/
this.state = manager.state;
2013-10-01 12:54:29 +00:00
/**
* @property {object} target - The target object, such as a Phaser.Sprite or property like Phaser.Sprite.scale.
2013-10-01 12:54:29 +00:00
*/
2014-11-18 20:58:25 +00:00
this.target = target;
2013-08-28 23:09:12 +00:00
2013-10-01 12:54:29 +00:00
/**
* @property {Array} timeline - An Array of TweenData objects that comprise the different parts of this Tween.
2013-10-01 12:54:29 +00:00
*/
this.timeline = [];
2013-10-01 12:54:29 +00:00
/**
* If set to `true` the current tween will play in reverse.
* If the tween hasn't yet started this has no effect.
* If there are child tweens then all child tweens will play in reverse from the current point.
* @property {boolean} reverse
2013-10-01 12:54:29 +00:00
* @default
*/
this.reverse = false;
2013-10-01 12:54:29 +00:00
/**
* The speed at which the tweens will run. A value of 1 means it will match the game frame rate. 0.5 will run at half the frame rate. 2 at double the frame rate, etc.
* If a tweens duration is 1 second but timeScale is 0.5 then it will take 2 seconds to complete.
2015-05-09 00:42:29 +00:00
*
* @property {number} timeScale
2013-10-01 12:54:29 +00:00
* @default
*/
this.timeScale = 1;
2013-10-01 12:54:29 +00:00
/**
* @property {number} repeatCounter - If the Tween and any child tweens are set to repeat this contains the current repeat count.
2013-10-01 12:54:29 +00:00
*/
this.repeatCounter = 0;
2013-10-01 12:54:29 +00:00
/**
* @property {boolean} pendingDelete - True if this Tween is ready to be deleted by the TweenManager.
* @default
* @readonly
2013-10-01 12:54:29 +00:00
*/
this.pendingDelete = false;
2014-03-23 07:59:28 +00:00
/**
* The onStart event is fired when the Tween begins. If there is a delay before the tween starts then onStart fires after the delay is finished.
* It will be sent 2 parameters: the target object and this tween.
* @property {Phaser.Signal} onStart
*/
this.onStart = new Phaser.Signal();
/**
* The onLoop event is fired if the Tween, or any child tweens loop.
* It will be sent 2 parameters: the target object and this tween.
*
* @property {Phaser.Signal} onLoop
*/
this.onLoop = new Phaser.Signal();
2013-10-01 12:54:29 +00:00
/**
2014-11-20 02:17:41 +00:00
* The onRepeat event is fired if the Tween and all of its children repeats. If this tween has no children this will never be fired.
* It will be sent 2 parameters: the target object and this tween.
* @property {Phaser.Signal} onRepeat
*/
this.onRepeat = new Phaser.Signal();
/**
* The onChildComplete event is fired when the Tween or any of its children completes.
* Fires every time a child completes unless a child is set to repeat forever.
* It will be sent 2 parameters: the target object and this tween.
* @property {Phaser.Signal} onChildComplete
*/
this.onChildComplete = new Phaser.Signal();
/**
* The onComplete event is fired when the Tween and all of its children completes. Does not fire if the Tween is set to loop or repeatAll(-1).
* It will be sent 2 parameters: the target object and this tween.
* @property {Phaser.Signal} onComplete
2013-10-01 12:54:29 +00:00
*/
this.onComplete = new Phaser.Signal();
2013-08-28 23:09:12 +00:00
/**
* @property {boolean} isRunning - If the tween is running this is set to true, otherwise false. Tweens that are in a delayed state or waiting to start are considered as being running.
* @default
*/
this.isRunning = false;
2013-10-01 12:54:29 +00:00
/**
* @property {number} current - The current Tween child being run.
2013-10-01 12:54:29 +00:00
* @default
* @readonly
2013-10-01 12:54:29 +00:00
*/
this.current = 0;
2013-10-01 12:54:29 +00:00
/**
* @property {object} properties - Target property cache used when building the child data values.
*/
this.properties = {};
/**
* @property {Phaser.Tween} chainedTween - If this Tween is chained to another this holds a reference to it.
*/
this.chainedTween = null;
Tweens have been completely rewritten. They're now much more flexible and efficient than before: When specifying the ease in `Tween.to` or `Tween.from` you can now use a string instead of the Function. This makes your code less verbose. For example instead of `Phaser.Easing.Sinusoidal.Out` and you can now just use the string "Sine".The string names match those used by TweenMax and includes: "Linear", "Quad", "Cubic", "Quart", "Quint", "Sine", "Expo", "Circ", "Elastic", "Back", "Bounce", "Power0", "Power1", "Power2", "Power3" and "Power4". You can append ".easeIn", ".easeOut" and "easeInOut" variants. All are supported for each ease types. Tweens now create a TweenData object. The Tween object itself acts like more of a timeline, managing multiple TweenData objects. You can now call `Tween.to` and each call will create a new child tween that is added to the timeline, which are played through in sequence. Tweens are now bound to the new Time.desiredFps value and update based on the new Game core loop, rather than being bound to time calculations. This means that tweens are now running with the same update logic as physics and the core loop. Tween.timeScale allows you to scale the duration of a tween (and any child tweens it may have). A value of 1.0 means it should play at the desiredFps rate. A value of 0.5 will run at half the frame rate, 2 at double and so on. You can even tween the timeScale value for interesting effects! Tween.reverse allows you to instantly reverse an active tween. If the Tween has children then it will smoothly reverse through all child tweens as well. Tween.repeatAll allows you to control how many times all child tweens will repeat before firing the Tween.onComplete event. You can set the value to -1 to repeat forever. Tween.loop now controls the looping of all child tweens. Tween.onRepeat is a new signal that is dispatched whenever a Tween repeats. If a Tween has many child tweens its dispatched once the sequence has repeated. Tween.onChildComplete is a new signal that is dispatched whenever any child tweens have completed. If a Tween consists of 4 sections you will get 3 onChildComplete events followed by 1 onComplete event as the final tween finishes. Chained tweens are now more intelligently handled. Because you can easily create child tweens (by simply calling Tween.to multiple times) chained tweens are now used to kick-off longer sequences. You can pass as many Tween objects to `Tween.chain` as you like as they'll all be played in sequence. As one Tween completes it passes on to the next until the entire chain is finished. Tween.stop has a new `complete` parameter that if set will still fire the onComplete event and start the next chained tween, if there is one. Tween.delay, Tween.repeat, Tween.yoyo, Tween.easing and Tween.interpolation all have a new `index` parameter. This allows you to target specific child tweens, or if set to -1 it will update all children at once. Tween.totalDuration reports the total duration of all child tweens in ms. There are new easing aliases: * Phaser.Easing.Power0 = Phaser.Easing.Linear.None * Phaser.Easing.Power1 = Phaser.Easing.Quadratic.Out * Phaser.Easing.Power2 = Phaser.Easing.Cubic.Out * Phaser.Easing.Power3 = Phaser.Easing.Quartic.Out * Phaser.Easing.Power4 = Phaser.Easing.Quintic.Out
2014-11-20 06:04:54 +00:00
/**
* @property {boolean} isPaused - Is this Tween paused or not?
* @default
*/
this.isPaused = false;
/**
* Is this Tween frame or time based? A frame based tween will use the physics elapsed timer when updating. This means
* it will retain the same consistent frame rate, regardless of the speed of the device. The duration value given should
* be given in frames.
*
* If the Tween uses a time based update (which is the default) then the duration is given in milliseconds.
* In this situation a 2000ms tween will last exactly 2 seconds, regardless of the device and how many visual updates the tween
* has actually been through. For very short tweens you may wish to experiment with a frame based update instead.
*
* The default value is whatever you've set in TweenManager.frameBased.
*
* @property {boolean} frameBased
* @default
*/
this.frameBased = manager.frameBased;
2013-10-01 12:54:29 +00:00
/**
* @property {function} _onUpdateCallback - An onUpdate callback.
* @private
* @default null
*/
this._onUpdateCallback = null;
/**
* @property {object} _onUpdateCallbackContext - The context in which to call the onUpdate callback.
* @private
* @default null
*/
this._onUpdateCallbackContext = null;
2013-10-01 12:54:29 +00:00
/**
* @property {number} _pausedTime - Private pause timer.
* @private
2013-10-01 12:54:29 +00:00
* @default
*/
this._pausedTime = 0;
2013-08-28 23:09:12 +00:00
/**
* @property {boolean} _codePaused - Was the Tween paused by code or by Game focus loss?
* @private
*/
this._codePaused = false;
2014-11-18 20:58:25 +00:00
/**
* @property {boolean} _hasStarted - Internal var to track if the Tween has started yet or not.
* @private
*/
this._hasStarted = false;
2013-08-28 23:09:12 +00:00
};
Phaser.Tween.prototype = {
/**
2014-07-07 10:07:00 +00:00
* Sets this tween to be a `to` tween on the properties given. A `to` tween starts at the current value and tweens to the destination value given.
* For example a Sprite with an `x` coordinate of 100 could be tweened to `x` 200 by giving a properties object of `{ x: 200 }`.
* The ease function allows you define the rate of change. You can pass either a function such as Phaser.Easing.Circular.Out or a string such as "Circ".
* ".easeIn", ".easeOut" and "easeInOut" variants are all supported for all ease types.
*
* @method Phaser.Tween#to
* @param {object} properties - An object containing the properties you want to tween, such as `Sprite.x` or `Sound.volume`. Given as a JavaScript object.
* @param {number} [duration=1000] - Duration of this tween in ms. Or if `Tween.frameBased` is true this represents the number of frames that should elapse.
* @param {function|string} [ease=null] - Easing function. If not set it will default to Phaser.Easing.Default, which is Phaser.Easing.Linear.None by default but can be over-ridden.
* @param {boolean} [autoStart=false] - Set to `true` to allow this tween to start automatically. Otherwise call Tween.start().
* @param {number} [delay=0] - Delay before this tween will start in milliseconds. Defaults to 0, no delay.
* @param {number} [repeat=0] - Should the tween automatically restart once complete? If you want it to run forever set as -1. This only effects this individual tween, not any chained tweens.
* @param {boolean} [yoyo=false] - A tween that yoyos will reverse itself and play backwards automatically. A yoyo'd tween doesn't fire the Tween.onComplete event, so listen for Tween.onLoop instead.
* @return {Phaser.Tween} This Tween object.
*/
to: function (properties, duration, ease, autoStart, delay, repeat, yoyo)
{
if (duration === undefined || duration <= 0) { duration = 1000; }
if (ease === undefined || ease === null) { ease = Phaser.Easing.Default; }
if (autoStart === undefined) { autoStart = false; }
if (delay === undefined) { delay = 0; }
if (repeat === undefined) { repeat = 0; }
if (yoyo === undefined) { yoyo = false; }
if (typeof ease === 'string' && this.manager.easeMap[ease])
{
ease = this.manager.easeMap[ease];
}
if (this.isRunning)
{
console.warn('Phaser.Tween.to cannot be called after Tween.start');
return this;
}
this.timeline.push(new Phaser.TweenData(this).to(properties, duration, ease, delay, repeat, yoyo));
2013-08-28 23:09:12 +00:00
if (autoStart)
{
this.start();
2013-08-28 23:09:12 +00:00
}
return this;
},
2013-08-28 23:09:12 +00:00
/**
* Sets this tween to be a `from` tween on the properties given. A `from` tween sets the target to the destination value and tweens to its current value.
* For example a Sprite with an `x` coordinate of 100 tweened from `x` 500 would be set to `x` 500 and then tweened to `x` 100 by giving a properties object of `{ x: 500 }`.
* The ease function allows you define the rate of change. You can pass either a function such as Phaser.Easing.Circular.Out or a string such as "Circ".
* ".easeIn", ".easeOut" and "easeInOut" variants are all supported for all ease types.
*
* @method Phaser.Tween#from
* @param {object} properties - An object containing the properties you want to tween., such as `Sprite.x` or `Sound.volume`. Given as a JavaScript object.
* @param {number} [duration=1000] - Duration of this tween in ms. Or if `Tween.frameBased` is true this represents the number of frames that should elapse.
* @param {function|string} [ease=null] - Easing function. If not set it will default to Phaser.Easing.Default, which is Phaser.Easing.Linear.None by default but can be over-ridden.
* @param {boolean} [autoStart=false] - Set to `true` to allow this tween to start automatically. Otherwise call Tween.start().
* @param {number} [delay=0] - Delay before this tween will start in milliseconds. Defaults to 0, no delay.
* @param {number} [repeat=0] - Should the tween automatically restart once complete? If you want it to run forever set as -1. This only effects this individual tween, not any chained tweens.
* @param {boolean} [yoyo=false] - A tween that yoyos will reverse itself and play backwards automatically. A yoyo'd tween doesn't fire the Tween.onComplete event, so listen for Tween.onLoop instead.
* @return {Phaser.Tween} This Tween object.
*/
Tweens have been completely rewritten. They're now much more flexible and efficient than before: When specifying the ease in `Tween.to` or `Tween.from` you can now use a string instead of the Function. This makes your code less verbose. For example instead of `Phaser.Easing.Sinusoidal.Out` and you can now just use the string "Sine".The string names match those used by TweenMax and includes: "Linear", "Quad", "Cubic", "Quart", "Quint", "Sine", "Expo", "Circ", "Elastic", "Back", "Bounce", "Power0", "Power1", "Power2", "Power3" and "Power4". You can append ".easeIn", ".easeOut" and "easeInOut" variants. All are supported for each ease types. Tweens now create a TweenData object. The Tween object itself acts like more of a timeline, managing multiple TweenData objects. You can now call `Tween.to` and each call will create a new child tween that is added to the timeline, which are played through in sequence. Tweens are now bound to the new Time.desiredFps value and update based on the new Game core loop, rather than being bound to time calculations. This means that tweens are now running with the same update logic as physics and the core loop. Tween.timeScale allows you to scale the duration of a tween (and any child tweens it may have). A value of 1.0 means it should play at the desiredFps rate. A value of 0.5 will run at half the frame rate, 2 at double and so on. You can even tween the timeScale value for interesting effects! Tween.reverse allows you to instantly reverse an active tween. If the Tween has children then it will smoothly reverse through all child tweens as well. Tween.repeatAll allows you to control how many times all child tweens will repeat before firing the Tween.onComplete event. You can set the value to -1 to repeat forever. Tween.loop now controls the looping of all child tweens. Tween.onRepeat is a new signal that is dispatched whenever a Tween repeats. If a Tween has many child tweens its dispatched once the sequence has repeated. Tween.onChildComplete is a new signal that is dispatched whenever any child tweens have completed. If a Tween consists of 4 sections you will get 3 onChildComplete events followed by 1 onComplete event as the final tween finishes. Chained tweens are now more intelligently handled. Because you can easily create child tweens (by simply calling Tween.to multiple times) chained tweens are now used to kick-off longer sequences. You can pass as many Tween objects to `Tween.chain` as you like as they'll all be played in sequence. As one Tween completes it passes on to the next until the entire chain is finished. Tween.stop has a new `complete` parameter that if set will still fire the onComplete event and start the next chained tween, if there is one. Tween.delay, Tween.repeat, Tween.yoyo, Tween.easing and Tween.interpolation all have a new `index` parameter. This allows you to target specific child tweens, or if set to -1 it will update all children at once. Tween.totalDuration reports the total duration of all child tweens in ms. There are new easing aliases: * Phaser.Easing.Power0 = Phaser.Easing.Linear.None * Phaser.Easing.Power1 = Phaser.Easing.Quadratic.Out * Phaser.Easing.Power2 = Phaser.Easing.Cubic.Out * Phaser.Easing.Power3 = Phaser.Easing.Quartic.Out * Phaser.Easing.Power4 = Phaser.Easing.Quintic.Out
2014-11-20 06:04:54 +00:00
from: function (properties, duration, ease, autoStart, delay, repeat, yoyo) {
2014-07-07 10:07:00 +00:00
if (duration === undefined) { duration = 1000; }
if (ease === undefined || ease === null) { ease = Phaser.Easing.Default; }
if (autoStart === undefined) { autoStart = false; }
if (delay === undefined) { delay = 0; }
if (repeat === undefined) { repeat = 0; }
if (yoyo === undefined) { yoyo = false; }
2014-07-07 10:07:00 +00:00
if (typeof ease === 'string' && this.manager.easeMap[ease])
2014-07-07 10:07:00 +00:00
{
ease = this.manager.easeMap[ease];
}
2014-07-07 10:07:00 +00:00
if (this.isRunning)
{
console.warn('Phaser.Tween.from cannot be called after Tween.start');
return this;
}
this.timeline.push(new Phaser.TweenData(this).from(properties, duration, ease, delay, repeat, yoyo));
2013-08-28 23:09:12 +00:00
2014-11-18 20:58:25 +00:00
if (autoStart)
{
this.start();
}
2013-08-28 23:09:12 +00:00
return this;
},
2013-08-28 23:09:12 +00:00
/**
* Starts the tween running. Can also be called by the autoStart parameter of `Tween.to` or `Tween.from`.
* This sets the `Tween.isRunning` property to `true` and dispatches a `Tween.onStart` signal.
* If the Tween has a delay set then nothing will start tweening until the delay has expired.
*
2014-11-18 20:58:25 +00:00
* @method Phaser.Tween#start
* @param {number} [index=0] - If this Tween contains child tweens you can specify which one to start from. The default is zero, i.e. the first tween created.
2014-11-18 20:58:25 +00:00
* @return {Phaser.Tween} This tween. Useful for method chaining.
*/
2014-11-18 20:58:25 +00:00
start: function (index) {
if (index === undefined) { index = 0; }
if (this.target === null || this.timeline.length === 0 || this.isRunning)
{
2014-11-18 20:58:25 +00:00
return this;
}
// Populate the tween data
for (var i = 0; i < this.timeline.length; i++)
{
// Build our master property list with the starting values
for (var property in this.timeline[i].vEnd)
{
this.properties[property] = this.target[property] || 0;
if (!Array.isArray(this.properties[property]))
{
// Ensures we're using numbers, not strings
this.properties[property] *= 1.0;
}
}
}
for (var i = 0; i < this.timeline.length; i++)
{
this.timeline[i].loadValues();
}
2014-11-18 20:58:25 +00:00
this.manager.add(this);
2014-11-18 20:58:25 +00:00
this.isRunning = true;
2014-11-18 20:58:25 +00:00
if (index < 0 || index > this.timeline.length - 1)
{
2014-11-18 20:58:25 +00:00
index = 0;
}
2014-11-18 20:58:25 +00:00
this.current = index;
2014-11-18 20:58:25 +00:00
this.timeline[this.current].start();
2014-11-18 20:58:25 +00:00
return this;
},
/**
* Stops the tween if running and flags it for deletion from the TweenManager.
Tweens have been completely rewritten. They're now much more flexible and efficient than before: When specifying the ease in `Tween.to` or `Tween.from` you can now use a string instead of the Function. This makes your code less verbose. For example instead of `Phaser.Easing.Sinusoidal.Out` and you can now just use the string "Sine".The string names match those used by TweenMax and includes: "Linear", "Quad", "Cubic", "Quart", "Quint", "Sine", "Expo", "Circ", "Elastic", "Back", "Bounce", "Power0", "Power1", "Power2", "Power3" and "Power4". You can append ".easeIn", ".easeOut" and "easeInOut" variants. All are supported for each ease types. Tweens now create a TweenData object. The Tween object itself acts like more of a timeline, managing multiple TweenData objects. You can now call `Tween.to` and each call will create a new child tween that is added to the timeline, which are played through in sequence. Tweens are now bound to the new Time.desiredFps value and update based on the new Game core loop, rather than being bound to time calculations. This means that tweens are now running with the same update logic as physics and the core loop. Tween.timeScale allows you to scale the duration of a tween (and any child tweens it may have). A value of 1.0 means it should play at the desiredFps rate. A value of 0.5 will run at half the frame rate, 2 at double and so on. You can even tween the timeScale value for interesting effects! Tween.reverse allows you to instantly reverse an active tween. If the Tween has children then it will smoothly reverse through all child tweens as well. Tween.repeatAll allows you to control how many times all child tweens will repeat before firing the Tween.onComplete event. You can set the value to -1 to repeat forever. Tween.loop now controls the looping of all child tweens. Tween.onRepeat is a new signal that is dispatched whenever a Tween repeats. If a Tween has many child tweens its dispatched once the sequence has repeated. Tween.onChildComplete is a new signal that is dispatched whenever any child tweens have completed. If a Tween consists of 4 sections you will get 3 onChildComplete events followed by 1 onComplete event as the final tween finishes. Chained tweens are now more intelligently handled. Because you can easily create child tweens (by simply calling Tween.to multiple times) chained tweens are now used to kick-off longer sequences. You can pass as many Tween objects to `Tween.chain` as you like as they'll all be played in sequence. As one Tween completes it passes on to the next until the entire chain is finished. Tween.stop has a new `complete` parameter that if set will still fire the onComplete event and start the next chained tween, if there is one. Tween.delay, Tween.repeat, Tween.yoyo, Tween.easing and Tween.interpolation all have a new `index` parameter. This allows you to target specific child tweens, or if set to -1 it will update all children at once. Tween.totalDuration reports the total duration of all child tweens in ms. There are new easing aliases: * Phaser.Easing.Power0 = Phaser.Easing.Linear.None * Phaser.Easing.Power1 = Phaser.Easing.Quadratic.Out * Phaser.Easing.Power2 = Phaser.Easing.Cubic.Out * Phaser.Easing.Power3 = Phaser.Easing.Quartic.Out * Phaser.Easing.Power4 = Phaser.Easing.Quintic.Out
2014-11-20 06:04:54 +00:00
* If called directly the `Tween.onComplete` signal is not dispatched and no chained tweens are started unless the complete parameter is set to `true`.
* If you just wish to pause a tween then use Tween.pause instead.
*
* @method Phaser.Tween#stop
* @param {boolean} [complete=false] - Set to `true` to dispatch the Tween.onComplete signal.
* @return {Phaser.Tween} This tween. Useful for method chaining.
*/
stop: function (complete) {
if (complete === undefined) { complete = false; }
2013-08-28 23:09:12 +00:00
this.isRunning = false;
this._onUpdateCallback = null;
this._onUpdateCallbackContext = null;
if (complete)
{
this.onComplete.dispatch(this.target, this);
this._hasStarted = false;
Tweens have been completely rewritten. They're now much more flexible and efficient than before: When specifying the ease in `Tween.to` or `Tween.from` you can now use a string instead of the Function. This makes your code less verbose. For example instead of `Phaser.Easing.Sinusoidal.Out` and you can now just use the string "Sine".The string names match those used by TweenMax and includes: "Linear", "Quad", "Cubic", "Quart", "Quint", "Sine", "Expo", "Circ", "Elastic", "Back", "Bounce", "Power0", "Power1", "Power2", "Power3" and "Power4". You can append ".easeIn", ".easeOut" and "easeInOut" variants. All are supported for each ease types. Tweens now create a TweenData object. The Tween object itself acts like more of a timeline, managing multiple TweenData objects. You can now call `Tween.to` and each call will create a new child tween that is added to the timeline, which are played through in sequence. Tweens are now bound to the new Time.desiredFps value and update based on the new Game core loop, rather than being bound to time calculations. This means that tweens are now running with the same update logic as physics and the core loop. Tween.timeScale allows you to scale the duration of a tween (and any child tweens it may have). A value of 1.0 means it should play at the desiredFps rate. A value of 0.5 will run at half the frame rate, 2 at double and so on. You can even tween the timeScale value for interesting effects! Tween.reverse allows you to instantly reverse an active tween. If the Tween has children then it will smoothly reverse through all child tweens as well. Tween.repeatAll allows you to control how many times all child tweens will repeat before firing the Tween.onComplete event. You can set the value to -1 to repeat forever. Tween.loop now controls the looping of all child tweens. Tween.onRepeat is a new signal that is dispatched whenever a Tween repeats. If a Tween has many child tweens its dispatched once the sequence has repeated. Tween.onChildComplete is a new signal that is dispatched whenever any child tweens have completed. If a Tween consists of 4 sections you will get 3 onChildComplete events followed by 1 onComplete event as the final tween finishes. Chained tweens are now more intelligently handled. Because you can easily create child tweens (by simply calling Tween.to multiple times) chained tweens are now used to kick-off longer sequences. You can pass as many Tween objects to `Tween.chain` as you like as they'll all be played in sequence. As one Tween completes it passes on to the next until the entire chain is finished. Tween.stop has a new `complete` parameter that if set will still fire the onComplete event and start the next chained tween, if there is one. Tween.delay, Tween.repeat, Tween.yoyo, Tween.easing and Tween.interpolation all have a new `index` parameter. This allows you to target specific child tweens, or if set to -1 it will update all children at once. Tween.totalDuration reports the total duration of all child tweens in ms. There are new easing aliases: * Phaser.Easing.Power0 = Phaser.Easing.Linear.None * Phaser.Easing.Power1 = Phaser.Easing.Quadratic.Out * Phaser.Easing.Power2 = Phaser.Easing.Cubic.Out * Phaser.Easing.Power3 = Phaser.Easing.Quartic.Out * Phaser.Easing.Power4 = Phaser.Easing.Quintic.Out
2014-11-20 06:04:54 +00:00
if (this.chainedTween)
{
this.chainedTween.start();
}
}
2014-11-18 20:58:25 +00:00
this.manager.remove(this);
return this;
},
/**
* Updates either a single TweenData or all TweenData objects properties to the given value.
* Used internally by methods like Tween.delay, Tween.yoyo, etc. but can also be called directly if you know which property you want to tweak.
* The property is not checked, so if you pass an invalid one you'll generate a run-time error.
*
* @method Phaser.Tween#updateTweenData
* @param {string} property - The property to update.
* @param {number|function} value - The value to set the property to.
* @param {number} [index=0] - If this tween has more than one child this allows you to target a specific child. If set to -1 it will set the delay on all the children.
* @return {Phaser.Tween} This tween. Useful for method chaining.
*/
updateTweenData: function (property, value, index) {
if (this.timeline.length === 0) { return this; }
if (index === undefined) { index = 0; }
if (index === -1)
{
for (var i = 0; i < this.timeline.length; i++)
{
this.timeline[i][property] = value;
}
}
else
{
this.timeline[index][property] = value;
}
return this;
},
/**
* Sets the delay in milliseconds before this tween will start. If there are child tweens it sets the delay before the first child starts.
* The delay is invoked as soon as you call `Tween.start`. If the tween is already running this method doesn't do anything for the current active tween.
* If you have not yet called `Tween.to` or `Tween.from` at least once then this method will do nothing, as there are no tweens to delay.
* If you have child tweens and pass -1 as the index value it sets the delay across all of them.
*
* @method Phaser.Tween#delay
* @param {number} duration - The amount of time in ms that the Tween should wait until it begins once started is called. Set to zero to remove any active delay.
* @param {number} [index=0] - If this tween has more than one child this allows you to target a specific child. If set to -1 it will set the delay on all the children.
* @return {Phaser.Tween} This tween. Useful for method chaining.
*/
delay: function (duration, index) {
return this.updateTweenData('delay', duration, index);
},
/**
* Sets the number of times this tween will repeat.
* If you have not yet called `Tween.to` or `Tween.from` at least once then this method will do nothing, as there are no tweens to repeat.
* If you have child tweens and pass -1 as the index value it sets the number of times they'll repeat across all of them.
* If you wish to define how many times this Tween and all children will repeat see Tween.repeatAll.
*
* @method Phaser.Tween#repeat
* @param {number} total - How many times a tween should repeat before completing. Set to zero to remove an active repeat. Set to -1 to repeat forever.
* @param {number} [repeat=0] - This is the amount of time to pause (in ms) before the repeat will start.
* @param {number} [index=0] - If this tween has more than one child this allows you to target a specific child. If set to -1 it will set the repeat value on all the children.
* @return {Phaser.Tween} This tween. Useful for method chaining.
*/
repeat: function (total, repeatDelay, index) {
if (repeatDelay === undefined) { repeatDelay = 0; }
this.updateTweenData('repeatCounter', total, index);
return this.updateTweenData('repeatDelay', repeatDelay, index);
},
/**
* Sets the delay in milliseconds before this tween will repeat itself.
* The repeatDelay is invoked as soon as you call `Tween.start`. If the tween is already running this method doesn't do anything for the current active tween.
* If you have not yet called `Tween.to` or `Tween.from` at least once then this method will do nothing, as there are no tweens to set repeatDelay on.
* If you have child tweens and pass -1 as the index value it sets the repeatDelay across all of them.
*
* @method Phaser.Tween#repeatDelay
* @param {number} duration - The amount of time in ms that the Tween should wait until it repeats or yoyos once start is called. Set to zero to remove any active repeatDelay.
* @param {number} [index=0] - If this tween has more than one child this allows you to target a specific child. If set to -1 it will set the repeatDelay on all the children.
* @return {Phaser.Tween} This tween. Useful for method chaining.
*/
repeatDelay: function (duration, index) {
return this.updateTweenData('repeatDelay', duration, index);
},
/**
2014-11-18 20:58:25 +00:00
* A Tween that has yoyo set to true will run through from its starting values to its end values and then play back in reverse from end to start.
* Used in combination with repeat you can create endless loops.
* If you have not yet called `Tween.to` or `Tween.from` at least once then this method will do nothing, as there are no tweens to yoyo.
* If you have child tweens and pass -1 as the index value it sets the yoyo property across all of them.
* If you wish to yoyo this Tween and all of its children then see Tween.yoyoAll.
*
* @method Phaser.Tween#yoyo
* @param {boolean} enable - Set to true to yoyo this tween, or false to disable an already active yoyo.
* @param {number} [yoyoDelay=0] - This is the amount of time to pause (in ms) before the yoyo will start.
* @param {number} [index=0] - If this tween has more than one child this allows you to target a specific child. If set to -1 it will set yoyo on all the children.
* @return {Phaser.Tween} This tween. Useful for method chaining.
*/
yoyo: function(enable, yoyoDelay, index) {
if (yoyoDelay === undefined) { yoyoDelay = 0; }
this.updateTweenData('yoyo', enable, index);
return this.updateTweenData('yoyoDelay', yoyoDelay, index);
},
/**
* Sets the delay in milliseconds before this tween will run a yoyo (only applies if yoyo is enabled).
* The repeatDelay is invoked as soon as you call `Tween.start`. If the tween is already running this method doesn't do anything for the current active tween.
* If you have not yet called `Tween.to` or `Tween.from` at least once then this method will do nothing, as there are no tweens to set repeatDelay on.
* If you have child tweens and pass -1 as the index value it sets the repeatDelay across all of them.
*
* @method Phaser.Tween#yoyoDelay
* @param {number} duration - The amount of time in ms that the Tween should wait until it repeats or yoyos once start is called. Set to zero to remove any active yoyoDelay.
* @param {number} [index=0] - If this tween has more than one child this allows you to target a specific child. If set to -1 it will set the yoyoDelay on all the children.
* @return {Phaser.Tween} This tween. Useful for method chaining.
*/
yoyoDelay: function (duration, index) {
return this.updateTweenData('yoyoDelay', duration, index);
},
/**
2014-03-23 07:59:28 +00:00
* Set easing function this tween will use, i.e. Phaser.Easing.Linear.None.
* The ease function allows you define the rate of change. You can pass either a function such as Phaser.Easing.Circular.Out or a string such as "Circ".
* ".easeIn", ".easeOut" and "easeInOut" variants are all supported for all ease types.
* If you have child tweens and pass -1 as the index value it sets the easing function defined here across all of them.
*
* @method Phaser.Tween#easing
* @param {function|string} ease - The easing function this tween will use, i.e. Phaser.Easing.Linear.None.
* @param {number} [index=0] - If this tween has more than one child this allows you to target a specific child. If set to -1 it will set the easing function on all children.
* @return {Phaser.Tween} This tween. Useful for method chaining.
*/
easing: function (ease, index) {
if (typeof ease === 'string' && this.manager.easeMap[ease])
{
ease = this.manager.easeMap[ease];
}
return this.updateTweenData('easingFunction', ease, index);
},
/**
* Sets the interpolation function the tween will use. By default it uses Phaser.Math.linearInterpolation.
* Also available: Phaser.Math.bezierInterpolation and Phaser.Math.catmullRomInterpolation.
* The interpolation function is only used if the target properties is an array.
* If you have child tweens and pass -1 as the index value and it will set the interpolation function across all of them.
*
* @method Phaser.Tween#interpolation
* @param {function} interpolation - The interpolation function to use (Phaser.Math.linearInterpolation by default)
* @param {object} [context] - The context under which the interpolation function will be run.
* @param {number} [index=0] - If this tween has more than one child this allows you to target a specific child. If set to -1 it will set the interpolation function on all children.
* @return {Phaser.Tween} This tween. Useful for method chaining.
*/
interpolation: function (interpolation, context, index) {
if (context === undefined) { context = Phaser.Math; }
this.updateTweenData('interpolationFunction', interpolation, index);
return this.updateTweenData('interpolationContext', context, index);
},
/**
* Set how many times this tween and all of its children will repeat.
* A tween (A) with 3 children (B,C,D) with a `repeatAll` value of 2 would play as: ABCDABCD before completing.
*
* @method Phaser.Tween#repeatAll
* @param {number} [total=0] - How many times this tween and all children should repeat before completing. Set to zero to remove an active repeat. Set to -1 to repeat forever.
* @return {Phaser.Tween} This tween. Useful for method chaining.
*/
repeatAll: function (total) {
if (total === undefined) { total = 0; }
this.repeatCounter = total;
return this;
},
/**
* This method allows you to chain tweens together. Any tween chained to this tween will have its `Tween.start` method called
* as soon as this tween completes. If this tween never completes (i.e. repeatAll or loop is set) then the chain will never progress.
* Note that `Tween.onComplete` will fire when *this* tween completes, not when the whole chain completes.
* For that you should listen to `onComplete` on the final tween in your chain.
2015-05-09 00:42:29 +00:00
*
* If you pass multiple tweens to this method they will be joined into a single long chain.
* For example if this is Tween A and you pass in B, C and D then B will be chained to A, C will be chained to B and D will be chained to C.
* Any previously chained tweens that may have been set will be overwritten.
*
* @method Phaser.Tween#chain
* @param {...Phaser.Tween} tweens - One or more tweens that will be chained to this one.
* @return {Phaser.Tween} This tween. Useful for method chaining.
*/
chain: function () {
var i = arguments.length;
while (i--)
{
if (i > 0)
{
arguments[i - 1].chainedTween = arguments[i];
}
else
{
this.chainedTween = arguments[i];
}
}
return this;
},
/**
* Enables the looping of this tween. The tween will loop forever, and onComplete will never fire.
*
* If `value` is `true` then this is the same as setting `Tween.repeatAll(-1)`.
* If `value` is `false` it is the same as setting `Tween.repeatAll(0)` and will reset the `repeatCounter` to zero.
2014-03-23 07:59:28 +00:00
*
* Usage:
* game.add.tween(p).to({ x: 700 }, 1000, Phaser.Easing.Linear.None, true)
* .to({ y: 300 }, 1000, Phaser.Easing.Linear.None)
* .to({ x: 0 }, 1000, Phaser.Easing.Linear.None)
* .to({ y: 0 }, 1000, Phaser.Easing.Linear.None)
* .loop();
* @method Phaser.Tween#loop
* @param {boolean} [value=true] - If `true` this tween will loop once it reaches the end. Set to `false` to remove an active loop.
* @return {Phaser.Tween} This tween. Useful for method chaining.
*/
loop: function (value) {
2014-11-18 20:58:25 +00:00
if (value === undefined) { value = true; }
2014-11-18 20:58:25 +00:00
this.repeatCounter = (value) ? -1 : 0;
return this;
},
/**
* Sets a callback to be fired each time this tween updates.
*
* @method Phaser.Tween#onUpdateCallback
* @param {function} callback - The callback to invoke each time this tween is updated. Set to `null` to remove an already active callback.
* @param {object} callbackContext - The context in which to call the onUpdate callback.
* @return {Phaser.Tween} This tween. Useful for method chaining.
*/
onUpdateCallback: function (callback, callbackContext) {
this._onUpdateCallback = callback;
this._onUpdateCallbackContext = callbackContext;
return this;
},
/**
* Pauses the tween. Resume playback with Tween.resume.
*
* @method Phaser.Tween#pause
*/
pause: function ()
{
this.isPaused = true;
this._codePaused = true;
this._pausedTime = this.game.time.time;
},
/**
* This is called by the core Game loop. Do not call it directly, instead use Tween.pause.
2015-05-09 00:42:29 +00:00
*
* @private
* @method Phaser.Tween#_pause
*/
_pause: function ()
{
if (!this._codePaused)
{
this.isPaused = true;
this._pausedTime = this.game.time.time;
}
},
/**
* Resumes a paused tween.
*
* @method Phaser.Tween#resume
*/
resume: function ()
{
if (this.isPaused)
{
this.isPaused = false;
this._codePaused = false;
for (var i = 0; i < this.timeline.length; i++)
{
if (!this.timeline[i].isRunning)
{
this.timeline[i].startTime += (this.game.time.time - this._pausedTime);
}
}
}
},
/**
* This is called by the core Game loop. Do not call it directly, instead use Tween.pause.
* @method Phaser.Tween#_resume
* @private
*/
_resume: function () {
if (this._codePaused)
{
return;
}
else
{
this.resume();
}
},
2013-08-28 23:09:12 +00:00
/**
* Core tween update function called by the TweenManager. Does not need to be invoked directly.
*
* @method Phaser.Tween#update
* @param {number} time - A timestamp passed in by the TweenManager.
* @return {boolean} false if the tween and all child tweens have completed and should be deleted from the manager, otherwise true (still active).
*/
2016-11-09 12:25:26 +00:00
update: function (frameDelta) {
2013-08-28 23:09:12 +00:00
if (this.pendingDelete || !this.target)
{
return false;
}
if (this.isPaused)
{
2013-08-28 23:09:12 +00:00
return true;
}
2016-11-09 12:25:26 +00:00
var status = this.timeline[this.current].update(frameDelta);
2013-08-28 23:09:12 +00:00
2014-11-18 20:58:25 +00:00
if (status === Phaser.TweenData.PENDING)
{
2014-11-18 20:58:25 +00:00
return true;
}
else if (status === Phaser.TweenData.RUNNING)
{
if (!this._hasStarted)
{
this.onStart.dispatch(this.target, this);
this._hasStarted = true;
}
2014-11-18 20:58:25 +00:00
if (this._onUpdateCallback !== null)
{
this._onUpdateCallback.call(this._onUpdateCallbackContext, this, this.timeline[this.current].value, this.timeline[this.current]);
}
2013-08-28 23:09:12 +00:00
2014-11-18 20:58:25 +00:00
// In case the update callback modifies this tween
return this.isRunning;
}
else if (status === Phaser.TweenData.LOOPED)
{
if (this.timeline[this.current].repeatCounter === -1)
{
this.onLoop.dispatch(this.target, this);
}
else
{
this.onRepeat.dispatch(this.target, this);
}
2014-11-18 20:58:25 +00:00
return true;
}
else if (status === Phaser.TweenData.COMPLETE)
{
2014-11-20 02:17:41 +00:00
var complete = false;
// What now?
if (this.reverse)
{
this.current--;
2014-11-20 02:17:41 +00:00
if (this.current < 0)
{
this.current = this.timeline.length - 1;
complete = true;
}
}
else
{
2014-11-18 20:58:25 +00:00
this.current++;
2014-11-20 02:17:41 +00:00
if (this.current === this.timeline.length)
{
this.current = 0;
complete = true;
}
}
2014-11-20 02:17:41 +00:00
if (complete)
{
2014-11-20 02:17:41 +00:00
// We've reached the start or end of the child tweens (depending on Tween.reverse), should we repeat it?
if (this.repeatCounter === -1)
{
2014-11-20 02:17:41 +00:00
this.timeline[this.current].start();
this.onLoop.dispatch(this.target, this);
2014-11-20 02:17:41 +00:00
return true;
}
2014-11-20 02:17:41 +00:00
else if (this.repeatCounter > 0)
{
2014-11-20 02:17:41 +00:00
this.repeatCounter--;
this.timeline[this.current].start();
this.onRepeat.dispatch(this.target, this);
return true;
}
2014-11-20 02:17:41 +00:00
else
{
2014-11-20 02:17:41 +00:00
// No more repeats and no more children, so we're done
this.isRunning = false;
this.onComplete.dispatch(this.target, this);
this._hasStarted = false;
if (this.chainedTween)
{
this.chainedTween.start();
}
2014-11-20 02:17:41 +00:00
return false;
}
}
else
{
2014-11-20 02:17:41 +00:00
// We've still got some children to go
this.onChildComplete.dispatch(this.target, this);
this.timeline[this.current].start();
return true;
2014-11-18 20:58:25 +00:00
}
}
},
2013-08-28 23:09:12 +00:00
2014-11-18 20:58:25 +00:00
/**
* This will generate an array populated with the tweened object values from start to end.
* It works by running the tween simulation at the given frame rate based on the values set-up in Tween.to and Tween.from.
* It ignores delay and repeat counts and any chained tweens, but does include child tweens.
* Just one play through of the tween data is returned, including yoyo if set.
2014-11-18 20:58:25 +00:00
*
* @method Phaser.Tween#generateData
* @param {number} [frameRate=60] - The speed in frames per second that the data should be generated at. The higher the value, the larger the array it creates.
* @param {array} [data] - If given the generated data will be appended to this array, otherwise a new array will be returned.
* @return {array} An array of tweened values.
*/
2014-11-18 20:58:25 +00:00
generateData: function (frameRate, data) {
if (this.target === null)
2014-11-18 20:58:25 +00:00
{
return null;
}
if (frameRate === undefined) { frameRate = 60; }
if (data === undefined) { data = []; }
2014-11-18 20:58:25 +00:00
// Populate the tween data
for (var i = 0; i < this.timeline.length; i++)
{
// Build our master property list with the starting values
for (var property in this.timeline[i].vEnd)
{
this.properties[property] = this.target[property] || 0;
2014-11-18 20:58:25 +00:00
if (!Array.isArray(this.properties[property]))
{
// Ensures we're using numbers, not strings
this.properties[property] *= 1.0;
}
2014-11-18 20:58:25 +00:00
}
}
for (var i = 0; i < this.timeline.length; i++)
2014-11-18 20:58:25 +00:00
{
this.timeline[i].loadValues();
2014-11-18 20:58:25 +00:00
}
2013-08-28 23:09:12 +00:00
for (var i = 0; i < this.timeline.length; i++)
2014-11-18 20:58:25 +00:00
{
data = data.concat(this.timeline[i].generateData(frameRate));
}
2013-08-28 23:09:12 +00:00
return data;
2013-08-28 23:09:12 +00:00
}
2014-03-23 07:59:28 +00:00
2013-08-28 23:09:12 +00:00
};
/**
* @name Phaser.Tween#totalDuration
* @property {Phaser.TweenData} totalDuration - Gets the total duration of this Tween, including all child tweens, in milliseconds.
*/
Object.defineProperty(Phaser.Tween.prototype, 'totalDuration', {
get: function () {
var total = 0;
for (var i = 0; i < this.timeline.length; i++)
{
total += this.timeline[i].duration;
}
return total;
}
});
Phaser.Tween.prototype.constructor = Phaser.Tween;