1 /****************************************************************************
  2  Copyright (c) 2011-2012 cocos2d-x.org
  3  Copyright (c) 2013-2014 Chukong Technologies Inc.
  4 
  5  http://www.cocos2d-x.org
  6 
  7  Permission is hereby granted, free of charge, to any person obtaining a copy
  8  of this software and associated documentation files (the "Software"), to deal
  9  in the Software without restriction, including without limitation the rights
 10  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 11  copies of the Software, and to permit persons to whom the Software is
 12  furnished to do so, subject to the following conditions:
 13 
 14  The above copyright notice and this permission notice shall be included in
 15  all copies or substantial portions of the Software.
 16 
 17  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 18  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 19  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 20  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 21  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 22  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 23  THE SOFTWARE.
 24  ****************************************************************************/
 25 
 26 /**
 27  * The main namespace of Cocos2d-JS, all engine core classes, functions, properties and constants are defined in this namespace
 28  * @namespace
 29  * @name cc
 30  */
 31 var cc = cc || {};
 32 cc._tmp = cc._tmp || {};
 33 cc._LogInfos = {};
 34 
 35 /** @expose */
 36 window._p;
 37 _p = window;
 38 /** @expose */
 39 _p.gl;
 40 /** @expose */
 41 _p.WebGLRenderingContext;
 42 /** @expose */
 43 _p.DeviceOrientationEvent;
 44 /** @expose */
 45 _p.DeviceMotionEvent;
 46 /** @expose */
 47 _p.AudioContext;
 48 /** @expose */
 49 _p.webkitAudioContext;
 50 /** @expose */
 51 _p.mozAudioContext;
 52 _p = Object.prototype;
 53 /** @expose */
 54 _p._super;
 55 /** @expose */
 56 _p.ctor;
 57 delete window._p;
 58 
 59 cc.newElement = function (x) {
 60     return document.createElement(x);
 61 };
 62 
 63 cc._addEventListener = function (element, type, listener, useCapture) {
 64     element.addEventListener(type, listener, useCapture);
 65 };
 66 
 67 //is nodejs ? Used to support node-webkit.
 68 cc._isNodeJs = typeof require !== 'undefined' && require("fs");
 69 
 70 /**
 71  * Iterate over an object or an array, executing a function for each matched element.
 72  * @param {object|array} obj
 73  * @param {function} iterator
 74  * @param {object} [context]
 75  */
 76 cc.each = function (obj, iterator, context) {
 77     if (!obj)
 78         return;
 79     if (obj instanceof Array) {
 80         for (var i = 0, li = obj.length; i < li; i++) {
 81             if (iterator.call(context, obj[i], i) === false)
 82                 return;
 83         }
 84     } else {
 85         for (var key in obj) {
 86             if (iterator.call(context, obj[key], key) === false)
 87                 return;
 88         }
 89     }
 90 };
 91 
 92 /**
 93  * Copy all of the properties in source objects to target object and return the target object.
 94  * @param {object} target
 95  * @param {object} *sources
 96  * @returns {object}
 97  */
 98 cc.extend = function(target) {
 99     var sources = arguments.length >= 2 ? Array.prototype.slice.call(arguments, 1) : [];
100 
101     cc.each(sources, function(src) {
102         for(var key in src) {
103             if (src.hasOwnProperty(key)) {
104                 target[key] = src[key];
105             }
106         }
107     });
108     return target;
109 };
110 
111 /**
112  * Check the obj whether is function or not
113  * @param {*} obj
114  * @returns {boolean}
115  */
116 cc.isFunction = function(obj) {
117     return typeof obj == 'function';
118 };
119 
120 /**
121  * Check the obj whether is number or not
122  * @param {*} obj
123  * @returns {boolean}
124  */
125 cc.isNumber = function(obj) {
126     return typeof obj == 'number' || Object.prototype.toString.call(obj) == '[object Number]';
127 };
128 
129 /**
130  * Check the obj whether is string or not
131  * @param {*} obj
132  * @returns {boolean}
133  */
134 cc.isString = function(obj) {
135     return typeof obj == 'string' || Object.prototype.toString.call(obj) == '[object String]';
136 };
137 
138 /**
139  * Check the obj whether is array or not
140  * @param {*} obj
141  * @returns {boolean}
142  */
143 cc.isArray = function(obj) {
144     return Object.prototype.toString.call(obj) == '[object Array]';
145 };
146 
147 /**
148  * Check the obj whether is undefined or not
149  * @param {*} obj
150  * @returns {boolean}
151  */
152 cc.isUndefined = function(obj) {
153     return typeof obj == 'undefined';
154 };
155 
156 /**
157  * Check the obj whether is object or not
158  * @param {*} obj
159  * @returns {boolean}
160  */
161 cc.isObject = function(obj) {
162     var type = typeof obj;
163 
164     return type == 'function' || (obj && type == 'object');
165 };
166 
167 /**
168  * Check the url whether cross origin
169  * @param {String} url
170  * @returns {boolean}
171  */
172 cc.isCrossOrigin = function (url) {
173     if (!url) {
174         cc.log("invalid URL");
175         return false;
176     }
177     var startIndex = url.indexOf("://");
178     if (startIndex == -1)
179         return false;
180 
181     var endIndex = url.indexOf("/", startIndex + 3);
182     var urlOrigin = (endIndex == -1) ? url : url.substring(0, endIndex);
183     return urlOrigin != location.origin;
184 };
185 
186 //+++++++++++++++++++++++++something about async begin+++++++++++++++++++++++++++++++
187 /**
188  * Async Pool class, a helper of cc.async
189  * @param {Object|Array} srcObj
190  * @param {Number} limit the limit of parallel number
191  * @param {function} iterator
192  * @param {function} onEnd
193  * @param {object} target
194  * @constructor
195  */
196 cc.AsyncPool = function(srcObj, limit, iterator, onEnd, target){
197     var self = this;
198     self._srcObj = srcObj;
199     self._limit = limit;
200     self._pool = [];
201     self._iterator = iterator;
202     self._iteratorTarget = target;
203     self._onEnd = onEnd;
204     self._onEndTarget = target;
205     self._results = srcObj instanceof Array ? [] : {};
206     self._isErr = false;
207 
208     cc.each(srcObj, function(value, index){
209         self._pool.push({index : index, value : value});
210     });
211 
212     self.size = self._pool.length;
213     self.finishedSize = 0;
214     self._workingSize = 0;
215 
216     self._limit = self._limit || self.size;
217 
218     self.onIterator = function(iterator, target){
219         self._iterator = iterator;
220         self._iteratorTarget = target;
221     };
222 
223     self.onEnd = function(endCb, endCbTarget){
224         self._onEnd = endCb;
225         self._onEndTarget = endCbTarget;
226     };
227 
228     self._handleItem = function(){
229         var self = this;
230         if(self._pool.length == 0)
231             return;                                                         //return directly if the array's length = 0
232         if(self._workingSize >= self._limit)
233             return;                                                         //return directly if the working size great equal limit number
234         var item = self._pool.shift();
235         var value = item.value, index = item.index;
236         self._workingSize++;
237         self._iterator.call(self._iteratorTarget, value, index, function(err){
238             if(self._isErr)
239                 return;
240 
241             self.finishedSize++;
242             self._workingSize--;
243             if(err) {
244                 self._isErr = true;
245                 if(self._onEnd)
246                     self._onEnd.call(self._onEndTarget, err);
247                 return
248             }
249 
250             var arr = Array.prototype.slice.call(arguments, 1);
251             self._results[this.index] = arr[0];
252             if(self.finishedSize == self.size) {
253                 if(self._onEnd)
254                     self._onEnd.call(self._onEndTarget, null, self._results);
255                 return
256             }
257             self._handleItem();
258         }.bind(item), self);
259     };
260 
261     self.flow = function(){
262         var self = this;
263         if(self._pool.length == 0) {
264             if(self._onEnd)
265                 self._onEnd.call(self._onEndTarget, null, []);
266                 return;
267         }
268         for(var i = 0; i < self._limit; i++)
269             self._handleItem();
270     }
271 };
272 
273 /**
274  * @class
275  */
276 cc.async = /** @lends cc.async# */{
277     /**
278      * Do tasks series.
279      * @param {Array|Object} tasks
280      * @param {function} [cb] callback
281      * @param {Object} [target]
282      * @return {cc.AsyncPool}
283      */
284     series : function(tasks, cb, target){
285         var asyncPool = new cc.AsyncPool(tasks, 1, function(func, index, cb1){
286             func.call(target, cb1);
287         }, cb, target);
288         asyncPool.flow();
289         return asyncPool;
290     },
291 
292     /**
293      * Do tasks parallel.
294      * @param {Array|Object} tasks
295      * @param {function} cb callback
296      * @param {Object} [target]
297      * @return {cc.AsyncPool}
298      */
299     parallel : function(tasks, cb, target){
300         var asyncPool = new cc.AsyncPool(tasks, 0, function(func, index, cb1){
301             func.call(target, cb1);
302         }, cb, target);
303         asyncPool.flow();
304         return asyncPool;
305     },
306 
307     /**
308      * Do tasks waterfall.
309      * @param {Array|Object} tasks
310      * @param {function} cb callback
311      * @param {Object} [target]
312      * @return {cc.AsyncPool}
313      */
314     waterfall : function(tasks, cb, target){
315         var args = [];
316         var asyncPool = new cc.AsyncPool(tasks, 1,
317             function (func, index, cb1) {
318                 args.push(function (err) {
319                     args = Array.prototype.slice.call(arguments, 1);
320                     cb1.apply(null, arguments);
321                 });
322                 func.apply(target, args);
323             }, function (err, results) {
324                 if (!cb)
325                     return;
326                 if (err)
327                     return cb.call(target, err);
328                 cb.call(target, null, results[results.length - 1]);
329             });
330         asyncPool.flow();
331         return asyncPool;
332     },
333 
334     /**
335      * Do tasks by iterator.
336      * @param {Array|Object} tasks
337      * @param {function|Object} iterator
338      * @param {function} cb callback
339      * @param {Object} [target]
340      * @return {cc.AsyncPool}
341      */
342     map : function(tasks, iterator, cb, target){
343         var locIterator = iterator;
344         if(typeof(iterator) == "object"){
345             cb = iterator.cb;
346             target = iterator.iteratorTarget;
347             locIterator = iterator.iterator;
348         }
349         var asyncPool = new cc.AsyncPool(tasks, 0, locIterator, cb, target);
350         asyncPool.flow();
351         return asyncPool;
352     },
353 
354     /**
355      * Do tasks by iterator limit.
356      * @param {Array|Object} tasks
357      * @param {Number} limit
358      * @param {function} iterator
359      * @param {function} cb callback
360      * @param {Object} [target]
361      */
362     mapLimit : function(tasks, limit, iterator, cb, target){
363         var asyncPool = new cc.AsyncPool(tasks, limit, iterator, cb, target);
364         asyncPool.flow();
365         return asyncPool;
366     }
367 };
368 //+++++++++++++++++++++++++something about async end+++++++++++++++++++++++++++++++++
369 
370 //+++++++++++++++++++++++++something about path begin++++++++++++++++++++++++++++++++
371 /**
372  * @class
373  */
374 cc.path = /** @lends cc.path# */{
375     /**
376      * Join strings to be a path.
377      * @example
378      cc.path.join("a", "b.png");//-->"a/b.png"
379      cc.path.join("a", "b", "c.png");//-->"a/b/c.png"
380      cc.path.join("a", "b");//-->"a/b"
381      cc.path.join("a", "b", "/");//-->"a/b/"
382      cc.path.join("a", "b/", "/");//-->"a/b/"
383      * @returns {string}
384      */
385     join: function () {
386         var l = arguments.length;
387         var result = "";
388         for (var i = 0; i < l; i++) {
389             result = (result + (result == "" ? "" : "/") + arguments[i]).replace(/(\/|\\\\)$/, "");
390         }
391         return result;
392     },
393 
394     /**
395      * Get the ext name of a path.
396      * @example
397      cc.path.extname("a/b.png");//-->".png"
398      cc.path.extname("a/b.png?a=1&b=2");//-->".png"
399      cc.path.extname("a/b");//-->null
400      cc.path.extname("a/b?a=1&b=2");//-->null
401      * @param {string} pathStr
402      * @returns {*}
403      */
404     extname: function (pathStr) {
405         var temp = /(\.[^\.\/\?\\]*)(\?.*)?$/.exec(pathStr);
406         return temp ? temp[1] : null;
407     },
408 
409     /**
410      * Get the main name of a file name
411      * @param {string} fileName
412      * @returns {string}
413      */
414     mainFileName: function(fileName){
415         if(fileName){
416            var idx = fileName.lastIndexOf(".");
417             if(idx !== -1)
418                return fileName.substring(0,idx);
419         }
420         return fileName
421     },
422 
423     /**
424      * Get the file name of a file path.
425      * @example
426      cc.path.basename("a/b.png");//-->"b.png"
427      cc.path.basename("a/b.png?a=1&b=2");//-->"b.png"
428      cc.path.basename("a/b.png", ".png");//-->"b"
429      cc.path.basename("a/b.png?a=1&b=2", ".png");//-->"b"
430      cc.path.basename("a/b.png", ".txt");//-->"b.png"
431      * @param {string} pathStr
432      * @param {string} [extname]
433      * @returns {*}
434      */
435     basename: function (pathStr, extname) {
436         var index = pathStr.indexOf("?");
437         if (index > 0) pathStr = pathStr.substring(0, index);
438         var reg = /(\/|\\\\)([^(\/|\\\\)]+)$/g;
439         var result = reg.exec(pathStr.replace(/(\/|\\\\)$/, ""));
440         if (!result) return null;
441         var baseName = result[2];
442         if (extname && pathStr.substring(pathStr.length - extname.length).toLowerCase() == extname.toLowerCase())
443             return baseName.substring(0, baseName.length - extname.length);
444         return baseName;
445     },
446 
447     /**
448      * Get dirname of a file path.
449      * @example
450      * unix
451      cc.path.driname("a/b/c.png");//-->"a/b"
452      cc.path.driname("a/b/c.png?a=1&b=2");//-->"a/b"
453      cc.path.dirname("a/b/");//-->"a/b"
454      cc.path.dirname("c.png");//-->""
455      * windows
456      cc.path.driname("a\\b\\c.png");//-->"a\b"
457      cc.path.driname("a\\b\\c.png?a=1&b=2");//-->"a\b"
458      * @param {string} pathStr
459      * @returns {*}
460      */
461     dirname: function (pathStr) {
462         return pathStr.replace(/((.*)(\/|\\|\\\\))?(.*?\..*$)?/, '$2');
463     },
464 
465     /**
466      * Change extname of a file path.
467      * @example
468      cc.path.changeExtname("a/b.png", ".plist");//-->"a/b.plist"
469      cc.path.changeExtname("a/b.png?a=1&b=2", ".plist");//-->"a/b.plist?a=1&b=2"
470      * @param {string} pathStr
471      * @param {string} [extname]
472      * @returns {string}
473      */
474     changeExtname: function (pathStr, extname) {
475         extname = extname || "";
476         var index = pathStr.indexOf("?");
477         var tempStr = "";
478         if (index > 0) {
479             tempStr = pathStr.substring(index);
480             pathStr = pathStr.substring(0, index);
481         }
482         index = pathStr.lastIndexOf(".");
483         if (index < 0) return pathStr + extname + tempStr;
484         return pathStr.substring(0, index) + extname + tempStr;
485     },
486     /**
487      * Change file name of a file path.
488      * @example
489      cc.path.changeBasename("a/b/c.plist", "b.plist");//-->"a/b/b.plist"
490      cc.path.changeBasename("a/b/c.plist?a=1&b=2", "b.plist");//-->"a/b/b.plist?a=1&b=2"
491      cc.path.changeBasename("a/b/c.plist", ".png");//-->"a/b/c.png"
492      cc.path.changeBasename("a/b/c.plist", "b");//-->"a/b/b"
493      cc.path.changeBasename("a/b/c.plist", "b", true);//-->"a/b/b.plist"
494      * @param {String} pathStr
495      * @param {String} basename
496      * @param {Boolean} [isSameExt]
497      * @returns {string}
498      */
499     changeBasename: function (pathStr, basename, isSameExt) {
500         if (basename.indexOf(".") == 0) return this.changeExtname(pathStr, basename);
501         var index = pathStr.indexOf("?");
502         var tempStr = "";
503         var ext = isSameExt ? this.extname(pathStr) : "";
504         if (index > 0) {
505             tempStr = pathStr.substring(index);
506             pathStr = pathStr.substring(0, index);
507         }
508         index = pathStr.lastIndexOf("/");
509         index = index <= 0 ? 0 : index + 1;
510         return pathStr.substring(0, index) + basename + ext + tempStr;
511     }
512 };
513 //+++++++++++++++++++++++++something about path end++++++++++++++++++++++++++++++++
514 
515 //+++++++++++++++++++++++++something about loader start+++++++++++++++++++++++++++
516 /**
517  * Loader for resource loading process. It's a singleton object.
518  * @class
519  */
520 cc.loader = /** @lends cc.loader# */{
521     _jsCache: {},//cache for js
522     _register: {},//register of loaders
523     _langPathCache: {},//cache for lang path
524     _aliases: {},//aliases for res url
525 
526     resPath: "",//root path of resource
527     audioPath: "",//root path of audio
528     cache: {},//cache for data loaded
529 
530     /**
531      * Get XMLHttpRequest.
532      * @returns {XMLHttpRequest}
533      */
534     getXMLHttpRequest: function () {
535         return window.XMLHttpRequest ? new window.XMLHttpRequest() : new ActiveXObject("MSXML2.XMLHTTP");
536     },
537 
538     //@MODE_BEGIN DEV
539 
540     _getArgs4Js: function (args) {
541         var a0 = args[0], a1 = args[1], a2 = args[2], results = ["", null, null];
542 
543         if (args.length === 1) {
544             results[1] = a0 instanceof Array ? a0 : [a0];
545         } else if (args.length === 2) {
546             if (typeof a1 == "function") {
547                 results[1] = a0 instanceof Array ? a0 : [a0];
548                 results[2] = a1;
549             } else {
550                 results[0] = a0 || "";
551                 results[1] = a1 instanceof Array ? a1 : [a1];
552             }
553         } else if (args.length === 3) {
554             results[0] = a0 || "";
555             results[1] = a1 instanceof Array ? a1 : [a1];
556             results[2] = a2;
557         } else throw "arguments error to load js!";
558         return results;
559     },
560 
561     /**
562      * Load js files.
563      * If the third parameter doesn't exist, then the baseDir turns to be "".
564      *
565      * @param {string} [baseDir]   The pre path for jsList or the list of js path.
566      * @param {array} jsList    List of js path.
567      * @param {function} [cb]  Callback function
568      * @returns {*}
569      */
570     loadJs: function (baseDir, jsList, cb) {
571         var self = this, localJsCache = self._jsCache,
572             args = self._getArgs4Js(arguments);
573 
574         var preDir = args[0], list = args[1], callback = args[2];
575         if (navigator.userAgent.indexOf("Trident/5") > -1) {
576             self._loadJs4Dependency(preDir, list, 0, callback);
577         } else {
578             cc.async.map(list, function (item, index, cb1) {
579                 var jsPath = cc.path.join(preDir, item);
580                 if (localJsCache[jsPath]) return cb1(null);
581                 self._createScript(jsPath, false, cb1);
582             }, callback);
583         }
584     },
585     /**
586      * Load js width loading image.
587      *
588      * @param {string} [baseDir]
589      * @param {array} jsList
590      * @param {function} [cb]
591      */
592     loadJsWithImg: function (baseDir, jsList, cb) {
593         var self = this, jsLoadingImg = self._loadJsImg(),
594             args = self._getArgs4Js(arguments);
595         this.loadJs(args[0], args[1], function (err) {
596             if (err) throw err;
597             jsLoadingImg.parentNode.removeChild(jsLoadingImg);//remove loading gif
598             if (args[2]) args[2]();
599         });
600     },
601     _createScript: function (jsPath, isAsync, cb) {
602         var d = document, self = this, s = cc.newElement('script');
603         s.async = isAsync;
604         s.src = jsPath;
605         self._jsCache[jsPath] = true;
606         cc._addEventListener(s, 'load', function () {
607             s.parentNode.removeChild(s);
608             this.removeEventListener('load', arguments.callee, false);
609             cb();
610         }, false);
611         cc._addEventListener(s, 'error', function () {
612             s.parentNode.removeChild(s);
613             cb("Load " + jsPath + " failed!");
614         }, false);
615         d.body.appendChild(s);
616     },
617     _loadJs4Dependency: function (baseDir, jsList, index, cb) {
618         if (index >= jsList.length) {
619             if (cb) cb();
620             return;
621         }
622         var self = this;
623         self._createScript(cc.path.join(baseDir, jsList[index]), false, function (err) {
624             if (err) return cb(err);
625             self._loadJs4Dependency(baseDir, jsList, index + 1, cb);
626         });
627     },
628     _loadJsImg: function () {
629         var d = document, jsLoadingImg = d.getElementById("cocos2d_loadJsImg");
630         if (!jsLoadingImg) {
631             jsLoadingImg = cc.newElement('img');
632 
633             if (cc._loadingImage)
634                 jsLoadingImg.src = cc._loadingImage;
635 
636             var canvasNode = d.getElementById(cc.game.config["id"]);
637             canvasNode.style.backgroundColor = "black";
638             canvasNode.parentNode.appendChild(jsLoadingImg);
639 
640             var canvasStyle = getComputedStyle ? getComputedStyle(canvasNode) : canvasNode.currentStyle;
641             if (!canvasStyle)
642                 canvasStyle = {width: canvasNode.width, height: canvasNode.height};
643             jsLoadingImg.style.left = canvasNode.offsetLeft + (parseFloat(canvasStyle.width) - jsLoadingImg.width) / 2 + "px";
644             jsLoadingImg.style.top = canvasNode.offsetTop + (parseFloat(canvasStyle.height) - jsLoadingImg.height) / 2 + "px";
645             jsLoadingImg.style.position = "absolute";
646         }
647         return jsLoadingImg;
648     },
649     //@MODE_END DEV
650 
651     /**
652      * Load a single resource as txt.
653      * @param {string} url
654      * @param {function} [cb] arguments are : err, txt
655      */
656     loadTxt: function (url, cb) {
657         if (!cc._isNodeJs) {
658             var xhr = this.getXMLHttpRequest(),
659                 errInfo = "load " + url + " failed!";
660             xhr.open("GET", url, true);
661             if (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) {
662                 // IE-specific logic here
663                 xhr.setRequestHeader("Accept-Charset", "utf-8");
664                 xhr.onreadystatechange = function () {
665                     if(xhr.readyState == 4)
666                         xhr.status == 200 ? cb(null, xhr.responseText) : cb(errInfo);
667                 };
668             } else {
669                 if (xhr.overrideMimeType) xhr.overrideMimeType("text\/plain; charset=utf-8");
670                 xhr.onload = function () {
671                     if(xhr.readyState == 4)
672                         xhr.status == 200 ? cb(null, xhr.responseText) : cb(errInfo);
673                 };
674             }
675             xhr.send(null);
676         } else {
677             var fs = require("fs");
678             fs.readFile(url, function (err, data) {
679                 err ? cb(err) : cb(null, data.toString());
680             });
681         }
682     },
683     _loadTxtSync: function (url) {
684         if (!cc._isNodeJs) {
685             var xhr = this.getXMLHttpRequest();
686             xhr.open("GET", url, false);
687             if (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) {
688                 // IE-specific logic here
689                 xhr.setRequestHeader("Accept-Charset", "utf-8");
690             } else {
691                 if (xhr.overrideMimeType) xhr.overrideMimeType("text\/plain; charset=utf-8");
692             }
693             xhr.send(null);
694             if (!xhr.readyState == 4 || xhr.status != 200) {
695                 return null;
696             }
697             return xhr.responseText;
698         } else {
699             var fs = require("fs");
700             return fs.readFileSync(url).toString();
701         }
702     },
703 
704     /**
705      * Load a single resource as json.
706      * @param {string} url
707      * @param {function} [cb] arguments are : err, json
708      */
709     loadJson: function (url, cb) {
710         this.loadTxt(url, function (err, txt) {
711             try {
712                 err ? cb(err) : cb(null, JSON.parse(txt));
713             } catch (e) {
714                 throw "load json [" + url + "] failed : " + e;
715             }
716         });
717     },
718 
719     _checkIsImageURL: function (url) {
720         var ext = /(\.png)|(\.jpg)|(\.bmp)|(\.jpeg)|(\.gif)/.exec(url);
721         return (ext != null);
722     },
723     /**
724      * Load a single image.
725      * @param {!string} url
726      * @param {object} [option]
727      * @param {function} cb
728      * @returns {Image}
729      */
730     loadImg: function (url, option, cb) {
731         var opt = {
732             isCrossOrigin: true
733         };
734         if (cb !== undefined)
735             opt.isCrossOrigin = option.isCrossOrigin == null ? opt.isCrossOrigin : option.isCrossOrigin;
736         else if (option !== undefined)
737             cb = option;
738 
739         var img = new Image();
740         if (opt.isCrossOrigin && location.origin != "file://")
741             img.crossOrigin = "Anonymous";
742 
743         var lcb = function () {
744             this.removeEventListener('load', lcb, false);
745             this.removeEventListener('error', ecb, false);
746             if (cb)
747                 cb(null, img);
748         };
749 
750         var ecb = function () {
751             this.removeEventListener('error', ecb, false);
752 
753             if(img.crossOrigin.toLowerCase() == "anonymous"){
754                 opt.isCrossOrigin = false;
755                 cc.loader.loadImg(url, opt, cb);
756             }else{
757                 typeof cb == "function" && cb("load image failed");
758             }
759 
760         };
761 
762         cc._addEventListener(img, "load", lcb);
763         cc._addEventListener(img, "error", ecb);
764         img.src = url;
765         return img;
766     },
767 
768     /**
769      * Iterator function to load res
770      * @param {object} item
771      * @param {number} index
772      * @param {function} [cb]
773      * @returns {*}
774      * @private
775      */
776     _loadResIterator: function (item, index, cb) {
777         var self = this, url = null;
778         var type = item.type;
779         if (type) {
780             type = "." + type.toLowerCase();
781             url = item.src ? item.src : item.name + type;
782         } else {
783             url = item;
784             type = cc.path.extname(url);
785         }
786 
787         var obj = self.cache[url];
788         if (obj)
789             return cb(null, obj);
790         var loader = self._register[type.toLowerCase()];
791         if (!loader) {
792             cc.error("loader for [" + type + "] not exists!");
793             return cb();
794         }
795         var basePath = loader.getBasePath ? loader.getBasePath() : self.resPath;
796         var realUrl = self.getUrl(basePath, url);
797         loader.load(realUrl, url, item, function (err, data) {
798             if (err) {
799                 cc.log(err);
800                 self.cache[url] = null;
801                 delete self.cache[url];
802                 cb();
803             } else {
804                 self.cache[url] = data;
805                 cb(null, data);
806             }
807         });
808     },
809 
810     /**
811      * Get url with basePath.
812      * @param {string} basePath
813      * @param {string} [url]
814      * @returns {*}
815      */
816     getUrl: function (basePath, url) {
817         var self = this, langPathCache = self._langPathCache, path = cc.path;
818         if (basePath !== undefined && url === undefined) {
819             url = basePath;
820             var type = path.extname(url);
821             type = type ? type.toLowerCase() : "";
822             var loader = self._register[type];
823             if (!loader)
824                 basePath = self.resPath;
825             else
826                 basePath = loader.getBasePath ? loader.getBasePath() : self.resPath;
827         }
828         url = cc.path.join(basePath || "", url);
829         if (url.match(/[\/(\\\\)]lang[\/(\\\\)]/i)) {
830             if (langPathCache[url])
831                 return langPathCache[url];
832             var extname = path.extname(url) || "";
833             url = langPathCache[url] = url.substring(0, url.length - extname.length) + "_" + cc.sys.language + extname;
834         }
835         return url;
836     },
837 
838     /**
839      * Load resources then call the callback.
840      * @param {string} resources
841      * @param {function} [option] callback or trigger
842      * @param {function|Object} [cb]
843      * @return {cc.AsyncPool}
844      */
845     load : function(resources, option, cb){
846         var self = this;
847         var len = arguments.length;
848         if(len == 0)
849             throw "arguments error!";
850 
851         if(len == 3){
852             if(typeof option == "function"){
853                 if(typeof cb == "function")
854                     option = {trigger : option, cb : cb };
855                 else
856                     option = { cb : option, cbTarget : cb};
857             }
858         }else if(len == 2){
859             if(typeof option == "function")
860                 option = {cb : option};
861         }else if(len == 1){
862             option = {};
863         }
864 
865         if(!(resources instanceof Array))
866             resources = [resources];
867         var asyncPool = new cc.AsyncPool(resources, 0, function(value, index, cb1, aPool){
868             self._loadResIterator(value, index, function(err){
869                 if(err)
870                     return cb1(err);
871                 var arr = Array.prototype.slice.call(arguments, 1);
872                 if(option.trigger)
873                     option.trigger.call(option.triggerTarget, arr[0], aPool.size, aPool.finishedSize); //call trigger
874                 cb1(null, arr[0]);
875             });
876         }, option.cb, option.cbTarget);
877         asyncPool.flow();
878         return asyncPool;
879     },
880 
881     _handleAliases: function (fileNames, cb) {
882         var self = this, aliases = self._aliases;
883         var resList = [];
884         for (var key in fileNames) {
885             var value = fileNames[key];
886             aliases[key] = value;
887             resList.push(value);
888         }
889         this.load(resList, cb);
890     },
891 
892     /**
893      * <p>
894      *     Loads alias map from the contents of a filename.                                        <br/>
895      *                                                                                                                 <br/>
896      *     @note The plist file name should follow the format below:                                                   <br/>
897      *     <?xml version="1.0" encoding="UTF-8"?>                                                                      <br/>
898      *         <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">  <br/>
899      *             <plist version="1.0">                                                                               <br/>
900      *                 <dict>                                                                                          <br/>
901      *                     <key>filenames</key>                                                                        <br/>
902      *                     <dict>                                                                                      <br/>
903      *                         <key>sounds/click.wav</key>                                                             <br/>
904      *                         <string>sounds/click.caf</string>                                                       <br/>
905      *                         <key>sounds/endgame.wav</key>                                                           <br/>
906      *                         <string>sounds/endgame.caf</string>                                                     <br/>
907      *                         <key>sounds/gem-0.wav</key>                                                             <br/>
908      *                         <string>sounds/gem-0.caf</string>                                                       <br/>
909      *                     </dict>                                                                                     <br/>
910      *                     <key>metadata</key>                                                                         <br/>
911      *                     <dict>                                                                                      <br/>
912      *                         <key>version</key>                                                                      <br/>
913      *                         <integer>1</integer>                                                                    <br/>
914      *                     </dict>                                                                                     <br/>
915      *                 </dict>                                                                                         <br/>
916      *              </plist>                                                                                           <br/>
917      * </p>
918      * @param {String} url  The plist file name.
919      * @param {Function} [cb]     callback
920      */
921     loadAliases: function (url, cb) {
922         var self = this, dict = self.getRes(url);
923         if (!dict) {
924             self.load(url, function (err, results) {
925                 self._handleAliases(results[0]["filenames"], cb);
926             });
927         } else
928             self._handleAliases(dict["filenames"], cb);
929     },
930 
931     /**
932      * Register a resource loader into loader.
933      * @param {string} extNames
934      * @param {function} loader
935      */
936     register: function (extNames, loader) {
937         if (!extNames || !loader) return;
938         var self = this;
939         if (typeof extNames == "string")
940             return this._register[extNames.trim().toLowerCase()] = loader;
941         for (var i = 0, li = extNames.length; i < li; i++) {
942             self._register["." + extNames[i].trim().toLowerCase()] = loader;
943         }
944     },
945 
946     /**
947      * Get resource data by url.
948      * @param url
949      * @returns {*}
950      */
951     getRes: function (url) {
952         return this.cache[url] || this.cache[this._aliases[url]];
953     },
954 
955     /**
956      * Release the cache of resource by url.
957      * @param url
958      */
959     release: function (url) {
960         var cache = this.cache, aliases = this._aliases;
961         delete cache[url];
962         delete cache[aliases[url]];
963         delete aliases[url];
964     },
965 
966     /**
967      * Resource cache of all resources.
968      */
969     releaseAll: function () {
970         var locCache = this.cache, aliases = this._aliases;
971         for (var key in locCache)
972             delete locCache[key];
973         for (var key in aliases)
974             delete aliases[key];
975     }
976 };
977 //+++++++++++++++++++++++++something about loader end+++++++++++++++++++++++++++++
978 
979 /**
980  * A string tool to construct a string with format string.
981  * for example:
982  *      cc.formatStr("a: %d, b: %b", a, b);
983  *      cc.formatStr(a, b, c);
984  * @returns {String}
985  */
986 cc.formatStr = function(){
987     var args = arguments;
988     var l = args.length;
989     if(l < 1)
990         return "";
991 
992     var str = args[0];
993     var needToFormat = true;
994     if(typeof str == "object"){
995         needToFormat = false;
996     }
997     for(var i = 1; i < l; ++i){
998         var arg = args[i];
999         if(needToFormat){
1000             while(true){
1001                 var result = null;
1002                 if(typeof arg == "number"){
1003                     result = str.match(/(%d)|(%s)/);
1004                     if(result){
1005                         str = str.replace(/(%d)|(%s)/, arg);
1006                         break;
1007                     }
1008                 }
1009                 result = str.match(/%s/);
1010                 if(result)
1011                     str = str.replace(/%s/, arg);
1012                 else
1013                     str += "    " + arg;
1014                 break;
1015             }
1016         }else
1017             str += "    " + arg;
1018     }
1019     return str;
1020 };
1021 
1022 
1023 //+++++++++++++++++++++++++something about window events begin+++++++++++++++++++++++++++
1024 (function () {
1025     var win = window, hidden, visibilityChange, _undef = "undefined";
1026     if (!cc.isUndefined(document.hidden)) {
1027         hidden = "hidden";
1028         visibilityChange = "visibilitychange";
1029     } else if (!cc.isUndefined(document.mozHidden)) {
1030         hidden = "mozHidden";
1031         visibilityChange = "mozvisibilitychange";
1032     } else if (!cc.isUndefined(document.msHidden)) {
1033         hidden = "msHidden";
1034         visibilityChange = "msvisibilitychange";
1035     } else if (!cc.isUndefined(document.webkitHidden)) {
1036         hidden = "webkitHidden";
1037         visibilityChange = "webkitvisibilitychange";
1038     }
1039 
1040     var onHidden = function () {
1041         if (cc.eventManager && cc.game._eventHide)
1042             cc.eventManager.dispatchEvent(cc.game._eventHide);
1043     };
1044     var onShow = function () {
1045         if (cc.eventManager && cc.game._eventShow)
1046             cc.eventManager.dispatchEvent(cc.game._eventShow);
1047 
1048         if(cc.game._intervalId){
1049             window.cancelAnimationFrame(cc.game._intervalId);
1050 
1051             cc.game._runMainLoop();
1052         }
1053     };
1054 
1055     if (hidden) {
1056         cc._addEventListener(document, visibilityChange, function () {
1057             if (document[hidden]) onHidden();
1058             else onShow();
1059         }, false);
1060     } else {
1061         cc._addEventListener(win, "blur", onHidden, false);
1062         cc._addEventListener(win, "focus", onShow, false);
1063     }
1064 
1065     if(navigator.userAgent.indexOf("MicroMessenger") > -1){
1066         win.onfocus = function(){ onShow() };
1067     }
1068 
1069     if ("onpageshow" in window && "onpagehide" in window) {
1070         cc._addEventListener(win, "pagehide", onHidden, false);
1071         cc._addEventListener(win, "pageshow", onShow, false);
1072     }
1073     win = null;
1074     visibilityChange = null;
1075 })();
1076 //+++++++++++++++++++++++++something about window events end+++++++++++++++++++++++++++++
1077 
1078 //+++++++++++++++++++++++++something about log start++++++++++++++++++++++++++++
1079 
1080 //to make sure the cc.log, cc.warn, cc.error and cc.assert would not throw error before init by debugger mode.
1081 
1082 cc.log = cc.warn = cc.error = cc.assert = function () {
1083 };
1084 
1085 //+++++++++++++++++++++++++something about log end+++++++++++++++++++++++++++++
1086 
1087 /**
1088  * create a webgl context
1089  * @param {HTMLCanvasElement} canvas
1090  * @param {Object} opt_attribs
1091  * @return {WebGLRenderingContext}
1092  */
1093 cc.create3DContext = function (canvas, opt_attribs) {
1094     var names = ["webgl", "experimental-webgl", "webkit-3d", "moz-webgl"];
1095     var context = null;
1096     for (var ii = 0; ii < names.length; ++ii) {
1097         try {
1098             context = canvas.getContext(names[ii], opt_attribs);
1099         } catch (e) {
1100         }
1101         if (context) {
1102             break;
1103         }
1104     }
1105     return context;
1106 };
1107 //+++++++++++++++++++++++++something about sys begin+++++++++++++++++++++++++++++
1108 cc._initSys = function (config, CONFIG_KEY) {
1109     /**
1110      * Canvas of render type
1111      * @constant
1112      * @type {Number}
1113      */
1114     cc._RENDER_TYPE_CANVAS = 0;
1115 
1116     /**
1117      * WebGL of render type
1118      * @constant
1119      * @type {Number}
1120      */
1121     cc._RENDER_TYPE_WEBGL = 1;
1122 
1123     /**
1124      * System variables
1125      * @namespace
1126      * @name cc.sys
1127      */
1128     cc.sys = {};
1129     var sys = cc.sys;
1130 
1131     /**
1132      * English language code
1133      * @memberof cc.sys
1134      * @name LANGUAGE_ENGLISH
1135      * @constant
1136      * @type {Number}
1137      */
1138     sys.LANGUAGE_ENGLISH = "en";
1139 
1140     /**
1141      * Chinese language code
1142      * @memberof cc.sys
1143      * @name LANGUAGE_CHINESE
1144      * @constant
1145      * @type {Number}
1146      */
1147     sys.LANGUAGE_CHINESE = "zh";
1148 
1149     /**
1150      * French language code
1151      * @memberof cc.sys
1152      * @name LANGUAGE_FRENCH
1153      * @constant
1154      * @type {Number}
1155      */
1156     sys.LANGUAGE_FRENCH = "fr";
1157 
1158     /**
1159      * Italian language code
1160      * @memberof cc.sys
1161      * @name LANGUAGE_ITALIAN
1162      * @constant
1163      * @type {Number}
1164      */
1165     sys.LANGUAGE_ITALIAN = "it";
1166 
1167     /**
1168      * German language code
1169      * @memberof cc.sys
1170      * @name LANGUAGE_GERMAN
1171      * @constant
1172      * @type {Number}
1173      */
1174     sys.LANGUAGE_GERMAN = "de";
1175 
1176     /**
1177      * Spanish language code
1178      * @memberof cc.sys
1179      * @name LANGUAGE_SPANISH
1180      * @constant
1181      * @type {Number}
1182      */
1183     sys.LANGUAGE_SPANISH = "es";
1184 
1185     /**
1186      * Spanish language code
1187      * @memberof cc.sys
1188      * @name LANGUAGE_DUTCH
1189      * @constant
1190      * @type {Number}
1191      */
1192     sys.LANGUAGE_DUTCH = "du";
1193 
1194     /**
1195      * Russian language code
1196      * @memberof cc.sys
1197      * @name LANGUAGE_RUSSIAN
1198      * @constant
1199      * @type {Number}
1200      */
1201     sys.LANGUAGE_RUSSIAN = "ru";
1202 
1203     /**
1204      * Korean language code
1205      * @memberof cc.sys
1206      * @name LANGUAGE_KOREAN
1207      * @constant
1208      * @type {Number}
1209      */
1210     sys.LANGUAGE_KOREAN = "ko";
1211 
1212     /**
1213      * Japanese language code
1214      * @memberof cc.sys
1215      * @name LANGUAGE_JAPANESE
1216      * @constant
1217      * @type {Number}
1218      */
1219     sys.LANGUAGE_JAPANESE = "ja";
1220 
1221     /**
1222      * Hungarian language code
1223      * @memberof cc.sys
1224      * @name LANGUAGE_HUNGARIAN
1225      * @constant
1226      * @type {Number}
1227      */
1228     sys.LANGUAGE_HUNGARIAN = "hu";
1229 
1230     /**
1231      * Portuguese language code
1232      * @memberof cc.sys
1233      * @name LANGUAGE_PORTUGUESE
1234      * @constant
1235      * @type {Number}
1236      */
1237     sys.LANGUAGE_PORTUGUESE = "pt";
1238 
1239     /**
1240      * Arabic language code
1241      * @memberof cc.sys
1242      * @name LANGUAGE_ARABIC
1243      * @constant
1244      * @type {Number}
1245      */
1246     sys.LANGUAGE_ARABIC = "ar";
1247 
1248     /**
1249      * Norwegian language code
1250      * @memberof cc.sys
1251      * @name LANGUAGE_NORWEGIAN
1252      * @constant
1253      * @type {Number}
1254      */
1255     sys.LANGUAGE_NORWEGIAN = "no";
1256 
1257     /**
1258      * Polish language code
1259      * @memberof cc.sys
1260      * @name LANGUAGE_POLISH
1261      * @constant
1262      * @type {Number}
1263      */
1264     sys.LANGUAGE_POLISH = "pl";
1265 
1266     /**
1267      * @memberof cc.sys
1268      * @name OS_WINDOWS
1269      * @constant
1270      * @type {string}
1271      */
1272     sys.OS_WINDOWS = "Windows";
1273     /**
1274      * @memberof cc.sys
1275      * @name OS_IOS
1276      * @constant
1277      * @type {string}
1278      */
1279     sys.OS_IOS = "iOS";
1280     /**
1281      * @memberof cc.sys
1282      * @name OS_OSX
1283      * @constant
1284      * @type {string}
1285      */
1286     sys.OS_OSX = "OS X";
1287     /**
1288      * @memberof cc.sys
1289      * @name OS_UNIX
1290      * @constant
1291      * @type {string}
1292      */
1293     sys.OS_UNIX = "UNIX";
1294     /**
1295      * @memberof cc.sys
1296      * @name OS_LINUX
1297      * @constant
1298      * @type {string}
1299      */
1300     sys.OS_LINUX = "Linux";
1301     /**
1302      * @memberof cc.sys
1303      * @name OS_ANDROID
1304      * @constant
1305      * @type {string}
1306      */
1307     sys.OS_ANDROID = "Android";
1308     /**
1309      * @memberof cc.sys
1310      * @name OS_UNKNOWN
1311      * @constant
1312      * @type {string}
1313      */
1314     sys.OS_UNKNOWN = "Unknown";
1315 
1316     /**
1317      * @memberof cc.sys
1318      * @name WINDOWS
1319      * @constant
1320      * @default
1321      * @type {Number}
1322      */
1323     sys.WINDOWS = 0;
1324     /**
1325      * @memberof cc.sys
1326      * @name LINUX
1327      * @constant
1328      * @default
1329      * @type {Number}
1330      */
1331     sys.LINUX = 1;
1332     /**
1333      * @memberof cc.sys
1334      * @name MACOS
1335      * @constant
1336      * @default
1337      * @type {Number}
1338      */
1339     sys.MACOS = 2;
1340     /**
1341      * @memberof cc.sys
1342      * @name ANDROID
1343      * @constant
1344      * @default
1345      * @type {Number}
1346      */
1347     sys.ANDROID = 3;
1348     /**
1349      * @memberof cc.sys
1350      * @name IPHONE
1351      * @constant
1352      * @default
1353      * @type {Number}
1354      */
1355     sys.IPHONE = 4;
1356     /**
1357      * @memberof cc.sys
1358      * @name IPAD
1359      * @constant
1360      * @default
1361      * @type {Number}
1362      */
1363     sys.IPAD = 5;
1364     /**
1365      * @memberof cc.sys
1366      * @name BLACKBERRY
1367      * @constant
1368      * @default
1369      * @type {Number}
1370      */
1371     sys.BLACKBERRY = 6;
1372     /**
1373      * @memberof cc.sys
1374      * @name NACL
1375      * @constant
1376      * @default
1377      * @type {Number}
1378      */
1379     sys.NACL = 7;
1380     /**
1381      * @memberof cc.sys
1382      * @name EMSCRIPTEN
1383      * @constant
1384      * @default
1385      * @type {Number}
1386      */
1387     sys.EMSCRIPTEN = 8;
1388     /**
1389      * @memberof cc.sys
1390      * @name TIZEN
1391      * @constant
1392      * @default
1393      * @type {Number}
1394      */
1395     sys.TIZEN = 9;
1396     /**
1397      * @memberof cc.sys
1398      * @name WINRT
1399      * @constant
1400      * @default
1401      * @type {Number}
1402      */
1403     sys.WINRT = 10;
1404     /**
1405      * @memberof cc.sys
1406      * @name WP8
1407      * @constant
1408      * @default
1409      * @type {Number}
1410      */
1411     sys.WP8 = 11;
1412     /**
1413      * @memberof cc.sys
1414      * @name MOBILE_BROWSER
1415      * @constant
1416      * @default
1417      * @type {Number}
1418      */
1419     sys.MOBILE_BROWSER = 100;
1420     /**
1421      * @memberof cc.sys
1422      * @name DESKTOP_BROWSER
1423      * @constant
1424      * @default
1425      * @type {Number}
1426      */
1427     sys.DESKTOP_BROWSER = 101;
1428 
1429     sys.BROWSER_TYPE_WECHAT = "wechat";
1430     sys.BROWSER_TYPE_ANDROID = "androidbrowser";
1431     sys.BROWSER_TYPE_IE = "ie";
1432     sys.BROWSER_TYPE_QQ = "qqbrowser";
1433     sys.BROWSER_TYPE_MOBILE_QQ = "mqqbrowser";
1434     sys.BROWSER_TYPE_UC = "ucbrowser";
1435     sys.BROWSER_TYPE_360 = "360browser";
1436     sys.BROWSER_TYPE_BAIDU_APP = "baiduboxapp";
1437     sys.BROWSER_TYPE_BAIDU = "baidubrowser";
1438     sys.BROWSER_TYPE_MAXTHON = "maxthon";
1439     sys.BROWSER_TYPE_OPERA = "opera";
1440     sys.BROWSER_TYPE_OUPENG = "oupeng";
1441     sys.BROWSER_TYPE_MIUI = "miuibrowser";
1442     sys.BROWSER_TYPE_FIREFOX = "firefox";
1443     sys.BROWSER_TYPE_SAFARI = "safari";
1444     sys.BROWSER_TYPE_CHROME = "chrome";
1445     sys.BROWSER_TYPE_UNKNOWN = "unknown";
1446 
1447     /**
1448      * Is native ? This is set to be true in jsb auto.
1449      * @memberof cc.sys
1450      * @name isNative
1451      * @type {Boolean}
1452      */
1453     sys.isNative = false;
1454 
1455     var webglWhiteList = [sys.BROWSER_TYPE_BAIDU, sys.BROWSER_TYPE_OPERA, sys.BROWSER_TYPE_FIREFOX, sys.BROWSER_TYPE_CHROME, sys.BROWSER_TYPE_SAFARI];
1456     var multipleAudioWhiteList = [
1457         sys.BROWSER_TYPE_BAIDU, sys.BROWSER_TYPE_OPERA, sys.BROWSER_TYPE_FIREFOX, sys.BROWSER_TYPE_CHROME, sys.BROWSER_TYPE_BAIDU_APP,
1458         sys.BROWSER_TYPE_SAFARI, sys.BROWSER_TYPE_UC, sys.BROWSER_TYPE_QQ, sys.BROWSER_TYPE_MOBILE_QQ, sys.BROWSER_TYPE_IE
1459     ];
1460 
1461     var win = window, nav = win.navigator, doc = document, docEle = doc.documentElement;
1462     var ua = nav.userAgent.toLowerCase();
1463 
1464     /**
1465      * Indicate whether system is mobile system
1466      * @memberof cc.sys
1467      * @name isMobile
1468      * @type {Boolean}
1469      */
1470     sys.isMobile = ua.indexOf('mobile') != -1 || ua.indexOf('android') != -1;
1471 
1472     /**
1473      * Indicate the running platform
1474      * @memberof cc.sys
1475      * @name platform
1476      * @type {Number}
1477      */
1478     sys.platform = sys.isMobile ? sys.MOBILE_BROWSER : sys.DESKTOP_BROWSER;
1479 
1480     var currLanguage = nav.language;
1481     currLanguage = currLanguage ? currLanguage : nav.browserLanguage;
1482     currLanguage = currLanguage ? currLanguage.split("-")[0] : sys.LANGUAGE_ENGLISH;
1483 
1484     /**
1485      * Indicate the current language of the running system
1486      * @memberof cc.sys
1487      * @name language
1488      * @type {String}
1489      */
1490     sys.language = currLanguage;
1491 
1492     var browserType = sys.BROWSER_TYPE_UNKNOWN;
1493     var browserTypes = ua.match(/micromessenger|qqbrowser|mqqbrowser|ucbrowser|360browser|baiduboxapp|baidubrowser|maxthon|trident|oupeng|opera|miuibrowser|firefox/i)
1494         || ua.match(/chrome|safari/i);
1495     if (browserTypes && browserTypes.length > 0) {
1496         browserType = browserTypes[0].toLowerCase();
1497         if (browserType == 'micromessenger') {
1498             browserType = sys.BROWSER_TYPE_WECHAT;
1499         } else if (browserType === "safari" && (ua.match(/android.*applewebkit/)))
1500             browserType = sys.BROWSER_TYPE_ANDROID;
1501         else if (browserType == "trident") browserType = sys.BROWSER_TYPE_IE;
1502     }
1503     /**
1504      * Indicate the running browser type
1505      * @memberof cc.sys
1506      * @name browserType
1507      * @type {String}
1508      */
1509     sys.browserType = browserType;
1510 
1511 
1512     sys._supportMultipleAudio = multipleAudioWhiteList.indexOf(sys.browserType) > -1;
1513 
1514 
1515     //++++++++++++++++++something about cc._renderTYpe and cc._supportRender begin++++++++++++++++++++++++++++
1516     var userRenderMode = parseInt(config[CONFIG_KEY.renderMode]);
1517     var renderType = cc._RENDER_TYPE_WEBGL;
1518     var tempCanvas = cc.newElement("Canvas");
1519     cc._supportRender = true;
1520     var notInWhiteList = webglWhiteList.indexOf(sys.browserType) == -1;
1521     if (userRenderMode === 1 || (userRenderMode === 0 && (sys.isMobile || notInWhiteList)) || (location.origin == "file://")) {
1522         renderType = cc._RENDER_TYPE_CANVAS;
1523     }
1524 
1525     sys._canUseCanvasNewBlendModes = function(){
1526         var canvas = document.createElement('canvas');
1527         canvas.width = 1;
1528         canvas.height = 1;
1529         var context = canvas.getContext('2d');
1530         context.fillStyle = '#000';
1531         context.fillRect(0,0,1,1);
1532         context.globalCompositeOperation = 'multiply';
1533 
1534         var canvas2 = document.createElement('canvas');
1535         canvas2.width = 1;
1536         canvas2.height = 1;
1537         var context2 = canvas2.getContext('2d');
1538         context2.fillStyle = '#fff';
1539         context2.fillRect(0,0,1,1);
1540 
1541         context.drawImage(canvas2, 0, 0, 1, 1);
1542 
1543         return context.getImageData(0,0,1,1).data[0] === 0;
1544     };
1545 
1546     //Whether or not the Canvas BlendModes are supported.
1547     sys._supportCanvasNewBlendModes = sys._canUseCanvasNewBlendModes();
1548 
1549     if (renderType == cc._RENDER_TYPE_WEBGL) {
1550         if (!win.WebGLRenderingContext
1551             || !cc.create3DContext(tempCanvas, {'stencil': true, 'preserveDrawingBuffer': true })) {
1552             if (userRenderMode == 0) renderType = cc._RENDER_TYPE_CANVAS;
1553             else cc._supportRender = false;
1554         }
1555     }
1556 
1557     if (renderType == cc._RENDER_TYPE_CANVAS) {
1558         try {
1559             tempCanvas.getContext("2d");
1560         } catch (e) {
1561             cc._supportRender = false;
1562         }
1563     }
1564     cc._renderType = renderType;
1565     //++++++++++++++++++something about cc._renderTYpe and cc._supportRender end++++++++++++++++++++++++++++++
1566 
1567     // check if browser supports Web Audio
1568     // check Web Audio's context
1569     try {
1570         sys._supportWebAudio = !!(new (win.AudioContext || win.webkitAudioContext || win.mozAudioContext)());
1571     } catch (e) {
1572         sys._supportWebAudio = false;
1573     }
1574 
1575     /**
1576      * cc.sys.localStorage is a local storage component.
1577      * @memberof cc.sys
1578      * @name localStorage
1579      * @type {Object}
1580      */
1581     try {
1582         var localStorage = sys.localStorage = win.localStorage;
1583         localStorage.setItem("storage", "");
1584         localStorage.removeItem("storage");
1585         localStorage = null;
1586     } catch (e) {
1587         if (e.name === "SECURITY_ERR" || e.name === "QuotaExceededError") {
1588             cc.warn("Warning: localStorage isn't enabled. Please confirm browser cookie or privacy option");
1589         }
1590         sys.localStorage = function () {
1591         };
1592     }
1593 
1594     var capabilities = sys.capabilities = {"canvas": true};
1595     if (cc._renderType == cc._RENDER_TYPE_WEBGL)
1596         capabilities["opengl"] = true;
1597     if (docEle['ontouchstart'] !== undefined || nav.msPointerEnabled)
1598         capabilities["touches"] = true;
1599     if (docEle['onmouseup'] !== undefined)
1600         capabilities["mouse"] = true;
1601     if (docEle['onkeyup'] !== undefined)
1602         capabilities["keyboard"] = true;
1603     if (win.DeviceMotionEvent || win.DeviceOrientationEvent)
1604         capabilities["accelerometer"] = true;
1605 
1606     // Get the os of system
1607     var iOS = ( ua.match(/(iPad|iPhone|iPod)/i) ? true : false );
1608     var isAndroid = ua.match(/android/i) || nav.platform.match(/android/i) ? true : false;
1609     var osName = sys.OS_UNKNOWN;
1610     if (nav.appVersion.indexOf("Win") != -1) osName = sys.OS_WINDOWS;
1611     else if (iOS) osName = sys.OS_IOS;
1612     else if (nav.appVersion.indexOf("Mac") != -1) osName = sys.OS_OSX;
1613     else if (nav.appVersion.indexOf("X11") != -1) osName = sys.OS_UNIX;
1614     else if (isAndroid) osName = sys.OS_ANDROID;
1615     else if (nav.appVersion.indexOf("Linux") != -1) osName = sys.OS_LINUX;
1616 
1617     /**
1618      * Indicate the running os name
1619      * @memberof cc.sys
1620      * @name os
1621      * @type {String}
1622      */
1623     sys.os = osName;
1624 
1625     /**
1626      * Forces the garbage collection
1627      * @memberof cc.sys
1628      * @name garbageCollect
1629      * @function
1630      */
1631     sys.garbageCollect = function () {
1632         // N/A in cocos2d-html5
1633     };
1634 
1635     /**
1636      * Dumps rooted objects
1637      * @memberof cc.sys
1638      * @name dumpRoot
1639      * @function
1640      */
1641     sys.dumpRoot = function () {
1642         // N/A in cocos2d-html5
1643     };
1644 
1645     /**
1646      * Restart the JS VM
1647      * @memberof cc.sys
1648      * @name restartVM
1649      * @function
1650      */
1651     sys.restartVM = function () {
1652         // N/A in cocos2d-html5
1653     };
1654 
1655     /**
1656      * Dump system informations
1657      * @memberof cc.sys
1658      * @name dump
1659      * @function
1660      */
1661     sys.dump = function () {
1662         var self = this;
1663         var str = "";
1664         str += "isMobile : " + self.isMobile + "\r\n";
1665         str += "language : " + self.language + "\r\n";
1666         str += "browserType : " + self.browserType + "\r\n";
1667         str += "capabilities : " + JSON.stringify(self.capabilities) + "\r\n";
1668         str += "os : " + self.os + "\r\n";
1669         str += "platform : " + self.platform + "\r\n";
1670         cc.log(str);
1671     }
1672 };
1673 
1674 //+++++++++++++++++++++++++something about sys end+++++++++++++++++++++++++++++
1675 
1676 //+++++++++++++++++++++++++something about CCGame begin+++++++++++++++++++++++++++
1677 
1678 /**
1679  * Device oriented vertically, home button on the bottom
1680  * @constant
1681  * @type {Number}
1682  */
1683 cc.ORIENTATION_PORTRAIT = 0;
1684 
1685 /**
1686  * Device oriented vertically, home button on the top
1687  * @constant
1688  * @type {Number}
1689  */
1690 cc.ORIENTATION_PORTRAIT_UPSIDE_DOWN = 1;
1691 
1692 /**
1693  * Device oriented horizontally, home button on the right
1694  * @constant
1695  * @type {Number}
1696  */
1697 cc.ORIENTATION_LANDSCAPE_LEFT = 2;
1698 
1699 /**
1700  * Device oriented horizontally, home button on the left
1701  * @constant
1702  * @type {Number}
1703  */
1704 cc.ORIENTATION_LANDSCAPE_RIGHT = 3;
1705 
1706 /**
1707  * drawing primitive of game engine
1708  * @type {cc.DrawingPrimitive}
1709  */
1710 cc._drawingUtil = null;
1711 
1712 /**
1713  * main Canvas 2D/3D Context of game engine
1714  * @type {CanvasRenderingContext2D|WebGLRenderingContext}
1715  */
1716 cc._renderContext = null;
1717 
1718 /**
1719  * main Canvas of game engine
1720  * @type {HTMLCanvasElement}
1721  */
1722 cc._canvas = null;
1723 
1724 /**
1725  * This Div element contain all game canvas
1726  * @type {HTMLDivElement}
1727  */
1728 cc._gameDiv = null;
1729 
1730 cc._rendererInitialized = false;
1731 /**
1732  * <p>
1733  *   setup game main canvas,renderContext,gameDiv and drawingUtil with argument  <br/>
1734  *   <br/>
1735  *   can receive follow type of arguemnt: <br/>
1736  *      - empty: create a canvas append to document's body, and setup other option    <br/>
1737  *      - string: search the element by document.getElementById(),    <br/>
1738  *          if this element is HTMLCanvasElement, set this element as main canvas of engine, and set it's ParentNode as cc._gameDiv.<br/>
1739  *          if this element is HTMLDivElement, set it's ParentNode to cc._gameDiv´╝î and create a canvas as main canvas of engine.   <br/>
1740  * </p>
1741  * @function
1742  * @example
1743  * //setup with null
1744  * cc._setup();
1745  *
1746  * // setup with HTMLCanvasElement, gameCanvas is Canvas element
1747  * // declare like this: <canvas id="gameCanvas" width="800" height="450"></canvas>
1748  * cc._setup("gameCanvas");
1749  *
1750  * //setup with HTMLDivElement, gameDiv is Div element
1751  * // declare like this: <div id="Cocos2dGameContainer" width="800" height="450"></div>
1752  * cc._setup("Cocos2dGameContainer");
1753  */
1754 cc._setupCalled = false;
1755 cc._setup = function (el, width, height) {
1756     // Avoid setup to be called twice.
1757     if (cc._setupCalled) return;
1758     else cc._setupCalled = true;
1759     var win = window;
1760     var lastTime = new Date();
1761     var frameTime = 1000 / cc.game.config[cc.game.CONFIG_KEY.frameRate];
1762 
1763     var stTime = function(callback){
1764         var currTime = new Date().getTime();
1765         var timeToCall = Math.max(0, frameTime - (currTime - lastTime));
1766         var id = window.setTimeout(function() { callback(); },
1767             timeToCall);
1768         lastTime = currTime + timeToCall;
1769         return id;
1770     };
1771 
1772     var ctTime = function(id){
1773         clearTimeout(id);
1774     };
1775 
1776     if(cc.sys.os === cc.sys.OS_IOS && cc.sys.browserType === cc.sys.BROWSER_TYPE_WECHAT){
1777         win.requestAnimFrame = stTime;
1778         win.cancelAnimationFrame = ctTime;
1779     }else if(cc.game.config[cc.game.CONFIG_KEY.frameRate] != 60){
1780         win.requestAnimFrame = stTime;
1781         win.cancelAnimationFrame = ctTime;
1782     }else{
1783         win.requestAnimFrame = win.requestAnimationFrame ||
1784             win.webkitRequestAnimationFrame ||
1785             win.mozRequestAnimationFrame ||
1786             win.oRequestAnimationFrame ||
1787             win.msRequestAnimationFrame ||
1788             stTime;
1789         win.cancelAnimationFrame = window.cancelAnimationFrame ||
1790             window.cancelRequestAnimationFrame ||
1791             window.msCancelRequestAnimationFrame ||
1792             window.mozCancelRequestAnimationFrame ||
1793             window.oCancelRequestAnimationFrame ||
1794             window.webkitCancelRequestAnimationFrame ||
1795             window.msCancelAnimationFrame ||
1796             window.mozCancelAnimationFrame ||
1797             window.webkitCancelAnimationFrame ||
1798             window.oCancelAnimationFrame ||
1799             ctTime;
1800     }
1801 
1802     var element = cc.$(el) || cc.$('#' + el);
1803     var localCanvas, localContainer, localConStyle;
1804     if (element.tagName == "CANVAS") {
1805         width = width || element.width;
1806         height = height || element.height;
1807 
1808         //it is already a canvas, we wrap it around with a div
1809         localContainer = cc.container = cc.newElement("DIV");
1810         localCanvas = cc._canvas = element;
1811         localCanvas.parentNode.insertBefore(localContainer, localCanvas);
1812         localCanvas.appendTo(localContainer);
1813         localContainer.setAttribute('id', 'Cocos2dGameContainer');
1814     } else {//we must make a new canvas and place into this element
1815         if (element.tagName != "DIV") {
1816             cc.log("Warning: target element is not a DIV or CANVAS");
1817         }
1818         width = width || element.clientWidth;
1819         height = height || element.clientHeight;
1820         localContainer = cc.container = element;
1821         localCanvas = cc._canvas = cc.$(cc.newElement("CANVAS"));
1822         element.appendChild(localCanvas);
1823     }
1824 
1825     localCanvas.addClass("gameCanvas");
1826     localCanvas.setAttribute("width", width || 480);
1827     localCanvas.setAttribute("height", height || 320);
1828     localCanvas.setAttribute("tabindex", 99);
1829     localCanvas.style.outline = "none";
1830     localConStyle = localContainer.style;
1831     localConStyle.width = (width || 480) + "px";
1832     localConStyle.height = (height || 320) + "px";
1833     localConStyle.margin = "0 auto";
1834 
1835     localConStyle.position = 'relative';
1836     localConStyle.overflow = 'hidden';
1837     localContainer.top = '100%';
1838 
1839     if (cc._renderType == cc._RENDER_TYPE_WEBGL)
1840         cc._renderContext = cc.webglContext = cc.create3DContext(localCanvas, {
1841             'stencil': true,
1842             'preserveDrawingBuffer': true,
1843             'antialias': !cc.sys.isMobile,
1844             'alpha': false});
1845     if (cc._renderContext) {
1846         win.gl = cc._renderContext; // global variable declared in CCMacro.js
1847         cc._drawingUtil = new cc.DrawingPrimitiveWebGL(cc._renderContext);
1848         cc._rendererInitialized = true;
1849         cc.textureCache._initializingRenderer();
1850         cc.shaderCache._init();
1851     } else {
1852         cc._renderContext = localCanvas.getContext("2d");
1853         cc._mainRenderContextBackup = cc._renderContext;
1854         cc._renderContext.translate(0, localCanvas.height);
1855         cc._drawingUtil = cc.DrawingPrimitiveCanvas ? new cc.DrawingPrimitiveCanvas(cc._renderContext) : null;
1856     }
1857 
1858     cc._gameDiv = localContainer;
1859     cc.log(cc.ENGINE_VERSION);
1860     cc._setContextMenuEnable(false);
1861 
1862     if (cc.sys.isMobile) {
1863         var fontStyle = cc.newElement("style");
1864         fontStyle.type = "text/css";
1865         document.body.appendChild(fontStyle);
1866 
1867         fontStyle.textContent = "body,canvas,div{ -moz-user-select: none;-webkit-user-select: none;-ms-user-select: none;-khtml-user-select: none;"
1868             + "-webkit-tap-highlight-color:rgba(0,0,0,0);}";
1869     }
1870 
1871     // Init singletons
1872 
1873     /**
1874      * @type {cc.EGLView}
1875      * @name cc.view
1876      * cc.view is the shared view object.
1877      */
1878     cc.view = cc.EGLView._getInstance();
1879     // register system events
1880     cc.inputManager.registerSystemEvent(cc._canvas);
1881 
1882     /**
1883      * @type {cc.Director}
1884      * @name cc.director
1885      */
1886     cc.director = cc.Director._getInstance();
1887     if (cc.director.setOpenGLView)
1888         cc.director.setOpenGLView(cc.view);
1889     /**
1890      * @type {cc.Size}
1891      * @name cc.winSize
1892      * cc.winSize is the alias object for the size of the current game window.
1893      */
1894     cc.winSize = cc.director.getWinSize();
1895 
1896     // Parsers
1897     cc.saxParser = new cc.SAXParser();
1898     /**
1899      * @type {cc.PlistParser}
1900      * @name cc.plistParser
1901      * A Plist Parser
1902      */
1903     cc.plistParser = new cc.PlistParser();
1904 };
1905 
1906 cc._checkWebGLRenderMode = function () {
1907     if (cc._renderType !== cc._RENDER_TYPE_WEBGL)
1908         throw "This feature supports WebGL render mode only.";
1909 };
1910 
1911 cc._isContextMenuEnable = false;
1912 /**
1913  * enable/disable contextMenu for Canvas
1914  * @param {Boolean} enabled
1915  */
1916 cc._setContextMenuEnable = function (enabled) {
1917     cc._isContextMenuEnable = enabled;
1918     cc._canvas.oncontextmenu = function () {
1919         if (!cc._isContextMenuEnable) return false;
1920     };
1921 };
1922 
1923 /**
1924  * An object to boot the game.
1925  * @class
1926  * @name cc.game
1927  */
1928 cc.game = /** @lends cc.game# */{
1929     DEBUG_MODE_NONE: 0,
1930     DEBUG_MODE_INFO: 1,
1931     DEBUG_MODE_WARN: 2,
1932     DEBUG_MODE_ERROR: 3,
1933     DEBUG_MODE_INFO_FOR_WEB_PAGE: 4,
1934     DEBUG_MODE_WARN_FOR_WEB_PAGE: 5,
1935     DEBUG_MODE_ERROR_FOR_WEB_PAGE: 6,
1936 
1937     EVENT_HIDE: "game_on_hide",
1938     EVENT_SHOW: "game_on_show",
1939     _eventHide: null,
1940     _eventShow: null,
1941     _onBeforeStartArr: [],
1942 
1943     /**
1944      * Key of config
1945      * @constant
1946      * @type {Object}
1947      */
1948     CONFIG_KEY: {
1949         engineDir: "engineDir",
1950         dependencies: "dependencies",
1951         debugMode: "debugMode",
1952         showFPS: "showFPS",
1953         frameRate: "frameRate",
1954         id: "id",
1955         renderMode: "renderMode",
1956         jsList: "jsList",
1957         classReleaseMode: "classReleaseMode"
1958     },
1959 
1960     _prepareCalled: false,//whether the prepare function has been called
1961     _prepared: false,//whether the engine has prepared
1962     _paused: true,//whether the game is paused
1963 
1964     _intervalId: null,//interval target of main
1965 
1966     /**
1967      * Config of game
1968      * @type {Object}
1969      */
1970     config: null,
1971 
1972     /**
1973      * Callback when the scripts of engine have been load.
1974      * @type {Function}
1975      */
1976     onStart: null,
1977 
1978     /**
1979      * Callback when game exits.
1980      * @type {Function}
1981      */
1982     onStop: null,
1983 
1984     /**
1985      * Set frameRate of game.
1986      * @param frameRate
1987      */
1988     setFrameRate: function (frameRate) {
1989         var self = this, config = self.config, CONFIG_KEY = self.CONFIG_KEY;
1990         config[CONFIG_KEY.frameRate] = frameRate;
1991         if (self._intervalId)
1992             window.cancelAnimationFrame(self._intervalId);
1993         self._paused = true;
1994         self._runMainLoop();
1995     },
1996     //Run game.
1997     _runMainLoop: function () {
1998         var self = this, callback, config = self.config, CONFIG_KEY = self.CONFIG_KEY,
1999             director = cc.director;
2000 
2001         director.setDisplayStats(config[CONFIG_KEY.showFPS]);
2002 
2003         callback = function () {
2004             if (!self._paused) {
2005                 director.mainLoop();
2006                 self._intervalId = window.requestAnimFrame(callback);
2007             }
2008         };
2009 
2010         window.requestAnimFrame(callback);
2011         self._paused = false;
2012     },
2013 
2014     /**
2015      * Run game.
2016      */
2017     run: function (id) {
2018         var self = this;
2019         var _run = function () {
2020             if (id) {
2021                 self.config[self.CONFIG_KEY.id] = id;
2022             }
2023             if (!self._prepareCalled) {
2024                 self.prepare(function () {
2025                     self._prepared = true;
2026                 });
2027             }
2028             if (cc._supportRender) {
2029                 self._checkPrepare = setInterval(function () {
2030                     if (self._prepared) {
2031                         cc._setup(self.config[self.CONFIG_KEY.id]);
2032                         self._runMainLoop();
2033                         self._eventHide = self._eventHide || new cc.EventCustom(self.EVENT_HIDE);
2034                         self._eventHide.setUserData(self);
2035                         self._eventShow = self._eventShow || new cc.EventCustom(self.EVENT_SHOW);
2036                         self._eventShow.setUserData(self);
2037                         self.onStart();
2038                         clearInterval(self._checkPrepare);
2039                     }
2040                 }, 10);
2041             }
2042         };
2043         document.body ?
2044             _run() :
2045             cc._addEventListener(window, 'load', function () {
2046                 this.removeEventListener('load', arguments.callee, false);
2047                 _run();
2048             }, false);
2049     },
2050 
2051     _initConfig: function () {
2052         var self = this, CONFIG_KEY = self.CONFIG_KEY;
2053         var _init = function (cfg) {
2054             cfg[CONFIG_KEY.engineDir] = cfg[CONFIG_KEY.engineDir] || "frameworks/cocos2d-html5";
2055             if(cfg[CONFIG_KEY.debugMode] == null)
2056                 cfg[CONFIG_KEY.debugMode] = 0;
2057             cfg[CONFIG_KEY.frameRate] = cfg[CONFIG_KEY.frameRate] || 60;
2058             if(cfg[CONFIG_KEY.renderMode] == null)
2059                 cfg[CONFIG_KEY.renderMode] = 1;
2060             return cfg;
2061         };
2062         if (document["ccConfig"]) {
2063             self.config = _init(document["ccConfig"]);
2064         } else {
2065             try {
2066                 var cocos_script = document.getElementsByTagName('script');
2067                 for(var i=0;i<cocos_script.length;i++){
2068                     var _t = cocos_script[i].getAttribute('cocos');
2069                     if(_t == '' || _t){break;}
2070                 }
2071                 var _src, txt, _resPath;
2072                 if(i < cocos_script.length){
2073                     _src = cocos_script[i].src;
2074                     if(_src){
2075                         _resPath = /(.*)\//.exec(_src)[0];
2076                         cc.loader.resPath = _resPath;
2077                         _src = cc.path.join(_resPath, 'project.json');
2078                     }
2079                     txt = cc.loader._loadTxtSync(_src);
2080                 }
2081                 if(!txt){
2082                     txt = cc.loader._loadTxtSync("project.json");
2083                 }
2084                 var data = JSON.parse(txt);
2085                 self.config = _init(data || {});
2086             } catch (e) {
2087                 cc.log("Failed to read or parse project.json");
2088                 self.config = _init({});
2089             }
2090         }
2091         //init debug move to CCDebugger
2092         cc._initSys(self.config, CONFIG_KEY);
2093     },
2094 
2095     //cache for js and module that has added into jsList to be loaded.
2096     _jsAddedCache: {},
2097     _getJsListOfModule: function (moduleMap, moduleName, dir) {
2098         var jsAddedCache = this._jsAddedCache;
2099         if (jsAddedCache[moduleName]) return null;
2100         dir = dir || "";
2101         var jsList = [];
2102         var tempList = moduleMap[moduleName];
2103         if (!tempList) throw "can not find module [" + moduleName + "]";
2104         var ccPath = cc.path;
2105         for (var i = 0, li = tempList.length; i < li; i++) {
2106             var item = tempList[i];
2107             if (jsAddedCache[item]) continue;
2108             var extname = ccPath.extname(item);
2109             if (!extname) {
2110                 var arr = this._getJsListOfModule(moduleMap, item, dir);
2111                 if (arr) jsList = jsList.concat(arr);
2112             } else if (extname.toLowerCase() == ".js") jsList.push(ccPath.join(dir, item));
2113             jsAddedCache[item] = 1;
2114         }
2115         return jsList;
2116     },
2117     /**
2118      * Prepare game.
2119      * @param cb
2120      */
2121     prepare: function (cb) {
2122         var self = this;
2123         var config = self.config, CONFIG_KEY = self.CONFIG_KEY, engineDir = config[CONFIG_KEY.engineDir], loader = cc.loader;
2124         if (!cc._supportRender) {
2125             throw "The renderer doesn't support the renderMode " + config[CONFIG_KEY.renderMode];
2126         }
2127         self._prepareCalled = true;
2128 
2129         var jsList = config[CONFIG_KEY.jsList] || [];
2130         if (cc.Class) {//is single file
2131             //load user's jsList only
2132             loader.loadJsWithImg("", jsList, function (err) {
2133                 if (err) throw err;
2134                 self._prepared = true;
2135                 if (cb) cb();
2136             });
2137         } else {
2138             //load cc's jsList first
2139             var ccModulesPath = cc.path.join(engineDir, "moduleConfig.json");
2140             loader.loadJson(ccModulesPath, function (err, modulesJson) {
2141                 if (err) throw err;
2142                 var modules = config["modules"] || [];
2143                 var moduleMap = modulesJson["module"];
2144                 var newJsList = [];
2145                 if (cc._renderType == cc._RENDER_TYPE_WEBGL) modules.splice(0, 0, "shaders");
2146                 else if (modules.indexOf("core") < 0) modules.splice(0, 0, "core");
2147                 for (var i = 0, li = modules.length; i < li; i++) {
2148                     var arr = self._getJsListOfModule(moduleMap, modules[i], engineDir);
2149                     if (arr) newJsList = newJsList.concat(arr);
2150                 }
2151                 newJsList = newJsList.concat(jsList);
2152                 cc.loader.loadJsWithImg(newJsList, function (err) {
2153                     if (err) throw err;
2154                     self._prepared = true;
2155                     if (cb) cb();
2156                 });
2157             });
2158         }
2159     }
2160 };
2161 cc.game._initConfig();
2162 //+++++++++++++++++++++++++something about CCGame end+++++++++++++++++++++++++++++
2163 
2164 Function.prototype.bind = Function.prototype.bind || function (oThis) {
2165     if (!cc.isFunction(this)) {
2166         // closest thing possible to the ECMAScript 5
2167         // internal IsCallable function
2168         throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
2169     }
2170 
2171     var aArgs = Array.prototype.slice.call(arguments, 1),
2172         fToBind = this,
2173         fNOP = function () {},
2174         fBound = function () {
2175             return fToBind.apply(this instanceof fNOP && oThis
2176                 ? this
2177                 : oThis,
2178                 aArgs.concat(Array.prototype.slice.call(arguments)));
2179         };
2180 
2181     fNOP.prototype = this.prototype;
2182     fBound.prototype = new fNOP();
2183 
2184     return fBound;
2185 };
2186