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