Skip to content

Commit 837d3cb

Browse files
committed
Merge pull request phaserjs#2505 from gotenxds/ReverseAnimation
Added a reverse functionality to animations.
2 parents f67d304 + 7fc34c1 commit 837d3cb

4 files changed

Lines changed: 2770 additions & 2682 deletions

File tree

src/animation/Animation.js

Lines changed: 69 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
/**
88
* An Animation instance contains a single animation and the controls to play it.
9-
*
9+
*
1010
* It is created by the AnimationManager, consists of Animation.Frame objects and belongs to a single Game Object such as a Sprite.
1111
*
1212
* @class Phaser.Animation
@@ -130,10 +130,10 @@ Phaser.Animation = function (game, parent, name, frameData, frames, frameRate, l
130130
this.onStart = new Phaser.Signal();
131131

132132
/**
133-
* This event is dispatched when the Animation changes frame.
133+
* This event is dispatched when the Animation changes frame.
134134
* By default this event is disabled due to its intensive nature. Enable it with: `Animation.enableUpdate = true`.
135135
* Note that the event is only dispatched with the current frame. In a low-FPS environment Animations
136-
* will automatically frame-skip to try and claw back time, so do not base your code on expecting to
136+
* will automatically frame-skip to try and claw back time, so do not base your code on expecting to
137137
* receive a perfectly sequential set of frames from this event.
138138
* @property {Phaser.Signal|null} onUpdate
139139
* @default
@@ -150,6 +150,12 @@ Phaser.Animation = function (game, parent, name, frameData, frames, frameRate, l
150150
*/
151151
this.onLoop = new Phaser.Signal();
152152

153+
/**
154+
* @property {boolean} isReversed - Indicates if the animation will play backwards.
155+
* @default
156+
*/
157+
this.isReversed = false;
158+
153159
// Set-up some event listeners
154160
this.game.onPause.add(this.onPause, this);
155161
this.game.onResume.add(this.onResume, this);
@@ -195,7 +201,7 @@ Phaser.Animation.prototype = {
195201
this._timeLastFrame = this.game.time.time;
196202
this._timeNextFrame = this.game.time.time + this.delay;
197203

198-
this._frameIndex = 0;
204+
this._frameIndex = this.isReversed ? this._frames.length - 1 : 0;
199205
this.updateCurrentFrame(false, true);
200206

201207
this._parent.events.onAnimationStart$dispatch(this._parent, this);
@@ -237,6 +243,32 @@ Phaser.Animation.prototype = {
237243

238244
},
239245

246+
/**
247+
* Reverses the animation direction
248+
*
249+
* @method Phaser.Animation#reverse
250+
* @return {Phaser.Animation} The animation instance.
251+
* */
252+
reverse: function () {
253+
this.reversed = !this.reversed;
254+
255+
return this;
256+
},
257+
258+
/**
259+
* Reverses the animation direction for the current/next animation only
260+
* Once the onComplete event is called this method will be called again and revert
261+
* the reversed state.
262+
*
263+
* @method Phaser.Animation#reverseOnce
264+
* @return {Phaser.Animation} The animation instance.
265+
* */
266+
reverseOnce: function () {
267+
this.onComplete.addOnce(this.reverse.bind(this));
268+
269+
return this.reverse();
270+
},
271+
240272
/**
241273
* Sets this animations playback to a given frame with the given ID.
242274
*
@@ -385,14 +417,23 @@ Phaser.Animation.prototype = {
385417
// And what's left now?
386418
this._timeNextFrame = this.game.time.time + (this.delay - this._frameDiff);
387419

388-
this._frameIndex += this._frameSkip;
420+
if (this.isReversed){
421+
this._frameIndex -= this._frameSkip;
422+
}else{
423+
this._frameIndex += this._frameSkip;
424+
}
389425

390-
if (this._frameIndex >= this._frames.length)
426+
if (!this.isReversed && this._frameIndex >= this._frames.length || this.isReversed && this._frameIndex <= -1)
391427
{
392428
if (this.loop)
393429
{
394430
// Update current state before event callback
395-
this._frameIndex %= this._frames.length;
431+
this._frameIndex = Math.abs(this._frameIndex) % this._frames.length;
432+
433+
if (this.isReversed){
434+
this._frameIndex = this._frames.length - 1 - this._frameIndex;
435+
}
436+
396437
this.currentFrame = this._frameData.getFrame(this._frames[this._frameIndex]);
397438

398439
// Instead of calling updateCurrentFrame we do it here instead
@@ -454,7 +495,7 @@ Phaser.Animation.prototype = {
454495
// The animation is already destroyed, probably from a callback
455496
return false;
456497
}
457-
498+
458499
// Previous index
459500
var idx = this.currentFrame.index;
460501

@@ -654,6 +695,26 @@ Object.defineProperty(Phaser.Animation.prototype, 'paused', {
654695

655696
});
656697

698+
/**
699+
* @name Phaser.Animation#reversed
700+
* @property {boolean} reversed - Gets and sets the isReversed state of this Animation.
701+
*/
702+
Object.defineProperty(Phaser.Animation.prototype, 'reversed', {
703+
704+
get: function () {
705+
706+
return this.isReversed;
707+
708+
},
709+
710+
set: function (value) {
711+
712+
this.isReversed = value;
713+
714+
}
715+
716+
});
717+
657718
/**
658719
* @name Phaser.Animation#frameTotal
659720
* @property {number} frameTotal - The total number of frames in the currently loaded FrameData, or -1 if no FrameData is loaded.

src/geom/Line.js

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
/**
88
* Creates a new Line object with a start and an end point.
9-
*
9+
*
1010
* @class Phaser.Line
1111
* @constructor
1212
* @param {number} [x1=0] - The x coordinate of the start of the line.
@@ -43,7 +43,7 @@ Phaser.Line.prototype = {
4343

4444
/**
4545
* Sets the components of the Line to the specified values.
46-
*
46+
*
4747
* @method Phaser.Line#setTo
4848
* @param {number} [x1=0] - The x coordinate of the start of the line.
4949
* @param {number} [y1=0] - The y coordinate of the start of the line.
@@ -63,7 +63,7 @@ Phaser.Line.prototype = {
6363
/**
6464
* Sets the line to match the x/y coordinates of the two given sprites.
6565
* Can optionally be calculated from their center coordinates.
66-
*
66+
*
6767
* @method Phaser.Line#fromSprite
6868
* @param {Phaser.Sprite} startSprite - The coordinates of this Sprite will be set to the Line.start point.
6969
* @param {Phaser.Sprite} endSprite - The coordinates of this Sprite will be set to the Line.start point.
@@ -85,7 +85,7 @@ Phaser.Line.prototype = {
8585

8686
/**
8787
* Sets this line to start at the given `x` and `y` coordinates and for the segment to extend at `angle` for the given `length`.
88-
*
88+
*
8989
* @method Phaser.Line#fromAngle
9090
* @param {number} x - The x coordinate of the start of the line.
9191
* @param {number} y - The y coordinate of the start of the line.
@@ -104,12 +104,12 @@ Phaser.Line.prototype = {
104104

105105
/**
106106
* Rotates the line by the amount specified in `angle`.
107-
*
107+
*
108108
* Rotation takes place from the center of the line.
109109
* If you wish to rotate around a different point see Line.rotateAround.
110-
*
110+
*
111111
* If you wish to rotate the ends of the Line then see Line.start.rotate or Line.end.rotate.
112-
*
112+
*
113113
* @method Phaser.Line#rotate
114114
* @param {number} angle - The angle in radians (unless asDegrees is true) to rotate the line by.
115115
* @param {boolean} [asDegrees=false] - Is the given angle in radians (false) or degrees (true)?
@@ -129,9 +129,9 @@ Phaser.Line.prototype = {
129129

130130
/**
131131
* Rotates the line by the amount specified in `angle`.
132-
*
132+
*
133133
* Rotation takes place around the coordinates given.
134-
*
134+
*
135135
* @method Phaser.Line#rotateAround
136136
* @param {number} x - The x coordinate to offset the rotation from.
137137
* @param {number} y - The y coordinate to offset the rotation from.
@@ -181,7 +181,7 @@ Phaser.Line.prototype = {
181181

182182
/**
183183
* Returns a Point object where the x and y values correspond to the center (or midpoint) of the Line segment.
184-
*
184+
*
185185
* @method Phaser.Line#midPoint
186186
* @param {Phaser.Point} [out] - A Phaser.Point object into which the result will be populated. If not given a new Point object is created.
187187
* @return {Phaser.Point} A Phaser.Point object with the x and y values set to the center of the line segment.
@@ -199,10 +199,10 @@ Phaser.Line.prototype = {
199199

200200
/**
201201
* Centers this Line on the given coordinates.
202-
*
202+
*
203203
* The line is centered by positioning the start and end points so that the lines midpoint matches
204204
* the coordinates given.
205-
*
205+
*
206206
* @method Phaser.Line#centerOn
207207
* @param {number} x - The x position to center the line on.
208208
* @param {number} y - The y position to center the line on.
@@ -223,7 +223,7 @@ Phaser.Line.prototype = {
223223

224224
/**
225225
* Tests if the given coordinates fall on this line. See pointOnSegment to test against just the line segment.
226-
*
226+
*
227227
* @method Phaser.Line#pointOnLine
228228
* @param {number} x - The line to check against this one.
229229
* @param {number} y - The line to check against this one.
@@ -237,7 +237,7 @@ Phaser.Line.prototype = {
237237

238238
/**
239239
* Tests if the given coordinates fall on this line and within the segment. See pointOnLine to test against just the line.
240-
*
240+
*
241241
* @method Phaser.Line#pointOnSegment
242242
* @param {number} x - The line to check against this one.
243243
* @param {number} y - The line to check against this one.
@@ -256,7 +256,7 @@ Phaser.Line.prototype = {
256256

257257
/**
258258
* Picks a random point from anywhere on the Line segment and returns it.
259-
*
259+
*
260260
* @method Phaser.Line#random
261261
* @param {Phaser.Point|object} [out] - A Phaser.Point, or any object with public x/y properties, that the values will be set in.
262262
* If no object is provided a new Phaser.Point object will be created. In high performance areas avoid this by re-using an object.
@@ -630,12 +630,12 @@ Phaser.Line.intersects = function (a, b, asSegment, result) {
630630
/**
631631
* Checks for intersection between the Line and a Rectangle shape, or a rectangle-like
632632
* object, with public `x`, `y`, `right` and `bottom` properties, such as a Sprite or Body.
633-
*
633+
*
634634
* An intersection is considered valid if:
635-
*
635+
*
636636
* The line starts within, or ends within, the Rectangle.
637637
* The line segment intersects one of the 4 rectangle edges.
638-
*
638+
*
639639
* The for the purposes of this function rectangles are considered 'solid'.
640640
*
641641
* @method intersectsRectangle
@@ -667,7 +667,7 @@ Phaser.Line.intersectsRectangle = function (line, rect) {
667667
// If the start or end of the line is inside the rect then we assume
668668
// collision, as rects are solid for our use-case.
669669

670-
if ((x1 >= bx1 && x1 <= bx2 && y1 >= by1 && y1 <= by2) ||
670+
if ((x1 >= bx1 && x1 <= bx2 && y1 >= by1 && y1 <= by2) ||
671671
(x2 >= bx1 && x2 <= bx2 && y2 >= by1 && y2 <= by2))
672672
{
673673
return true;

0 commit comments

Comments
 (0)