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