1 /**************************************************************************** 2 Copyright (c) 2010-2012 cocos2d-x.org 3 Copyright (c) 2008-2010 Ricardo Quesada 4 Copyright (c) 2011 Zynga Inc. 5 6 http://www.cocos2d-x.org 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy 9 of this software and associated documentation files (the "Software"), to deal 10 in the Software without restriction, including without limitation the rights 11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 copies of the Software, and to permit persons to whom the Software is 13 furnished to do so, subject to the following conditions: 14 15 The above copyright notice and this permission notice shall be included in 16 all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 THE SOFTWARE. 25 ****************************************************************************/ 26 27 /** 28 * <p> An interval action is an action that takes place within a certain period of time. <br/> 29 * It has an start time, and a finish time. The finish time is the parameter<br/> 30 * duration plus the start time.</p> 31 * 32 * <p>These CCActionInterval actions have some interesting properties, like:<br/> 33 * - They can run normally (default) <br/> 34 * - They can run reversed with the reverse method <br/> 35 * - They can run with the time altered with the Accelerate, AccelDeccel and Speed actions. </p> 36 * 37 * <p>For example, you can simulate a Ping Pong effect running the action normally and<br/> 38 * then running it again in Reverse mode. </p> 39 * 40 * @class 41 * @extends cc.FiniteTimeAction 42 * @Example 43 * // example 44 * var pingPongAction = cc.Sequence.create(action, action.reverse()); 45 */ 46 cc.ActionInterval = cc.FiniteTimeAction.extend(/** @lends cc.ActionInterval# */{ 47 _elapsed:0, 48 _firstTick:false, 49 50 ctor:function () { 51 cc.FiniteTimeAction.prototype.ctor.call(this); 52 this._elapsed = 0; 53 this._firstTick = false; 54 }, 55 56 /** how many seconds had elapsed since the actions started to run. 57 * @return {Number} 58 */ 59 getElapsed:function () { 60 return this._elapsed; 61 }, 62 63 /** initializes the action 64 * @param {Number} d duration in seconds 65 * @return {Boolean} 66 */ 67 initWithDuration:function (d) { 68 this._duration = (d === 0) ? cc.FLT_EPSILON : d; 69 // prevent division by 0 70 // This comparison could be in step:, but it might decrease the performance 71 // by 3% in heavy based action games. 72 this._elapsed = 0; 73 this._firstTick = true; 74 return true; 75 }, 76 77 /** returns true if the action has finished 78 * @return {Boolean} 79 */ 80 isDone:function () { 81 return (this._elapsed >= this._duration); 82 }, 83 84 /** 85 * returns a new clone of the action 86 * @returns {cc.ActionInterval} 87 */ 88 clone:function () { 89 var action = new cc.ActionInterval(); 90 action.initWithDuration(this._duration); 91 return action; 92 }, 93 94 /** 95 * @param {Number} dt delta time in seconds 96 */ 97 step:function (dt) { 98 if (this._firstTick) { 99 this._firstTick = false; 100 this._elapsed = 0; 101 } else 102 this._elapsed += dt; 103 104 //this.update((1 > (this._elapsed / this._duration)) ? this._elapsed / this._duration : 1); 105 //this.update(Math.max(0, Math.min(1, this._elapsed / Math.max(this._duration, cc.FLT_EPSILON)))); 106 var t = this._elapsed / (this._duration > 0.0000001192092896 ? this._duration : 0.0000001192092896); 107 t = (1 > t ? t : 1); 108 this.update(t > 0 ? t : 0); 109 }, 110 111 /** 112 * @param {cc.Node} target 113 */ 114 startWithTarget:function (target) { 115 cc.Action.prototype.startWithTarget.call(this, target); 116 this._elapsed = 0; 117 this._firstTick = true; 118 }, 119 120 /** 121 * @return {Null} 122 */ 123 reverse:function () { 124 cc.log("cc.IntervalAction: reverse not implemented."); 125 return null; 126 }, 127 128 /** 129 * @param {Number} amp 130 */ 131 setAmplitudeRate:function (amp) { 132 // Abstract class needs implementation 133 cc.log("cc.ActionInterval.setAmplitudeRate(): it should be overridden in subclass."); 134 }, 135 136 /** 137 * @return {Number} 138 */ 139 getAmplitudeRate:function () { 140 // Abstract class needs implementation 141 cc.log("cc.ActionInterval.getAmplitudeRate(): it should be overridden in subclass."); 142 } 143 }); 144 145 /** 146 * @param {Number} d duration in seconds 147 * @return {cc.ActionInterval} 148 * @example 149 * // example 150 * var actionInterval = cc.ActionInterval.create(3); 151 */ 152 cc.ActionInterval.create = function (d) { 153 var action = new cc.ActionInterval(); 154 action.initWithDuration(d); 155 return action; 156 }; 157 158 159 /** Runs actions sequentially, one after another 160 * @class 161 * @extends cc.ActionInterval 162 */ 163 cc.Sequence = cc.ActionInterval.extend(/** @lends cc.Sequence# */{ 164 _actions:null, 165 _split:null, 166 _last:0, 167 168 /** 169 * Constructor 170 */ 171 ctor:function () { 172 cc.ActionInterval.prototype.ctor.call(this); 173 this._actions = []; 174 this._split = null; 175 this._last = 0; 176 }, 177 178 /** initializes the action <br/> 179 * @param {cc.FiniteTimeAction} actionOne 180 * @param {cc.FiniteTimeAction} actionTwo 181 * @return {Boolean} 182 */ 183 initWithTwoActions:function (actionOne, actionTwo) { 184 if(!actionOne || !actionTwo) 185 throw "cc.Sequence.initWithTwoActions(): arguments must all be non nil"; 186 187 var d = actionOne.getDuration() + actionTwo.getDuration(); 188 this.initWithDuration(d); 189 190 this._actions[0] = actionOne; 191 this._actions[1] = actionTwo; 192 return true; 193 }, 194 195 /** 196 * returns a new clone of the action 197 * @returns {cc.Sequence} 198 */ 199 clone:function () { 200 var action = new cc.Sequence(); 201 action.initWithTwoActions(this._actions[0].clone(), this._actions[1].clone()); 202 return action; 203 }, 204 205 /** 206 * @param {cc.Node} target 207 */ 208 startWithTarget:function (target) { 209 cc.ActionInterval.prototype.startWithTarget.call(this, target); 210 this._split = this._actions[0].getDuration() / this._duration; 211 this._last = -1; 212 }, 213 214 /** 215 * stop the action 216 */ 217 stop:function () { 218 // Issue #1305 219 if (this._last !== -1) 220 this._actions[this._last].stop(); 221 cc.Action.prototype.stop.call(this); 222 }, 223 224 /** 225 * @param {Number} time time in seconds 226 */ 227 update:function (time) { 228 var new_t, found = 0; 229 var locSplit = this._split, locActions = this._actions, locLast = this._last; 230 if (time < locSplit) { 231 // action[0] 232 new_t = (locSplit !== 0) ? time / locSplit : 1; 233 234 if (found === 0 && locLast === 1) { 235 // Reverse mode ? 236 // XXX: Bug. this case doesn't contemplate when _last==-1, found=0 and in "reverse mode" 237 // since it will require a hack to know if an action is on reverse mode or not. 238 // "step" should be overriden, and the "reverseMode" value propagated to inner Sequences. 239 locActions[1].update(0); 240 locActions[1].stop(); 241 } 242 } else { 243 // action[1] 244 found = 1; 245 new_t = (locSplit === 1) ? 1 : (time - locSplit) / (1 - locSplit); 246 247 if (locLast === -1) { 248 // action[0] was skipped, execute it. 249 locActions[0].startWithTarget(this._target); 250 locActions[0].update(1); 251 locActions[0].stop(); 252 } 253 if (!locLast) { 254 // switching to action 1. stop action 0. 255 locActions[0].update(1); 256 locActions[0].stop(); 257 } 258 } 259 260 // Last action found and it is done. 261 if (locLast === found && locActions[found].isDone()) 262 return; 263 264 // Last action found and it is done 265 if (locLast !== found) 266 locActions[found].startWithTarget(this._target); 267 268 locActions[found].update(new_t); 269 this._last = found; 270 }, 271 272 /** 273 * @return {cc.ActionInterval} 274 */ 275 reverse:function () { 276 return cc.Sequence._actionOneTwo(this._actions[1].reverse(), this._actions[0].reverse()); 277 }, 278 279 /** 280 * to copy object with deep copy. 281 * @return {object} 282 */ 283 copy:function () { 284 return this.clone(); 285 } 286 }); 287 /** helper constructor to create an array of sequenceable actions 288 * @param {Array|cc.FiniteTimeAction} tempArray 289 * @return {cc.Sequence} 290 * @example 291 * // example 292 * // create sequence with actions 293 * var seq = cc.Sequence.create(act1, act2); 294 * 295 * // create sequence with array 296 * var seq = cc.Sequence.create(actArray); 297 */ 298 cc.Sequence.create = function (/*Multiple Arguments*/tempArray) { 299 var paraArray = (tempArray instanceof Array) ? tempArray : arguments; 300 if ((paraArray.length > 0) && (paraArray[paraArray.length - 1] == null)) 301 cc.log("parameters should not be ending with null in Javascript"); 302 303 var prev = paraArray[0]; 304 for (var i = 1; i < paraArray.length; i++) { 305 if (paraArray[i]) 306 prev = cc.Sequence._actionOneTwo(prev, paraArray[i]); 307 } 308 return prev; 309 }; 310 311 /** creates the action 312 * @param {cc.FiniteTimeAction} actionOne 313 * @param {cc.FiniteTimeAction} actionTwo 314 * @return {cc.Sequence} 315 * @private 316 */ 317 cc.Sequence._actionOneTwo = function (actionOne, actionTwo) { 318 var sequence = new cc.Sequence(); 319 sequence.initWithTwoActions(actionOne, actionTwo); 320 return sequence; 321 }; 322 323 324 /** Repeats an action a number of times. 325 * To repeat an action forever use the CCRepeatForever action. 326 * @class 327 * @extends cc.ActionInterval 328 */ 329 cc.Repeat = cc.ActionInterval.extend(/** @lends cc.Repeat# */{ 330 _times:0, 331 _total:0, 332 _nextDt:0, 333 _actionInstant:false, 334 _innerAction:null, //CCFiniteTimeAction 335 336 ctor:function () { 337 cc.ActionInterval.prototype.ctor.call(this); 338 this._times = 0; 339 this._total = 0; 340 this._nextDt = 0; 341 this._actionInstant = false; 342 this._innerAction = null; 343 }, 344 345 /** 346 * @param {cc.FiniteTimeAction} action 347 * @param {Number} times 348 * @return {Boolean} 349 */ 350 initWithAction:function (action, times) { 351 var duration = action.getDuration() * times; 352 353 if (this.initWithDuration(duration)) { 354 this._times = times; 355 this._innerAction = action; 356 if (action instanceof cc.ActionInstant) 357 this._times -= 1; 358 this._total = 0; 359 return true; 360 } 361 return false; 362 }, 363 364 /** 365 * returns a new clone of the action 366 * @returns {cc.Repeat} 367 */ 368 clone:function () { 369 var action = new cc.Repeat(); 370 action.initWithAction(this._innerAction.clone(), this._times); 371 return action; 372 }, 373 374 /** 375 * @param {cc.Node} target 376 */ 377 startWithTarget:function (target) { 378 this._total = 0; 379 this._nextDt = this._innerAction.getDuration() / this._duration; 380 cc.ActionInterval.prototype.startWithTarget.call(this, target); 381 this._innerAction.startWithTarget(target); 382 }, 383 384 /** 385 * stop the action 386 */ 387 stop:function () { 388 this._innerAction.stop(); 389 cc.Action.prototype.stop.call(this); 390 }, 391 392 /** 393 * @param {Number} time time in seconds 394 */ 395 update:function (time) { 396 var locInnerAction = this._innerAction; 397 var locDuration = this._duration; 398 var locTimes = this._times; 399 var locNextDt = this._nextDt; 400 401 if (time >= locNextDt) { 402 while (time > locNextDt && this._total < locTimes) { 403 locInnerAction.update(1); 404 this._total++; 405 locInnerAction.stop(); 406 locInnerAction.startWithTarget(this._target); 407 locNextDt += locInnerAction.getDuration() / locDuration; 408 this._nextDt = locNextDt; 409 } 410 411 // fix for issue #1288, incorrect end value of repeat 412 if (time >= 1.0 && this._total < locTimes) 413 this._total++; 414 415 // don't set a instantaction back or update it, it has no use because it has no duration 416 if (this._actionInstant) { 417 if (this._total == locTimes) { 418 locInnerAction.update(1); 419 locInnerAction.stop(); 420 } else { 421 // issue #390 prevent jerk, use right update 422 locInnerAction.update(time - (locNextDt - locInnerAction.getDuration() / locDuration)); 423 } 424 } 425 } else { 426 locInnerAction.update((time * locTimes) % 1.0); 427 } 428 }, 429 430 /** 431 * @return {Boolean} 432 */ 433 isDone:function () { 434 return this._total == this._times; 435 }, 436 437 /** 438 * @return {cc.ActionInterval} 439 */ 440 reverse:function () { 441 return cc.Repeat.create(this._innerAction.reverse(), this._times); 442 }, 443 444 /** 445 * @param {cc.FiniteTimeAction} action 446 */ 447 setInnerAction:function (action) { 448 if (this._innerAction != action) { 449 this._innerAction = action; 450 } 451 }, 452 453 /** 454 * @return {cc.FiniteTimeAction} 455 */ 456 getInnerAction:function () { 457 return this._innerAction; 458 } 459 }); 460 /** creates a CCRepeat action. Times is an unsigned integer between 1 and pow(2,30) 461 * @param {cc.FiniteTimeAction} action 462 * @param {Number} times 463 * @return {cc.Repeat} 464 * @example 465 * // example 466 * var rep = cc.Repeat.create(cc.Sequence.create(jump2, jump1), 5); 467 */ 468 cc.Repeat.create = function (action, times) { 469 var repeat = new cc.Repeat(); 470 repeat.initWithAction(action, times); 471 return repeat; 472 }; 473 474 475 /** Repeats an action for ever. <br/> 476 * To repeat the an action for a limited number of times use the Repeat action. <br/> 477 * @warning This action can't be Sequencable because it is not an IntervalAction 478 * @class 479 * @extends cc.ActionInterval 480 */ 481 482 cc.RepeatForever = cc.ActionInterval.extend(/** @lends cc.RepeatForever# */{ 483 _innerAction:null, //CCActionInterval 484 485 ctor:function () { 486 cc.ActionInterval.prototype.ctor.call(this); 487 this._innerAction = null; 488 }, 489 490 /** 491 * @param {cc.ActionInterval} action 492 * @return {Boolean} 493 */ 494 initWithAction:function (action) { 495 if(!action) 496 throw "cc.RepeatForever.initWithAction(): action must be non null"; 497 498 this._innerAction = action; 499 return true; 500 }, 501 502 /** 503 * returns a new clone of the action 504 * @returns {cc.RepeatForever} 505 */ 506 clone:function () { 507 var action = new cc.RepeatForever(); 508 action.initWithAction(this._innerAction.clone()); 509 return action; 510 }, 511 512 /** 513 * @param {cc.Node} target 514 */ 515 startWithTarget:function (target) { 516 cc.ActionInterval.prototype.startWithTarget.call(this, target); 517 this._innerAction.startWithTarget(target); 518 }, 519 520 /** 521 * @param dt delta time in seconds 522 */ 523 step:function (dt) { 524 var locInnerAction = this._innerAction; 525 locInnerAction.step(dt); 526 if (locInnerAction.isDone()) { 527 //var diff = locInnerAction.getElapsed() - locInnerAction.getDuration(); 528 locInnerAction.startWithTarget(this._target); 529 // to prevent jerk. issue #390 ,1247 530 //this._innerAction.step(0); 531 //this._innerAction.step(diff); 532 locInnerAction.step(locInnerAction.getElapsed() - locInnerAction.getDuration()); 533 } 534 }, 535 536 /** 537 * @return {Boolean} 538 */ 539 isDone:function () { 540 return false; 541 }, 542 543 /** 544 * @return {cc.ActionInterval} 545 */ 546 reverse:function () { 547 return (cc.RepeatForever.create(this._innerAction.reverse())); 548 }, 549 550 /** 551 * 552 * @param {cc.ActionInterval} action 553 */ 554 setInnerAction:function (action) { 555 if (this._innerAction != action) { 556 this._innerAction = action; 557 } 558 }, 559 560 /** 561 * @return {cc.ActionInterval} 562 */ 563 getInnerAction:function () { 564 return this._innerAction; 565 } 566 }); 567 /** 568 * Repeat the acton forever 569 * @param action 570 * @return {cc.RepeatForever} 571 * @example 572 * // example 573 * var repeat = cc.RepeatForever.create(cc.RotateBy.create(1.0, 360)); 574 */ 575 cc.RepeatForever.create = function (action) { 576 var ret = new cc.RepeatForever(); 577 if (ret && ret.initWithAction(action)) 578 return ret; 579 return null; 580 }; 581 582 583 /** Spawn a new action immediately 584 * @class 585 * @extends cc.ActionInterval 586 */ 587 cc.Spawn = cc.ActionInterval.extend(/** @lends cc.Spawn# */{ 588 _one:null, 589 _two:null, 590 591 ctor:function () { 592 cc.ActionInterval.prototype.ctor.call(this); 593 this._one = null; 594 this._two = null; 595 }, 596 597 /** initializes the Spawn action with the 2 actions to spawn 598 * @param {cc.FiniteTimeAction} action1 599 * @param {cc.FiniteTimeAction} action2 600 * @return {Boolean} 601 */ 602 initWithTwoActions:function (action1, action2) { 603 if(!action1 || !action2) 604 throw "cc.Spawn.initWithTwoActions(): arguments must all be non null" ; 605 606 var ret = false; 607 608 var d1 = action1.getDuration(); 609 var d2 = action2.getDuration(); 610 611 if (this.initWithDuration(Math.max(d1, d2))) { 612 this._one = action1; 613 this._two = action2; 614 615 if (d1 > d2) { 616 this._two = cc.Sequence._actionOneTwo(action2, cc.DelayTime.create(d1 - d2)); 617 } else if (d1 < d2) { 618 this._one = cc.Sequence._actionOneTwo(action1, cc.DelayTime.create(d2 - d1)); 619 } 620 621 ret = true; 622 } 623 return ret; 624 }, 625 626 /** 627 * returns a new clone of the action 628 * @returns {cc.Spawn} 629 */ 630 clone:function () { 631 var action = new cc.Spawn(); 632 action.initWithTwoActions(this._one.clone(), this._two.clone()); 633 return action; 634 }, 635 636 /** 637 * @param {cc.Node} target 638 */ 639 startWithTarget:function (target) { 640 cc.ActionInterval.prototype.startWithTarget.call(this, target); 641 this._one.startWithTarget(target); 642 this._two.startWithTarget(target); 643 }, 644 645 /** 646 * Stop the action 647 */ 648 stop:function () { 649 this._one.stop(); 650 this._two.stop(); 651 cc.Action.prototype.stop.call(this); 652 }, 653 654 /** 655 * @param {Number} time time in seconds 656 */ 657 update:function (time) { 658 if (this._one) 659 this._one.update(time); 660 if (this._two) 661 this._two.update(time); 662 }, 663 664 /** 665 * @return {cc.FiniteTimeAction} 666 */ 667 reverse:function () { 668 return cc.Spawn._actionOneTwo(this._one.reverse(), this._two.reverse()); 669 } 670 }); 671 672 /** 673 * @param {Array|cc.FiniteTimeAction}tempArray 674 * @return {cc.FiniteTimeAction} 675 * @example 676 * // example 677 * var action = cc.Spawn.create(cc.JumpBy.create(2, cc.p(300, 0), 50, 4), cc.RotateBy.create(2, 720)); 678 */ 679 cc.Spawn.create = function (/*Multiple Arguments*/tempArray) { 680 var paramArray = (tempArray instanceof Array) ? tempArray : arguments; 681 if ((paramArray.length > 0) && (paramArray[paramArray.length - 1] == null)) 682 cc.log("parameters should not be ending with null in Javascript"); 683 684 var prev = paramArray[0]; 685 for (var i = 1; i < paramArray.length; i++) { 686 if (paramArray[i] != null) 687 prev = this._actionOneTwo(prev, paramArray[i]); 688 } 689 return prev; 690 }; 691 692 /** 693 * @param {cc.FiniteTimeAction} action1 694 * @param {cc.FiniteTimeAction} action2 695 * @return {cc.Spawn} 696 * @private 697 */ 698 cc.Spawn._actionOneTwo = function (action1, action2) { 699 var pSpawn = new cc.Spawn(); 700 pSpawn.initWithTwoActions(action1, action2); 701 return pSpawn; 702 }; 703 704 705 /** Rotates a cc.Node object to a certain angle by modifying it's 706 * rotation attribute. <br/> 707 * The direction will be decided by the shortest angle. 708 * @class 709 * @extends cc.ActionInterval 710 */ 711 cc.RotateTo = cc.ActionInterval.extend(/** @lends cc.RotateTo# */{ 712 _dstAngleX:0, 713 _startAngleX:0, 714 _diffAngleX:0, 715 716 _dstAngleY:0, 717 _startAngleY:0, 718 _diffAngleY:0, 719 720 ctor:function () { 721 cc.ActionInterval.prototype.ctor.call(this); 722 this._dstAngleX = 0; 723 this._startAngleX = 0; 724 this._diffAngleX = 0; 725 726 this._dstAngleY = 0; 727 this._startAngleY = 0; 728 this._diffAngleY = 0; 729 }, 730 731 /** 732 * @param {Number} duration 733 * @param {Number} deltaAngleX 734 * @param {Number} deltaAngleY 735 * @return {Boolean} 736 */ 737 initWithDuration:function (duration, deltaAngleX, deltaAngleY) { 738 if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) { 739 this._dstAngleX = deltaAngleX || 0; 740 this._dstAngleY = deltaAngleY || this._dstAngleX; 741 return true; 742 } 743 return false; 744 }, 745 746 /** 747 * returns a new clone of the action 748 * @returns {cc.RotateTo} 749 */ 750 clone:function () { 751 var action = new cc.RotateTo(); 752 action.initWithDuration(this._duration, this._dstAngleX, this._dstAngleY); 753 return action; 754 }, 755 756 /** 757 * @param {cc.Node} target 758 */ 759 startWithTarget:function (target) { 760 cc.ActionInterval.prototype.startWithTarget.call(this, target); 761 762 // Calculate X 763 var locStartAngleX = target.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.log("cc.RotateTo.reverse(): it should be overridden in subclass."); 787 }, 788 789 /** 790 * @param {Number} time time in seconds 791 */ 792 update:function (time) { 793 if (this._target) { 794 this._target.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 an object that implements the cc.RGBAProtocol protocol. It modifies the opacity from the current value to a custom one. 1821 * @warning This action doesn't support "reverse" 1822 * @class 1823 * @extends cc.ActionInterval 1824 */ 1825 cc.FadeTo = cc.ActionInterval.extend(/** @lends cc.FadeTo# */{ 1826 _toOpacity:null, 1827 _fromOpacity:null, 1828 1829 ctor:function () { 1830 cc.ActionInterval.prototype.ctor.call(this); 1831 this._toOpacity = 0; 1832 this._fromOpacity = 0; 1833 }, 1834 1835 /** 1836 * @param {Number} duration duration in seconds 1837 * @param {Number} opacity 1838 * @return {Boolean} 1839 */ 1840 initWithDuration:function (duration, opacity) { 1841 if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) { 1842 this._toOpacity = opacity; 1843 return true; 1844 } 1845 return false; 1846 }, 1847 1848 /** 1849 * returns a new clone of the action 1850 * @returns {cc.FadeTo} 1851 */ 1852 clone:function () { 1853 var action = new cc.FadeTo(); 1854 action.initWithDuration(this._duration, this._toOpacity); 1855 return action; 1856 }, 1857 1858 /** 1859 * @param {Number} time time in seconds 1860 */ 1861 update:function (time) { 1862 if (this._target.RGBAProtocol) { 1863 var fromOpacity = this._fromOpacity; 1864 this._target.setOpacity((fromOpacity + (this._toOpacity - fromOpacity) * time)); 1865 } 1866 }, 1867 1868 /** 1869 * @param {cc.Sprite} target 1870 */ 1871 startWithTarget:function (target) { 1872 cc.ActionInterval.prototype.startWithTarget.call(this, target); 1873 if(this._target.RGBAProtocol){ 1874 this._fromOpacity = target.getOpacity(); 1875 } 1876 } 1877 }); 1878 1879 /** 1880 * @param {Number} duration 1881 * @param {Number} opacity 0-255, 0 is transparent 1882 * @return {cc.FadeTo} 1883 * @example 1884 * // example 1885 * var action = cc.FadeTo.create(1.0, 0); 1886 */ 1887 cc.FadeTo.create = function (duration, opacity) { 1888 var fadeTo = new cc.FadeTo(); 1889 fadeTo.initWithDuration(duration, opacity); 1890 return fadeTo; 1891 }; 1892 1893 /** Fades In an object that implements the cc.RGBAProtocol protocol. It modifies the opacity from 0 to 255.<br/> 1894 * The "reverse" of this action is FadeOut 1895 * @class 1896 * @extends cc.FadeTo 1897 */ 1898 cc.FadeIn = cc.FadeTo.extend(/** @lends cc.FadeIn# */{ 1899 _reverseAction: null, 1900 /** 1901 * @return {cc.ActionInterval} 1902 */ 1903 reverse:function () { 1904 var action = new cc.FadeOut(); 1905 action.initWithDuration(this._duration, 0); 1906 return action; 1907 }, 1908 1909 /** 1910 * returns a new clone of the action 1911 * @returns {cc.FadeIn} 1912 */ 1913 clone:function () { 1914 var action = new cc.FadeIn(); 1915 action.initWithDuration(this._duration, this._toOpacity); 1916 return action; 1917 }, 1918 1919 /** 1920 * @param {cc.Sprite} target 1921 */ 1922 startWithTarget:function (target) { 1923 if(this._reverseAction) 1924 this._toOpacity = this._reverseAction._fromOpacity; 1925 cc.FadeTo.prototype.startWithTarget.call(this, target); 1926 } 1927 }); 1928 1929 /** 1930 * @param {Number} duration duration in seconds 1931 * @param {Number} [toOpacity] to opacity 1932 * @return {cc.FadeIn} 1933 * @example 1934 * //example 1935 * var action = cc.FadeIn.create(1.0); 1936 */ 1937 cc.FadeIn.create = function (duration, toOpacity) { 1938 if(toOpacity == null) 1939 toOpacity = 255; 1940 var action = new cc.FadeIn(); 1941 action.initWithDuration(duration, toOpacity); 1942 return action; 1943 }; 1944 1945 1946 /** Fades Out an object that implements the cc.RGBAProtocol protocol. It modifies the opacity from 255 to 0. 1947 * The "reverse" of this action is FadeIn 1948 * @class 1949 * @extends cc.FadeTo 1950 */ 1951 cc.FadeOut = cc.FadeTo.extend(/** @lends cc.FadeOut# */{ 1952 /** 1953 * @return {cc.ActionInterval} 1954 */ 1955 reverse:function () { 1956 var action = new cc.FadeIn(); 1957 action._reverseAction = this; 1958 action.initWithDuration(this._duration, 255); 1959 return action; 1960 }, 1961 1962 /** 1963 * returns a new clone of the action 1964 * @returns {cc.FadeOut} 1965 */ 1966 clone:function () { 1967 var action = new cc.FadeOut(); 1968 action.initWithDuration(this._duration, this._toOpacity); 1969 return action; 1970 } 1971 }); 1972 1973 /** 1974 * @param {Number} d duration in seconds 1975 * @return {cc.FadeOut} 1976 * @example 1977 * // example 1978 * var action = cc.FadeOut.create(1.0); 1979 */ 1980 cc.FadeOut.create = function (d) { 1981 var action = new cc.FadeOut(); 1982 action.initWithDuration(d, 0); 1983 return action; 1984 }; 1985 1986 /** Tints a cc.Node that implements the cc.NodeRGB protocol from current tint to a custom one. 1987 * @warning This action doesn't support "reverse" 1988 * @class 1989 * @extends cc.ActionInterval 1990 */ 1991 cc.TintTo = cc.ActionInterval.extend(/** @lends cc.TintTo# */{ 1992 _to:null, 1993 _from:null, 1994 1995 ctor:function () { 1996 cc.ActionInterval.prototype.ctor.call(this); 1997 this._to = cc.c3b(0, 0, 0); 1998 this._from = cc.c3b(0, 0, 0); 1999 }, 2000 2001 /** 2002 * @param {Number} duration 2003 * @param {Number} red 0-255 2004 * @param {Number} green 0-255 2005 * @param {Number} blue 0-255 2006 * @return {Boolean} 2007 */ 2008 initWithDuration:function (duration, red, green, blue) { 2009 if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) { 2010 this._to = cc.c3b(red, green, blue); 2011 return true; 2012 } 2013 return false; 2014 }, 2015 2016 /** 2017 * returns a new clone of the action 2018 * @returns {cc.TintTo} 2019 */ 2020 clone:function () { 2021 var action = new cc.TintTo(); 2022 var locTo = this._to; 2023 action.initWithDuration(this._duration, locTo.r, locTo.g, locTo.b); 2024 return action; 2025 }, 2026 2027 /** 2028 * @param {cc.Sprite} target 2029 */ 2030 startWithTarget:function (target) { 2031 cc.ActionInterval.prototype.startWithTarget.call(this, target); 2032 if (this._target.RGBAProtocol) { 2033 this._from = this._target.getColor(); 2034 } 2035 }, 2036 2037 /** 2038 * @param {Number} time time in seconds 2039 */ 2040 update:function (time) { 2041 var locFrom = this._from, locTo = this._to; 2042 if (this._target.RGBAProtocol) { 2043 this._target.setColor(cc.c3b(locFrom.r + (locTo.r - locFrom.r) * time, 2044 (locFrom.g + (locTo.g - locFrom.g) * time), (locFrom.b + (locTo.b - locFrom.b) * time))); 2045 } 2046 } 2047 }); 2048 2049 /** 2050 * @param {Number} duration 2051 * @param {Number} red 0-255 2052 * @param {Number} green 0-255 2053 * @param {Number} blue 0-255 2054 * @return {cc.TintTo} 2055 * @example 2056 * // example 2057 * var action = cc.TintTo.create(2, 255, 0, 255); 2058 */ 2059 cc.TintTo.create = function (duration, red, green, blue) { 2060 var tintTo = new cc.TintTo(); 2061 tintTo.initWithDuration(duration, red, green, blue); 2062 return tintTo; 2063 }; 2064 2065 2066 /** Tints a cc.Node that implements the cc.NodeRGB protocol from current tint to a custom one. 2067 * @class 2068 * @extends cc.ActionInterval 2069 */ 2070 cc.TintBy = cc.ActionInterval.extend(/** @lends cc.TintBy# */{ 2071 _deltaR:0, 2072 _deltaG:0, 2073 _deltaB:0, 2074 2075 _fromR:0, 2076 _fromG:0, 2077 _fromB:0, 2078 2079 ctor:function () { 2080 cc.ActionInterval.prototype.ctor.call(this); 2081 this._deltaR = 0; 2082 this._deltaG = 0; 2083 this._deltaB = 0; 2084 this._fromR = 0; 2085 this._fromG = 0; 2086 this._fromB = 0; 2087 }, 2088 2089 /** 2090 * @param {Number} duration 2091 * @param {Number} deltaRed 0-255 2092 * @param {Number} deltaGreen 0-255 2093 * @param {Number} deltaBlue 0-255 2094 * @return {Boolean} 2095 */ 2096 initWithDuration:function (duration, deltaRed, deltaGreen, deltaBlue) { 2097 if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) { 2098 this._deltaR = deltaRed; 2099 this._deltaG = deltaGreen; 2100 this._deltaB = deltaBlue; 2101 return true; 2102 } 2103 return false; 2104 }, 2105 2106 /** 2107 * returns a new clone of the action 2108 * @returns {cc.TintBy} 2109 */ 2110 clone:function () { 2111 var action = new cc.TintBy(); 2112 action.initWithDuration(this._duration, this._deltaR, this._deltaG, this._deltaB); 2113 return action; 2114 }, 2115 2116 /** 2117 * @param {cc.Sprite} target 2118 */ 2119 startWithTarget:function (target) { 2120 cc.ActionInterval.prototype.startWithTarget.call(this, target); 2121 if (target.RGBAProtocol) { 2122 var color = target.getColor(); 2123 this._fromR = color.r; 2124 this._fromG = color.g; 2125 this._fromB = color.b; 2126 } 2127 }, 2128 2129 /** 2130 * @param {Number} time time in seconds 2131 */ 2132 update:function (time) { 2133 if (this._target.RGBAProtocol) { 2134 this._target.setColor(cc.c3b((this._fromR + this._deltaR * time), 2135 (this._fromG + this._deltaG * time), 2136 (this._fromB + this._deltaB * time))); 2137 } 2138 }, 2139 2140 /** 2141 * @return {cc.ActionInterval} 2142 */ 2143 reverse:function () { 2144 return cc.TintBy.create(this._duration, -this._deltaR, -this._deltaG, -this._deltaB); 2145 } 2146 }); 2147 2148 /** 2149 * @param {Number} duration duration in seconds 2150 * @param {Number} deltaRed 2151 * @param {Number} deltaGreen 2152 * @param {Number} deltaBlue 2153 * @return {cc.TintBy} 2154 * @example 2155 * // example 2156 * var action = cc.TintBy.create(2, -127, -255, -127); 2157 */ 2158 cc.TintBy.create = function (duration, deltaRed, deltaGreen, deltaBlue) { 2159 var tintBy = new cc.TintBy(); 2160 tintBy.initWithDuration(duration, deltaRed, deltaGreen, deltaBlue); 2161 return tintBy; 2162 }; 2163 2164 /** Delays the action a certain amount of seconds 2165 * @class 2166 * @extends cc.ActionInterval 2167 */ 2168 cc.DelayTime = cc.ActionInterval.extend(/** @lends cc.DelayTime# */{ 2169 /** 2170 * @param {Number} time time in seconds 2171 */ 2172 update:function (time) { 2173 }, 2174 2175 /** 2176 * @return {cc.ActionInterval} 2177 */ 2178 reverse:function () { 2179 return cc.DelayTime.create(this._duration); 2180 }, 2181 2182 /** 2183 * returns a new clone of the action 2184 * @returns {cc.DelayTime} 2185 */ 2186 clone:function () { 2187 var action = new cc.DelayTime(); 2188 action.initWithDuration(this._duration); 2189 return action; 2190 } 2191 }); 2192 2193 /** 2194 * @param {Number} d duration in seconds 2195 * @return {cc.DelayTime} 2196 * @example 2197 * // example 2198 * var delay = cc.DelayTime.create(1); 2199 */ 2200 cc.DelayTime.create = function (d) { 2201 var action = new cc.DelayTime(); 2202 action.initWithDuration(d); 2203 return action; 2204 }; 2205 2206 /** 2207 * Executes an action in reverse order, from time=duration to time=0 2208 * @warning Use this action carefully. This action is not 2209 * sequenceable. Use it as the default "reversed" method 2210 * of your own actions, but using it outside the "reversed" 2211 * scope is not recommended. 2212 * @class 2213 * @extends cc.ActionInterval 2214 */ 2215 cc.ReverseTime = cc.ActionInterval.extend(/** @lends cc.ReverseTime# */{ 2216 _other:null, 2217 2218 ctor:function () { 2219 cc.ActionInterval.prototype.ctor.call(this); 2220 this._other = null; 2221 }, 2222 2223 /** 2224 * @param {cc.FiniteTimeAction} action 2225 * @return {Boolean} 2226 */ 2227 initWithAction:function (action) { 2228 if(!action) 2229 throw "cc.ReverseTime.initWithAction(): action must be non null"; 2230 if(action == this._other) 2231 throw "cc.ReverseTime.initWithAction(): the action was already passed in."; 2232 2233 if (cc.ActionInterval.prototype.initWithDuration.call(this, action.getDuration())) { 2234 // Don't leak if action is reused 2235 this._other = action; 2236 return true; 2237 } 2238 return false; 2239 }, 2240 2241 /** 2242 * returns a new clone of the action 2243 * @returns {cc.ReverseTime} 2244 */ 2245 clone:function () { 2246 var action = new cc.ReverseTime(); 2247 action.initWithAction(this._other.clone()); 2248 return action; 2249 }, 2250 2251 /** 2252 * @param {cc.Node} target 2253 */ 2254 startWithTarget:function (target) { 2255 cc.ActionInterval.prototype.startWithTarget.call(this, target); 2256 this._other.startWithTarget(target); 2257 }, 2258 2259 /** 2260 * @param {Number} time time in seconds 2261 */ 2262 update:function (time) { 2263 if (this._other) 2264 this._other.update(1 - time); 2265 }, 2266 2267 /** 2268 * @return {cc.ActionInterval} 2269 */ 2270 reverse:function () { 2271 return this._other.clone(); 2272 }, 2273 2274 /** 2275 * Stop the action 2276 */ 2277 stop:function () { 2278 this._other.stop(); 2279 cc.Action.prototype.stop.call(this); 2280 } 2281 }); 2282 2283 /** 2284 * @param {cc.FiniteTimeAction} action 2285 * @return {cc.ReverseTime} 2286 * @example 2287 * // example 2288 * var reverse = cc.ReverseTime.create(this); 2289 */ 2290 cc.ReverseTime.create = function (action) { 2291 var reverseTime = new cc.ReverseTime(); 2292 reverseTime.initWithAction(action); 2293 return reverseTime; 2294 }; 2295 2296 2297 /** Animates a sprite given the name of an Animation 2298 * @class 2299 * @extends cc.ActionInterval 2300 */ 2301 cc.Animate = cc.ActionInterval.extend(/** @lends cc.Animate# */{ 2302 _animation:null, 2303 _nextFrame:0, 2304 _origFrame:null, 2305 _executedLoops:0, 2306 _splitTimes:null, 2307 2308 ctor:function () { 2309 cc.ActionInterval.prototype.ctor.call(this); 2310 this._animation = null; 2311 this._nextFrame = 0; 2312 this._origFrame = null; 2313 this._executedLoops = 0; 2314 this._splitTimes = []; 2315 }, 2316 2317 /** 2318 * @return {cc.Animation} 2319 */ 2320 getAnimation:function () { 2321 return this._animation; 2322 }, 2323 2324 /** 2325 * @param {cc.Animation} animation 2326 */ 2327 setAnimation:function (animation) { 2328 this._animation = animation; 2329 }, 2330 2331 /** 2332 * @param {cc.Animation} animation 2333 * @return {Boolean} 2334 */ 2335 initWithAnimation:function (animation) { 2336 if(!animation) 2337 throw "cc.Animate.initWithAnimation(): animation must be non-NULL"; 2338 var singleDuration = animation.getDuration(); 2339 if (this.initWithDuration(singleDuration * animation.getLoops())) { 2340 this._nextFrame = 0; 2341 this.setAnimation(animation); 2342 2343 this._origFrame = null; 2344 this._executedLoops = 0; 2345 var locTimes = this._splitTimes; 2346 locTimes.length = 0; 2347 2348 var accumUnitsOfTime = 0; 2349 var newUnitOfTimeValue = singleDuration / animation.getTotalDelayUnits(); 2350 2351 var frames = animation.getFrames(); 2352 cc.ArrayVerifyType(frames, cc.AnimationFrame); 2353 2354 for (var i = 0; i < frames.length; i++) { 2355 var frame = frames[i]; 2356 var value = (accumUnitsOfTime * newUnitOfTimeValue) / singleDuration; 2357 accumUnitsOfTime += frame.getDelayUnits(); 2358 locTimes.push(value); 2359 } 2360 return true; 2361 } 2362 return false; 2363 }, 2364 2365 /** 2366 * returns a new clone of the action 2367 * @returns {cc.Animate} 2368 */ 2369 clone:function () { 2370 var action = new cc.Animate(); 2371 action.initWithAnimation(this._animation.clone()); 2372 return action; 2373 }, 2374 2375 /** 2376 * @param {cc.Sprite} target 2377 */ 2378 startWithTarget:function (target) { 2379 cc.ActionInterval.prototype.startWithTarget.call(this, target); 2380 if (this._animation.getRestoreOriginalFrame()) 2381 this._origFrame = target.displayFrame(); 2382 this._nextFrame = 0; 2383 this._executedLoops = 0; 2384 }, 2385 2386 /** 2387 * @param {Number} time 2388 */ 2389 update:function (time) { 2390 // if t==1, ignore. Animation should finish with t==1 2391 if (time < 1.0) { 2392 time *= this._animation.getLoops(); 2393 2394 // new loop? If so, reset frame counter 2395 var loopNumber = 0 | time; 2396 if (loopNumber > this._executedLoops) { 2397 this._nextFrame = 0; 2398 this._executedLoops++; 2399 } 2400 2401 // new t for animations 2402 time = time % 1.0; 2403 } 2404 2405 var frames = this._animation.getFrames(); 2406 var numberOfFrames = frames.length, locSplitTimes = this._splitTimes; 2407 for (var i = this._nextFrame; i < numberOfFrames; i++) { 2408 if (locSplitTimes[i] <= time) { 2409 this._target.setDisplayFrame(frames[i].getSpriteFrame()); 2410 this._nextFrame = i + 1; 2411 } else { 2412 // Issue 1438. Could be more than one frame per tick, due to low frame rate or frame delta < 1/FPS 2413 break; 2414 } 2415 } 2416 }, 2417 2418 /** 2419 * @return {cc.ActionInterval} 2420 */ 2421 reverse:function () { 2422 var locAnimation = this._animation; 2423 var oldArray = locAnimation.getFrames(); 2424 var newArray = []; 2425 cc.ArrayVerifyType(oldArray, cc.AnimationFrame); 2426 if (oldArray.length > 0) { 2427 for (var i = oldArray.length - 1; i >= 0; i--) { 2428 var element = oldArray[i]; 2429 if (!element) 2430 break; 2431 newArray.push(element.clone()); 2432 } 2433 } 2434 var newAnim = cc.Animation.createWithAnimationFrames(newArray, locAnimation.getDelayPerUnit(), locAnimation.getLoops()); 2435 newAnim.setRestoreOriginalFrame(locAnimation.getRestoreOriginalFrame()); 2436 return cc.Animate.create(newAnim); 2437 }, 2438 2439 /** 2440 * stop the action 2441 */ 2442 stop:function () { 2443 if (this._animation.getRestoreOriginalFrame() && this._target) 2444 this._target.setDisplayFrame(this._origFrame); 2445 cc.Action.prototype.stop.call(this); 2446 } 2447 }); 2448 2449 /** 2450 * create the animate with animation 2451 * @param {cc.Animation} animation 2452 * @return {cc.Animate} 2453 * @example 2454 * // example 2455 * // create the animation with animation 2456 * var anim = cc.Animate.create(dance_grey); 2457 */ 2458 cc.Animate.create = function (animation) { 2459 var animate = new cc.Animate(); 2460 animate.initWithAnimation(animation); 2461 return animate; 2462 }; 2463 2464 /** 2465 * <p> 2466 * Overrides the target of an action so that it always runs on the target<br/> 2467 * specified at action creation rather than the one specified by runAction. 2468 * </p> 2469 * @class 2470 * @extends cc.ActionInterval 2471 */ 2472 cc.TargetedAction = cc.ActionInterval.extend(/** @lends cc.TargetedAction# */{ 2473 _action:null, 2474 _forcedTarget:null, 2475 2476 ctor:function () { 2477 cc.ActionInterval.prototype.ctor.call(this); 2478 this._action = null; 2479 this._forcedTarget = null; 2480 }, 2481 2482 /** 2483 * Init an action with the specified action and forced target 2484 * @param {cc.Node} target 2485 * @param {cc.FiniteTimeAction} action 2486 * @return {Boolean} 2487 */ 2488 initWithTarget:function (target, action) { 2489 if (this.initWithDuration(action.getDuration())) { 2490 this._forcedTarget = target; 2491 this._action = action; 2492 return true; 2493 } 2494 return false; 2495 }, 2496 2497 /** 2498 * returns a new clone of the action 2499 * @returns {cc.TargetedAction} 2500 */ 2501 clone:function () { 2502 var action = new cc.TargetedAction(); 2503 action.initWithTarget(this._forcedTarget, this._action.clone()); 2504 return action; 2505 }, 2506 2507 startWithTarget:function (target) { 2508 cc.ActionInterval.prototype.startWithTarget.call(this, target); 2509 this._action.startWithTarget(this._forcedTarget); 2510 }, 2511 2512 stop:function () { 2513 this._action.stop(); 2514 }, 2515 2516 update:function (time) { 2517 this._action.update(time); 2518 }, 2519 2520 /** 2521 * return the target that the action will be forced to run with 2522 * @return {cc.Node} 2523 */ 2524 getForcedTarget:function () { 2525 return this._forcedTarget; 2526 }, 2527 2528 /** 2529 * set the target that the action will be forced to run with 2530 * @param {cc.Node} forcedTarget 2531 */ 2532 setForcedTarget:function (forcedTarget) { 2533 if (this._forcedTarget != forcedTarget) 2534 this._forcedTarget = forcedTarget; 2535 } 2536 }); 2537 2538 /** 2539 * Create an action with the specified action and forced target 2540 * @param {cc.Node} target 2541 * @param {cc.FiniteTimeAction} action 2542 */ 2543 cc.TargetedAction.create = function (target, action) { 2544 var retObj = new cc.TargetedAction(); 2545 retObj.initWithTarget(target, action); 2546 return retObj; 2547 }; 2548