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