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 In an object that implements the cc.RGBAProtocol protocol. It modifies the opacity from 0 to 255.<br/> 1821 * The "reverse" of this action is FadeOut 1822 * @class 1823 * @extends cc.ActionInterval 1824 */ 1825 cc.FadeIn = cc.ActionInterval.extend(/** @lends cc.FadeIn# */{ 1826 /** 1827 * @param {Number} time time in seconds 1828 */ 1829 update:function (time) { 1830 if (this._target.RGBAProtocol) { 1831 this._target.setOpacity(255 * time); 1832 } 1833 }, 1834 1835 /** 1836 * @return {cc.ActionInterval} 1837 */ 1838 reverse:function () { 1839 return cc.FadeOut.create(this._duration); 1840 }, 1841 1842 /** 1843 * returns a new clone of the action 1844 * @returns {cc.FadeIn} 1845 */ 1846 clone:function () { 1847 var action = new cc.FadeIn(); 1848 action.initWithDuration(this._duration); 1849 return action; 1850 } 1851 }); 1852 1853 /** 1854 * @param {Number} duration duration in seconds 1855 * @return {cc.FadeIn} 1856 * @example 1857 * //example 1858 * var action = cc.FadeIn.create(1.0); 1859 */ 1860 cc.FadeIn.create = function (duration) { 1861 var action = new cc.FadeIn(); 1862 action.initWithDuration(duration); 1863 return action; 1864 }; 1865 1866 1867 /** Fades Out an object that implements the cc.RGBAProtocol protocol. It modifies the opacity from 255 to 0. 1868 * The "reverse" of this action is FadeIn 1869 * @class 1870 * @extends cc.ActionInterval 1871 */ 1872 cc.FadeOut = cc.ActionInterval.extend(/** @lends cc.FadeOut# */{ 1873 /** 1874 * @param {Number} time time in seconds 1875 */ 1876 update:function (time) { 1877 if (this._target.RGBAProtocol) { 1878 this._target.setOpacity(255 * (1 - time)); 1879 } 1880 }, 1881 1882 /** 1883 * @return {cc.ActionInterval} 1884 */ 1885 reverse:function () { 1886 return cc.FadeIn.create(this._duration); 1887 }, 1888 1889 /** 1890 * returns a new clone of the action 1891 * @returns {cc.FadeOut} 1892 */ 1893 clone:function () { 1894 var action = new cc.FadeOut(); 1895 action.initWithDuration(this._duration); 1896 return action; 1897 } 1898 }); 1899 1900 /** 1901 * @param {Number} d duration in seconds 1902 * @return {cc.FadeOut} 1903 * @example 1904 * // example 1905 * var action = cc.FadeOut.create(1.0); 1906 */ 1907 cc.FadeOut.create = function (d) { 1908 var action = new cc.FadeOut(); 1909 action.initWithDuration(d); 1910 return action; 1911 }; 1912 1913 /** Fades an object that implements the cc.RGBAProtocol protocol. It modifies the opacity from the current value to a custom one. 1914 * @warning This action doesn't support "reverse" 1915 * @class 1916 * @extends cc.ActionInterval 1917 */ 1918 cc.FadeTo = cc.ActionInterval.extend(/** @lends cc.FadeTo# */{ 1919 _toOpacity:null, 1920 _fromOpacity:null, 1921 1922 ctor:function () { 1923 cc.ActionInterval.prototype.ctor.call(this); 1924 this._toOpacity = 0; 1925 this._fromOpacity = 0; 1926 }, 1927 1928 /** 1929 * @param {Number} duration duration in seconds 1930 * @param {Number} opacity 1931 * @return {Boolean} 1932 */ 1933 initWithDuration:function (duration, opacity) { 1934 if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) { 1935 this._toOpacity = opacity; 1936 return true; 1937 } 1938 return false; 1939 }, 1940 1941 /** 1942 * returns a new clone of the action 1943 * @returns {cc.FadeTo} 1944 */ 1945 clone:function () { 1946 var action = new cc.FadeTo(); 1947 action.initWithDuration(this._duration, this._toOpacity); 1948 return action; 1949 }, 1950 1951 /** 1952 * @param {Number} time time in seconds 1953 */ 1954 update:function (time) { 1955 if (this._target.RGBAProtocol) { 1956 this._target.setOpacity((this._fromOpacity + (this._toOpacity - this._fromOpacity) * time)); 1957 } 1958 }, 1959 1960 /** 1961 * @param {cc.Sprite} target 1962 */ 1963 startWithTarget:function (target) { 1964 cc.ActionInterval.prototype.startWithTarget.call(this, target); 1965 if(this._target.RGBAProtocol){ 1966 this._fromOpacity = target.getOpacity(); 1967 } 1968 } 1969 }); 1970 1971 /** 1972 * @param {Number} duration 1973 * @param {Number} opacity 0-255, 0 is transparent 1974 * @return {cc.FadeTo} 1975 * @example 1976 * // example 1977 * var action = cc.FadeTo.create(1.0, 0); 1978 */ 1979 cc.FadeTo.create = function (duration, opacity) { 1980 var fadeTo = new cc.FadeTo(); 1981 fadeTo.initWithDuration(duration, opacity); 1982 return fadeTo; 1983 }; 1984 1985 /** Tints a cc.Node that implements the cc.NodeRGB protocol from current tint to a custom one. 1986 * @warning This action doesn't support "reverse" 1987 * @class 1988 * @extends cc.ActionInterval 1989 */ 1990 cc.TintTo = cc.ActionInterval.extend(/** @lends cc.TintTo# */{ 1991 _to:null, 1992 _from:null, 1993 1994 ctor:function () { 1995 cc.ActionInterval.prototype.ctor.call(this); 1996 this._to = cc.c3b(0, 0, 0); 1997 this._from = cc.c3b(0, 0, 0); 1998 }, 1999 2000 /** 2001 * @param {Number} duration 2002 * @param {Number} red 0-255 2003 * @param {Number} green 0-255 2004 * @param {Number} blue 0-255 2005 * @return {Boolean} 2006 */ 2007 initWithDuration:function (duration, red, green, blue) { 2008 if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) { 2009 this._to = cc.c3b(red, green, blue); 2010 return true; 2011 } 2012 return false; 2013 }, 2014 2015 /** 2016 * returns a new clone of the action 2017 * @returns {cc.TintTo} 2018 */ 2019 clone:function () { 2020 var action = new cc.TintTo(); 2021 var locTo = this._to; 2022 action.initWithDuration(this._duration, locTo.r, locTo.g, locTo.b); 2023 return action; 2024 }, 2025 2026 /** 2027 * @param {cc.Sprite} target 2028 */ 2029 startWithTarget:function (target) { 2030 cc.ActionInterval.prototype.startWithTarget.call(this, target); 2031 if (this._target.RGBAProtocol) { 2032 this._from = this._target.getColor(); 2033 } 2034 }, 2035 2036 /** 2037 * @param {Number} time time in seconds 2038 */ 2039 update:function (time) { 2040 var locFrom = this._from, locTo = this._to; 2041 if (this._target.RGBAProtocol) { 2042 this._target.setColor(cc.c3b(locFrom.r + (locTo.r - locFrom.r) * time, 2043 (locFrom.g + (locTo.g - locFrom.g) * time), (locFrom.b + (locTo.b - locFrom.b) * time))); 2044 } 2045 } 2046 }); 2047 2048 /** 2049 * @param {Number} duration 2050 * @param {Number} red 0-255 2051 * @param {Number} green 0-255 2052 * @param {Number} blue 0-255 2053 * @return {cc.TintTo} 2054 * @example 2055 * // example 2056 * var action = cc.TintTo.create(2, 255, 0, 255); 2057 */ 2058 cc.TintTo.create = function (duration, red, green, blue) { 2059 var tintTo = new cc.TintTo(); 2060 tintTo.initWithDuration(duration, red, green, blue); 2061 return tintTo; 2062 }; 2063 2064 2065 /** Tints a cc.Node that implements the cc.NodeRGB protocol from current tint to a custom one. 2066 * @class 2067 * @extends cc.ActionInterval 2068 */ 2069 cc.TintBy = cc.ActionInterval.extend(/** @lends cc.TintBy# */{ 2070 _deltaR:0, 2071 _deltaG:0, 2072 _deltaB:0, 2073 2074 _fromR:0, 2075 _fromG:0, 2076 _fromB:0, 2077 2078 ctor:function () { 2079 cc.ActionInterval.prototype.ctor.call(this); 2080 this._deltaR = 0; 2081 this._deltaG = 0; 2082 this._deltaB = 0; 2083 this._fromR = 0; 2084 this._fromG = 0; 2085 this._fromB = 0; 2086 }, 2087 2088 /** 2089 * @param {Number} duration 2090 * @param {Number} deltaRed 0-255 2091 * @param {Number} deltaGreen 0-255 2092 * @param {Number} deltaBlue 0-255 2093 * @return {Boolean} 2094 */ 2095 initWithDuration:function (duration, deltaRed, deltaGreen, deltaBlue) { 2096 if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) { 2097 this._deltaR = deltaRed; 2098 this._deltaG = deltaGreen; 2099 this._deltaB = deltaBlue; 2100 return true; 2101 } 2102 return false; 2103 }, 2104 2105 /** 2106 * returns a new clone of the action 2107 * @returns {cc.TintBy} 2108 */ 2109 clone:function () { 2110 var action = new cc.TintBy(); 2111 action.initWithDuration(this._duration, this._deltaR, this._deltaG, this._deltaB); 2112 return action; 2113 }, 2114 2115 /** 2116 * @param {cc.Sprite} target 2117 */ 2118 startWithTarget:function (target) { 2119 cc.ActionInterval.prototype.startWithTarget.call(this, target); 2120 if (target.RGBAProtocol) { 2121 var color = target.getColor(); 2122 this._fromR = color.r; 2123 this._fromG = color.g; 2124 this._fromB = color.b; 2125 } 2126 }, 2127 2128 /** 2129 * @param {Number} time time in seconds 2130 */ 2131 update:function (time) { 2132 if (this._target.RGBAProtocol) { 2133 this._target.setColor(cc.c3b((this._fromR + this._deltaR * time), 2134 (this._fromG + this._deltaG * time), 2135 (this._fromB + this._deltaB * time))); 2136 } 2137 }, 2138 2139 /** 2140 * @return {cc.ActionInterval} 2141 */ 2142 reverse:function () { 2143 return cc.TintBy.create(this._duration, -this._deltaR, -this._deltaG, -this._deltaB); 2144 } 2145 }); 2146 2147 /** 2148 * @param {Number} duration duration in seconds 2149 * @param {Number} deltaRed 2150 * @param {Number} deltaGreen 2151 * @param {Number} deltaBlue 2152 * @return {cc.TintBy} 2153 * @example 2154 * // example 2155 * var action = cc.TintBy.create(2, -127, -255, -127); 2156 */ 2157 cc.TintBy.create = function (duration, deltaRed, deltaGreen, deltaBlue) { 2158 var tintBy = new cc.TintBy(); 2159 tintBy.initWithDuration(duration, deltaRed, deltaGreen, deltaBlue); 2160 return tintBy; 2161 }; 2162 2163 /** Delays the action a certain amount of seconds 2164 * @class 2165 * @extends cc.ActionInterval 2166 */ 2167 cc.DelayTime = cc.ActionInterval.extend(/** @lends cc.DelayTime# */{ 2168 /** 2169 * @param {Number} time time in seconds 2170 */ 2171 update:function (time) { 2172 }, 2173 2174 /** 2175 * @return {cc.ActionInterval} 2176 */ 2177 reverse:function () { 2178 return cc.DelayTime.create(this._duration); 2179 }, 2180 2181 /** 2182 * returns a new clone of the action 2183 * @returns {cc.DelayTime} 2184 */ 2185 clone:function () { 2186 var action = new cc.DelayTime(); 2187 action.initWithDuration(this._duration); 2188 return action; 2189 } 2190 }); 2191 2192 /** 2193 * @param {Number} d duration in seconds 2194 * @return {cc.DelayTime} 2195 * @example 2196 * // example 2197 * var delay = cc.DelayTime.create(1); 2198 */ 2199 cc.DelayTime.create = function (d) { 2200 var action = new cc.DelayTime(); 2201 action.initWithDuration(d); 2202 return action; 2203 }; 2204 2205 /** 2206 * Executes an action in reverse order, from time=duration to time=0 2207 * @warning Use this action carefully. This action is not 2208 * sequenceable. Use it as the default "reversed" method 2209 * of your own actions, but using it outside the "reversed" 2210 * scope is not recommended. 2211 * @class 2212 * @extends cc.ActionInterval 2213 */ 2214 cc.ReverseTime = cc.ActionInterval.extend(/** @lends cc.ReverseTime# */{ 2215 _other:null, 2216 2217 ctor:function () { 2218 cc.ActionInterval.prototype.ctor.call(this); 2219 this._other = null; 2220 }, 2221 2222 /** 2223 * @param {cc.FiniteTimeAction} action 2224 * @return {Boolean} 2225 */ 2226 initWithAction:function (action) { 2227 if(!action) 2228 throw "cc.ReverseTime.initWithAction(): action must be non null"; 2229 if(action == this._other) 2230 throw "cc.ReverseTime.initWithAction(): the action was already passed in."; 2231 2232 if (cc.ActionInterval.prototype.initWithDuration.call(this, action.getDuration())) { 2233 // Don't leak if action is reused 2234 this._other = action; 2235 return true; 2236 } 2237 return false; 2238 }, 2239 2240 /** 2241 * returns a new clone of the action 2242 * @returns {cc.ReverseTime} 2243 */ 2244 clone:function () { 2245 var action = new cc.ReverseTime(); 2246 action.initWithAction(this._other.clone()); 2247 return action; 2248 }, 2249 2250 /** 2251 * @param {cc.Node} target 2252 */ 2253 startWithTarget:function (target) { 2254 cc.ActionInterval.prototype.startWithTarget.call(this, target); 2255 this._other.startWithTarget(target); 2256 }, 2257 2258 /** 2259 * @param {Number} time time in seconds 2260 */ 2261 update:function (time) { 2262 if (this._other) 2263 this._other.update(1 - time); 2264 }, 2265 2266 /** 2267 * @return {cc.ActionInterval} 2268 */ 2269 reverse:function () { 2270 return this._other.clone(); 2271 }, 2272 2273 /** 2274 * Stop the action 2275 */ 2276 stop:function () { 2277 this._other.stop(); 2278 cc.Action.prototype.stop.call(this); 2279 } 2280 }); 2281 2282 /** 2283 * @param {cc.FiniteTimeAction} action 2284 * @return {cc.ReverseTime} 2285 * @example 2286 * // example 2287 * var reverse = cc.ReverseTime.create(this); 2288 */ 2289 cc.ReverseTime.create = function (action) { 2290 var reverseTime = new cc.ReverseTime(); 2291 reverseTime.initWithAction(action); 2292 return reverseTime; 2293 }; 2294 2295 2296 /** Animates a sprite given the name of an Animation 2297 * @class 2298 * @extends cc.ActionInterval 2299 */ 2300 cc.Animate = cc.ActionInterval.extend(/** @lends cc.Animate# */{ 2301 _animation:null, 2302 _nextFrame:0, 2303 _origFrame:null, 2304 _executedLoops:0, 2305 _splitTimes:null, 2306 2307 ctor:function () { 2308 cc.ActionInterval.prototype.ctor.call(this); 2309 this._animation = null; 2310 this._nextFrame = 0; 2311 this._origFrame = null; 2312 this._executedLoops = 0; 2313 this._splitTimes = []; 2314 }, 2315 2316 /** 2317 * @return {cc.Animation} 2318 */ 2319 getAnimation:function () { 2320 return this._animation; 2321 }, 2322 2323 /** 2324 * @param {cc.Animation} animation 2325 */ 2326 setAnimation:function (animation) { 2327 this._animation = animation; 2328 }, 2329 2330 /** 2331 * @param {cc.Animation} animation 2332 * @return {Boolean} 2333 */ 2334 initWithAnimation:function (animation) { 2335 if(!animation) 2336 throw "cc.Animate.initWithAnimation(): animation must be non-NULL"; 2337 var singleDuration = animation.getDuration(); 2338 if (this.initWithDuration(singleDuration * animation.getLoops())) { 2339 this._nextFrame = 0; 2340 this.setAnimation(animation); 2341 2342 this._origFrame = null; 2343 this._executedLoops = 0; 2344 var locTimes = this._splitTimes; 2345 locTimes.length = 0; 2346 2347 var accumUnitsOfTime = 0; 2348 var newUnitOfTimeValue = singleDuration / animation.getTotalDelayUnits(); 2349 2350 var frames = animation.getFrames(); 2351 cc.ArrayVerifyType(frames, cc.AnimationFrame); 2352 2353 for (var i = 0; i < frames.length; i++) { 2354 var frame = frames[i]; 2355 var value = (accumUnitsOfTime * newUnitOfTimeValue) / singleDuration; 2356 accumUnitsOfTime += frame.getDelayUnits(); 2357 locTimes.push(value); 2358 } 2359 return true; 2360 } 2361 return false; 2362 }, 2363 2364 /** 2365 * returns a new clone of the action 2366 * @returns {cc.Animate} 2367 */ 2368 clone:function () { 2369 var action = new cc.Animate(); 2370 action.initWithAnimation(this._animation.clone()); 2371 return action; 2372 }, 2373 2374 /** 2375 * @param {cc.Sprite} target 2376 */ 2377 startWithTarget:function (target) { 2378 cc.ActionInterval.prototype.startWithTarget.call(this, target); 2379 if (this._animation.getRestoreOriginalFrame()) 2380 this._origFrame = target.displayFrame(); 2381 this._nextFrame = 0; 2382 this._executedLoops = 0; 2383 }, 2384 2385 /** 2386 * @param {Number} time 2387 */ 2388 update:function (time) { 2389 // if t==1, ignore. Animation should finish with t==1 2390 if (time < 1.0) { 2391 time *= this._animation.getLoops(); 2392 2393 // new loop? If so, reset frame counter 2394 var loopNumber = 0 | time; 2395 if (loopNumber > this._executedLoops) { 2396 this._nextFrame = 0; 2397 this._executedLoops++; 2398 } 2399 2400 // new t for animations 2401 time = time % 1.0; 2402 } 2403 2404 var frames = this._animation.getFrames(); 2405 var numberOfFrames = frames.length, locSplitTimes = this._splitTimes; 2406 for (var i = this._nextFrame; i < numberOfFrames; i++) { 2407 if (locSplitTimes[i] <= time) { 2408 this._target.setDisplayFrame(frames[i].getSpriteFrame()); 2409 this._nextFrame = i + 1; 2410 } else { 2411 // Issue 1438. Could be more than one frame per tick, due to low frame rate or frame delta < 1/FPS 2412 break; 2413 } 2414 } 2415 }, 2416 2417 /** 2418 * @return {cc.ActionInterval} 2419 */ 2420 reverse:function () { 2421 var locAnimation = this._animation; 2422 var oldArray = locAnimation.getFrames(); 2423 var newArray = []; 2424 cc.ArrayVerifyType(oldArray, cc.AnimationFrame); 2425 if (oldArray.length > 0) { 2426 for (var i = oldArray.length - 1; i >= 0; i--) { 2427 var element = oldArray[i]; 2428 if (!element) 2429 break; 2430 newArray.push(element.clone()); 2431 } 2432 } 2433 var newAnim = cc.Animation.createWithAnimationFrames(newArray, locAnimation.getDelayPerUnit(), locAnimation.getLoops()); 2434 newAnim.setRestoreOriginalFrame(locAnimation.getRestoreOriginalFrame()); 2435 return cc.Animate.create(newAnim); 2436 }, 2437 2438 /** 2439 * stop the action 2440 */ 2441 stop:function () { 2442 if (this._animation.getRestoreOriginalFrame() && this._target) 2443 this._target.setDisplayFrame(this._origFrame); 2444 cc.Action.prototype.stop.call(this); 2445 } 2446 }); 2447 2448 /** 2449 * create the animate with animation 2450 * @param {cc.Animation} animation 2451 * @return {cc.Animate} 2452 * @example 2453 * // example 2454 * // create the animation with animation 2455 * var anim = cc.Animate.create(dance_grey); 2456 */ 2457 cc.Animate.create = function (animation) { 2458 var animate = new cc.Animate(); 2459 animate.initWithAnimation(animation); 2460 return animate; 2461 }; 2462 2463 /** 2464 * <p> 2465 * Overrides the target of an action so that it always runs on the target<br/> 2466 * specified at action creation rather than the one specified by runAction. 2467 * </p> 2468 * @class 2469 * @extends cc.ActionInterval 2470 */ 2471 cc.TargetedAction = cc.ActionInterval.extend(/** @lends cc.TargetedAction# */{ 2472 _action:null, 2473 _forcedTarget:null, 2474 2475 ctor:function () { 2476 cc.ActionInterval.prototype.ctor.call(this); 2477 this._action = null; 2478 this._forcedTarget = null; 2479 }, 2480 2481 /** 2482 * Init an action with the specified action and forced target 2483 * @param {cc.Node} target 2484 * @param {cc.FiniteTimeAction} action 2485 * @return {Boolean} 2486 */ 2487 initWithTarget:function (target, action) { 2488 if (this.initWithDuration(action.getDuration())) { 2489 this._forcedTarget = target; 2490 this._action = action; 2491 return true; 2492 } 2493 return false; 2494 }, 2495 2496 /** 2497 * returns a new clone of the action 2498 * @returns {cc.TargetedAction} 2499 */ 2500 clone:function () { 2501 var action = new cc.TargetedAction(); 2502 action.initWithTarget(this._forcedTarget, this._action.clone()); 2503 return action; 2504 }, 2505 2506 startWithTarget:function (target) { 2507 cc.ActionInterval.prototype.startWithTarget.call(this, target); 2508 this._action.startWithTarget(this._forcedTarget); 2509 }, 2510 2511 stop:function () { 2512 this._action.stop(); 2513 }, 2514 2515 update:function (time) { 2516 this._action.update(time); 2517 }, 2518 2519 /** 2520 * return the target that the action will be forced to run with 2521 * @return {cc.Node} 2522 */ 2523 getForcedTarget:function () { 2524 return this._forcedTarget; 2525 }, 2526 2527 /** 2528 * set the target that the action will be forced to run with 2529 * @param {cc.Node} forcedTarget 2530 */ 2531 setForcedTarget:function (forcedTarget) { 2532 if (this._forcedTarget != forcedTarget) 2533 this._forcedTarget = forcedTarget; 2534 } 2535 }); 2536 2537 /** 2538 * Create an action with the specified action and forced target 2539 * @param {cc.Node} target 2540 * @param {cc.FiniteTimeAction} action 2541 */ 2542 cc.TargetedAction.create = function (target, action) { 2543 var retObj = new cc.TargetedAction(); 2544 retObj.initWithTarget(target, action); 2545 return retObj; 2546 }; 2547