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.Assert(false, "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.Assert(0, 'Actioninterval setAmplitudeRate');
134     },
135 
136     /**
137      * @return {Number}
138      */
139     getAmplitudeRate:function () {
140         // Abstract class needs implementation
141         cc.Assert(0, 'Actioninterval getAmplitudeRate');
142         return 0;
143     }
144 });
145 
146 /**
147  * @param {Number} d duration in seconds
148  * @return {cc.ActionInterval}
149  * @example
150  * // example
151  * var actionInterval = cc.ActionInterval.create(3);
152  */
153 cc.ActionInterval.create = function (d) {
154     var action = new cc.ActionInterval();
155     action.initWithDuration(d);
156     return action;
157 };
158 
159 
160 /** Runs actions sequentially, one after another
161  * @class
162  * @extends cc.ActionInterval
163  */
164 cc.Sequence = cc.ActionInterval.extend(/** @lends cc.Sequence# */{
165     _actions:null,
166     _split:null,
167     _last:0,
168 
169     /**
170      * Constructor
171      */
172     ctor:function () {
173         cc.ActionInterval.prototype.ctor.call(this);
174         this._actions = [];
175         this._split = null;
176         this._last = 0;
177     },
178 
179     /** initializes the action <br/>
180      * @param {cc.FiniteTimeAction} actionOne
181      * @param {cc.FiniteTimeAction} actionTwo
182      * @return {Boolean}
183      */
184     initWithTwoActions:function (actionOne, actionTwo) {
185         cc.Assert(actionOne != null, "Sequence.initWithTwoActions");
186         cc.Assert(actionTwo != null, "Sequence.initWithTwoActions");
187 
188         var d = actionOne.getDuration() + actionTwo.getDuration();
189         this.initWithDuration(d);
190 
191         this._actions[0] = actionOne;
192         this._actions[1] = actionTwo;
193         return true;
194     },
195 
196     /**
197      * returns a new clone of the action
198      * @returns {cc.Sequence}
199      */
200     clone:function () {
201         var action = new cc.Sequence();
202         action.initWithTwoActions(this._actions[0].clone(), this._actions[1].clone());
203         return action;
204     },
205 
206     /**
207      * @param {cc.Node} target
208      */
209     startWithTarget:function (target) {
210         cc.ActionInterval.prototype.startWithTarget.call(this, target);
211         this._split = this._actions[0].getDuration() / this._duration;
212         this._last = -1;
213     },
214 
215     /**
216      * stop the action
217      */
218     stop:function () {
219         // Issue #1305
220         if (this._last !== -1)
221             this._actions[this._last].stop();
222         cc.Action.prototype.stop.call(this);
223     },
224 
225     /**
226      * @param {Number} time  time in seconds
227      */
228     update:function (time) {
229         var new_t, found = 0;
230         var locSplit = this._split, locActions = this._actions, locLast = this._last;
231         if (time < locSplit) {
232             // action[0]
233             new_t = (locSplit) ? time / locSplit : 1;
234 
235             if (found === 0 && locLast === 1) {
236                 // Reverse mode ?
237                 // XXX: Bug. this case doesn't contemplate when _last==-1, found=0 and in "reverse mode"
238                 // since it will require a hack to know if an action is on reverse mode or not.
239                 // "step" should be overriden, and the "reverseMode" value propagated to inner Sequences.
240                 locActions[1].update(0);
241                 locActions[1].stop();
242             }
243         } else {
244             // action[1]
245             found = 1;
246             new_t = (locSplit === 1) ? 1 : (time - locSplit) / (1 - locSplit);
247 
248             if (locLast === -1) {
249                 // action[0] was skipped, execute it.
250                 locActions[0].startWithTarget(this._target);
251                 locActions[0].update(1);
252                 locActions[0].stop();
253             }
254             if (!locLast) {
255                 // switching to action 1. stop action 0.
256                 locActions[0].update(1);
257                 locActions[0].stop();
258             }
259         }
260 
261         // Last action found and it is done.
262         if (locLast === found && locActions[found].isDone())
263             return;
264 
265         // Last action found and it is done
266         if (locLast !== found)
267             locActions[found].startWithTarget(this._target);
268 
269         locActions[found].update(new_t);
270         this._last = found;
271     },
272 
273     /**
274      * @return {cc.ActionInterval}
275      */
276     reverse:function () {
277         return cc.Sequence._actionOneTwo(this._actions[1].reverse(), this._actions[0].reverse());
278     },
279 
280     /**
281      * to copy object with deep copy.
282      * @return {object}
283      */
284     copy:function () {
285         return this.clone();
286     }
287 });
288 /** helper constructor to create an array of sequenceable actions
289  * @param {Array|cc.FiniteTimeAction} tempArray
290  * @return {cc.Sequence}
291  * @example
292  * // example
293  * // create sequence with actions
294  * var seq = cc.Sequence.create(act1, act2);
295  *
296  * // create sequence with array
297  * var seq = cc.Sequence.create(actArray);
298  */
299 cc.Sequence.create = function (/*Multiple Arguments*/tempArray) {
300     var paraArray = (tempArray instanceof Array) ? tempArray : arguments;
301     if ((paraArray.length > 0) && (paraArray[paraArray.length - 1] == null))
302         cc.log("parameters should not be ending with null in Javascript");
303 
304     var prev = paraArray[0];
305     for (var i = 1; i < paraArray.length; i++) {
306         if (paraArray[i])
307             prev = cc.Sequence._actionOneTwo(prev, paraArray[i]);
308     }
309     return prev;
310 };
311 
312 /** creates the action
313  * @param {cc.FiniteTimeAction} actionOne
314  * @param {cc.FiniteTimeAction} actionTwo
315  * @return {cc.Sequence}
316  * @private
317  */
318 cc.Sequence._actionOneTwo = function (actionOne, actionTwo) {
319     var sequence = new cc.Sequence();
320     sequence.initWithTwoActions(actionOne, actionTwo);
321     return sequence;
322 };
323 
324 
325 /** Repeats an action a number of times.
326  * To repeat an action forever use the CCRepeatForever action.
327  * @class
328  * @extends cc.ActionInterval
329  */
330 cc.Repeat = cc.ActionInterval.extend(/** @lends cc.Repeat# */{
331     _times:0,
332     _total:0,
333     _nextDt:0,
334     _actionInstant:false,
335     _innerAction:null, //CCFiniteTimeAction
336 
337     ctor:function () {
338         cc.ActionInterval.prototype.ctor.call(this);
339         this._times = 0;
340         this._total = 0;
341         this._nextDt = 0;
342         this._actionInstant = false;
343         this._innerAction = null;
344     },
345 
346     /**
347      * @param {cc.FiniteTimeAction} action
348      * @param {Number} times
349      * @return {Boolean}
350      */
351     initWithAction:function (action, times) {
352         var duration = action.getDuration() * times;
353 
354         if (this.initWithDuration(duration)) {
355             this._times = times;
356             this._innerAction = action;
357             if (action instanceof cc.ActionInstant)
358                 this._times -= 1;
359             this._total = 0;
360             return true;
361         }
362         return false;
363     },
364 
365     /**
366      * returns a new clone of the action
367      * @returns {cc.Repeat}
368      */
369     clone:function () {
370         var action = new cc.Repeat();
371         action.initWithAction(this._innerAction.clone(), this._times);
372         return action;
373     },
374 
375     /**
376      * @param {cc.Node} target
377      */
378     startWithTarget:function (target) {
379         this._total = 0;
380         this._nextDt = this._innerAction.getDuration() / this._duration;
381         cc.ActionInterval.prototype.startWithTarget.call(this, target);
382         this._innerAction.startWithTarget(target);
383     },
384 
385     /**
386      * stop the action
387      */
388     stop:function () {
389         this._innerAction.stop();
390         cc.Action.prototype.stop.call(this);
391     },
392 
393     /**
394      * @param {Number} time time in seconds
395      */
396     update:function (time) {
397         var locInnerAction = this._innerAction;
398         var locDuration = this._duration;
399         var locTimes = this._times;
400         var locNextDt = this._nextDt;
401 
402         if (time >= locNextDt) {
403             while (time > locNextDt && this._total < locTimes) {
404                 locInnerAction.update(1);
405                 this._total++;
406                 locInnerAction.stop();
407                 locInnerAction.startWithTarget(this._target);
408                 locNextDt += locInnerAction.getDuration() / locDuration;
409                 this._nextDt = locNextDt;
410             }
411 
412             // fix for issue #1288, incorrect end value of repeat
413             if (time >= 1.0 && this._total < locTimes)
414                 this._total++;
415 
416             // don't set a instantaction back or update it, it has no use because it has no duration
417             if (this._actionInstant) {
418                 if (this._total == locTimes) {
419                     locInnerAction.update(1);
420                     locInnerAction.stop();
421                 } else {
422                     // issue #390 prevent jerk, use right update
423                     locInnerAction.update(time - (locNextDt - locInnerAction.getDuration() / locDuration));
424                 }
425             }
426         } else {
427             locInnerAction.update((time * locTimes) % 1.0);
428         }
429     },
430 
431     /**
432      * @return {Boolean}
433      */
434     isDone:function () {
435         return this._total == this._times;
436     },
437 
438     /**
439      * @return {cc.ActionInterval}
440      */
441     reverse:function () {
442         return cc.Repeat.create(this._innerAction.reverse(), this._times);
443     },
444 
445     /**
446      * @param {cc.FiniteTimeAction} action
447      */
448     setInnerAction:function (action) {
449         if (this._innerAction != action) {
450             this._innerAction = action;
451         }
452     },
453 
454     /**
455      * @return {cc.FiniteTimeAction}
456      */
457     getInnerAction:function () {
458         return this._innerAction;
459     }
460 });
461 /** creates a CCRepeat action. Times is an unsigned integer between 1 and pow(2,30)
462  * @param {cc.FiniteTimeAction} action
463  * @param {Number} times
464  * @return {cc.Repeat}
465  * @example
466  * // example
467  * var rep = cc.Repeat.create(cc.Sequence.create(jump2, jump1), 5);
468  */
469 cc.Repeat.create = function (action, times) {
470     var repeat = new cc.Repeat();
471     repeat.initWithAction(action, times);
472     return repeat;
473 };
474 
475 
476 /**  Repeats an action for ever.  <br/>
477  * To repeat the an action for a limited number of times use the Repeat action. <br/>
478  * @warning This action can't be Sequenceable because it is not an IntervalAction
479  * @class
480  * @extends cc.ActionInterval
481  */
482 
483 cc.RepeatForever = cc.ActionInterval.extend(/** @lends cc.RepeatForever# */{
484     _innerAction:null, //CCActionInterval
485 
486     ctor:function () {
487         cc.ActionInterval.prototype.ctor.call(this);
488         this._innerAction = null;
489     },
490 
491     /**
492      * @param {cc.ActionInterval} action
493      * @return {Boolean}
494      */
495     initWithAction:function (action) {
496         cc.Assert(action != 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         cc.Assert(action1 != null, "no action1");
604         cc.Assert(action2 != null, "no action2");
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.getRotationX() % 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.getRotationY() % 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.Assert(0, "RotateTo reverse not implemented");
787     },
788 
789     /**
790      * @param {Number} time time in seconds
791      */
792     update:function (time) {
793         if (this._target) {
794             this._target.setRotationX(this._startAngleX + this._diffAngleX * time);
795             this._target.setRotationY(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.getRotationX();
866         this._startAngleY = target.getRotationY();
867     },
868 
869     /**
870      * @param {Number} time
871      */
872     update:function (time) {
873         if (this._target) {
874             this._target.setRotationX(this._startAngleX + this._angleX * time);
875             this._target.setRotationY(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 
981                 this._target.setPosition(x, y);
982                 locPreviousPosition.x = x;
983                 locPreviousPosition.y = y;
984             } else {
985                 this._target.setPosition(locStartPosition.x + x, locStartPosition.y + y);
986             }
987         }
988     },
989 
990     /**
991      * MoveTo reverse is not implemented
992      */
993     reverse:function () {
994         return cc.MoveBy.create(this._duration, cc.p(-this._positionDelta.x, -this._positionDelta.y));
995     }
996 });
997 
998 /**
999  * @param {Number} duration duration in seconds
1000  * @param {cc.Point} deltaPosition
1001  * @return {cc.MoveBy}
1002  * @example
1003  * // example
1004  * var actionTo = cc.MoveBy.create(2, cc.p(windowSize.width - 40, windowSize.height - 40));
1005  */
1006 cc.MoveBy.create = function (duration, deltaPosition) {
1007     var moveBy = new cc.MoveBy();
1008     moveBy.initWithDuration(duration, deltaPosition);
1009     return moveBy;
1010 };
1011 
1012 
1013 /**
1014  * Moves a CCNode object to the position x,y. x and y are absolute coordinates by modifying it's position attribute. <br/>
1015  * Several CCMoveTo actions can be concurrently called, and the resulting                                            <br/>
1016  * movement will be the sum of individual movements.
1017  * @class
1018  * @extends cc.MoveBy
1019  */
1020 cc.MoveTo = cc.MoveBy.extend(/** @lends cc.MoveTo# */{
1021     _endPosition:null,
1022     ctor:function () {
1023         cc.MoveBy.prototype.ctor.call(this);
1024         this._endPosition = cc.p(0, 0);
1025     },
1026 
1027     /**
1028      * @param {Number} duration  duration in seconds
1029      * @param {cc.Point} position
1030      * @return {Boolean}
1031      */
1032     initWithDuration:function (duration, position) {
1033         if (cc.MoveBy.prototype.initWithDuration.call(this, duration, position)) {
1034             this._endPosition.x = position.x;
1035             this._endPosition.y = position.y;
1036             return true;
1037         }
1038         return false;
1039     },
1040 
1041     /**
1042      * returns a new clone of the action
1043      * @returns {cc.MoveTo}
1044      */
1045     clone:function () {
1046         var action = new cc.MoveTo();
1047         action.initWithDuration(this._duration, this._endPosition);
1048         return action;
1049     },
1050 
1051     /**
1052      * @param {cc.Node} target
1053      */
1054     startWithTarget:function (target) {
1055         cc.MoveBy.prototype.startWithTarget.call(this, target);
1056         this._positionDelta.x = this._endPosition.x - target.getPositionX();
1057         this._positionDelta.y = this._endPosition.y - target.getPositionY();
1058     }
1059 });
1060 /**
1061  * @param {Number} duration duration in seconds
1062  * @param {cc.Point} position
1063  * @return {cc.MoveBy}
1064  * @example
1065  * // example
1066  * var actionBy = cc.MoveTo.create(2, cc.p(80, 80));
1067  */
1068 cc.MoveTo.create = function (duration, position) {
1069     var moveTo = new cc.MoveTo();
1070     moveTo.initWithDuration(duration, position);
1071     return moveTo;
1072 };
1073 
1074 /**
1075  * Skews a cc.Node object to given angles by modifying it's skewX and skewY attributes
1076  * @class
1077  * @extends cc.ActionInterval
1078  */
1079 cc.SkewTo = cc.ActionInterval.extend(/** @lends cc.SkewTo# */{
1080     _skewX:0,
1081     _skewY:0,
1082     _startSkewX:0,
1083     _startSkewY:0,
1084     _endSkewX:0,
1085     _endSkewY:0,
1086     _deltaX:0,
1087     _deltaY:0,
1088 
1089     ctor:function () {
1090         cc.ActionInterval.prototype.ctor.call(this);
1091         this._skewX = 0;
1092         this._skewY = 0;
1093         this._startSkewX = 0;
1094         this._startSkewY = 0;
1095         this._endSkewX = 0;
1096         this._endSkewY = 0;
1097         this._deltaX = 0;
1098         this._deltaY = 0;
1099     },
1100 
1101     /**
1102      * @param {Number} t time in seconds
1103      * @param {Number} sx
1104      * @param {Number} sy
1105      * @return {Boolean}
1106      */
1107     initWithDuration:function (t, sx, sy) {
1108         var ret = false;
1109         if (cc.ActionInterval.prototype.initWithDuration.call(this, t)) {
1110             this._endSkewX = sx;
1111             this._endSkewY = sy;
1112             ret = true;
1113         }
1114         return ret;
1115     },
1116 
1117     /**
1118      * returns a new clone of the action
1119      * @returns {cc.SkewTo}
1120      */
1121     clone:function () {
1122         var action = new cc.SkewTo();
1123         action.initWithDuration(this._duration, this._endSkewX, this._endSkewY);
1124         return action;
1125     },
1126 
1127     /**
1128      * @param {cc.Node} target
1129      */
1130     startWithTarget:function (target) {
1131         cc.ActionInterval.prototype.startWithTarget.call(this, target);
1132 
1133         this._startSkewX = target.getSkewX() % 180;
1134         this._deltaX = this._endSkewX - this._startSkewX;
1135         if (this._deltaX > 180)
1136             this._deltaX -= 360;
1137         if (this._deltaX < -180)
1138             this._deltaX += 360;
1139 
1140         this._startSkewY = target.getSkewY() % 360;
1141         this._deltaY = this._endSkewY - this._startSkewY;
1142         if (this._deltaY > 180)
1143             this._deltaY -= 360;
1144         if (this._deltaY < -180)
1145             this._deltaY += 360;
1146     },
1147 
1148     /**
1149      * @param {Number} t time in seconds
1150      */
1151     update:function (t) {
1152         this._target.setSkewX(this._startSkewX + this._deltaX * t);
1153         this._target.setSkewY(this._startSkewY + this._deltaY * t);
1154     }
1155 });
1156 /**
1157  * @param {Number} t time in seconds
1158  * @param {Number} sx
1159  * @param {Number} sy
1160  * @return {cc.SkewTo}
1161  * @example
1162  * // example
1163  * var actionTo = cc.SkewTo.create(2, 37.2, -37.2);
1164  */
1165 cc.SkewTo.create = function (t, sx, sy) {
1166     var skewTo = new cc.SkewTo();
1167     if (skewTo)
1168         skewTo.initWithDuration(t, sx, sy);
1169     return skewTo;
1170 };
1171 
1172 /** Skews a cc.Node object by skewX and skewY degrees
1173  * @class
1174  * @extends cc.SkewTo
1175  */
1176 cc.SkewBy = cc.SkewTo.extend(/** @lends cc.SkewBy# */{
1177     /**
1178      * @param {Number} t time in seconds
1179      * @param {Number} deltaSkewX  skew in degrees for X axis
1180      * @param {Number} deltaSkewY  skew in degrees for Y axis
1181      * @return {Boolean}
1182      */
1183     initWithDuration:function (t, deltaSkewX, deltaSkewY) {
1184         var ret = false;
1185         if (cc.SkewTo.prototype.initWithDuration.call(this, t, deltaSkewX, deltaSkewY)) {
1186             this._skewX = deltaSkewX;
1187             this._skewY = deltaSkewY;
1188             ret = true;
1189         }
1190         return ret;
1191     },
1192 
1193     /**
1194      * returns a new clone of the action
1195      * @returns {cc.SkewBy}
1196      */
1197     clone:function () {
1198         var action = new cc.SkewBy();
1199         action.initWithDuration(this._duration, this._skewX, this._skewY);
1200         return action;
1201     },
1202 
1203     /**
1204      * @param {cc.Node} target
1205      */
1206     startWithTarget:function (target) {
1207         cc.SkewTo.prototype.startWithTarget.call(this, target);
1208         this._deltaX = this._skewX;
1209         this._deltaY = this._skewY;
1210         this._endSkewX = this._startSkewX + this._deltaX;
1211         this._endSkewY = this._startSkewY + this._deltaY;
1212     },
1213 
1214     /**
1215      * @return {cc.ActionInterval}
1216      */
1217     reverse:function () {
1218         return cc.SkewBy.create(this._duration, -this._skewX, -this._skewY);
1219     }
1220 });
1221 /**
1222  * @param {Number} t time in seconds
1223  * @param {Number} sx sx skew in degrees for X axis
1224  * @param {Number} sy sy skew in degrees for Y axis
1225  * @return {cc.SkewBy}
1226  * @example
1227  * // example
1228  * var actionBy = cc.SkewBy.create(2, 0, -90);
1229  */
1230 cc.SkewBy.create = function (t, sx, sy) {
1231     var skewBy = new cc.SkewBy();
1232     if (skewBy)
1233         skewBy.initWithDuration(t, sx, sy);
1234     return skewBy;
1235 };
1236 
1237 
1238 /**  Moves a cc.Node object simulating a parabolic jump movement by modifying it's position attribute.
1239  * @class
1240  * @extends cc.ActionInterval
1241  */
1242 cc.JumpBy = cc.ActionInterval.extend(/** @lends cc.JumpBy# */{
1243     _startPosition:null,
1244     _delta:null,
1245     _height:0,
1246     _jumps:0,
1247     _previousPosition:null,
1248 
1249     ctor:function () {
1250         cc.ActionInterval.prototype.ctor.call(this);
1251         this._startPosition = cc.p(0, 0);
1252         this._previousPosition = cc.p(0, 0);
1253         this._delta = cc.p(0, 0);
1254         this._height = 0;
1255         this._jumps = 0;
1256     },
1257     /**
1258      * @param {Number} duration
1259      * @param {cc.Point} position
1260      * @param {Number} height
1261      * @param {Number} jumps
1262      * @return {Boolean}
1263      */
1264     initWithDuration:function (duration, position, height, jumps) {
1265         if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) {
1266             this._delta.x = position.x;
1267             this._delta.y = position.y;
1268             this._height = height;
1269             this._jumps = jumps;
1270             return true;
1271         }
1272         return false;
1273     },
1274 
1275     /**
1276      * returns a new clone of the action
1277      * @returns {cc.JumpBy}
1278      */
1279     clone:function () {
1280         var action = new cc.JumpBy();
1281         action.initWithDuration(this._duration, this._delta, this._height, this._jumps);
1282         return action;
1283     },
1284 
1285     /**
1286      * @param {cc.Node} target
1287      */
1288     startWithTarget:function (target) {
1289         cc.ActionInterval.prototype.startWithTarget.call(this, target);
1290         var locPosX = target.getPositionX();
1291         var locPosY = target.getPositionY();
1292         this._previousPosition.x = locPosX;
1293         this._previousPosition.y = locPosY;
1294         this._startPosition.x = locPosX;
1295         this._startPosition.y = locPosY;
1296     },
1297 
1298     /**
1299      * @param {Number} time
1300      */
1301     update:function (time) {
1302         if (this._target) {
1303             var frac = time * this._jumps % 1.0;
1304             var y = this._height * 4 * frac * (1 - frac);
1305             y += this._delta.y * time;
1306 
1307             var x = this._delta.x * time;
1308             var locStartPosition = this._startPosition;
1309             if (cc.ENABLE_STACKABLE_ACTIONS) {
1310                 var targetX = this._target.getPositionX();
1311                 var targetY = this._target.getPositionY();
1312                 var locPreviousPosition = this._previousPosition;
1313 
1314                 locStartPosition.x = locStartPosition.x + targetX - locPreviousPosition.x;
1315                 locStartPosition.y = locStartPosition.y + targetY - locPreviousPosition.y;
1316                 x = x + locStartPosition.x;
1317                 y = y + locStartPosition.y;
1318 
1319                 this._target.setPosition(x, y);
1320                 locPreviousPosition.x = x;
1321                 locPreviousPosition.y = y;
1322             } else {
1323                 this._target.setPosition(locStartPosition.x + x, locStartPosition.y + y);
1324             }
1325         }
1326     },
1327 
1328     /**
1329      * @return {cc.ActionInterval}
1330      */
1331     reverse:function () {
1332         return cc.JumpBy.create(this._duration, cc.p(-this._delta.x, -this._delta.y), this._height, this._jumps);
1333     }
1334 });
1335 
1336 /**
1337  * @param {Number} duration
1338  * @param {cc.Point} position
1339  * @param {Number} height
1340  * @param {Number} jumps
1341  * @return {cc.JumpBy}
1342  * @example
1343  * // example
1344  * var actionBy = cc.JumpBy.create(2, cc.p(300, 0), 50, 4);
1345  */
1346 cc.JumpBy.create = function (duration, position, height, jumps) {
1347     var jumpBy = new cc.JumpBy();
1348     jumpBy.initWithDuration(duration, position, height, jumps);
1349     return jumpBy;
1350 };
1351 
1352 /**  Moves a cc.Node object to a parabolic position simulating a jump movement by modifying it's position attribute.
1353  * @class
1354  * @extends cc.JumpBy
1355  */
1356 cc.JumpTo = cc.JumpBy.extend(/** @lends cc.JumpTo# */{
1357     /**
1358      * @param {cc.Node} target
1359      */
1360     startWithTarget:function (target) {
1361         cc.JumpBy.prototype.startWithTarget.call(this, target);
1362         this._delta.x = this._delta.x - this._startPosition.x;
1363         this._delta.y = this._delta.y - this._startPosition.y;
1364     },
1365 
1366     /**
1367      * returns a new clone of the action
1368      * @returns {cc.JumpTo}
1369      */
1370     clone:function () {
1371         var action = new cc.JumpTo();
1372         action.initWithDuration(this._duration, this._delta, this._height, this._jumps);
1373         return action;
1374     }
1375 });
1376 
1377 /**
1378  * @param {Number} duration
1379  * @param {cc.Point} position
1380  * @param {Number} height
1381  * @param {Number} jumps
1382  * @return {cc.JumpTo}
1383  * @example
1384  * // example
1385  * var actionTo = cc.JumpTo.create(2, cc.p(300, 300), 50, 4);
1386  */
1387 cc.JumpTo.create = function (duration, position, height, jumps) {
1388     var jumpTo = new cc.JumpTo();
1389     jumpTo.initWithDuration(duration, position, height, jumps);
1390     return jumpTo;
1391 };
1392 
1393 /**
1394  * @function
1395  * @param {Number} a
1396  * @param {Number} b
1397  * @param {Number} c
1398  * @param {Number} d
1399  * @param {Number} t
1400  * @return {Number}
1401  */
1402 cc.bezierAt = function (a, b, c, d, t) {
1403     return (Math.pow(1 - t, 3) * a +
1404         3 * t * (Math.pow(1 - t, 2)) * b +
1405         3 * Math.pow(t, 2) * (1 - t) * c +
1406         Math.pow(t, 3) * d );
1407 };
1408 
1409 /** An action that moves the target with a cubic Bezier curve by a certain distance.
1410  * @class
1411  * @extends cc.ActionInterval
1412  */
1413 cc.BezierBy = cc.ActionInterval.extend(/** @lends cc.BezierBy# */{
1414     _config:null,
1415     _startPosition:null,
1416     _previousPosition:null,
1417 
1418     /**
1419      * Constructor
1420      */
1421     ctor:function () {
1422         cc.ActionInterval.prototype.ctor.call(this);
1423         this._config = [];
1424         this._startPosition = cc.p(0, 0);
1425         this._previousPosition = cc.p(0, 0);
1426     },
1427     /**
1428      * @param {Number} t time in seconds
1429      * @param {Array} c Array of points
1430      * @return {Boolean}
1431      */
1432     initWithDuration:function (t, c) {
1433         if (cc.ActionInterval.prototype.initWithDuration.call(this, t)) {
1434             this._config = c;
1435             return true;
1436         }
1437         return false;
1438     },
1439 
1440     /**
1441      * returns a new clone of the action
1442      * @returns {cc.BezierBy}
1443      */
1444     clone:function () {
1445         var action = new cc.BezierBy();
1446         var newConfigs = [];
1447         for (var i = 0; i < this._config.length; i++) {
1448             var selConf = this._config[i];
1449             newConfigs.push(cc.p(selConf.x, selConf.y));
1450         }
1451         action.initWithDuration(this._duration, newConfigs);
1452         return action;
1453     },
1454 
1455     /**
1456      * @param {cc.Node} target
1457      */
1458     startWithTarget:function (target) {
1459         cc.ActionInterval.prototype.startWithTarget.call(this, target);
1460         var locPosX = target.getPositionX();
1461         var locPosY = target.getPositionY();
1462         this._previousPosition.x = locPosX;
1463         this._previousPosition.y = locPosY;
1464         this._startPosition.x = locPosX;
1465         this._startPosition.y = locPosY;
1466     },
1467 
1468     /**
1469      * @param {Number} time
1470      */
1471     update:function (time) {
1472         if (this._target) {
1473             var locConfig = this._config;
1474             var xa = 0;
1475             var xb = locConfig[0].x;
1476             var xc = locConfig[1].x;
1477             var xd = locConfig[2].x;
1478 
1479             var ya = 0;
1480             var yb = locConfig[0].y;
1481             var yc = locConfig[1].y;
1482             var yd = locConfig[2].y;
1483 
1484             var x = cc.bezierAt(xa, xb, xc, xd, time);
1485             var y = cc.bezierAt(ya, yb, yc, yd, time);
1486 
1487             var locStartPosition = this._startPosition;
1488             if (cc.ENABLE_STACKABLE_ACTIONS) {
1489                 var targetX = this._target.getPositionX();
1490                 var targetY = this._target.getPositionY();
1491                 var locPreviousPosition = this._previousPosition;
1492 
1493                 locStartPosition.x = locStartPosition.x + targetX - locPreviousPosition.x;
1494                 locStartPosition.y = locStartPosition.y + targetY - locPreviousPosition.y;
1495                 x = x + locStartPosition.x;
1496                 y = y + locStartPosition.y;
1497                 this._target.setPosition(x, y);
1498                 locPreviousPosition.x = x;
1499                 locPreviousPosition.y = y;
1500             } else {
1501                 this._target.setPosition(locStartPosition.x + x, locStartPosition.y + y);
1502             }
1503         }
1504     },
1505 
1506     /**
1507      * @return {cc.ActionInterval}
1508      */
1509     reverse:function () {
1510         var locConfig = this._config;
1511         var r = [
1512             cc.pAdd(locConfig[1], cc.pNeg(locConfig[2])),
1513             cc.pAdd(locConfig[0], cc.pNeg(locConfig[2])),
1514             cc.pNeg(locConfig[2]) ];
1515         return cc.BezierBy.create(this._duration, r);
1516     }
1517 });
1518 
1519 /**
1520  * @param {Number} t time in seconds
1521  * @param {Array} c Array of points
1522  * @return {cc.BezierBy}
1523  * @example
1524  * // example
1525  * var bezier = [cc.p(0, windowSize.height / 2), cc.p(300, -windowSize.height / 2), cc.p(300, 100)];
1526  * var bezierForward = cc.BezierBy.create(3, bezier);
1527  *
1528  */
1529 cc.BezierBy.create = function (t, c) {
1530     var bezierBy = new cc.BezierBy();
1531     bezierBy.initWithDuration(t, c);
1532     return bezierBy;
1533 };
1534 
1535 
1536 /** An action that moves the target with a cubic Bezier curve to a destination point.
1537  * @class
1538  * @extends cc.BezierBy
1539  */
1540 cc.BezierTo = cc.BezierBy.extend(/** @lends cc.BezierTo# */{
1541     _toConfig:null,
1542 
1543     ctor:function () {
1544         cc.BezierBy.prototype.ctor.call(this);
1545         this._toConfig = [];
1546     },
1547 
1548     /**
1549      * @param {Number} t time in seconds
1550      * @param {Array} c Array of points
1551      * @return {Boolean}
1552      */
1553     initWithDuration:function (t, c) {
1554         if (cc.ActionInterval.prototype.initWithDuration.call(this, t)) {
1555             this._toConfig = c;
1556             return true;
1557         }
1558         return false;
1559     },
1560 
1561     /**
1562      * returns a new clone of the action
1563      * @returns {cc.BezierTo}
1564      */
1565     clone:function () {
1566         var action = new cc.BezierTo();
1567         action.initWithDuration(this._duration, this._toConfig);
1568         return action;
1569     },
1570 
1571     /**
1572      * @param {cc.Node} target
1573      */
1574     startWithTarget:function (target) {
1575         cc.BezierBy.prototype.startWithTarget.call(this, target);
1576         var locStartPos = this._startPosition;
1577         var locToConfig = this._toConfig;
1578         var locConfig = this._config;
1579 
1580         locConfig[0] = cc.pSub(locToConfig[0], locStartPos);
1581         locConfig[1] = cc.pSub(locToConfig[1], locStartPos);
1582         locConfig[2] = cc.pSub(locToConfig[2], locStartPos);
1583     }
1584 });
1585 /**
1586  * @param {Number} t
1587  * @param {Array} c array of points
1588  * @return {cc.BezierTo}
1589  * @example
1590  * // example
1591  * var bezier = [cc.p(0, windowSize.height / 2), cc.p(300, -windowSize.height / 2), cc.p(300, 100)];
1592  * var bezierTo = cc.BezierTo.create(2, bezier);
1593  */
1594 cc.BezierTo.create = function (t, c) {
1595     var bezierTo = new cc.BezierTo();
1596     bezierTo.initWithDuration(t, c);
1597     return bezierTo;
1598 };
1599 
1600 
1601 /** Scales a cc.Node object to a zoom factor by modifying it's scale attribute.
1602  * @warning This action doesn't support "reverse"
1603  * @class
1604  * @extends cc.ActionInterval
1605  */
1606 cc.ScaleTo = cc.ActionInterval.extend(/** @lends cc.ScaleTo# */{
1607     _scaleX:1,
1608     _scaleY:1,
1609     _startScaleX:1,
1610     _startScaleY:1,
1611     _endScaleX:0,
1612     _endScaleY:0,
1613     _deltaX:0,
1614     _deltaY:0,
1615 
1616     ctor:function () {
1617         cc.ActionInterval.prototype.ctor.call(this);
1618         this._scaleX = 1;
1619         this._scaleY = 1;
1620         this._startScaleX = 1;
1621         this._startScaleY = 1;
1622         this._endScaleX = 0;
1623         this._endScaleY = 0;
1624         this._deltaX = 0;
1625         this._deltaY = 0;
1626     },
1627 
1628     /**
1629      * @param {Number} duration
1630      * @param {Number} sx
1631      * @param {Number} [sy=]
1632      * @return {Boolean}
1633      */
1634     initWithDuration:function (duration, sx, sy) { //function overload here
1635         if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) {
1636             this._endScaleX = sx;
1637             this._endScaleY = (sy != null) ? sy : sx;
1638             return true;
1639         }
1640         return false;
1641     },
1642 
1643     /**
1644      * returns a new clone of the action
1645      * @returns {cc.ScaleTo}
1646      */
1647     clone:function () {
1648         var action = new cc.ScaleTo();
1649         action.initWithDuration(this._duration, this._endScaleX, this._endScaleY);
1650         return action;
1651     },
1652 
1653     /**
1654      * @param {cc.Node} target
1655      */
1656     startWithTarget:function (target) {
1657         cc.ActionInterval.prototype.startWithTarget.call(this, target);
1658         this._startScaleX = target.getScaleX();
1659         this._startScaleY = target.getScaleY();
1660         this._deltaX = this._endScaleX - this._startScaleX;
1661         this._deltaY = this._endScaleY - this._startScaleY;
1662     },
1663 
1664     /**
1665      * @param {Number} time
1666      */
1667     update:function (time) {
1668         if (this._target)
1669             this._target.setScale(this._startScaleX + this._deltaX * time, this._startScaleY + this._deltaY * time);
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.setVisible(m > (slice / 2));
1786         }
1787     },
1788 
1789     startWithTarget:function (target) {
1790         cc.ActionInterval.prototype.startWithTarget.call(this, target);
1791         this._originalState = target.isVisible();
1792     },
1793 
1794     stop:function () {
1795         this._target.setVisible(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 In an object that implements the cc.RGBAProtocol protocol. It modifies the opacity from 0 to 255.<br/>
1821  * The "reverse" of this action is FadeOut
1822  * @class
1823  * @extends cc.ActionInterval
1824  */
1825 cc.FadeIn = cc.ActionInterval.extend(/** @lends cc.FadeIn# */{
1826     /**
1827      * @param {Number} time time in seconds
1828      */
1829     update:function (time) {
1830         this._target.setOpacity(255 * time);
1831     },
1832 
1833     /**
1834      * @return {cc.ActionInterval}
1835      */
1836     reverse:function () {
1837         return cc.FadeOut.create(this._duration);
1838     },
1839 
1840     /**
1841      * returns a new clone of the action
1842      * @returns {cc.FadeIn}
1843      */
1844     clone:function () {
1845         var action = new cc.FadeIn();
1846         action.initWithDuration(this._duration);
1847         return action;
1848     }
1849 });
1850 
1851 /**
1852  * @param {Number} duration duration in seconds
1853  * @return {cc.FadeIn}
1854  * @example
1855  * //example
1856  * var action = cc.FadeIn.create(1.0);
1857  */
1858 cc.FadeIn.create = function (duration) {
1859     var action = new cc.FadeIn();
1860     action.initWithDuration(duration);
1861     return action;
1862 };
1863 
1864 
1865 /** Fades Out an object that implements the cc.RGBAProtocol protocol. It modifies the opacity from 255 to 0.
1866  * The "reverse" of this action is FadeIn
1867  * @class
1868  * @extends cc.ActionInterval
1869  */
1870 cc.FadeOut = cc.ActionInterval.extend(/** @lends cc.FadeOut# */{
1871     /**
1872      * @param {Number} time  time in seconds
1873      */
1874     update:function (time) {
1875         this._target.setOpacity(255 * (1 - time));
1876     },
1877 
1878     /**
1879      * @return {cc.ActionInterval}
1880      */
1881     reverse:function () {
1882         return cc.FadeIn.create(this._duration);
1883     },
1884 
1885     /**
1886      * returns a new clone of the action
1887      * @returns {cc.FadeOut}
1888      */
1889     clone:function () {
1890         var action = new cc.FadeOut();
1891         action.initWithDuration(this._duration);
1892         return action;
1893     }
1894 });
1895 
1896 /**
1897  * @param {Number} d  duration in seconds
1898  * @return {cc.FadeOut}
1899  * @example
1900  * // example
1901  * var action = cc.FadeOut.create(1.0);
1902  */
1903 cc.FadeOut.create = function (d) {
1904     var action = new cc.FadeOut();
1905     action.initWithDuration(d);
1906     return action;
1907 };
1908 
1909 /** Fades an object that implements the cc.RGBAProtocol protocol. It modifies the opacity from the current value to a custom one.
1910  * @warning This action doesn't support "reverse"
1911  * @class
1912  * @extends cc.ActionInterval
1913  */
1914 cc.FadeTo = cc.ActionInterval.extend(/** @lends cc.FadeTo# */{
1915     _toOpacity:null,
1916     _fromOpacity:null,
1917 
1918     ctor:function () {
1919         cc.ActionInterval.prototype.ctor.call(this);
1920         this._toOpacity = 0;
1921         this._fromOpacity = 0;
1922     },
1923 
1924     /**
1925      * @param {Number} duration  duration in seconds
1926      * @param {Number} opacity
1927      * @return {Boolean}
1928      */
1929     initWithDuration:function (duration, opacity) {
1930         if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) {
1931             this._toOpacity = opacity;
1932             return true;
1933         }
1934         return false;
1935     },
1936 
1937     /**
1938      * returns a new clone of the action
1939      * @returns {cc.FadeTo}
1940      */
1941     clone:function () {
1942         var action = new cc.FadeTo();
1943         action.initWithDuration(this._duration, this._toOpacity);
1944         return action;
1945     },
1946 
1947     /**
1948      * @param {Number} time time in seconds
1949      */
1950     update:function (time) {
1951         this._target.setOpacity((this._fromOpacity + (this._toOpacity - this._fromOpacity) * time));
1952     },
1953 
1954     /**
1955      * @param {cc.Sprite} target
1956      */
1957     startWithTarget:function (target) {
1958         cc.ActionInterval.prototype.startWithTarget.call(this, target);
1959         this._fromOpacity = target.getOpacity();
1960     }
1961 });
1962 
1963 /**
1964  * @param {Number} duration
1965  * @param {Number} opacity 0-255, 0 is transparent
1966  * @return {cc.FadeTo}
1967  * @example
1968  * // example
1969  * var action = cc.FadeTo.create(1.0, 0);
1970  */
1971 cc.FadeTo.create = function (duration, opacity) {
1972     var fadeTo = new cc.FadeTo();
1973     fadeTo.initWithDuration(duration, opacity);
1974     return fadeTo;
1975 };
1976 
1977 /** Tints a cc.Node that implements the cc.NodeRGB protocol from current tint to a custom one.
1978  * @warning This action doesn't support "reverse"
1979  * @class
1980  * @extends cc.ActionInterval
1981  */
1982 cc.TintTo = cc.ActionInterval.extend(/** @lends cc.TintTo# */{
1983     _to:null,
1984     _from:null,
1985 
1986     ctor:function () {
1987         cc.ActionInterval.prototype.ctor.call(this);
1988         this._to = cc.c3b(0, 0, 0);
1989         this._from = cc.c3b(0, 0, 0);
1990     },
1991 
1992     /**
1993      * @param {Number} duration
1994      * @param {Number} red 0-255
1995      * @param {Number} green 0-255
1996      * @param {Number} blue 0-255
1997      * @return {Boolean}
1998      */
1999     initWithDuration:function (duration, red, green, blue) {
2000         if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) {
2001             this._to = cc.c3b(red, green, blue);
2002             return true;
2003         }
2004         return false;
2005     },
2006 
2007     /**
2008      * returns a new clone of the action
2009      * @returns {cc.TintTo}
2010      */
2011     clone:function () {
2012         var action = new cc.TintTo();
2013         var locTo = this._to;
2014         action.initWithDuration(this._duration, locTo.r, locTo.g, locTo.b);
2015         return action;
2016     },
2017 
2018     /**
2019      * @param {cc.Sprite} target
2020      */
2021     startWithTarget:function (target) {
2022         cc.ActionInterval.prototype.startWithTarget.call(this, target);
2023         this._from = this._target.getColor();
2024     },
2025 
2026     /**
2027      * @param {Number} time time in seconds
2028      */
2029     update:function (time) {
2030         var locFrom = this._from, locTo = this._to;
2031         this._target.setColor(cc.c3b(locFrom.r + (locTo.r - locFrom.r) * time,
2032             (locFrom.g + (locTo.g - locFrom.g) * time), (locFrom.b + (locTo.b - locFrom.b) * time)));
2033     }
2034 });
2035 
2036 /**
2037  * @param {Number} duration
2038  * @param {Number} red 0-255
2039  * @param {Number} green  0-255
2040  * @param {Number} blue 0-255
2041  * @return {cc.TintTo}
2042  * @example
2043  * // example
2044  * var action = cc.TintTo.create(2, 255, 0, 255);
2045  */
2046 cc.TintTo.create = function (duration, red, green, blue) {
2047     var tintTo = new cc.TintTo();
2048     tintTo.initWithDuration(duration, red, green, blue);
2049     return tintTo;
2050 };
2051 
2052 
2053 /**  Tints a cc.Node that implements the cc.NodeRGB protocol from current tint to a custom one.
2054  * @class
2055  * @extends cc.ActionInterval
2056  */
2057 cc.TintBy = cc.ActionInterval.extend(/** @lends cc.TintBy# */{
2058     _deltaR:0,
2059     _deltaG:0,
2060     _deltaB:0,
2061 
2062     _fromR:0,
2063     _fromG:0,
2064     _fromB:0,
2065 
2066     ctor:function () {
2067         cc.ActionInterval.prototype.ctor.call(this);
2068         this._deltaR = 0;
2069         this._deltaG = 0;
2070         this._deltaB = 0;
2071         this._fromR = 0;
2072         this._fromG = 0;
2073         this._fromB = 0;
2074     },
2075 
2076     /**
2077      * @param {Number} duration
2078      * @param {Number} deltaRed 0-255
2079      * @param {Number} deltaGreen 0-255
2080      * @param {Number} deltaBlue 0-255
2081      * @return {Boolean}
2082      */
2083     initWithDuration:function (duration, deltaRed, deltaGreen, deltaBlue) {
2084         if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) {
2085             this._deltaR = deltaRed;
2086             this._deltaG = deltaGreen;
2087             this._deltaB = deltaBlue;
2088             return true;
2089         }
2090         return false;
2091     },
2092 
2093     /**
2094      * returns a new clone of the action
2095      * @returns {cc.TintBy}
2096      */
2097     clone:function () {
2098         var action = new cc.TintBy();
2099         action.initWithDuration(this._duration, this._deltaR, this._deltaG, this._deltaB);
2100         return action;
2101     },
2102 
2103     /**
2104      * @param {cc.Sprite} target
2105      */
2106     startWithTarget:function (target) {
2107         cc.ActionInterval.prototype.startWithTarget.call(this, target);
2108         if (target.RGBAProtocol) {
2109             var color = target.getColor();
2110             this._fromR = color.r;
2111             this._fromG = color.g;
2112             this._fromB = color.b;
2113         }
2114     },
2115 
2116     /**
2117      * @param {Number} time time in seconds
2118      */
2119     update:function (time) {
2120         if (this._target.RGBAProtocol) {
2121             this._target.setColor(cc.c3b((this._fromR + this._deltaR * time),
2122                 (this._fromG + this._deltaG * time),
2123                 (this._fromB + this._deltaB * time)));
2124         }
2125     },
2126 
2127     /**
2128      * @return {cc.ActionInterval}
2129      */
2130     reverse:function () {
2131         return cc.TintBy.create(this._duration, -this._deltaR, -this._deltaG, -this._deltaB);
2132     }
2133 });
2134 
2135 /**
2136  * @param {Number} duration  duration in seconds
2137  * @param {Number} deltaRed
2138  * @param {Number} deltaGreen
2139  * @param {Number} deltaBlue
2140  * @return {cc.TintBy}
2141  * @example
2142  * // example
2143  * var action = cc.TintBy.create(2, -127, -255, -127);
2144  */
2145 cc.TintBy.create = function (duration, deltaRed, deltaGreen, deltaBlue) {
2146     var tintBy = new cc.TintBy();
2147     tintBy.initWithDuration(duration, deltaRed, deltaGreen, deltaBlue);
2148     return tintBy;
2149 };
2150 
2151 /** Delays the action a certain amount of seconds
2152  * @class
2153  * @extends cc.ActionInterval
2154  */
2155 cc.DelayTime = cc.ActionInterval.extend(/** @lends cc.DelayTime# */{
2156     /**
2157      * @param {Number} time time in seconds
2158      */
2159     update:function (time) {
2160     },
2161 
2162     /**
2163      * @return {cc.ActionInterval}
2164      */
2165     reverse:function () {
2166         return cc.DelayTime.create(this._duration);
2167     },
2168 
2169     /**
2170      * returns a new clone of the action
2171      * @returns {cc.DelayTime}
2172      */
2173     clone:function () {
2174         var action = new cc.DelayTime();
2175         action.initWithDuration(this._duration);
2176         return action;
2177     }
2178 });
2179 
2180 /**
2181  * @param {Number} d duration in seconds
2182  * @return {cc.DelayTime}
2183  * @example
2184  * // example
2185  * var delay = cc.DelayTime.create(1);
2186  */
2187 cc.DelayTime.create = function (d) {
2188     var action = new cc.DelayTime();
2189     action.initWithDuration(d);
2190     return action;
2191 };
2192 
2193 /**
2194  * Executes an action in reverse order, from time=duration to time=0
2195  * @warning Use this action carefully. This action is not
2196  * sequenceable. Use it as the default "reversed" method
2197  * of your own actions, but using it outside the "reversed"
2198  * scope is not recommended.
2199  * @class
2200  * @extends cc.ActionInterval
2201  */
2202 cc.ReverseTime = cc.ActionInterval.extend(/** @lends cc.ReverseTime# */{
2203     _other:null,
2204 
2205     ctor:function () {
2206         cc.ActionInterval.prototype.ctor.call(this);
2207         this._other = null;
2208     },
2209 
2210     /**
2211      * @param {cc.FiniteTimeAction} action
2212      * @return {Boolean}
2213      */
2214     initWithAction:function (action) {
2215         cc.Assert(action != null, "");
2216         cc.Assert(action != this._other, "");
2217 
2218         if (cc.ActionInterval.prototype.initWithDuration.call(this, action.getDuration())) {
2219             // Don't leak if action is reused
2220             this._other = action;
2221             return true;
2222         }
2223         return false;
2224     },
2225 
2226     /**
2227      * returns a new clone of the action
2228      * @returns {cc.ReverseTime}
2229      */
2230     clone:function () {
2231         var action = new cc.ReverseTime();
2232         action.initWithAction(this._other.clone());
2233         return action;
2234     },
2235 
2236     /**
2237      * @param {cc.Node} target
2238      */
2239     startWithTarget:function (target) {
2240         cc.ActionInterval.prototype.startWithTarget.call(this, target);
2241         this._other.startWithTarget(target);
2242     },
2243 
2244     /**
2245      * @param {Number} time time in seconds
2246      */
2247     update:function (time) {
2248         if (this._other)
2249             this._other.update(1 - time);
2250     },
2251 
2252     /**
2253      * @return {cc.ActionInterval}
2254      */
2255     reverse:function () {
2256         return this._other.clone();
2257     },
2258 
2259     /**
2260      * Stop the action
2261      */
2262     stop:function () {
2263         this._other.stop();
2264         cc.Action.prototype.stop.call(this);
2265     }
2266 });
2267 
2268 /**
2269  * @param {cc.FiniteTimeAction} action
2270  * @return {cc.ReverseTime}
2271  * @example
2272  * // example
2273  *  var reverse = cc.ReverseTime.create(this);
2274  */
2275 cc.ReverseTime.create = function (action) {
2276     var reverseTime = new cc.ReverseTime();
2277     reverseTime.initWithAction(action);
2278     return reverseTime;
2279 };
2280 
2281 
2282 /**  Animates a sprite given the name of an Animation
2283  * @class
2284  * @extends cc.ActionInterval
2285  */
2286 cc.Animate = cc.ActionInterval.extend(/** @lends cc.Animate# */{
2287     _animation:null,
2288     _nextFrame:0,
2289     _origFrame:null,
2290     _executedLoops:0,
2291     _splitTimes:null,
2292 
2293     ctor:function () {
2294         cc.ActionInterval.prototype.ctor.call(this);
2295         this._animation = null;
2296         this._nextFrame = 0;
2297         this._origFrame = null;
2298         this._executedLoops = 0;
2299         this._splitTimes = null;
2300     },
2301 
2302     /**
2303      * @return {cc.Animation}
2304      */
2305     getAnimation:function () {
2306         return this._animation;
2307     },
2308 
2309     /**
2310      * @param {cc.Animation} animation
2311      */
2312     setAnimation:function (animation) {
2313         this._animation = animation;
2314     },
2315 
2316     /**
2317      * @param {cc.Animation} animation
2318      * @return {Boolean}
2319      */
2320     initWithAnimation:function (animation) {
2321         cc.Assert(animation != null, "Animate: argument Animation must be non-NULL");
2322         var singleDuration = animation.getDuration();
2323         if (this.initWithDuration(singleDuration * animation.getLoops())) {
2324             this._nextFrame = 0;
2325             this.setAnimation(animation);
2326 
2327             this._origFrame = null;
2328             this._executedLoops = 0;
2329             var locTimes = [];
2330 
2331             var accumUnitsOfTime = 0;
2332             var newUnitOfTimeValue = singleDuration / animation.getTotalDelayUnits();
2333 
2334             var frames = animation.getFrames();
2335             cc.ArrayVerifyType(frames, cc.AnimationFrame);
2336 
2337             for (var i = 0; i < frames.length; i++) {
2338                 var frame = frames[i];
2339                 var value = (accumUnitsOfTime * newUnitOfTimeValue) / singleDuration;
2340                 accumUnitsOfTime += frame.getDelayUnits();
2341                 locTimes.push(value);
2342             }
2343             this._splitTimes = locTimes;
2344             return true;
2345         }
2346         return false;
2347     },
2348 
2349     /**
2350      * returns a new clone of the action
2351      * @returns {cc.Animate}
2352      */
2353     clone:function () {
2354         var action = new cc.Animate();
2355         action.initWithAnimation(this._animation.clone());
2356         return action;
2357     },
2358 
2359     /**
2360      * @param {cc.Sprite} target
2361      */
2362     startWithTarget:function (target) {
2363         cc.ActionInterval.prototype.startWithTarget.call(this, target);
2364         if (this._animation.getRestoreOriginalFrame())
2365             this._origFrame = target.displayFrame();
2366         this._nextFrame = 0;
2367         this._executedLoops = 0;
2368     },
2369 
2370     /**
2371      * @param {Number} time
2372      */
2373     update:function (time) {
2374         // if t==1, ignore. Animation should finish with t==1
2375         if (time < 1.0) {
2376             time *= this._animation.getLoops();
2377 
2378             // new loop?  If so, reset frame counter
2379             var loopNumber = 0 | time;
2380             if (loopNumber > this._executedLoops) {
2381                 this._nextFrame = 0;
2382                 this._executedLoops++;
2383             }
2384 
2385             // new t for animations
2386             time = time % 1.0;
2387         }
2388 
2389         var frames = this._animation.getFrames();
2390         var numberOfFrames = frames.length, locSplitTimes = this._splitTimes;
2391         for (var i = this._nextFrame; i < numberOfFrames; i++) {
2392             if (locSplitTimes[i] <= time) {
2393                 this._target.setDisplayFrame(frames[i].getSpriteFrame());
2394                 this._nextFrame = i + 1;
2395             } else {
2396                 // Issue 1438. Could be more than one frame per tick, due to low frame rate or frame delta < 1/FPS
2397                 break;
2398             }
2399         }
2400     },
2401 
2402     /**
2403      * @return {cc.ActionInterval}
2404      */
2405     reverse:function () {
2406         var locAnimation = this._animation;
2407         var oldArray = locAnimation.getFrames();
2408         var newArray = [];
2409         cc.ArrayVerifyType(oldArray, cc.AnimationFrame);
2410         if (oldArray.length > 0) {
2411             for (var i = oldArray.length - 1; i >= 0; i--) {
2412                 var element = oldArray[i];
2413                 if (!element)
2414                     break;
2415                 newArray.push(element.clone());
2416             }
2417         }
2418         var newAnim = cc.Animation.createWithAnimationFrames(newArray, locAnimation.getDelayPerUnit(), locAnimation.getLoops());
2419         newAnim.setRestoreOriginalFrame(locAnimation.getRestoreOriginalFrame());
2420         return cc.Animate.create(newAnim);
2421     },
2422 
2423     /**
2424      * stop the action
2425      */
2426     stop:function () {
2427         if (this._animation.getRestoreOriginalFrame() && this._target)
2428             this._target.setDisplayFrame(this._origFrame);
2429         cc.Action.prototype.stop.call(this);
2430     }
2431 });
2432 
2433 /**
2434  * create the animate with animation
2435  * @param {cc.Animation} animation
2436  * @return {cc.Animate}
2437  * @example
2438  * // example
2439  * // create the animation with animation
2440  * var anim = cc.Animate.create(dance_grey);
2441  */
2442 cc.Animate.create = function (animation) {
2443     var animate = new cc.Animate();
2444     animate.initWithAnimation(animation);
2445     return animate;
2446 };
2447 
2448 /**
2449  * <p>
2450  *     Overrides the target of an action so that it always runs on the target<br/>
2451  *     specified at action creation rather than the one specified by runAction.
2452  * </p>
2453  * @class
2454  * @extends cc.ActionInterval
2455  */
2456 cc.TargetedAction = cc.ActionInterval.extend(/** @lends cc.TargetedAction# */{
2457     _action:null,
2458     _forcedTarget:null,
2459 
2460     ctor:function () {
2461         cc.ActionInterval.prototype.ctor.call(this);
2462         this._action = null;
2463         this._forcedTarget = null;
2464     },
2465 
2466     /**
2467      * Init an action with the specified action and forced target
2468      * @param {cc.Node} target
2469      * @param {cc.FiniteTimeAction} action
2470      * @return {Boolean}
2471      */
2472     initWithTarget:function (target, action) {
2473         if (this.initWithDuration(action.getDuration())) {
2474             this._forcedTarget = target;
2475             this._action = action;
2476             return true;
2477         }
2478         return false;
2479     },
2480 
2481     /**
2482      * returns a new clone of the action
2483      * @returns {cc.TargetedAction}
2484      */
2485     clone:function () {
2486         var action = new cc.TargetedAction();
2487         action.initWithTarget(this._forcedTarget, this._action.clone());
2488         return action;
2489     },
2490 
2491     startWithTarget:function (target) {
2492         cc.ActionInterval.prototype.startWithTarget.call(this, target);
2493         this._action.startWithTarget(this._forcedTarget);
2494     },
2495 
2496     stop:function () {
2497         this._action.stop();
2498     },
2499 
2500     update:function (time) {
2501         this._action.update(time);
2502     },
2503 
2504     /**
2505      * return the target that the action will be forced to run with
2506      * @return {cc.Node}
2507      */
2508     getForcedTarget:function () {
2509         return this._forcedTarget;
2510     },
2511 
2512     /**
2513      * set the target that the action will be forced to run with
2514      * @param {cc.Node} forcedTarget
2515      */
2516     setForcedTarget:function (forcedTarget) {
2517         if (this._forcedTarget != forcedTarget)
2518             this._forcedTarget = forcedTarget;
2519     }
2520 });
2521 
2522 /**
2523  * Create an action with the specified action and forced target
2524  * @param {cc.Node} target
2525  * @param {cc.FiniteTimeAction} action
2526  */
2527 cc.TargetedAction.create = function (target, action) {
2528     var retObj = new cc.TargetedAction();
2529     retObj.initWithTarget(target, action);
2530     return retObj;
2531 };
2532