1 /****************************************************************************
  2  Copyright (c) 2010-2012 cocos2d-x.org
  3  Copyright (c) 2008-2010 Ricardo Quesada
  4  Copyright (c) 2011      Zynga Inc.
  5 
  6  http://www.cocos2d-x.org
  7 
  8  Permission is hereby granted, free of charge, to any person obtaining a copy
  9  of this software and associated documentation files (the "Software"), to deal
 10  in the Software without restriction, including without limitation the rights
 11  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 12  copies of the Software, and to permit persons to whom the Software is
 13  furnished to do so, subject to the following conditions:
 14 
 15  The above copyright notice and this permission notice shall be included in
 16  all copies or substantial portions of the Software.
 17 
 18  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 19  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 20  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 21  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 22  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 23  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 24  THE SOFTWARE.
 25  ****************************************************************************/
 26 
 27 /**
 28  * <p> An interval action is an action that takes place within a certain period of time. <br/>
 29  * It has an start time, and a finish time. The finish time is the parameter<br/>
 30  * duration plus the start time.</p>
 31  *
 32  * <p>These CCActionInterval actions have some interesting properties, like:<br/>
 33  * - They can run normally (default)  <br/>
 34  * - They can run reversed with the reverse method   <br/>
 35  * - They can run with the time altered with the Accelerate, AccelDeccel and Speed actions. </p>
 36  *
 37  * <p>For example, you can simulate a Ping Pong effect running the action normally and<br/>
 38  * then running it again in Reverse mode. </p>
 39  *
 40  * @class
 41  * @extends cc.FiniteTimeAction
 42  * @Example
 43  * // example
 44  * var pingPongAction = cc.Sequence.create(action, action.reverse());
 45  */
 46 cc.ActionInterval = cc.FiniteTimeAction.extend(/** @lends cc.ActionInterval# */{
 47     _elapsed:0,
 48     _firstTick:false,
 49 
 50     ctor:function () {
 51         cc.FiniteTimeAction.prototype.ctor.call(this);
 52         this._elapsed = 0;
 53         this._firstTick = false;
 54     },
 55 
 56     /** how many seconds had elapsed since the actions started to run.
 57      * @return {Number}
 58      */
 59     getElapsed:function () {
 60         return this._elapsed;
 61     },
 62 
 63     /** initializes the action
 64      * @param {Number} d duration in seconds
 65      * @return {Boolean}
 66      */
 67     initWithDuration:function (d) {
 68         this._duration = (d === 0) ? cc.FLT_EPSILON : d;
 69         // prevent division by 0
 70         // This comparison could be in step:, but it might decrease the performance
 71         // by 3% in heavy based action games.
 72         this._elapsed = 0;
 73         this._firstTick = true;
 74         return true;
 75     },
 76 
 77     /** returns true if the action has finished
 78      * @return {Boolean}
 79      */
 80     isDone:function () {
 81         return (this._elapsed >= this._duration);
 82     },
 83 
 84     /**
 85      * returns a new clone of the action
 86      * @returns {cc.ActionInterval}
 87      */
 88     clone:function () {
 89         var action = new cc.ActionInterval();
 90         action.initWithDuration(this._duration);
 91         return action;
 92     },
 93 
 94     /**
 95      * @param {Number} dt delta time in seconds
 96      */
 97     step:function (dt) {
 98         if (this._firstTick) {
 99             this._firstTick = false;
100             this._elapsed = 0;
101         } else
102             this._elapsed += dt;
103 
104         //this.update((1 > (this._elapsed / this._duration)) ? this._elapsed / this._duration : 1);
105         //this.update(Math.max(0, Math.min(1, this._elapsed / Math.max(this._duration, cc.FLT_EPSILON))));
106         var t = this._elapsed / (this._duration > 0.0000001192092896 ? this._duration : 0.0000001192092896);
107         t = (1 > t ? t : 1);
108         this.update(t > 0 ? t : 0);
109     },
110 
111     /**
112      * @param {cc.Node} target
113      */
114     startWithTarget:function (target) {
115         cc.Action.prototype.startWithTarget.call(this, target);
116         this._elapsed = 0;
117         this._firstTick = true;
118     },
119 
120     /**
121      * @return {Null}
122      */
123     reverse:function () {
124         cc.log("cc.IntervalAction: reverse not implemented.");
125         return null;
126     },
127 
128     /**
129      * @param {Number} amp
130      */
131     setAmplitudeRate:function (amp) {
132         // Abstract class needs implementation
133         cc.log("cc.ActionInterval.setAmplitudeRate(): it should be overridden in subclass.");
134     },
135 
136     /**
137      * @return {Number}
138      */
139     getAmplitudeRate:function () {
140         // Abstract class needs implementation
141         cc.log("cc.ActionInterval.getAmplitudeRate(): it should be overridden in subclass.");
142     }
143 });
144 
145 /**
146  * @param {Number} d duration in seconds
147  * @return {cc.ActionInterval}
148  * @example
149  * // example
150  * var actionInterval = cc.ActionInterval.create(3);
151  */
152 cc.ActionInterval.create = function (d) {
153     var action = new cc.ActionInterval();
154     action.initWithDuration(d);
155     return action;
156 };
157 
158 
159 /** Runs actions sequentially, one after another
160  * @class
161  * @extends cc.ActionInterval
162  */
163 cc.Sequence = cc.ActionInterval.extend(/** @lends cc.Sequence# */{
164     _actions:null,
165     _split:null,
166     _last:0,
167 
168     /**
169      * Constructor
170      */
171     ctor:function () {
172         cc.ActionInterval.prototype.ctor.call(this);
173         this._actions = [];
174         this._split = null;
175         this._last = 0;
176     },
177 
178     /** initializes the action <br/>
179      * @param {cc.FiniteTimeAction} actionOne
180      * @param {cc.FiniteTimeAction} actionTwo
181      * @return {Boolean}
182      */
183     initWithTwoActions:function (actionOne, actionTwo) {
184         if(!actionOne || !actionTwo)
185             throw "cc.Sequence.initWithTwoActions(): arguments must all be non nil";
186 
187         var d = actionOne.getDuration() + actionTwo.getDuration();
188         this.initWithDuration(d);
189 
190         this._actions[0] = actionOne;
191         this._actions[1] = actionTwo;
192         return true;
193     },
194 
195     /**
196      * returns a new clone of the action
197      * @returns {cc.Sequence}
198      */
199     clone:function () {
200         var action = new cc.Sequence();
201         action.initWithTwoActions(this._actions[0].clone(), this._actions[1].clone());
202         return action;
203     },
204 
205     /**
206      * @param {cc.Node} target
207      */
208     startWithTarget:function (target) {
209         cc.ActionInterval.prototype.startWithTarget.call(this, target);
210         this._split = this._actions[0].getDuration() / this._duration;
211         this._last = -1;
212     },
213 
214     /**
215      * stop the action
216      */
217     stop:function () {
218         // Issue #1305
219         if (this._last !== -1)
220             this._actions[this._last].stop();
221         cc.Action.prototype.stop.call(this);
222     },
223 
224     /**
225      * @param {Number} time  time in seconds
226      */
227     update:function (time) {
228         var new_t, found = 0;
229         var locSplit = this._split, locActions = this._actions, locLast = this._last;
230         if (time < locSplit) {
231             // action[0]
232             new_t = (locSplit !== 0) ? time / locSplit : 1;
233 
234             if (found === 0 && locLast === 1) {
235                 // Reverse mode ?
236                 // XXX: Bug. this case doesn't contemplate when _last==-1, found=0 and in "reverse mode"
237                 // since it will require a hack to know if an action is on reverse mode or not.
238                 // "step" should be overriden, and the "reverseMode" value propagated to inner Sequences.
239                 locActions[1].update(0);
240                 locActions[1].stop();
241             }
242         } else {
243             // action[1]
244             found = 1;
245             new_t = (locSplit === 1) ? 1 : (time - locSplit) / (1 - locSplit);
246 
247             if (locLast === -1) {
248                 // action[0] was skipped, execute it.
249                 locActions[0].startWithTarget(this.target);
250                 locActions[0].update(1);
251                 locActions[0].stop();
252             }
253             if (!locLast) {
254                 // switching to action 1. stop action 0.
255                 locActions[0].update(1);
256                 locActions[0].stop();
257             }
258         }
259 
260         // Last action found and it is done.
261         if (locLast === found && locActions[found].isDone())
262             return;
263 
264         // Last action found and it is done
265         if (locLast !== found)
266             locActions[found].startWithTarget(this.target);
267 
268         locActions[found].update(new_t);
269         this._last = found;
270     },
271 
272     /**
273      * @return {cc.ActionInterval}
274      */
275     reverse:function () {
276         return cc.Sequence._actionOneTwo(this._actions[1].reverse(), this._actions[0].reverse());
277     },
278 
279     /**
280      * to copy object with deep copy.
281      * @return {object}
282      */
283     copy:function () {
284         return this.clone();
285     }
286 });
287 /** helper constructor to create an array of sequenceable actions
288  * @param {Array|cc.FiniteTimeAction} tempArray
289  * @return {cc.Sequence}
290  * @example
291  * // example
292  * // create sequence with actions
293  * var seq = cc.Sequence.create(act1, act2);
294  *
295  * // create sequence with array
296  * var seq = cc.Sequence.create(actArray);
297  */
298 cc.Sequence.create = function (/*Multiple Arguments*/tempArray) {
299     var paraArray = (tempArray instanceof Array) ? tempArray : arguments;
300     if ((paraArray.length > 0) && (paraArray[paraArray.length - 1] == null))
301         cc.log("parameters should not be ending with null in Javascript");
302 
303     var prev = paraArray[0];
304     for (var i = 1; i < paraArray.length; i++) {
305         if (paraArray[i])
306             prev = cc.Sequence._actionOneTwo(prev, paraArray[i]);
307     }
308     return prev;
309 };
310 
311 /** creates the action
312  * @param {cc.FiniteTimeAction} actionOne
313  * @param {cc.FiniteTimeAction} actionTwo
314  * @return {cc.Sequence}
315  * @private
316  */
317 cc.Sequence._actionOneTwo = function (actionOne, actionTwo) {
318     var sequence = new cc.Sequence();
319     sequence.initWithTwoActions(actionOne, actionTwo);
320     return sequence;
321 };
322 
323 
324 /** Repeats an action a number of times.
325  * To repeat an action forever use the CCRepeatForever action.
326  * @class
327  * @extends cc.ActionInterval
328  */
329 cc.Repeat = cc.ActionInterval.extend(/** @lends cc.Repeat# */{
330     _times:0,
331     _total:0,
332     _nextDt:0,
333     _actionInstant:false,
334     _innerAction:null, //CCFiniteTimeAction
335 
336     ctor:function () {
337         cc.ActionInterval.prototype.ctor.call(this);
338         this._times = 0;
339         this._total = 0;
340         this._nextDt = 0;
341         this._actionInstant = false;
342         this._innerAction = null;
343     },
344 
345     /**
346      * @param {cc.FiniteTimeAction} action
347      * @param {Number} times
348      * @return {Boolean}
349      */
350     initWithAction:function (action, times) {
351         var duration = action.getDuration() * times;
352 
353         if (this.initWithDuration(duration)) {
354             this._times = times;
355             this._innerAction = action;
356             if (action instanceof cc.ActionInstant)
357                 this._times -= 1;
358             this._total = 0;
359             return true;
360         }
361         return false;
362     },
363 
364     /**
365      * returns a new clone of the action
366      * @returns {cc.Repeat}
367      */
368     clone:function () {
369         var action = new cc.Repeat();
370         action.initWithAction(this._innerAction.clone(), this._times);
371         return action;
372     },
373 
374     /**
375      * @param {cc.Node} target
376      */
377     startWithTarget:function (target) {
378         this._total = 0;
379         this._nextDt = this._innerAction.getDuration() / this._duration;
380         cc.ActionInterval.prototype.startWithTarget.call(this, target);
381         this._innerAction.startWithTarget(target);
382     },
383 
384     /**
385      * stop the action
386      */
387     stop:function () {
388         this._innerAction.stop();
389         cc.Action.prototype.stop.call(this);
390     },
391 
392     /**
393      * @param {Number} time time in seconds
394      */
395     update:function (time) {
396         var locInnerAction = this._innerAction;
397         var locDuration = this._duration;
398         var locTimes = this._times;
399         var locNextDt = this._nextDt;
400 
401         if (time >= locNextDt) {
402             while (time > locNextDt && this._total < locTimes) {
403                 locInnerAction.update(1);
404                 this._total++;
405                 locInnerAction.stop();
406                 locInnerAction.startWithTarget(this.target);
407                 locNextDt += locInnerAction.getDuration() / locDuration;
408                 this._nextDt = locNextDt;
409             }
410 
411             // fix for issue #1288, incorrect end value of repeat
412             if (time >= 1.0 && this._total < locTimes)
413                 this._total++;
414 
415             // don't set a instantaction back or update it, it has no use because it has no duration
416             if (this._actionInstant) {
417                 if (this._total == locTimes) {
418                     locInnerAction.update(1);
419                     locInnerAction.stop();
420                 } else {
421                     // issue #390 prevent jerk, use right update
422                     locInnerAction.update(time - (locNextDt - locInnerAction.getDuration() / locDuration));
423                 }
424             }
425         } else {
426             locInnerAction.update((time * locTimes) % 1.0);
427         }
428     },
429 
430     /**
431      * @return {Boolean}
432      */
433     isDone:function () {
434         return this._total == this._times;
435     },
436 
437     /**
438      * @return {cc.ActionInterval}
439      */
440     reverse:function () {
441         return cc.Repeat.create(this._innerAction.reverse(), this._times);
442     },
443 
444     /**
445      * @param {cc.FiniteTimeAction} action
446      */
447     setInnerAction:function (action) {
448         if (this._innerAction != action) {
449             this._innerAction = action;
450         }
451     },
452 
453     /**
454      * @return {cc.FiniteTimeAction}
455      */
456     getInnerAction:function () {
457         return this._innerAction;
458     }
459 });
460 /** creates a CCRepeat action. Times is an unsigned integer between 1 and pow(2,30)
461  * @param {cc.FiniteTimeAction} action
462  * @param {Number} times
463  * @return {cc.Repeat}
464  * @example
465  * // example
466  * var rep = cc.Repeat.create(cc.Sequence.create(jump2, jump1), 5);
467  */
468 cc.Repeat.create = function (action, times) {
469     var repeat = new cc.Repeat();
470     repeat.initWithAction(action, times);
471     return repeat;
472 };
473 
474 
475 /**  Repeats an action for ever.  <br/>
476  * To repeat the an action for a limited number of times use the Repeat action. <br/>
477  * @warning This action can't be Sequencable because it is not an IntervalAction
478  * @class
479  * @extends cc.ActionInterval
480  */
481 
482 cc.RepeatForever = cc.ActionInterval.extend(/** @lends cc.RepeatForever# */{
483     _innerAction:null, //CCActionInterval
484 
485     ctor:function () {
486         cc.ActionInterval.prototype.ctor.call(this);
487         this._innerAction = null;
488     },
489 
490     /**
491      * @param {cc.ActionInterval} action
492      * @return {Boolean}
493      */
494     initWithAction:function (action) {
495         if(!action)
496             throw "cc.RepeatForever.initWithAction(): action must be non null";
497 
498         this._innerAction = action;
499         return true;
500     },
501 
502     /**
503      * returns a new clone of the action
504      * @returns {cc.RepeatForever}
505      */
506     clone:function () {
507         var action = new cc.RepeatForever();
508         action.initWithAction(this._innerAction.clone());
509         return action;
510     },
511 
512     /**
513      * @param {cc.Node} target
514      */
515     startWithTarget:function (target) {
516         cc.ActionInterval.prototype.startWithTarget.call(this, target);
517         this._innerAction.startWithTarget(target);
518     },
519 
520     /**
521      * @param dt delta time in seconds
522      */
523     step:function (dt) {
524         var locInnerAction = this._innerAction;
525         locInnerAction.step(dt);
526         if (locInnerAction.isDone()) {
527             //var diff = locInnerAction.getElapsed() - locInnerAction.getDuration();
528             locInnerAction.startWithTarget(this.target);
529             // to prevent jerk. issue #390 ,1247
530             //this._innerAction.step(0);
531             //this._innerAction.step(diff);
532             locInnerAction.step(locInnerAction.getElapsed() - locInnerAction.getDuration());
533         }
534     },
535 
536     /**
537      * @return {Boolean}
538      */
539     isDone:function () {
540         return false;
541     },
542 
543     /**
544      * @return {cc.ActionInterval}
545      */
546     reverse:function () {
547         return (cc.RepeatForever.create(this._innerAction.reverse()));
548     },
549 
550     /**
551      *
552      * @param {cc.ActionInterval} action
553      */
554     setInnerAction:function (action) {
555         if (this._innerAction != action) {
556             this._innerAction = action;
557         }
558     },
559 
560     /**
561      * @return {cc.ActionInterval}
562      */
563     getInnerAction:function () {
564         return this._innerAction;
565     }
566 });
567 /**
568  * Repeat the acton forever
569  * @param action
570  * @return {cc.RepeatForever}
571  * @example
572  * // example
573  * var repeat = cc.RepeatForever.create(cc.RotateBy.create(1.0, 360));
574  */
575 cc.RepeatForever.create = function (action) {
576     var ret = new cc.RepeatForever();
577     if (ret && ret.initWithAction(action))
578         return ret;
579     return null;
580 };
581 
582 
583 /** Spawn a new action immediately
584  * @class
585  * @extends cc.ActionInterval
586  */
587 cc.Spawn = cc.ActionInterval.extend(/** @lends cc.Spawn# */{
588     _one:null,
589     _two:null,
590 
591     ctor:function () {
592         cc.ActionInterval.prototype.ctor.call(this);
593         this._one = null;
594         this._two = null;
595     },
596 
597     /** initializes the Spawn action with the 2 actions to spawn
598      * @param {cc.FiniteTimeAction} action1
599      * @param {cc.FiniteTimeAction} action2
600      * @return {Boolean}
601      */
602     initWithTwoActions:function (action1, action2) {
603         if(!action1 || !action2)
604             throw "cc.Spawn.initWithTwoActions(): arguments must all be non null" ;
605 
606         var ret = false;
607 
608         var d1 = action1.getDuration();
609         var d2 = action2.getDuration();
610 
611         if (this.initWithDuration(Math.max(d1, d2))) {
612             this._one = action1;
613             this._two = action2;
614 
615             if (d1 > d2) {
616                 this._two = cc.Sequence._actionOneTwo(action2, cc.DelayTime.create(d1 - d2));
617             } else if (d1 < d2) {
618                 this._one = cc.Sequence._actionOneTwo(action1, cc.DelayTime.create(d2 - d1));
619             }
620 
621             ret = true;
622         }
623         return ret;
624     },
625 
626     /**
627      * returns a new clone of the action
628      * @returns {cc.Spawn}
629      */
630     clone:function () {
631         var action = new cc.Spawn();
632         action.initWithTwoActions(this._one.clone(), this._two.clone());
633         return action;
634     },
635 
636     /**
637      * @param {cc.Node} target
638      */
639     startWithTarget:function (target) {
640         cc.ActionInterval.prototype.startWithTarget.call(this, target);
641         this._one.startWithTarget(target);
642         this._two.startWithTarget(target);
643     },
644 
645     /**
646      * Stop the action
647      */
648     stop:function () {
649         this._one.stop();
650         this._two.stop();
651         cc.Action.prototype.stop.call(this);
652     },
653 
654     /**
655      * @param {Number} time time in seconds
656      */
657     update:function (time) {
658         if (this._one)
659             this._one.update(time);
660         if (this._two)
661             this._two.update(time);
662     },
663 
664     /**
665      * @return {cc.FiniteTimeAction}
666      */
667     reverse:function () {
668         return cc.Spawn._actionOneTwo(this._one.reverse(), this._two.reverse());
669     }
670 });
671 
672 /**
673  * @param {Array|cc.FiniteTimeAction}tempArray
674  * @return {cc.FiniteTimeAction}
675  * @example
676  * // example
677  * var action = cc.Spawn.create(cc.JumpBy.create(2, cc.p(300, 0), 50, 4), cc.RotateBy.create(2, 720));
678  */
679 cc.Spawn.create = function (/*Multiple Arguments*/tempArray) {
680     var paramArray = (tempArray instanceof Array) ? tempArray : arguments;
681     if ((paramArray.length > 0) && (paramArray[paramArray.length - 1] == null))
682         cc.log("parameters should not be ending with null in Javascript");
683 
684     var prev = paramArray[0];
685     for (var i = 1; i < paramArray.length; i++) {
686         if (paramArray[i] != null)
687             prev = this._actionOneTwo(prev, paramArray[i]);
688     }
689     return prev;
690 };
691 
692 /**
693  * @param {cc.FiniteTimeAction} action1
694  * @param {cc.FiniteTimeAction} action2
695  * @return {cc.Spawn}
696  * @private
697  */
698 cc.Spawn._actionOneTwo = function (action1, action2) {
699     var pSpawn = new cc.Spawn();
700     pSpawn.initWithTwoActions(action1, action2);
701     return pSpawn;
702 };
703 
704 
705 /** Rotates a cc.Node object to a certain angle by modifying it's
706  * rotation attribute. <br/>
707  * The direction will be decided by the shortest angle.
708  * @class
709  * @extends cc.ActionInterval
710  */
711 cc.RotateTo = cc.ActionInterval.extend(/** @lends cc.RotateTo# */{
712     _dstAngleX:0,
713     _startAngleX:0,
714     _diffAngleX:0,
715 
716     _dstAngleY:0,
717     _startAngleY:0,
718     _diffAngleY:0,
719 
720     ctor:function () {
721         cc.ActionInterval.prototype.ctor.call(this);
722         this._dstAngleX = 0;
723         this._startAngleX = 0;
724         this._diffAngleX = 0;
725 
726         this._dstAngleY = 0;
727         this._startAngleY = 0;
728         this._diffAngleY = 0;
729     },
730 
731     /**
732      * @param {Number} duration
733      * @param {Number} deltaAngleX
734      * @param {Number} deltaAngleY
735      * @return {Boolean}
736      */
737     initWithDuration:function (duration, deltaAngleX, deltaAngleY) {
738         if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) {
739             this._dstAngleX = deltaAngleX || 0;
740             this._dstAngleY = deltaAngleY || this._dstAngleX;
741             return true;
742         }
743         return false;
744     },
745 
746     /**
747      * returns a new clone of the action
748      * @returns {cc.RotateTo}
749      */
750     clone:function () {
751         var action = new cc.RotateTo();
752         action.initWithDuration(this._duration, this._dstAngleX, this._dstAngleY);
753         return action;
754     },
755 
756     /**
757      * @param {cc.Node} target
758      */
759     startWithTarget:function (target) {
760         cc.ActionInterval.prototype.startWithTarget.call(this, target);
761 
762         // Calculate X
763         var locStartAngleX = target.rotationX % 360.0;
764         var locDiffAngleX = this._dstAngleX - locStartAngleX;
765         if (locDiffAngleX > 180)
766             locDiffAngleX -= 360;
767         if (locDiffAngleX < -180)
768             locDiffAngleX += 360;
769         this._startAngleX = locStartAngleX;
770         this._diffAngleX = locDiffAngleX;
771 
772         // Calculate Y  It's duplicated from calculating X since the rotation wrap should be the same
773         this._startAngleY = target.rotationY % 360.0;
774         var locDiffAngleY = this._dstAngleY - this._startAngleY;
775         if (locDiffAngleY > 180)
776             locDiffAngleY -= 360;
777         if (locDiffAngleY < -180)
778             locDiffAngleY += 360;
779         this._diffAngleY = locDiffAngleY;
780     },
781 
782     /**
783      * RotateTo reverse not implemented
784      */
785     reverse:function () {
786         cc.log("cc.RotateTo.reverse(): it should be overridden in subclass.");
787     },
788 
789     /**
790      * @param {Number} time time in seconds
791      */
792     update:function (time) {
793         if (this.target) {
794             this.target.rotationX = this._startAngleX + this._diffAngleX * time;
795             this.target.rotationY = this._startAngleY + this._diffAngleY * time;
796         }
797     }
798 });
799 
800 /**
801  * creates the action with separate rotation angles
802  * @param {Number} duration duration in seconds
803  * @param {Number} deltaAngleX deltaAngleX in degrees.
804  * @param {Number} [deltaAngleY=] deltaAngleY in degrees.
805  * @return {cc.RotateTo}
806  * @example
807  * // example
808  * var rotateTo = cc.RotateTo.create(2, 61.0);
809  */
810 cc.RotateTo.create = function (duration, deltaAngleX, deltaAngleY) {
811     var rotateTo = new cc.RotateTo();
812     rotateTo.initWithDuration(duration, deltaAngleX, deltaAngleY);
813     return rotateTo;
814 };
815 
816 
817 /** Rotates a cc.Node object clockwise a number of degrees by modifying it's rotation attribute.
818  * @class
819  * @extends  cc.ActionInterval
820  */
821 cc.RotateBy = cc.ActionInterval.extend(/** @lends cc.RotateBy# */{
822     _angleX:0,
823     _startAngleX:0,
824     _angleY:0,
825     _startAngleY:0,
826 
827     ctor:function () {
828         cc.ActionInterval.prototype.ctor.call(this);
829         this._angleX = 0;
830         this._startAngleX = 0;
831         this._angleY = 0;
832         this._startAngleY = 0;
833     },
834 
835     /**
836      * @param {Number} duration duration in seconds
837      * @param {Number} deltaAngleX deltaAngleX in degrees
838      * @param {Number} [deltaAngleY=] deltaAngleY in degrees
839      * @return {Boolean}
840      */
841     initWithDuration:function (duration, deltaAngleX, deltaAngleY) {
842         if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) {
843             this._angleX = deltaAngleX || 0;
844             this._angleY = deltaAngleY || this._angleX;
845             return true;
846         }
847         return false;
848     },
849 
850     /**
851      * returns a new clone of the action
852      * @returns {cc.RotateBy}
853      */
854     clone:function () {
855         var action = new cc.RotateBy();
856         action.initWithDuration(this._duration, this._angleX, this._angleY);
857         return action;
858     },
859 
860     /**
861      * @param {cc.Node} target
862      */
863     startWithTarget:function (target) {
864         cc.ActionInterval.prototype.startWithTarget.call(this, target);
865         this._startAngleX = target.rotationX;
866         this._startAngleY = target.rotationY;
867     },
868 
869     /**
870      * @param {Number} time
871      */
872     update:function (time) {
873         if (this.target) {
874             this.target.rotationX = this._startAngleX + this._angleX * time;
875             this.target.rotationY = this._startAngleY + this._angleY * time;
876         }
877     },
878 
879     /**
880      * @return {cc.ActionInterval}
881      */
882     reverse:function () {
883         return cc.RotateBy.create(this._duration, -this._angleX, -this._angleY);
884     }
885 });
886 
887 /**
888  * @param {Number} duration druation in seconds
889  * @param {Number} deltaAngleX deltaAngleX in degrees
890  * @param {Number} [deltaAngleY=] deltaAngleY in degrees
891  * @return {cc.RotateBy}
892  * @example
893  * // example
894  * var actionBy = cc.RotateBy.create(2, 360);
895  */
896 cc.RotateBy.create = function (duration, deltaAngleX, deltaAngleY) {
897     var rotateBy = new cc.RotateBy();
898     rotateBy.initWithDuration(duration, deltaAngleX, deltaAngleY);
899     return rotateBy;
900 };
901 
902 
903 /**
904  * <p>
905  *     Moves a CCNode object x,y pixels by modifying it's position attribute.                                  <br/>
906  *     x and y are relative to the position of the object.                                                     <br/>
907  *     Several CCMoveBy actions can be concurrently called, and the resulting                                  <br/>
908  *     movement will be the sum of individual movements.
909  * </p>
910  * @class
911  * @extends cc.ActionInterval
912  */
913 cc.MoveBy = cc.ActionInterval.extend(/** @lends cc.MoveBy# */{
914     _positionDelta:null,
915     _startPosition:null,
916     _previousPosition:null,
917 
918     ctor:function () {
919         cc.ActionInterval.prototype.ctor.call(this);
920 
921         this._positionDelta = cc.p(0, 0);
922         this._startPosition = cc.p(0, 0);
923         this._previousPosition = cc.p(0, 0);
924     },
925 
926     /**
927      * @param {Number} duration duration in seconds
928      * @param {cc.Point} position
929      * @return {Boolean}
930      */
931     initWithDuration:function (duration, position) {
932         if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) {
933             this._positionDelta.x = position.x;
934             this._positionDelta.y = position.y;
935             return true;
936         }
937         return false;
938     },
939 
940     /**
941      * returns a new clone of the action
942      * @returns {cc.MoveBy}
943      */
944     clone:function () {
945         var action = new cc.MoveBy();
946         action.initWithDuration(this._duration, this._positionDelta)
947         return action;
948     },
949 
950     /**
951      * @param {Number} target
952      */
953     startWithTarget:function (target) {
954         cc.ActionInterval.prototype.startWithTarget.call(this, target);
955         var locPosX = target.getPositionX();
956         var locPosY = target.getPositionY();
957         this._previousPosition.x = locPosX;
958         this._previousPosition.y = locPosY;
959         this._startPosition.x = locPosX;
960         this._startPosition.y = locPosY;
961     },
962 
963     /**
964      * @param {Number} time time in seconds
965      */
966     update:function (time) {
967         if (this.target) {
968             var x = this._positionDelta.x * time;
969             var y = this._positionDelta.y * time;
970             var locStartPosition = this._startPosition;
971             if (cc.ENABLE_STACKABLE_ACTIONS) {
972                 var targetX = this.target.getPositionX();
973                 var targetY = this.target.getPositionY();
974                 var locPreviousPosition = this._previousPosition;
975 
976                 locStartPosition.x = locStartPosition.x + targetX - locPreviousPosition.x;
977                 locStartPosition.y = locStartPosition.y + targetY - locPreviousPosition.y;
978                 x = x + locStartPosition.x;
979                 y = y + locStartPosition.y;
980 	            locPreviousPosition.x = x;
981 	            locPreviousPosition.y = y;
982 	            this.target.setPosition(x, y);
983             } else {
984                 this.target.setPosition(locStartPosition.x + x, locStartPosition.y + y);
985             }
986         }
987     },
988 
989     /**
990      * MoveTo reverse is not implemented
991      */
992     reverse:function () {
993         return cc.MoveBy.create(this._duration, cc.p(-this._positionDelta.x, -this._positionDelta.y));
994     }
995 });
996 
997 /**
998  * @param {Number} duration duration in seconds
999  * @param {cc.Point} deltaPosition
1000  * @return {cc.MoveBy}
1001  * @example
1002  * // example
1003  * var actionTo = cc.MoveBy.create(2, cc.p(windowSize.width - 40, windowSize.height - 40));
1004  */
1005 cc.MoveBy.create = function (duration, deltaPosition) {
1006     var moveBy = new cc.MoveBy();
1007     moveBy.initWithDuration(duration, deltaPosition);
1008     return moveBy;
1009 };
1010 
1011 
1012 /**
1013  * Moves a CCNode object to the position x,y. x and y are absolute coordinates by modifying it's position attribute. <br/>
1014  * Several CCMoveTo actions can be concurrently called, and the resulting                                            <br/>
1015  * movement will be the sum of individual movements.
1016  * @class
1017  * @extends cc.MoveBy
1018  */
1019 cc.MoveTo = cc.MoveBy.extend(/** @lends cc.MoveTo# */{
1020     _endPosition:null,
1021     ctor:function () {
1022         cc.MoveBy.prototype.ctor.call(this);
1023         this._endPosition = cc.p(0, 0);
1024     },
1025 
1026     /**
1027      * @param {Number} duration  duration in seconds
1028      * @param {cc.Point} position
1029      * @return {Boolean}
1030      */
1031     initWithDuration:function (duration, position) {
1032         if (cc.MoveBy.prototype.initWithDuration.call(this, duration, position)) {
1033             this._endPosition.x = position.x;
1034             this._endPosition.y = position.y;
1035             return true;
1036         }
1037         return false;
1038     },
1039 
1040     /**
1041      * returns a new clone of the action
1042      * @returns {cc.MoveTo}
1043      */
1044     clone:function () {
1045         var action = new cc.MoveTo();
1046         action.initWithDuration(this._duration, this._endPosition);
1047         return action;
1048     },
1049 
1050     /**
1051      * @param {cc.Node} target
1052      */
1053     startWithTarget:function (target) {
1054         cc.MoveBy.prototype.startWithTarget.call(this, target);
1055         this._positionDelta.x = this._endPosition.x - target.getPositionX();
1056         this._positionDelta.y = this._endPosition.y - target.getPositionY();
1057     }
1058 });
1059 /**
1060  * @param {Number} duration duration in seconds
1061  * @param {cc.Point} position
1062  * @return {cc.MoveBy}
1063  * @example
1064  * // example
1065  * var actionBy = cc.MoveTo.create(2, cc.p(80, 80));
1066  */
1067 cc.MoveTo.create = function (duration, position) {
1068     var moveTo = new cc.MoveTo();
1069     moveTo.initWithDuration(duration, position);
1070     return moveTo;
1071 };
1072 
1073 /**
1074  * Skews a cc.Node object to given angles by modifying it's skewX and skewY attributes
1075  * @class
1076  * @extends cc.ActionInterval
1077  */
1078 cc.SkewTo = cc.ActionInterval.extend(/** @lends cc.SkewTo# */{
1079     _skewX:0,
1080     _skewY:0,
1081     _startSkewX:0,
1082     _startSkewY:0,
1083     _endSkewX:0,
1084     _endSkewY:0,
1085     _deltaX:0,
1086     _deltaY:0,
1087 
1088     ctor:function () {
1089         cc.ActionInterval.prototype.ctor.call(this);
1090         this._skewX = 0;
1091         this._skewY = 0;
1092         this._startSkewX = 0;
1093         this._startSkewY = 0;
1094         this._endSkewX = 0;
1095         this._endSkewY = 0;
1096         this._deltaX = 0;
1097         this._deltaY = 0;
1098     },
1099 
1100     /**
1101      * @param {Number} t time in seconds
1102      * @param {Number} sx
1103      * @param {Number} sy
1104      * @return {Boolean}
1105      */
1106     initWithDuration:function (t, sx, sy) {
1107         var ret = false;
1108         if (cc.ActionInterval.prototype.initWithDuration.call(this, t)) {
1109             this._endSkewX = sx;
1110             this._endSkewY = sy;
1111             ret = true;
1112         }
1113         return ret;
1114     },
1115 
1116     /**
1117      * returns a new clone of the action
1118      * @returns {cc.SkewTo}
1119      */
1120     clone:function () {
1121         var action = new cc.SkewTo();
1122         action.initWithDuration(this._duration, this._endSkewX, this._endSkewY);
1123         return action;
1124     },
1125 
1126     /**
1127      * @param {cc.Node} target
1128      */
1129     startWithTarget:function (target) {
1130         cc.ActionInterval.prototype.startWithTarget.call(this, target);
1131 
1132         this._startSkewX = target.skewX % 180;
1133         this._deltaX = this._endSkewX - this._startSkewX;
1134         if (this._deltaX > 180)
1135             this._deltaX -= 360;
1136         if (this._deltaX < -180)
1137             this._deltaX += 360;
1138 
1139         this._startSkewY = target.skewY % 360;
1140         this._deltaY = this._endSkewY - this._startSkewY;
1141         if (this._deltaY > 180)
1142             this._deltaY -= 360;
1143         if (this._deltaY < -180)
1144             this._deltaY += 360;
1145     },
1146 
1147     /**
1148      * @param {Number} t time in seconds
1149      */
1150     update:function (t) {
1151         this.target.skewX = this._startSkewX + this._deltaX * t;
1152         this.target.skewY = this._startSkewY + this._deltaY * t;
1153     }
1154 });
1155 /**
1156  * @param {Number} t time in seconds
1157  * @param {Number} sx
1158  * @param {Number} sy
1159  * @return {cc.SkewTo}
1160  * @example
1161  * // example
1162  * var actionTo = cc.SkewTo.create(2, 37.2, -37.2);
1163  */
1164 cc.SkewTo.create = function (t, sx, sy) {
1165     var skewTo = new cc.SkewTo();
1166     if (skewTo)
1167         skewTo.initWithDuration(t, sx, sy);
1168     return skewTo;
1169 };
1170 
1171 /** Skews a cc.Node object by skewX and skewY degrees
1172  * @class
1173  * @extends cc.SkewTo
1174  */
1175 cc.SkewBy = cc.SkewTo.extend(/** @lends cc.SkewBy# */{
1176     /**
1177      * @param {Number} t time in seconds
1178      * @param {Number} deltaSkewX  skew in degrees for X axis
1179      * @param {Number} deltaSkewY  skew in degrees for Y axis
1180      * @return {Boolean}
1181      */
1182     initWithDuration:function (t, deltaSkewX, deltaSkewY) {
1183         var ret = false;
1184         if (cc.SkewTo.prototype.initWithDuration.call(this, t, deltaSkewX, deltaSkewY)) {
1185             this._skewX = deltaSkewX;
1186             this._skewY = deltaSkewY;
1187             ret = true;
1188         }
1189         return ret;
1190     },
1191 
1192     /**
1193      * returns a new clone of the action
1194      * @returns {cc.SkewBy}
1195      */
1196     clone:function () {
1197         var action = new cc.SkewBy();
1198         action.initWithDuration(this._duration, this._skewX, this._skewY);
1199         return action;
1200     },
1201 
1202     /**
1203      * @param {cc.Node} target
1204      */
1205     startWithTarget:function (target) {
1206         cc.SkewTo.prototype.startWithTarget.call(this, target);
1207         this._deltaX = this._skewX;
1208         this._deltaY = this._skewY;
1209         this._endSkewX = this._startSkewX + this._deltaX;
1210         this._endSkewY = this._startSkewY + this._deltaY;
1211     },
1212 
1213     /**
1214      * @return {cc.ActionInterval}
1215      */
1216     reverse:function () {
1217         return cc.SkewBy.create(this._duration, -this._skewX, -this._skewY);
1218     }
1219 });
1220 /**
1221  * @param {Number} t time in seconds
1222  * @param {Number} sx sx skew in degrees for X axis
1223  * @param {Number} sy sy skew in degrees for Y axis
1224  * @return {cc.SkewBy}
1225  * @example
1226  * // example
1227  * var actionBy = cc.SkewBy.create(2, 0, -90);
1228  */
1229 cc.SkewBy.create = function (t, sx, sy) {
1230     var skewBy = new cc.SkewBy();
1231     if (skewBy)
1232         skewBy.initWithDuration(t, sx, sy);
1233     return skewBy;
1234 };
1235 
1236 
1237 /**  Moves a cc.Node object simulating a parabolic jump movement by modifying it's position attribute.
1238  * @class
1239  * @extends cc.ActionInterval
1240  */
1241 cc.JumpBy = cc.ActionInterval.extend(/** @lends cc.JumpBy# */{
1242     _startPosition:null,
1243     _delta:null,
1244     _height:0,
1245     _jumps:0,
1246     _previousPosition:null,
1247 
1248     ctor:function () {
1249         cc.ActionInterval.prototype.ctor.call(this);
1250         this._startPosition = cc.p(0, 0);
1251         this._previousPosition = cc.p(0, 0);
1252         this._delta = cc.p(0, 0);
1253         this._height = 0;
1254         this._jumps = 0;
1255     },
1256     /**
1257      * @param {Number} duration
1258      * @param {cc.Point} position
1259      * @param {Number} height
1260      * @param {Number} jumps
1261      * @return {Boolean}
1262      */
1263     initWithDuration:function (duration, position, height, jumps) {
1264         if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) {
1265             this._delta.x = position.x;
1266             this._delta.y = position.y;
1267             this._height = height;
1268             this._jumps = jumps;
1269             return true;
1270         }
1271         return false;
1272     },
1273 
1274     /**
1275      * returns a new clone of the action
1276      * @returns {cc.JumpBy}
1277      */
1278     clone:function () {
1279         var action = new cc.JumpBy();
1280         action.initWithDuration(this._duration, this._delta, this._height, this._jumps);
1281         return action;
1282     },
1283 
1284     /**
1285      * @param {cc.Node} target
1286      */
1287     startWithTarget:function (target) {
1288         cc.ActionInterval.prototype.startWithTarget.call(this, target);
1289         var locPosX = target.getPositionX();
1290         var locPosY = target.getPositionY();
1291         this._previousPosition.x = locPosX;
1292         this._previousPosition.y = locPosY;
1293         this._startPosition.x = locPosX;
1294         this._startPosition.y = locPosY;
1295     },
1296 
1297     /**
1298      * @param {Number} time
1299      */
1300     update:function (time) {
1301         if (this.target) {
1302             var frac = time * this._jumps % 1.0;
1303             var y = this._height * 4 * frac * (1 - frac);
1304             y += this._delta.y * time;
1305 
1306             var x = this._delta.x * time;
1307             var locStartPosition = this._startPosition;
1308             if (cc.ENABLE_STACKABLE_ACTIONS) {
1309                 var targetX = this.target.getPositionX();
1310                 var targetY = this.target.getPositionY();
1311                 var locPreviousPosition = this._previousPosition;
1312 
1313                 locStartPosition.x = locStartPosition.x + targetX - locPreviousPosition.x;
1314                 locStartPosition.y = locStartPosition.y + targetY - locPreviousPosition.y;
1315                 x = x + locStartPosition.x;
1316                 y = y + locStartPosition.y;
1317 	            locPreviousPosition.x = x;
1318 	            locPreviousPosition.y = y;
1319 	            this.target.setPosition(x, y);
1320             } else {
1321                 this.target.setPosition(locStartPosition.x + x, locStartPosition.y + y);
1322             }
1323         }
1324     },
1325 
1326     /**
1327      * @return {cc.ActionInterval}
1328      */
1329     reverse:function () {
1330         return cc.JumpBy.create(this._duration, cc.p(-this._delta.x, -this._delta.y), this._height, this._jumps);
1331     }
1332 });
1333 
1334 /**
1335  * @param {Number} duration
1336  * @param {cc.Point} position
1337  * @param {Number} height
1338  * @param {Number} jumps
1339  * @return {cc.JumpBy}
1340  * @example
1341  * // example
1342  * var actionBy = cc.JumpBy.create(2, cc.p(300, 0), 50, 4);
1343  */
1344 cc.JumpBy.create = function (duration, position, height, jumps) {
1345     var jumpBy = new cc.JumpBy();
1346     jumpBy.initWithDuration(duration, position, height, jumps);
1347     return jumpBy;
1348 };
1349 
1350 /**  Moves a cc.Node object to a parabolic position simulating a jump movement by modifying it's position attribute.
1351  * @class
1352  * @extends cc.JumpBy
1353  */
1354 cc.JumpTo = cc.JumpBy.extend(/** @lends cc.JumpTo# */{
1355     /**
1356      * @param {cc.Node} target
1357      */
1358     startWithTarget:function (target) {
1359         cc.JumpBy.prototype.startWithTarget.call(this, target);
1360         this._delta.x = this._delta.x - this._startPosition.x;
1361         this._delta.y = this._delta.y - this._startPosition.y;
1362     },
1363 
1364     /**
1365      * returns a new clone of the action
1366      * @returns {cc.JumpTo}
1367      */
1368     clone:function () {
1369         var action = new cc.JumpTo();
1370         action.initWithDuration(this._duration, this._delta, this._height, this._jumps);
1371         return action;
1372     }
1373 });
1374 
1375 /**
1376  * @param {Number} duration
1377  * @param {cc.Point} position
1378  * @param {Number} height
1379  * @param {Number} jumps
1380  * @return {cc.JumpTo}
1381  * @example
1382  * // example
1383  * var actionTo = cc.JumpTo.create(2, cc.p(300, 300), 50, 4);
1384  */
1385 cc.JumpTo.create = function (duration, position, height, jumps) {
1386     var jumpTo = new cc.JumpTo();
1387     jumpTo.initWithDuration(duration, position, height, jumps);
1388     return jumpTo;
1389 };
1390 
1391 /**
1392  * @function
1393  * @param {Number} a
1394  * @param {Number} b
1395  * @param {Number} c
1396  * @param {Number} d
1397  * @param {Number} t
1398  * @return {Number}
1399  */
1400 cc.bezierAt = function (a, b, c, d, t) {
1401     return (Math.pow(1 - t, 3) * a +
1402         3 * t * (Math.pow(1 - t, 2)) * b +
1403         3 * Math.pow(t, 2) * (1 - t) * c +
1404         Math.pow(t, 3) * d );
1405 };
1406 
1407 /** An action that moves the target with a cubic Bezier curve by a certain distance.
1408  * @class
1409  * @extends cc.ActionInterval
1410  */
1411 cc.BezierBy = cc.ActionInterval.extend(/** @lends cc.BezierBy# */{
1412     _config:null,
1413     _startPosition:null,
1414     _previousPosition:null,
1415 
1416     /**
1417      * Constructor
1418      */
1419     ctor:function () {
1420         cc.ActionInterval.prototype.ctor.call(this);
1421         this._config = [];
1422         this._startPosition = cc.p(0, 0);
1423         this._previousPosition = cc.p(0, 0);
1424     },
1425     /**
1426      * @param {Number} t time in seconds
1427      * @param {Array} c Array of points
1428      * @return {Boolean}
1429      */
1430     initWithDuration:function (t, c) {
1431         if (cc.ActionInterval.prototype.initWithDuration.call(this, t)) {
1432             this._config = c;
1433             return true;
1434         }
1435         return false;
1436     },
1437 
1438     /**
1439      * returns a new clone of the action
1440      * @returns {cc.BezierBy}
1441      */
1442     clone:function () {
1443         var action = new cc.BezierBy();
1444         var newConfigs = [];
1445         for (var i = 0; i < this._config.length; i++) {
1446             var selConf = this._config[i];
1447             newConfigs.push(cc.p(selConf.x, selConf.y));
1448         }
1449         action.initWithDuration(this._duration, newConfigs);
1450         return action;
1451     },
1452 
1453     /**
1454      * @param {cc.Node} target
1455      */
1456     startWithTarget:function (target) {
1457         cc.ActionInterval.prototype.startWithTarget.call(this, target);
1458         var locPosX = target.getPositionX();
1459         var locPosY = target.getPositionY();
1460         this._previousPosition.x = locPosX;
1461         this._previousPosition.y = locPosY;
1462         this._startPosition.x = locPosX;
1463         this._startPosition.y = locPosY;
1464     },
1465 
1466     /**
1467      * @param {Number} time
1468      */
1469     update:function (time) {
1470         if (this.target) {
1471             var locConfig = this._config;
1472             var xa = 0;
1473             var xb = locConfig[0].x;
1474             var xc = locConfig[1].x;
1475             var xd = locConfig[2].x;
1476 
1477             var ya = 0;
1478             var yb = locConfig[0].y;
1479             var yc = locConfig[1].y;
1480             var yd = locConfig[2].y;
1481 
1482             var x = cc.bezierAt(xa, xb, xc, xd, time);
1483             var y = cc.bezierAt(ya, yb, yc, yd, time);
1484 
1485             var locStartPosition = this._startPosition;
1486             if (cc.ENABLE_STACKABLE_ACTIONS) {
1487                 var targetX = this.target.getPositionX();
1488                 var targetY = this.target.getPositionY();
1489                 var locPreviousPosition = this._previousPosition;
1490 
1491                 locStartPosition.x = locStartPosition.x + targetX - locPreviousPosition.x;
1492                 locStartPosition.y = locStartPosition.y + targetY - locPreviousPosition.y;
1493                 x = x + locStartPosition.x;
1494                 y = y + locStartPosition.y;
1495 	            locPreviousPosition.x = x;
1496 	            locPreviousPosition.y = y;
1497 	            this.target.setPosition(x, y);
1498             } else {
1499                 this.target.setPosition(locStartPosition.x + x, locStartPosition.y + y);
1500             }
1501         }
1502     },
1503 
1504     /**
1505      * @return {cc.ActionInterval}
1506      */
1507     reverse:function () {
1508         var locConfig = this._config;
1509         var r = [
1510             cc.pAdd(locConfig[1], cc.pNeg(locConfig[2])),
1511             cc.pAdd(locConfig[0], cc.pNeg(locConfig[2])),
1512             cc.pNeg(locConfig[2]) ];
1513         return cc.BezierBy.create(this._duration, r);
1514     }
1515 });
1516 
1517 /**
1518  * @param {Number} t time in seconds
1519  * @param {Array} c Array of points
1520  * @return {cc.BezierBy}
1521  * @example
1522  * // example
1523  * var bezier = [cc.p(0, windowSize.height / 2), cc.p(300, -windowSize.height / 2), cc.p(300, 100)];
1524  * var bezierForward = cc.BezierBy.create(3, bezier);
1525  *
1526  */
1527 cc.BezierBy.create = function (t, c) {
1528     var bezierBy = new cc.BezierBy();
1529     bezierBy.initWithDuration(t, c);
1530     return bezierBy;
1531 };
1532 
1533 
1534 /** An action that moves the target with a cubic Bezier curve to a destination point.
1535  * @class
1536  * @extends cc.BezierBy
1537  */
1538 cc.BezierTo = cc.BezierBy.extend(/** @lends cc.BezierTo# */{
1539     _toConfig:null,
1540 
1541     ctor:function () {
1542         cc.BezierBy.prototype.ctor.call(this);
1543         this._toConfig = [];
1544     },
1545 
1546     /**
1547      * @param {Number} t time in seconds
1548      * @param {Array} c Array of points
1549      * @return {Boolean}
1550      */
1551     initWithDuration:function (t, c) {
1552         if (cc.ActionInterval.prototype.initWithDuration.call(this, t)) {
1553             this._toConfig = c;
1554             return true;
1555         }
1556         return false;
1557     },
1558 
1559     /**
1560      * returns a new clone of the action
1561      * @returns {cc.BezierTo}
1562      */
1563     clone:function () {
1564         var action = new cc.BezierTo();
1565         action.initWithDuration(this._duration, this._toConfig);
1566         return action;
1567     },
1568 
1569     /**
1570      * @param {cc.Node} target
1571      */
1572     startWithTarget:function (target) {
1573         cc.BezierBy.prototype.startWithTarget.call(this, target);
1574         var locStartPos = this._startPosition;
1575         var locToConfig = this._toConfig;
1576         var locConfig = this._config;
1577 
1578         locConfig[0] = cc.pSub(locToConfig[0], locStartPos);
1579         locConfig[1] = cc.pSub(locToConfig[1], locStartPos);
1580         locConfig[2] = cc.pSub(locToConfig[2], locStartPos);
1581     }
1582 });
1583 /**
1584  * @param {Number} t
1585  * @param {Array} c array of points
1586  * @return {cc.BezierTo}
1587  * @example
1588  * // example
1589  * var bezier = [cc.p(0, windowSize.height / 2), cc.p(300, -windowSize.height / 2), cc.p(300, 100)];
1590  * var bezierTo = cc.BezierTo.create(2, bezier);
1591  */
1592 cc.BezierTo.create = function (t, c) {
1593     var bezierTo = new cc.BezierTo();
1594     bezierTo.initWithDuration(t, c);
1595     return bezierTo;
1596 };
1597 
1598 
1599 /** Scales a cc.Node object to a zoom factor by modifying it's scale attribute.
1600  * @warning This action doesn't support "reverse"
1601  * @class
1602  * @extends cc.ActionInterval
1603  */
1604 cc.ScaleTo = cc.ActionInterval.extend(/** @lends cc.ScaleTo# */{
1605     _scaleX:1,
1606     _scaleY:1,
1607     _startScaleX:1,
1608     _startScaleY:1,
1609     _endScaleX:0,
1610     _endScaleY:0,
1611     _deltaX:0,
1612     _deltaY:0,
1613 
1614     ctor:function () {
1615         cc.ActionInterval.prototype.ctor.call(this);
1616         this._scaleX = 1;
1617         this._scaleY = 1;
1618         this._startScaleX = 1;
1619         this._startScaleY = 1;
1620         this._endScaleX = 0;
1621         this._endScaleY = 0;
1622         this._deltaX = 0;
1623         this._deltaY = 0;
1624     },
1625 
1626     /**
1627      * @param {Number} duration
1628      * @param {Number} sx
1629      * @param {Number} [sy=]
1630      * @return {Boolean}
1631      */
1632     initWithDuration:function (duration, sx, sy) { //function overload here
1633         if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) {
1634             this._endScaleX = sx;
1635             this._endScaleY = (sy != null) ? sy : sx;
1636             return true;
1637         }
1638         return false;
1639     },
1640 
1641     /**
1642      * returns a new clone of the action
1643      * @returns {cc.ScaleTo}
1644      */
1645     clone:function () {
1646         var action = new cc.ScaleTo();
1647         action.initWithDuration(this._duration, this._endScaleX, this._endScaleY);
1648         return action;
1649     },
1650 
1651     /**
1652      * @param {cc.Node} target
1653      */
1654     startWithTarget:function (target) {
1655         cc.ActionInterval.prototype.startWithTarget.call(this, target);
1656         this._startScaleX = target.scaleX;
1657         this._startScaleY = target.scaleY;
1658         this._deltaX = this._endScaleX - this._startScaleX;
1659         this._deltaY = this._endScaleY - this._startScaleY;
1660     },
1661 
1662     /**
1663      * @param {Number} time
1664      */
1665     update:function (time) {
1666         if (this.target) {
1667             this.target.scaleX = this._startScaleX + this._deltaX * time;
1668 	        this.target.scaleY = this._startScaleY + this._deltaY * time;
1669         }
1670     }
1671 });
1672 /**
1673  * @param {Number} duration
1674  * @param {Number} sx  scale parameter in X
1675  * @param {Number} [sy=] scale parameter in Y, if Null equal to sx
1676  * @return {cc.ScaleTo}
1677  * @example
1678  * // example
1679  * // It scales to 0.5 in both X and Y.
1680  * var actionTo = cc.ScaleTo.create(2, 0.5);
1681  *
1682  * // It scales to 0.5 in x and 2 in Y
1683  * var actionTo = cc.ScaleTo.create(2, 0.5, 2);
1684  */
1685 cc.ScaleTo.create = function (duration, sx, sy) { //function overload
1686     var scaleTo = new cc.ScaleTo();
1687     scaleTo.initWithDuration(duration, sx, sy);
1688     return scaleTo;
1689 };
1690 
1691 
1692 /** Scales a cc.Node object a zoom factor by modifying it's scale attribute.
1693  * @class
1694  * @extends cc.ScaleTo
1695  */
1696 cc.ScaleBy = cc.ScaleTo.extend(/** @lends cc.ScaleBy# */{
1697     /**
1698      * @param {Number} target
1699      */
1700     startWithTarget:function (target) {
1701         cc.ScaleTo.prototype.startWithTarget.call(this, target);
1702         this._deltaX = this._startScaleX * this._endScaleX - this._startScaleX;
1703         this._deltaY = this._startScaleY * this._endScaleY - this._startScaleY;
1704     },
1705 
1706     /**
1707      * @return {cc.ActionInterval}
1708      */
1709     reverse:function () {
1710         return cc.ScaleBy.create(this._duration, 1 / this._endScaleX, 1 / this._endScaleY);
1711     },
1712 
1713     /**
1714      * returns a new clone of the action
1715      * @returns {cc.ScaleBy}
1716      */
1717     clone:function () {
1718         var action = new cc.ScaleBy();
1719         action.initWithDuration(this._duration, this._endScaleX, this._endScaleY);
1720         return action;
1721     }
1722 });
1723 /**
1724  * @param {Number} duration duration in seconds
1725  * @param {Number} sx sx  scale parameter in X
1726  * @param {Number|Null} [sy=] sy scale parameter in Y, if Null equal to sx
1727  * @return {cc.ScaleBy}
1728  * @example
1729  * // example without sy, it scales by 2 both in X and Y
1730  * var actionBy = cc.ScaleBy.create(2, 2);
1731  *
1732  * //example with sy, it scales by 0.25 in X and 4.5 in Y
1733  * var actionBy2 = cc.ScaleBy.create(2, 0.25, 4.5);
1734  */
1735 cc.ScaleBy.create = function (duration, sx, sy) {
1736     var scaleBy = new cc.ScaleBy();
1737     scaleBy.initWithDuration(duration, sx, sy);
1738     return scaleBy;
1739 };
1740 
1741 /** Blinks a cc.Node object by modifying it's visible attribute
1742  * @class
1743  * @extends cc.ActionInterval
1744  */
1745 cc.Blink = cc.ActionInterval.extend(/** @lends cc.Blink# */{
1746     _times:0,
1747     _originalState:false,
1748 
1749     ctor:function () {
1750         cc.ActionInterval.prototype.ctor.call(this);
1751         this._times = 0;
1752         this._originalState = false;
1753     },
1754 
1755     /**
1756      * @param {Number} duration duration in seconds
1757      * @param {Number} blinks blinks in times
1758      * @return {Boolean}
1759      */
1760     initWithDuration:function (duration, blinks) {
1761         if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) {
1762             this._times = blinks;
1763             return true;
1764         }
1765         return false;
1766     },
1767 
1768     /**
1769      * returns a new clone of the action
1770      * @returns {cc.Blink}
1771      */
1772     clone:function () {
1773         var action = new cc.Blink();
1774         action.initWithDuration(this._duration, this._times);
1775         return action;
1776     },
1777 
1778     /**
1779      * @param {Number} time time in seconds
1780      */
1781     update:function (time) {
1782         if (this.target && !this.isDone()) {
1783             var slice = 1.0 / this._times;
1784             var m = time % slice;
1785             this.target.visible = (m > (slice / 2));
1786         }
1787     },
1788 
1789     startWithTarget:function (target) {
1790         cc.ActionInterval.prototype.startWithTarget.call(this, target);
1791         this._originalState = target.visible;
1792     },
1793 
1794     stop:function () {
1795         this.target.visible = this._originalState;
1796         cc.ActionInterval.prototype.stop.call(this);
1797     },
1798 
1799     /**
1800      * @return {cc.ActionInterval}
1801      */
1802     reverse:function () {
1803         return cc.Blink.create(this._duration, this._times);
1804     }
1805 });
1806 /**
1807  * @param {Number} duration  duration in seconds
1808  * @param blinks blinks in times
1809  * @return {cc.Blink}
1810  * @example
1811  * // example
1812  * var action = cc.Blink.create(2, 10);
1813  */
1814 cc.Blink.create = function (duration, blinks) {
1815     var blink = new cc.Blink();
1816     blink.initWithDuration(duration, blinks);
1817     return blink;
1818 };
1819 
1820 /** Fades an object that implements the cc.RGBAProtocol protocol. It modifies the opacity from the current value to a custom one.
1821  * @warning This action doesn't support "reverse"
1822  * @class
1823  * @extends cc.ActionInterval
1824  */
1825 cc.FadeTo = cc.ActionInterval.extend(/** @lends cc.FadeTo# */{
1826     _toOpacity:null,
1827     _fromOpacity:null,
1828 
1829     ctor:function () {
1830         cc.ActionInterval.prototype.ctor.call(this);
1831         this._toOpacity = 0;
1832         this._fromOpacity = 0;
1833     },
1834 
1835     /**
1836      * @param {Number} duration  duration in seconds
1837      * @param {Number} opacity
1838      * @return {Boolean}
1839      */
1840     initWithDuration:function (duration, opacity) {
1841         if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) {
1842             this._toOpacity = opacity;
1843             return true;
1844         }
1845         return false;
1846     },
1847 
1848     /**
1849      * returns a new clone of the action
1850      * @returns {cc.FadeTo}
1851      */
1852     clone:function () {
1853         var action = new cc.FadeTo();
1854         action.initWithDuration(this._duration, this._toOpacity);
1855         return action;
1856     },
1857 
1858     /**
1859      * @param {Number} time time in seconds
1860      */
1861     update:function (time) {
1862         if (this.target.RGBAProtocol) {
1863             var fromOpacity = this._fromOpacity;
1864             this.target.opacity = fromOpacity + (this._toOpacity - fromOpacity) * time;
1865         }
1866     },
1867 
1868     /**
1869      * @param {cc.Sprite} target
1870      */
1871     startWithTarget:function (target) {
1872         cc.ActionInterval.prototype.startWithTarget.call(this, target);
1873         if(this.target.RGBAProtocol){
1874             this._fromOpacity = target.opacity;
1875         }
1876     }
1877 });
1878 
1879 /**
1880  * @param {Number} duration
1881  * @param {Number} opacity 0-255, 0 is transparent
1882  * @return {cc.FadeTo}
1883  * @example
1884  * // example
1885  * var action = cc.FadeTo.create(1.0, 0);
1886  */
1887 cc.FadeTo.create = function (duration, opacity) {
1888     var fadeTo = new cc.FadeTo();
1889     fadeTo.initWithDuration(duration, opacity);
1890     return fadeTo;
1891 };
1892 
1893 /** Fades In an object that implements the cc.RGBAProtocol protocol. It modifies the opacity from 0 to 255.<br/>
1894  * The "reverse" of this action is FadeOut
1895  * @class
1896  * @extends cc.FadeTo
1897  */
1898 cc.FadeIn = cc.FadeTo.extend(/** @lends cc.FadeIn# */{
1899     _reverseAction: null,
1900     /**
1901      * @return {cc.ActionInterval}
1902      */
1903     reverse:function () {
1904         var action = new cc.FadeOut();
1905         action.initWithDuration(this._duration, 0);
1906         return action;
1907     },
1908 
1909     /**
1910      * returns a new clone of the action
1911      * @returns {cc.FadeIn}
1912      */
1913     clone:function () {
1914         var action = new cc.FadeIn();
1915         action.initWithDuration(this._duration, this._toOpacity);
1916         return action;
1917     },
1918 
1919     /**
1920      * @param {cc.Sprite} target
1921      */
1922     startWithTarget:function (target) {
1923         if(this._reverseAction)
1924             this._toOpacity = this._reverseAction._fromOpacity;
1925         cc.FadeTo.prototype.startWithTarget.call(this, target);
1926     }
1927 });
1928 
1929 /**
1930  * @param {Number} duration duration in seconds
1931  * @param {Number} [toOpacity] to opacity
1932  * @return {cc.FadeIn}
1933  * @example
1934  * //example
1935  * var action = cc.FadeIn.create(1.0);
1936  */
1937 cc.FadeIn.create = function (duration, toOpacity) {
1938     if(toOpacity == null)
1939         toOpacity = 255;
1940     var action = new cc.FadeIn();
1941     action.initWithDuration(duration, toOpacity);
1942     return action;
1943 };
1944 
1945 
1946 /** Fades Out an object that implements the cc.RGBAProtocol protocol. It modifies the opacity from 255 to 0.
1947  * The "reverse" of this action is FadeIn
1948  * @class
1949  * @extends cc.FadeTo
1950  */
1951 cc.FadeOut = cc.FadeTo.extend(/** @lends cc.FadeOut# */{
1952     /**
1953      * @return {cc.ActionInterval}
1954      */
1955     reverse:function () {
1956         var action = new cc.FadeIn();
1957         action._reverseAction = this;
1958         action.initWithDuration(this._duration, 255);
1959         return action;
1960     },
1961 
1962     /**
1963      * returns a new clone of the action
1964      * @returns {cc.FadeOut}
1965      */
1966     clone:function () {
1967         var action = new cc.FadeOut();
1968         action.initWithDuration(this._duration, this._toOpacity);
1969         return action;
1970     }
1971 });
1972 
1973 /**
1974  * @param {Number} d  duration in seconds
1975  * @return {cc.FadeOut}
1976  * @example
1977  * // example
1978  * var action = cc.FadeOut.create(1.0);
1979  */
1980 cc.FadeOut.create = function (d) {
1981     var action = new cc.FadeOut();
1982     action.initWithDuration(d, 0);
1983     return action;
1984 };
1985 
1986 /** Tints a cc.Node that implements the cc.NodeRGB protocol from current tint to a custom one.
1987  * @warning This action doesn't support "reverse"
1988  * @class
1989  * @extends cc.ActionInterval
1990  */
1991 cc.TintTo = cc.ActionInterval.extend(/** @lends cc.TintTo# */{
1992     _to:null,
1993     _from:null,
1994 
1995     ctor:function () {
1996         cc.ActionInterval.prototype.ctor.call(this);
1997         this._to = cc.color(0, 0, 0);
1998         this._from = cc.color(0, 0, 0);
1999     },
2000 
2001     /**
2002      * @param {Number} duration
2003      * @param {Number} red 0-255
2004      * @param {Number} green 0-255
2005      * @param {Number} blue 0-255
2006      * @return {Boolean}
2007      */
2008     initWithDuration:function (duration, red, green, blue) {
2009         if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) {
2010             this._to = cc.color(red, green, blue);
2011             return true;
2012         }
2013         return false;
2014     },
2015 
2016     /**
2017      * returns a new clone of the action
2018      * @returns {cc.TintTo}
2019      */
2020     clone:function () {
2021         var action = new cc.TintTo();
2022         var locTo = this._to;
2023         action.initWithDuration(this._duration, locTo.r, locTo.g, locTo.b);
2024         return action;
2025     },
2026 
2027     /**
2028      * @param {cc.Sprite} target
2029      */
2030     startWithTarget:function (target) {
2031         cc.ActionInterval.prototype.startWithTarget.call(this, target);
2032         if (this.target.RGBAProtocol) {
2033             this._from = this.target.color;
2034         }
2035     },
2036 
2037     /**
2038      * @param {Number} time time in seconds
2039      */
2040     update:function (time) {
2041         var locFrom = this._from, locTo = this._to;
2042         if (this.target.RGBAProtocol) {
2043             this.target.color = cc.color(locFrom.r + (locTo.r - locFrom.r) * time,
2044                                         locFrom.g + (locTo.g - locFrom.g) * time,
2045 	                                    locFrom.b + (locTo.b - locFrom.b) * time);
2046         }
2047     }
2048 });
2049 
2050 /**
2051  * @param {Number} duration
2052  * @param {Number} red 0-255
2053  * @param {Number} green  0-255
2054  * @param {Number} blue 0-255
2055  * @return {cc.TintTo}
2056  * @example
2057  * // example
2058  * var action = cc.TintTo.create(2, 255, 0, 255);
2059  */
2060 cc.TintTo.create = function (duration, red, green, blue) {
2061     var tintTo = new cc.TintTo();
2062     tintTo.initWithDuration(duration, red, green, blue);
2063     return tintTo;
2064 };
2065 
2066 
2067 /**  Tints a cc.Node that implements the cc.NodeRGB protocol from current tint to a custom one.
2068  * @class
2069  * @extends cc.ActionInterval
2070  */
2071 cc.TintBy = cc.ActionInterval.extend(/** @lends cc.TintBy# */{
2072     _deltaR:0,
2073     _deltaG:0,
2074     _deltaB:0,
2075 
2076     _fromR:0,
2077     _fromG:0,
2078     _fromB:0,
2079 
2080     ctor:function () {
2081         cc.ActionInterval.prototype.ctor.call(this);
2082         this._deltaR = 0;
2083         this._deltaG = 0;
2084         this._deltaB = 0;
2085         this._fromR = 0;
2086         this._fromG = 0;
2087         this._fromB = 0;
2088     },
2089 
2090     /**
2091      * @param {Number} duration
2092      * @param {Number} deltaRed 0-255
2093      * @param {Number} deltaGreen 0-255
2094      * @param {Number} deltaBlue 0-255
2095      * @return {Boolean}
2096      */
2097     initWithDuration:function (duration, deltaRed, deltaGreen, deltaBlue) {
2098         if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) {
2099             this._deltaR = deltaRed;
2100             this._deltaG = deltaGreen;
2101             this._deltaB = deltaBlue;
2102             return true;
2103         }
2104         return false;
2105     },
2106 
2107     /**
2108      * returns a new clone of the action
2109      * @returns {cc.TintBy}
2110      */
2111     clone:function () {
2112         var action = new cc.TintBy();
2113         action.initWithDuration(this._duration, this._deltaR, this._deltaG, this._deltaB);
2114         return action;
2115     },
2116 
2117     /**
2118      * @param {cc.Sprite} target
2119      */
2120     startWithTarget:function (target) {
2121         cc.ActionInterval.prototype.startWithTarget.call(this, target);
2122         if (target.RGBAProtocol) {
2123             var color = target.color;
2124             this._fromR = color.r;
2125             this._fromG = color.g;
2126             this._fromB = color.b;
2127         }
2128     },
2129 
2130     /**
2131      * @param {Number} time time in seconds
2132      */
2133     update:function (time) {
2134         if (this.target.RGBAProtocol) {
2135             this.target.color = cc.color(this._fromR + this._deltaR * time,
2136                                         this._fromG + this._deltaG * time,
2137                                         this._fromB + this._deltaB * time);
2138         }
2139     },
2140 
2141     /**
2142      * @return {cc.ActionInterval}
2143      */
2144     reverse:function () {
2145         return cc.TintBy.create(this._duration, -this._deltaR, -this._deltaG, -this._deltaB);
2146     }
2147 });
2148 
2149 /**
2150  * @param {Number} duration  duration in seconds
2151  * @param {Number} deltaRed
2152  * @param {Number} deltaGreen
2153  * @param {Number} deltaBlue
2154  * @return {cc.TintBy}
2155  * @example
2156  * // example
2157  * var action = cc.TintBy.create(2, -127, -255, -127);
2158  */
2159 cc.TintBy.create = function (duration, deltaRed, deltaGreen, deltaBlue) {
2160     var tintBy = new cc.TintBy();
2161     tintBy.initWithDuration(duration, deltaRed, deltaGreen, deltaBlue);
2162     return tintBy;
2163 };
2164 
2165 /** Delays the action a certain amount of seconds
2166  * @class
2167  * @extends cc.ActionInterval
2168  */
2169 cc.DelayTime = cc.ActionInterval.extend(/** @lends cc.DelayTime# */{
2170     /**
2171      * @param {Number} time time in seconds
2172      */
2173     update:function (time) {
2174     },
2175 
2176     /**
2177      * @return {cc.ActionInterval}
2178      */
2179     reverse:function () {
2180         return cc.DelayTime.create(this._duration);
2181     },
2182 
2183     /**
2184      * returns a new clone of the action
2185      * @returns {cc.DelayTime}
2186      */
2187     clone:function () {
2188         var action = new cc.DelayTime();
2189         action.initWithDuration(this._duration);
2190         return action;
2191     }
2192 });
2193 
2194 /**
2195  * @param {Number} d duration in seconds
2196  * @return {cc.DelayTime}
2197  * @example
2198  * // example
2199  * var delay = cc.DelayTime.create(1);
2200  */
2201 cc.DelayTime.create = function (d) {
2202     var action = new cc.DelayTime();
2203     action.initWithDuration(d);
2204     return action;
2205 };
2206 
2207 /**
2208  * Executes an action in reverse order, from time=duration to time=0
2209  * @warning Use this action carefully. This action is not
2210  * sequenceable. Use it as the default "reversed" method
2211  * of your own actions, but using it outside the "reversed"
2212  * scope is not recommended.
2213  * @class
2214  * @extends cc.ActionInterval
2215  */
2216 cc.ReverseTime = cc.ActionInterval.extend(/** @lends cc.ReverseTime# */{
2217     _other:null,
2218 
2219     ctor:function () {
2220         cc.ActionInterval.prototype.ctor.call(this);
2221         this._other = null;
2222     },
2223 
2224     /**
2225      * @param {cc.FiniteTimeAction} action
2226      * @return {Boolean}
2227      */
2228     initWithAction:function (action) {
2229         if(!action)
2230             throw "cc.ReverseTime.initWithAction(): action must be non null";
2231         if(action == this._other)
2232             throw "cc.ReverseTime.initWithAction(): the action was already passed in.";
2233 
2234         if (cc.ActionInterval.prototype.initWithDuration.call(this, action.getDuration())) {
2235             // Don't leak if action is reused
2236             this._other = action;
2237             return true;
2238         }
2239         return false;
2240     },
2241 
2242     /**
2243      * returns a new clone of the action
2244      * @returns {cc.ReverseTime}
2245      */
2246     clone:function () {
2247         var action = new cc.ReverseTime();
2248         action.initWithAction(this._other.clone());
2249         return action;
2250     },
2251 
2252     /**
2253      * @param {cc.Node} target
2254      */
2255     startWithTarget:function (target) {
2256         cc.ActionInterval.prototype.startWithTarget.call(this, target);
2257         this._other.startWithTarget(target);
2258     },
2259 
2260     /**
2261      * @param {Number} time time in seconds
2262      */
2263     update:function (time) {
2264         if (this._other)
2265             this._other.update(1 - time);
2266     },
2267 
2268     /**
2269      * @return {cc.ActionInterval}
2270      */
2271     reverse:function () {
2272         return this._other.clone();
2273     },
2274 
2275     /**
2276      * Stop the action
2277      */
2278     stop:function () {
2279         this._other.stop();
2280         cc.Action.prototype.stop.call(this);
2281     }
2282 });
2283 
2284 /**
2285  * @param {cc.FiniteTimeAction} action
2286  * @return {cc.ReverseTime}
2287  * @example
2288  * // example
2289  *  var reverse = cc.ReverseTime.create(this);
2290  */
2291 cc.ReverseTime.create = function (action) {
2292     var reverseTime = new cc.ReverseTime();
2293     reverseTime.initWithAction(action);
2294     return reverseTime;
2295 };
2296 
2297 
2298 /**  Animates a sprite given the name of an Animation
2299  * @class
2300  * @extends cc.ActionInterval
2301  */
2302 cc.Animate = cc.ActionInterval.extend(/** @lends cc.Animate# */{
2303     _animation:null,
2304     _nextFrame:0,
2305     _origFrame:null,
2306     _executedLoops:0,
2307     _splitTimes:null,
2308 
2309     ctor:function () {
2310         cc.ActionInterval.prototype.ctor.call(this);
2311         this._animation = null;
2312         this._nextFrame = 0;
2313         this._origFrame = null;
2314         this._executedLoops = 0;
2315         this._splitTimes = [];
2316     },
2317 
2318     /**
2319      * @return {cc.Animation}
2320      */
2321     getAnimation:function () {
2322         return this._animation;
2323     },
2324 
2325     /**
2326      * @param {cc.Animation} animation
2327      */
2328     setAnimation:function (animation) {
2329         this._animation = animation;
2330     },
2331 
2332     /**
2333      * @param {cc.Animation} animation
2334      * @return {Boolean}
2335      */
2336     initWithAnimation:function (animation) {
2337         if(!animation)
2338             throw "cc.Animate.initWithAnimation(): animation must be non-NULL";
2339         var singleDuration = animation.getDuration();
2340         if (this.initWithDuration(singleDuration * animation.getLoops())) {
2341             this._nextFrame = 0;
2342             this.setAnimation(animation);
2343 
2344             this._origFrame = null;
2345             this._executedLoops = 0;
2346             var locTimes = this._splitTimes;
2347             locTimes.length = 0;
2348 
2349             var accumUnitsOfTime = 0;
2350             var newUnitOfTimeValue = singleDuration / animation.getTotalDelayUnits();
2351 
2352             var frames = animation.getFrames();
2353             cc.arrayVerifyType(frames, cc.AnimationFrame);
2354 
2355             for (var i = 0; i < frames.length; i++) {
2356                 var frame = frames[i];
2357                 var value = (accumUnitsOfTime * newUnitOfTimeValue) / singleDuration;
2358                 accumUnitsOfTime += frame.getDelayUnits();
2359                 locTimes.push(value);
2360             }
2361             return true;
2362         }
2363         return false;
2364     },
2365 
2366     /**
2367      * returns a new clone of the action
2368      * @returns {cc.Animate}
2369      */
2370     clone:function () {
2371         var action = new cc.Animate();
2372         action.initWithAnimation(this._animation.clone());
2373         return action;
2374     },
2375 
2376     /**
2377      * @param {cc.Sprite} target
2378      */
2379     startWithTarget:function (target) {
2380         cc.ActionInterval.prototype.startWithTarget.call(this, target);
2381         if (this._animation.getRestoreOriginalFrame())
2382             this._origFrame = target.displayFrame();
2383         this._nextFrame = 0;
2384         this._executedLoops = 0;
2385     },
2386 
2387     /**
2388      * @param {Number} time
2389      */
2390     update:function (time) {
2391         // if t==1, ignore. Animation should finish with t==1
2392         if (time < 1.0) {
2393             time *= this._animation.getLoops();
2394 
2395             // new loop?  If so, reset frame counter
2396             var loopNumber = 0 | time;
2397             if (loopNumber > this._executedLoops) {
2398                 this._nextFrame = 0;
2399                 this._executedLoops++;
2400             }
2401 
2402             // new t for animations
2403             time = time % 1.0;
2404         }
2405 
2406         var frames = this._animation.getFrames();
2407         var numberOfFrames = frames.length, locSplitTimes = this._splitTimes;
2408         for (var i = this._nextFrame; i < numberOfFrames; i++) {
2409             if (locSplitTimes[i] <= time) {
2410                 this.target.setSpriteFrame(frames[i].getSpriteFrame());
2411                 this._nextFrame = i + 1;
2412             } else {
2413                 // Issue 1438. Could be more than one frame per tick, due to low frame rate or frame delta < 1/FPS
2414                 break;
2415             }
2416         }
2417     },
2418 
2419     /**
2420      * @return {cc.ActionInterval}
2421      */
2422     reverse:function () {
2423         var locAnimation = this._animation;
2424         var oldArray = locAnimation.getFrames();
2425         var newArray = [];
2426         cc.arrayVerifyType(oldArray, cc.AnimationFrame);
2427         if (oldArray.length > 0) {
2428             for (var i = oldArray.length - 1; i >= 0; i--) {
2429                 var element = oldArray[i];
2430                 if (!element)
2431                     break;
2432                 newArray.push(element.clone());
2433             }
2434         }
2435         var newAnim = cc.Animation.create(newArray, locAnimation.getDelayPerUnit(), locAnimation.getLoops());
2436         newAnim.setRestoreOriginalFrame(locAnimation.getRestoreOriginalFrame());
2437         return cc.Animate.create(newAnim);
2438     },
2439 
2440     /**
2441      * stop the action
2442      */
2443     stop:function () {
2444         if (this._animation.getRestoreOriginalFrame() && this.target)
2445             this.target.setSpriteFrame(this._origFrame);
2446         cc.Action.prototype.stop.call(this);
2447     }
2448 });
2449 
2450 /**
2451  * create the animate with animation
2452  * @param {cc.Animation} animation
2453  * @return {cc.Animate}
2454  * @example
2455  * // example
2456  * // create the animation with animation
2457  * var anim = cc.Animate.create(dance_grey);
2458  */
2459 cc.Animate.create = function (animation) {
2460     var animate = new cc.Animate();
2461     animate.initWithAnimation(animation);
2462     return animate;
2463 };
2464 
2465 /**
2466  * <p>
2467  *     Overrides the target of an action so that it always runs on the target<br/>
2468  *     specified at action creation rather than the one specified by runAction.
2469  * </p>
2470  * @class
2471  * @extends cc.ActionInterval
2472  */
2473 cc.TargetedAction = cc.ActionInterval.extend(/** @lends cc.TargetedAction# */{
2474     _action:null,
2475     _forcedTarget:null,
2476 
2477     ctor:function () {
2478         cc.ActionInterval.prototype.ctor.call(this);
2479         this._action = null;
2480         this._forcedTarget = null;
2481     },
2482 
2483     /**
2484      * Init an action with the specified action and forced target
2485      * @param {cc.Node} target
2486      * @param {cc.FiniteTimeAction} action
2487      * @return {Boolean}
2488      */
2489     initWithTarget:function (target, action) {
2490         if (this.initWithDuration(action.getDuration())) {
2491             this._forcedTarget = target;
2492             this._action = action;
2493             return true;
2494         }
2495         return false;
2496     },
2497 
2498     /**
2499      * returns a new clone of the action
2500      * @returns {cc.TargetedAction}
2501      */
2502     clone:function () {
2503         var action = new cc.TargetedAction();
2504         action.initWithTarget(this._forcedTarget, this._action.clone());
2505         return action;
2506     },
2507 
2508     startWithTarget:function (target) {
2509         cc.ActionInterval.prototype.startWithTarget.call(this, target);
2510         this._action.startWithTarget(this._forcedTarget);
2511     },
2512 
2513     stop:function () {
2514         this._action.stop();
2515     },
2516 
2517     update:function (time) {
2518         this._action.update(time);
2519     },
2520 
2521     /**
2522      * return the target that the action will be forced to run with
2523      * @return {cc.Node}
2524      */
2525     getForcedTarget:function () {
2526         return this._forcedTarget;
2527     },
2528 
2529     /**
2530      * set the target that the action will be forced to run with
2531      * @param {cc.Node} forcedTarget
2532      */
2533     setForcedTarget:function (forcedTarget) {
2534         if (this._forcedTarget != forcedTarget)
2535             this._forcedTarget = forcedTarget;
2536     }
2537 });
2538 
2539 /**
2540  * Create an action with the specified action and forced target
2541  * @param {cc.Node} target
2542  * @param {cc.FiniteTimeAction} action
2543  */
2544 cc.TargetedAction.create = function (target, action) {
2545     var retObj = new cc.TargetedAction();
2546     retObj.initWithTarget(target, action);
2547     return retObj;
2548 };
2549