1 /**************************************************************************** 2 Copyright (c) 2008-2010 Ricardo Quesada 3 Copyright (c) 2011-2012 cocos2d-x.org 4 Copyright (c) 2013-2014 Chukong Technologies 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> 29 * cc.AnimationFrame 30 * A frame of the animation. It contains information like: 31 * - sprite frame name 32 * - # of delay units. 33 * - offset 34 * </p> 35 * @class 36 * @extends cc.Class 37 * @param spriteFrame 38 * @param delayUnits 39 * @param userInfo 40 * @returns {AnimationFrame} 41 */ 42 cc.AnimationFrame = cc.Class.extend(/** @lends cc.AnimationFrame# */{ 43 _spriteFrame:null, 44 _delayPerUnit:0, 45 _userInfo:null, 46 47 ctor:function (spriteFrame, delayUnits, userInfo) { 48 this._spriteFrame = spriteFrame || null; 49 this._delayPerUnit = delayUnits || 0; 50 this._userInfo = userInfo || null; 51 }, 52 53 /** 54 * Create a new animation frame and copy all contents into it 55 * @returns {AnimationFrame} 56 */ 57 clone: function(){ 58 var frame = new cc.AnimationFrame(); 59 frame.initWithSpriteFrame(this._spriteFrame.clone(), this._delayPerUnit, this._userInfo); 60 return frame; 61 }, 62 63 /** 64 * Create a new animation frame and copy all contents into it 65 * @returns {AnimationFrame} 66 */ 67 copyWithZone:function (pZone) { 68 return cc.clone(this); 69 }, 70 71 /** 72 * Create a new animation frame and copy all contents into it 73 * @returns {AnimationFrame} 74 */ 75 copy:function (pZone) { 76 var newFrame = new cc.AnimationFrame(); 77 newFrame.initWithSpriteFrame(this._spriteFrame.clone(), this._delayPerUnit, this._userInfo); 78 return newFrame; 79 }, 80 81 /** 82 * initializes the animation frame with a spriteframe, number of delay units and a notification user info 83 * @param {cc.SpriteFrame} spriteFrame 84 * @param {Number} delayUnits 85 * @param {object} userInfo 86 */ 87 initWithSpriteFrame:function (spriteFrame, delayUnits, userInfo) { 88 this._spriteFrame = spriteFrame; 89 this._delayPerUnit = delayUnits; 90 this._userInfo = userInfo; 91 92 return true; 93 }, 94 95 /** 96 * Returns sprite frame to be used 97 * @return {cc.SpriteFrame} 98 */ 99 getSpriteFrame:function () { 100 return this._spriteFrame; 101 }, 102 103 /** 104 * Sets sprite frame to be used 105 * @param {cc.SpriteFrame} spriteFrame 106 */ 107 setSpriteFrame:function (spriteFrame) { 108 this._spriteFrame = spriteFrame; 109 }, 110 111 /** 112 * Returns how many units of time the frame takes getter 113 * @return {Number} 114 */ 115 getDelayUnits:function () { 116 return this._delayPerUnit; 117 }, 118 119 /** 120 * Sets how many units of time the frame takes setter 121 * @param delayUnits 122 */ 123 setDelayUnits:function (delayUnits) { 124 this._delayPerUnit = delayUnits; 125 }, 126 127 /** 128 * Returns the user custom information 129 * @return {object} 130 */ 131 getUserInfo:function () { 132 return this._userInfo; 133 }, 134 135 /** 136 * Sets the user custom information 137 * @param {object} userInfo 138 */ 139 setUserInfo:function (userInfo) { 140 this._userInfo = userInfo; 141 } 142 }); 143 144 /** 145 * Creates an animation frame. 146 * @deprecated since v3.0, please use the new construction instead 147 * @param {cc.SpriteFrame} spriteFrame 148 * @param {Number} delayUnits 149 * @param {object} userInfo 150 * @see cc.AnimationFrame 151 */ 152 cc.AnimationFrame.create = function(spriteFrame,delayUnits,userInfo){ 153 return new cc.AnimationFrame(spriteFrame,delayUnits,userInfo); 154 }; 155 156 /** 157 * <p> 158 * A cc.Animation object is used to perform animations on the cc.Sprite objects.<br/> 159 * <br/> 160 * The cc.Animation object contains cc.SpriteFrame objects, and a possible delay between the frames. <br/> 161 * You can animate a cc.Animation object by using the cc.Animate action. 162 * </p> 163 * @class 164 * @extends cc.Class 165 * @param {Array} frames 166 * @param {Number} delay 167 * @param {Number} [loops=1] 168 * 169 * @example 170 * // 1. Creates an empty animation 171 * var animation1 = new cc.Animation(); 172 * 173 * // 2. Create an animation with sprite frames, delay and loops. 174 * var spriteFrames = []; 175 * var frame = cc.spriteFrameCache.getSpriteFrame("grossini_dance_01.png"); 176 * spriteFrames.push(frame); 177 * var animation1 = new cc.Animation(spriteFrames); 178 * var animation2 = new cc.Animation(spriteFrames, 0.2); 179 * var animation2 = new cc.Animation(spriteFrames, 0.2, 2); 180 * 181 * // 3. Create an animation with animation frames, delay and loops. 182 * var animationFrames = []; 183 * var frame = new cc.AnimationFrame(); 184 * animationFrames.push(frame); 185 * var animation1 = new cc.Animation(animationFrames); 186 * var animation2 = new cc.Animation(animationFrames, 0.2); 187 * var animation3 = new cc.Animation(animationFrames, 0.2, 2); 188 * 189 * //create an animate with this animation 190 * var action = cc.animate(animation1); 191 * 192 * //run animate 193 * sprite.runAction(action); 194 */ 195 cc.Animation = cc.Class.extend(/** @lends cc.Animation# */{ 196 _frames:null, 197 _loops:0, 198 _restoreOriginalFrame:false, 199 _duration:0, 200 _delayPerUnit:0, 201 _totalDelayUnits:0, 202 203 ctor:function (frames, delay, loops) { 204 this._frames = []; 205 206 if (frames === undefined) { 207 this.initWithSpriteFrames(null, 0); 208 } else { 209 var frame0 = frames[0]; 210 if(frame0){ 211 if (frame0 instanceof cc.SpriteFrame) { 212 //init with sprite frames , delay and loops. 213 this.initWithSpriteFrames(frames, delay, loops); 214 }else if(frame0 instanceof cc.AnimationFrame) { 215 //init with sprite frames , delay and loops. 216 this.initWithAnimationFrames(frames, delay, loops); 217 } 218 } 219 } 220 }, 221 222 // attributes 223 224 /** 225 * Returns the array of animation frames 226 * @return {Array} 227 */ 228 getFrames:function () { 229 return this._frames; 230 }, 231 232 /** 233 * Sets array of animation frames 234 * @param {Array} frames 235 */ 236 setFrames:function (frames) { 237 this._frames = frames; 238 }, 239 240 /** 241 * Adds a frame to a cc.Animation, the frame will be added with one "delay unit". 242 * @param {cc.SpriteFrame} frame 243 */ 244 addSpriteFrame:function (frame) { 245 var animFrame = new cc.AnimationFrame(); 246 247 animFrame.initWithSpriteFrame(frame, 1, null); 248 this._frames.push(animFrame); 249 // update duration 250 this._totalDelayUnits++; 251 }, 252 253 /** 254 * Adds a frame with an image filename. Internally it will create a cc.SpriteFrame and it will add it. The frame will be added with one "delay unit". 255 * @param {String} fileName 256 */ 257 addSpriteFrameWithFile:function (fileName) { 258 var texture = cc.textureCache.addImage(fileName); 259 var rect = cc.rect(0, 0, 0, 0); 260 rect.width = texture.width; 261 rect.height = texture.height; 262 var frame = new cc.SpriteFrame(texture, rect); 263 this.addSpriteFrame(frame); 264 }, 265 266 /** 267 * Adds a frame with a texture and a rect. Internally it will create a cc.SpriteFrame and it will add it. The frame will be added with one "delay unit". 268 * @param {cc.Texture2D} texture 269 * @param {cc.Rect} rect 270 */ 271 addSpriteFrameWithTexture:function (texture, rect) { 272 var pFrame = new cc.SpriteFrame(texture, rect); 273 this.addSpriteFrame(pFrame); 274 }, 275 276 /** 277 * Initializes a cc.Animation with cc.AnimationFrame, do not call this method yourself, please pass parameters to constructor to initialize. 278 * @param {Array} arrayOfAnimationFrames 279 * @param {Number} delayPerUnit 280 * @param {Number} [loops=1] 281 */ 282 initWithAnimationFrames:function (arrayOfAnimationFrames, delayPerUnit, loops) { 283 cc.arrayVerifyType(arrayOfAnimationFrames, cc.AnimationFrame); 284 285 this._delayPerUnit = delayPerUnit; 286 this._loops = loops === undefined ? 1 : loops; 287 this._totalDelayUnits = 0; 288 289 var locFrames = this._frames; 290 locFrames.length = 0; 291 for (var i = 0; i < arrayOfAnimationFrames.length; i++) { 292 var animFrame = arrayOfAnimationFrames[i]; 293 locFrames.push(animFrame); 294 this._totalDelayUnits += animFrame.getDelayUnits(); 295 } 296 297 return true; 298 }, 299 300 /** 301 * Clone the current animation 302 * @return {cc.Animation} 303 */ 304 clone: function(){ 305 var animation = new cc.Animation(); 306 animation.initWithAnimationFrames(this._copyFrames(), this._delayPerUnit, this._loops); 307 animation.setRestoreOriginalFrame(this._restoreOriginalFrame); 308 return animation; 309 }, 310 311 /** 312 * Clone the current animation 313 * @return {cc.Animation} 314 */ 315 copyWithZone:function (pZone) { 316 var pCopy = new cc.Animation(); 317 pCopy.initWithAnimationFrames(this._copyFrames(), this._delayPerUnit, this._loops); 318 pCopy.setRestoreOriginalFrame(this._restoreOriginalFrame); 319 return pCopy; 320 }, 321 322 _copyFrames:function(){ 323 var copyFrames = []; 324 for(var i = 0; i< this._frames.length;i++) 325 copyFrames.push(this._frames[i].clone()); 326 return copyFrames; 327 }, 328 329 /** 330 * Clone the current animation 331 * @param pZone 332 * @returns {cc.Animation} 333 */ 334 copy:function (pZone) { 335 return this.copyWithZone(null); 336 }, 337 338 /** 339 * Returns how many times the animation is going to loop. 0 means animation is not animated. 1, animation is executed one time, ... 340 * @return {Number} 341 */ 342 getLoops:function () { 343 return this._loops; 344 }, 345 346 /** 347 * Sets how many times the animation is going to loop. 0 means animation is not animated. 1, animation is executed one time, ... 348 * @param {Number} value 349 */ 350 setLoops:function (value) { 351 this._loops = value; 352 }, 353 354 /** 355 * Sets whether or not it shall restore the original frame when the animation finishes 356 * @param {Boolean} restOrigFrame 357 */ 358 setRestoreOriginalFrame:function (restOrigFrame) { 359 this._restoreOriginalFrame = restOrigFrame; 360 }, 361 362 /** 363 * Returns whether or not it shall restore the original frame when the animation finishes 364 * @return {Boolean} 365 */ 366 getRestoreOriginalFrame:function () { 367 return this._restoreOriginalFrame; 368 }, 369 370 /** 371 * Returns duration in seconds of the whole animation. It is the result of totalDelayUnits * delayPerUnit 372 * @return {Number} 373 */ 374 getDuration:function () { 375 return this._totalDelayUnits * this._delayPerUnit; 376 }, 377 378 /** 379 * Returns delay in seconds of the "delay unit" 380 * @return {Number} 381 */ 382 getDelayPerUnit:function () { 383 return this._delayPerUnit; 384 }, 385 386 /** 387 * Sets delay in seconds of the "delay unit" 388 * @param {Number} delayPerUnit 389 */ 390 setDelayPerUnit:function (delayPerUnit) { 391 this._delayPerUnit = delayPerUnit; 392 }, 393 394 /** 395 * Returns total delay units of the cc.Animation. 396 * @return {Number} 397 */ 398 getTotalDelayUnits:function () { 399 return this._totalDelayUnits; 400 }, 401 402 /** 403 * Initializes a cc.Animation with frames and a delay between frames, do not call this method yourself, please pass parameters to constructor to initialize. 404 * @param {Array} frames 405 * @param {Number} delay 406 * @param {Number} [loops=1] 407 */ 408 initWithSpriteFrames:function (frames, delay, loops) { 409 cc.arrayVerifyType(frames, cc.SpriteFrame); 410 this._loops = loops === undefined ? 1 : loops; 411 this._delayPerUnit = delay || 0; 412 this._totalDelayUnits = 0; 413 414 var locFrames = this._frames; 415 locFrames.length = 0; 416 if (frames) { 417 for (var i = 0; i < frames.length; i++) { 418 var frame = frames[i]; 419 var animFrame = new cc.AnimationFrame(); 420 animFrame.initWithSpriteFrame(frame, 1, null); 421 locFrames.push(animFrame); 422 } 423 this._totalDelayUnits += frames.length; 424 } 425 return true; 426 }, 427 /** 428 * <p>Currently JavaScript Bindings (JSB), in some cases, needs to use retain and release. This is a bug in JSB, 429 * and the ugly workaround is to use retain/release. So, these 2 methods were added to be compatible with JSB. 430 * This is a hack, and should be removed once JSB fixes the retain/release bug<br/> 431 * You will need to retain an object if you created an engine object and haven't added it into the scene graph during the same frame.<br/> 432 * Otherwise, JSB's native autorelease pool will consider this object a useless one and release it directly,<br/> 433 * when you want to use it later, a "Invalid Native Object" error will be raised.<br/> 434 * The retain function can increase a reference count for the native object to avoid it being released,<br/> 435 * you need to manually invoke release function when you think this object is no longer needed, otherwise, there will be memory learks.<br/> 436 * retain and release function call should be paired in developer's game code.</p> 437 * @function 438 * @see cc.Animation#release 439 */ 440 retain:function () { 441 }, 442 /** 443 * <p>Currently JavaScript Bindings (JSB), in some cases, needs to use retain and release. This is a bug in JSB, 444 * and the ugly workaround is to use retain/release. So, these 2 methods were added to be compatible with JSB. 445 * This is a hack, and should be removed once JSB fixes the retain/release bug<br/> 446 * You will need to retain an object if you created an engine object and haven't added it into the scene graph during the same frame.<br/> 447 * Otherwise, JSB's native autorelease pool will consider this object a useless one and release it directly,<br/> 448 * when you want to use it later, a "Invalid Native Object" error will be raised.<br/> 449 * The retain function can increase a reference count for the native object to avoid it being released,<br/> 450 * you need to manually invoke release function when you think this object is no longer needed, otherwise, there will be memory learks.<br/> 451 * retain and release function call should be paired in developer's game code.</p> 452 * @function 453 * @see cc.Animation#retain 454 */ 455 release:function () { 456 } 457 }); 458 459 /** 460 * Creates an animation. 461 * @deprecated since v3.0, please use new construction instead 462 * @see cc.Animation 463 * @param {Array} frames 464 * @param {Number} delay 465 * @param {Number} [loops=1] 466 * @return {cc.Animation} 467 */ 468 cc.Animation.create = function (frames, delay, loops) { 469 return new cc.Animation(frames, delay, loops); 470 }; 471 472 /** 473 * @deprecated since v3.0, please use new construction instead 474 * @see cc.Animation 475 * @type {Function} 476 */ 477 cc.Animation.createWithAnimationFrames = cc.Animation.create;