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