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