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  * resource type
 29  * @constant
 30  * @type Object
 31  */
 32 cc.RESOURCE_TYPE = {
 33     "IMAGE": ["png", "jpg", "bmp","jpeg","gif"],
 34     "SOUND": ["mp3", "ogg", "wav", "mp4", "m4a"],
 35     "XML": ["plist", "xml", "fnt", "tmx", "tsx"],
 36     "BINARY": ["ccbi"],
 37     "FONT": "FONT",
 38     "TEXT":["txt", "vsh", "fsh","json"],
 39     "UNKNOW": []
 40 };
 41 
 42 /**
 43  * A class to pre-load resources before engine start game main loop.
 44  * @class
 45  * @extends cc.Scene
 46  */
 47 cc.Loader = cc.Class.extend(/** @lends cc.Loader# */{
 48     _curNumber: 0,
 49     _totalNumber: 0,
 50     _loadedNumber: 0,
 51     _resouces: null,
 52     _animationInterval: 1 / 60,
 53     _interval: null,
 54     _isAsync: false,
 55 
 56     /**
 57      * Constructor
 58      */
 59     ctor: function () {
 60         this._resouces = [];
 61     },
 62 
 63     /**
 64      * init with resources
 65      * @param {Array} resources
 66      * @param {Function|String} selector
 67      * @param {Object} target
 68      */
 69     initWithResources: function (resources, selector, target) {
 70         cc.Assert(resources != null, "resources should not null");
 71 
 72         if (selector) {
 73             this._selector = selector;
 74             this._target = target;
 75         }
 76 
 77         if ((resources != this._resouces) || (this._curNumber == 0)) {
 78             this._curNumber = 0;
 79             this._loadedNumber = 0;
 80             if (resources[0] instanceof Array) {
 81                 for (var i = 0; i < resources.length; i++) {
 82                     var each = resources[i];
 83                     this._resouces = this._resouces.concat(each);
 84                 }
 85             } else
 86                 this._resouces = resources;
 87             this._totalNumber = this._resouces.length;
 88         }
 89 
 90         //load resources
 91         this._schedulePreload();
 92     },
 93 
 94     setAsync: function (isAsync) {
 95         this._isAsync = isAsync;
 96     },
 97 
 98     /**
 99      * Callback when a resource file load failed.
100      * @example
101      * //example
102      * cc.Loader.getInstance().onResLoaded();
103      */
104     onResLoadingErr: function (name) {
105         cc.log("cocos2d:Failed loading resource: " + name);
106     },
107 
108     /**
109      * Callback when a resource file loaded.
110      * @example
111      * //example
112      * cc.Loader.getInstance().onResLoaded();
113      */
114     onResLoaded: function () {
115         this._loadedNumber++;
116     },
117 
118     /**
119      * Get loading percentage
120      * @return {Number}
121      * @example
122      * //example
123      * cc.log(cc.Loader.getInstance().getPercentage() + "%");
124      */
125     getPercentage: function () {
126         var percent = 0;
127         if (this._totalNumber == 0) {
128             percent = 100;
129         } else {
130             percent = (0 | (this._loadedNumber / this._totalNumber * 100));
131         }
132         return percent;
133     },
134 
135     /**
136      * release resources from a list
137      * @param resources
138      */
139     releaseResources: function (resources) {
140         if (resources && resources.length > 0) {
141             var sharedTextureCache = cc.TextureCache.getInstance();
142             var sharedEngine = cc.AudioEngine.getInstance();
143             var sharedParser = cc.SAXParser.getInstance();
144             var sharedFileUtils = cc.FileUtils.getInstance();
145 
146             var resInfo;
147             for (var i = 0; i < resources.length; i++) {
148                 resInfo = resources[i];
149                 var type = this._getResType(resInfo);
150                 switch (type) {
151                     case "IMAGE":
152                         sharedTextureCache.removeTextureForKey(resInfo.src);
153                         break;
154                     case "SOUND":
155                         sharedEngine.unloadEffect(resInfo.src);
156                         break;
157                     case "XML":
158                         sharedParser.unloadPlist(resInfo.src);
159                         break;
160                     case "BINARY":
161                         sharedFileUtils.unloadBinaryFileData(resInfo.src);
162                         break;
163                     case "TEXT":
164                         sharedFileUtils.unloadTextFileData(resInfo.src);
165                         break;
166                     case "FONT":
167                         this._unregisterFaceFont(resInfo);
168                         break;
169                     default:
170                         throw "cocos2d:unknown filename extension: " + type;
171                         break;
172                 }
173             }
174         }
175     },
176 
177     _preload: function () {
178         this._updatePercent();
179         if (this._isAsync) {
180             var frameRate = cc.Director.getInstance()._frameRate;
181             if (frameRate != null && frameRate < 20) {
182                 cc.log("cocos2d: frame rate less than 20 fps, skip frame.");
183                 return;
184             }
185         }
186 
187         if (this._curNumber < this._totalNumber) {
188             this._loadOneResource();
189             this._curNumber++;
190         }
191     },
192 
193     _loadOneResource: function () {
194         var sharedTextureCache = cc.TextureCache.getInstance();
195         var sharedEngine = cc.AudioEngine.getInstance();
196         var sharedParser = cc.SAXParser.getInstance();
197         var sharedFileUtils = cc.FileUtils.getInstance();
198 
199         var resInfo = this._resouces[this._curNumber];
200         var type = this._getResType(resInfo);
201         switch (type) {
202             case "IMAGE":
203                 sharedTextureCache.addImage(resInfo.src);
204                 break;
205             case "SOUND":
206                 sharedEngine.preloadSound(resInfo.src);
207                 break;
208             case "XML":
209                 sharedParser.preloadPlist(resInfo.src);
210                 break;
211             case "BINARY":
212                 sharedFileUtils.preloadBinaryFileData(resInfo.src);
213                 break;
214             case "TEXT" :
215                 sharedFileUtils.preloadTextFileData(resInfo.src);
216                 break;
217             case "FONT":
218                 this._registerFaceFont(resInfo);
219                 break;
220             default:
221                 throw "cocos2d:unknown filename extension: " + type;
222                 break;
223         }
224     },
225 
226     _schedulePreload: function () {
227         var _self = this;
228         this._interval = setInterval(function () {
229             _self._preload();
230         }, this._animationInterval * 1000);
231     },
232 
233     _unschedulePreload: function () {
234         clearInterval(this._interval);
235     },
236 
237     _getResType: function (resInfo) {
238         var isFont = resInfo.fontName;
239         if (isFont != null) {
240             return cc.RESOURCE_TYPE["FONT"];
241         } else {
242             var src = resInfo.src;
243             var ext = src.substring(src.lastIndexOf(".") + 1, src.length);
244 
245             var index = ext.indexOf("?");
246             if(index > 0) ext = ext.substring(0, index);
247 
248             for (var resType in cc.RESOURCE_TYPE) {
249                 if (cc.RESOURCE_TYPE[resType].indexOf(ext) != -1) {
250                     return resType;
251                 }
252             }
253             return ext;
254         }
255     },
256 
257     _updatePercent: function () {
258         var percent = this.getPercentage();
259 
260         if (percent >= 100) {
261             this._unschedulePreload();
262             this._complete();
263         }
264     },
265 
266     _complete: function () {
267         if (this._target && (typeof(this._selector) == "string")) {
268             this._target[this._selector](this);
269         } else if (this._target && (typeof(this._selector) == "function")) {
270             this._selector.call(this._target, this);
271         } else {
272             this._selector(this);
273         }
274 
275         this._curNumber = 0;
276         this._loadedNumber = 0;
277         this._totalNumber = 0;
278     },
279 
280     _registerFaceFont: function (fontRes) {
281         var srcArr = fontRes.src;
282         var fileUtils = cc.FileUtils.getInstance();
283         if (srcArr && srcArr.length > 0) {
284             var fontStyle = document.createElement("style");
285             fontStyle.type = "text/css";
286             document.body.appendChild(fontStyle);
287 
288             var fontStr = "@font-face { font-family:" + fontRes.fontName + "; src:";
289             for (var i = 0; i < srcArr.length; i++) {
290                 fontStr += "url('" + fileUtils.fullPathForFilename(encodeURI(srcArr[i].src)) + "') format('" + srcArr[i].type + "')";
291                 fontStr += (i == (srcArr.length - 1)) ? ";" : ",";
292             }
293             fontStyle.textContent += fontStr + "};";
294 
295             //preload
296             //<div style="font-family: PressStart;">.</div>
297             var preloadDiv = document.createElement("div");
298             preloadDiv.style.fontFamily = fontRes.fontName;
299             preloadDiv.innerHTML = ".";
300             preloadDiv.style.position = "absolute";
301             preloadDiv.style.left = "-100px";
302             preloadDiv.style.top = "-100px";
303             document.body.appendChild(preloadDiv);
304         }
305         cc.Loader.getInstance().onResLoaded();
306     },
307 
308     _unregisterFaceFont: function (fontRes) {
309         //todo remove style
310     }
311 });
312 
313 /**
314  * Preload resources in the background
315  * @param {Array} resources
316  * @param {Function|String} selector
317  * @param {Object} target
318  * @return {cc.Loader}
319  * @example
320  * //example
321  * var g_mainmenu = [
322  *    {src:"res/hello.png"},
323  *    {src:"res/hello.plist"},
324  *
325  *    {src:"res/logo.png"},
326  *    {src:"res/btn.png"},
327  *
328  *    {src:"res/boom.mp3"},
329  * ]
330  *
331  * var g_level = [
332  *    {src:"res/level01.png"},
333  *    {src:"res/level02.png"},
334  *    {src:"res/level03.png"}
335  * ]
336  *
337  * //load a list of resources
338  * cc.Loader.preload(g_mainmenu, this.startGame, this);
339  *
340  * //load multi lists of resources
341  * cc.Loader.preload([g_mainmenu,g_level], this.startGame, this);
342  */
343 cc.Loader.preload = function (resources, selector, target) {
344     if (!this._instance) {
345         this._instance = new cc.Loader();
346     }
347     this._instance.initWithResources(resources, selector, target);
348     return this._instance;
349 };
350 
351 /**
352  * Preload resources async
353  * @param {Array} resources
354  * @param {Function|String} selector
355  * @param {Object} target
356  * @return {cc.Loader}
357  */
358 cc.Loader.preloadAsync = function (resources, selector, target) {
359     if (!this._instance) {
360         this._instance = new cc.Loader();
361     }
362     this._instance.setAsync(true);
363     this._instance.initWithResources(resources, selector, target);
364     return this._instance;
365 };
366 
367 /**
368  * Release the resources from a list
369  * @param {Array} resources
370  */
371 cc.Loader.purgeCachedData = function (resources) {
372     if (this._instance) {
373         this._instance.releaseResources(resources);
374     }
375 };
376 
377 /**
378  * Returns a shared instance of the loader
379  * @function
380  * @return {cc.Loader}
381  */
382 cc.Loader.getInstance = function () {
383     if (!this._instance) {
384         this._instance = new cc.Loader();
385     }
386     return this._instance;
387 };
388 
389 cc.Loader._instance = null;
390 
391 
392 /**
393  * Used to display the loading screen
394  * @class
395  * @extends cc.Scene
396  */
397 cc.LoaderScene = cc.Scene.extend(/** @lends cc.LoaderScene# */{
398     _logo: null,
399     _logoTexture: null,
400     _texture2d: null,
401     _bgLayer: null,
402     _label: null,
403     _winSize:null,
404 
405     /**
406      * Constructor
407      */
408     ctor: function () {
409         cc.Scene.prototype.ctor.call(this);
410         this._winSize = cc.Director.getInstance().getWinSize();
411     },
412     init:function(){
413         cc.Scene.prototype.init.call(this);
414 
415         //logo
416         var logoHeight = 200;
417         var centerPos = cc.p(this._winSize.width / 2, this._winSize.height / 2);
418 
419         this._logoTexture = new Image();
420         var _this = this;
421         this._logoTexture.addEventListener("load", function () {
422             _this._initStage(centerPos);
423             this.removeEventListener('load', arguments.callee, false);
424         });
425         this._logoTexture.src = "data:image/jpeg;base64,/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP/sABFEdWNreQABAAQAAAAlAAD/4QMpaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjAtYzA2MCA2MS4xMzQ3NzcsIDIwMTAvMDIvMTItMTc6MzI6MDAgICAgICAgICI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjM4MDBEMDY2QTU1MjExRTFBQTAzQjEzMUNFNzMxRkQwIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjM4MDBEMDY1QTU1MjExRTFBQTAzQjEzMUNFNzMxRkQwIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDUzUgV2luZG93cyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkU2RTk0OEM4OERCNDExRTE5NEUyRkE3M0M3QkE1NTlEIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkU2RTk0OEM5OERCNDExRTE5NEUyRkE3M0M3QkE1NTlEIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+/+4ADkFkb2JlAGTAAAAAAf/bAIQADQkJCQoJDQoKDRMMCwwTFhENDREW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";
426         this._logoTexture.width = 160;
427         this._logoTexture.height = 200;
428 
429         // bg
430         this._bgLayer = cc.LayerColor.create(cc.c4(32, 32, 32, 255));
431         this._bgLayer.setPosition(0, 0);
432         this.addChild(this._bgLayer, 0);
433 
434         //loading percent
435         this._label = cc.LabelTTF.create("Loading... 0%", "Arial", 14);
436         this._label.setColor(cc.c3(180, 180, 180));
437         this._label.setOpacity(0);
438         this._label.setPosition(cc.pAdd(centerPos, cc.p(0, -logoHeight / 2 - 10)));
439         this._bgLayer.addChild(this._label, 10);
440     },
441 
442     _initStage: function (centerPos) {
443         this._texture2d = new cc.Texture2D();
444         this._texture2d.initWithElement(this._logoTexture);
445         this._texture2d.handleLoadedTexture();
446         this._logo = cc.Sprite.createWithTexture(this._texture2d);
447 
448         this._logo.setPosition(centerPos);
449         this._bgLayer.addChild(this._logo, 10);
450 
451         //load resources
452         this._logoFadeIn();
453     },
454 
455     onEnter: function () {
456         cc.Node.prototype.onEnter.call(this);
457         this.schedule(this._startLoading, 0.3);
458     },
459 
460     onExit: function () {
461         cc.Node.prototype.onExit.call(this);
462         var tmpStr = "Loading... 0%";
463         this._label.setString(tmpStr);
464     },
465 
466     /**
467      * init with resources
468      * @param {Array} resources
469      * @param {Function|String} selector
470      * @param {Object} target
471      */
472     initWithResources: function (resources, selector, target) {
473         this.resources = resources;
474         this.selector = selector;
475         this.target = target;
476     },
477 
478     _startLoading: function () {
479         this.unschedule(this._startLoading);
480         cc.Loader.preload(this.resources, this.selector, this.target);
481         this.schedule(this._updatePercent);
482     },
483 
484     _logoFadeIn: function () {
485         var logoAction = cc.Spawn.create(
486             cc.EaseBounce.create(cc.MoveBy.create(0.25, cc.p(0, 10))),
487             cc.FadeIn.create(0.5));
488 
489         var labelAction = cc.Sequence.create(
490             cc.DelayTime.create(0.15),
491             logoAction.clone());
492 
493         this._logo.runAction(logoAction);
494         this._label.runAction(labelAction);
495     },
496 
497     _updatePercent: function () {
498         var percent = cc.Loader.getInstance().getPercentage();
499         var tmpStr = "Loading... " + percent + "%";
500         this._label.setString(tmpStr);
501 
502         if (percent >= 100)
503             this.unschedule(this._updatePercent);
504     }
505 });
506 
507 /**
508  * Preload multi scene resources.
509  * @param {Array} resources
510  * @param {Function|String} selector
511  * @param {Object} target
512  * @return {cc.LoaderScene}
513  * @example
514  * //example
515  * var g_mainmenu = [
516  *    {src:"res/hello.png"},
517  *    {src:"res/hello.plist"},
518  *
519  *    {src:"res/logo.png"},
520  *    {src:"res/btn.png"},
521  *
522  *    {src:"res/boom.mp3"},
523  * ]
524  *
525  * var g_level = [
526  *    {src:"res/level01.png"},
527  *    {src:"res/level02.png"},
528  *    {src:"res/level03.png"}
529  * ]
530  *
531  * //load a list of resources
532  * cc.LoaderScene.preload(g_mainmenu, this.startGame, this);
533  *
534  * //load multi lists of resources
535  * cc.LoaderScene.preload([g_mainmenu,g_level], this.startGame, this);
536  */
537 cc.LoaderScene.preload = function (resources, selector, target) {
538     if (!this._instance) {
539         this._instance = new cc.LoaderScene();
540         this._instance.init();
541     }
542 
543     this._instance.initWithResources(resources, selector, target);
544 
545     var director = cc.Director.getInstance();
546     if (director.getRunningScene()) {
547         director.replaceScene(this._instance);
548     } else {
549         director.runWithScene(this._instance);
550     }
551 
552     return this._instance;
553 };