1 /****************************************************************************
  2  Copyright (c) 2011-2012 cocos2d-x.org
  3  Copyright (c) 2013-2015 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 var _p = window;
 36 /** @expose */
 37 _p.gl;
 38 /** @expose */
 39 _p.WebGLRenderingContext;
 40 /** @expose */
 41 _p.DeviceOrientationEvent;
 42 /** @expose */
 43 _p.DeviceMotionEvent;
 44 /** @expose */
 45 _p.AudioContext;
 46 if (!_p.AudioContext) {
 47     /** @expose */
 48     _p.webkitAudioContext;
 49 }
 50 /** @expose */
 51 _p.mozAudioContext;
 52 _p = Object.prototype;
 53 /** @expose */
 54 _p._super;
 55 /** @expose */
 56 _p.ctor;
 57 _p = null;
 58 
 59 /**
 60  * Device oriented vertically, home button on the bottom
 61  * @constant
 62  * @type {Number}
 63  */
 64 cc.ORIENTATION_PORTRAIT = 0;
 65 
 66 /**
 67  * Device oriented vertically, home button on the top
 68  * @constant
 69  * @type {Number}
 70  */
 71 cc.ORIENTATION_PORTRAIT_UPSIDE_DOWN = 1;
 72 
 73 /**
 74  * Device oriented horizontally, home button on the right
 75  * @constant
 76  * @type {Number}
 77  */
 78 cc.ORIENTATION_LANDSCAPE_LEFT = 2;
 79 
 80 /**
 81  * Device oriented horizontally, home button on the left
 82  * @constant
 83  * @type {Number}
 84  */
 85 cc.ORIENTATION_LANDSCAPE_RIGHT = 3;
 86 
 87 /**
 88  * drawing primitive of game engine
 89  * @type {cc.DrawingPrimitive}
 90  */
 91 cc._drawingUtil = null;
 92 
 93 /**
 94  * main Canvas 2D/3D Context of game engine
 95  * @type {CanvasRenderingContext2D|WebGLRenderingContext}
 96  */
 97 cc._renderContext = null;
 98 cc._supportRender = false;
 99 
100 /**
101  * Main canvas of game engine
102  * @type {HTMLCanvasElement}
103  */
104 cc._canvas = null;
105 
106 /**
107  * The element contains the game canvas
108  * @type {HTMLDivElement}
109  */
110 cc.container = null;
111 cc._gameDiv = null;
112 
113 cc.newElement = function (x) {
114     return document.createElement(x);
115 };
116 
117 /**
118  * Iterate over an object or an array, executing a function for each matched element.
119  * @param {object|array} obj
120  * @param {function} iterator
121  * @param {object} [context]
122  */
123 cc.each = function (obj, iterator, context) {
124     if (!obj)
125         return;
126     if (obj instanceof Array) {
127         for (var i = 0, li = obj.length; i < li; i++) {
128             if (iterator.call(context, obj[i], i) === false)
129                 return;
130         }
131     } else {
132         for (var key in obj) {
133             if (iterator.call(context, obj[key], key) === false)
134                 return;
135         }
136     }
137 };
138 
139 /**
140  * Copy all of the properties in source objects to target object and return the target object.
141  * @param {object} target
142  * @param {object} *sources
143  * @returns {object}
144  */
145 cc.extend = function(target) {
146     var sources = arguments.length >= 2 ? Array.prototype.slice.call(arguments, 1) : [];
147 
148     cc.each(sources, function(src) {
149         for(var key in src) {
150             if (src.hasOwnProperty(key)) {
151                 target[key] = src[key];
152             }
153         }
154     });
155     return target;
156 };
157 
158 /**
159  * Check the obj whether is function or not
160  * @param {*} obj
161  * @returns {boolean}
162  */
163 cc.isFunction = function(obj) {
164     return typeof obj === 'function';
165 };
166 
167 /**
168  * Check the obj whether is number or not
169  * @param {*} obj
170  * @returns {boolean}
171  */
172 cc.isNumber = function(obj) {
173     return typeof obj === 'number' || Object.prototype.toString.call(obj) === '[object Number]';
174 };
175 
176 /**
177  * Check the obj whether is string or not
178  * @param {*} obj
179  * @returns {boolean}
180  */
181 cc.isString = function(obj) {
182     return typeof obj === 'string' || Object.prototype.toString.call(obj) === '[object String]';
183 };
184 
185 /**
186  * Check the obj whether is array or not
187  * @param {*} obj
188  * @returns {boolean}
189  */
190 cc.isArray = function(obj) {
191     return Array.isArray(obj) ||
192         (typeof obj === 'object' && Object.prototype.toString.call(obj) === '[object Array]');
193 };
194 
195 /**
196  * Check the obj whether is undefined or not
197  * @param {*} obj
198  * @returns {boolean}
199  */
200 cc.isUndefined = function(obj) {
201     return typeof obj === 'undefined';
202 };
203 
204 /**
205  * Check the obj whether is object or not
206  * @param {*} obj
207  * @returns {boolean}
208  */
209 cc.isObject = function(obj) {
210     return typeof obj === "object" && Object.prototype.toString.call(obj) === '[object Object]';
211 };
212 
213 /**
214  * Check the url whether cross origin
215  * @param {String} url
216  * @returns {boolean}
217  */
218 cc.isCrossOrigin = function (url) {
219     if (!url) {
220         cc.log("invalid URL");
221         return false;
222     }
223     var startIndex = url.indexOf("://");
224     if (startIndex === -1)
225         return false;
226 
227     var endIndex = url.indexOf("/", startIndex + 3);
228     var urlOrigin = (endIndex === -1) ? url : url.substring(0, endIndex);
229     return urlOrigin !== location.origin;
230 };
231 
232 //+++++++++++++++++++++++++something about async begin+++++++++++++++++++++++++++++++
233 /**
234  * Async Pool class, a helper of cc.async
235  * @param {Object|Array} srcObj
236  * @param {Number} limit the limit of parallel number
237  * @param {function} iterator
238  * @param {function} onEnd
239  * @param {object} target
240  * @constructor
241  */
242 cc.AsyncPool = function(srcObj, limit, iterator, onEnd, target){
243     var self = this;
244     self._srcObj = srcObj;
245     self._limit = limit;
246     self._pool = [];
247     self._iterator = iterator;
248     self._iteratorTarget = target;
249     self._onEnd = onEnd;
250     self._onEndTarget = target;
251     self._results = srcObj instanceof Array ? [] : {};
252 
253     cc.each(srcObj, function(value, index){
254         self._pool.push({index : index, value : value});
255     });
256 
257     self.size = self._pool.length;
258     self.finishedSize = 0;
259     self._workingSize = 0;
260 
261     self._limit = self._limit || self.size;
262 
263     self.onIterator = function(iterator, target){
264         self._iterator = iterator;
265         self._iteratorTarget = target;
266     };
267 
268     self.onEnd = function(endCb, endCbTarget){
269         self._onEnd = endCb;
270         self._onEndTarget = endCbTarget;
271     };
272 
273     self._handleItem = function(){
274         var self = this;
275         if(self._pool.length === 0 || self._workingSize >= self._limit)
276             return;                                                         //return directly if the array's length = 0 or the working size great equal limit number
277 
278         var item = self._pool.shift();
279         var value = item.value, index = item.index;
280         self._workingSize++;
281         self._iterator.call(self._iteratorTarget, value, index,
282             function(err) {
283 
284                 self.finishedSize++;
285                 self._workingSize--;
286 
287                 var arr = Array.prototype.slice.call(arguments, 1);
288                 self._results[this.index] = arr[0];
289                 if (self.finishedSize === self.size) {
290                     if (self._onEnd)
291                         self._onEnd.call(self._onEndTarget, null, self._results);
292                     return;
293                 }
294                 self._handleItem();
295             }.bind(item),
296             self);
297     };
298 
299     self.flow = function(){
300         var self = this;
301         if(self._pool.length === 0) {
302             if(self._onEnd)
303                 self._onEnd.call(self._onEndTarget, null, []);
304             return;
305         }
306         for(var i = 0; i < self._limit; i++)
307             self._handleItem();
308     }
309 };
310 
311 /**
312  * @class
313  */
314 cc.async = /** @lends cc.async# */{
315     /**
316      * Do tasks series.
317      * @param {Array|Object} tasks
318      * @param {function} [cb] callback
319      * @param {Object} [target]
320      * @return {cc.AsyncPool}
321      */
322     series : function(tasks, cb, target){
323         var asyncPool = new cc.AsyncPool(tasks, 1, function(func, index, cb1){
324             func.call(target, cb1);
325         }, cb, target);
326         asyncPool.flow();
327         return asyncPool;
328     },
329 
330     /**
331      * Do tasks parallel.
332      * @param {Array|Object} tasks
333      * @param {function} cb callback
334      * @param {Object} [target]
335      * @return {cc.AsyncPool}
336      */
337     parallel : function(tasks, cb, target){
338         var asyncPool = new cc.AsyncPool(tasks, 0, function(func, index, cb1){
339             func.call(target, cb1);
340         }, cb, target);
341         asyncPool.flow();
342         return asyncPool;
343     },
344 
345     /**
346      * Do tasks waterfall.
347      * @param {Array|Object} tasks
348      * @param {function} cb callback
349      * @param {Object} [target]
350      * @return {cc.AsyncPool}
351      */
352     waterfall : function(tasks, cb, target){
353         var args = [];
354         var lastResults = [null];//the array to store the last results
355         var asyncPool = new cc.AsyncPool(tasks, 1,
356             function (func, index, cb1) {
357                 args.push(function (err) {
358                     args = Array.prototype.slice.call(arguments, 1);
359                     if(tasks.length - 1 === index) lastResults = lastResults.concat(args);//while the last task
360                     cb1.apply(null, arguments);
361                 });
362                 func.apply(target, args);
363             }, function (err) {
364                 if (!cb)
365                     return;
366                 if (err)
367                     return cb.call(target, err);
368                 cb.apply(target, lastResults);
369             });
370         asyncPool.flow();
371         return asyncPool;
372     },
373 
374     /**
375      * Do tasks by iterator.
376      * @param {Array|Object} tasks
377      * @param {function|Object} iterator
378      * @param {function} [callback]
379      * @param {Object} [target]
380      * @return {cc.AsyncPool}
381      */
382     map : function(tasks, iterator, callback, target){
383         var locIterator = iterator;
384         if(typeof(iterator) === "object"){
385             callback = iterator.cb;
386             target = iterator.iteratorTarget;
387             locIterator = iterator.iterator;
388         }
389         var asyncPool = new cc.AsyncPool(tasks, 0, locIterator, callback, target);
390         asyncPool.flow();
391         return asyncPool;
392     },
393 
394     /**
395      * Do tasks by iterator limit.
396      * @param {Array|Object} tasks
397      * @param {Number} limit
398      * @param {function} iterator
399      * @param {function} cb callback
400      * @param {Object} [target]
401      */
402     mapLimit : function(tasks, limit, iterator, cb, target){
403         var asyncPool = new cc.AsyncPool(tasks, limit, iterator, cb, target);
404         asyncPool.flow();
405         return asyncPool;
406     }
407 };
408 //+++++++++++++++++++++++++something about async end+++++++++++++++++++++++++++++++++
409 
410 //+++++++++++++++++++++++++something about path begin++++++++++++++++++++++++++++++++
411 /**
412  * @class
413  */
414 cc.path = /** @lends cc.path# */{
415     normalizeRE: /[^\.\/]+\/\.\.\//,
416 
417     /**
418      * Join strings to be a path.
419      * @example
420      cc.path.join("a", "b.png");//-->"a/b.png"
421      cc.path.join("a", "b", "c.png");//-->"a/b/c.png"
422      cc.path.join("a", "b");//-->"a/b"
423      cc.path.join("a", "b", "/");//-->"a/b/"
424      cc.path.join("a", "b/", "/");//-->"a/b/"
425      * @returns {string}
426      */
427     join: function () {
428         var l = arguments.length;
429         var result = "";
430         for (var i = 0; i < l; i++) {
431             result = (result + (result === "" ? "" : "/") + arguments[i]).replace(/(\/|\\\\)$/, "");
432         }
433         return result;
434     },
435 
436     /**
437      * Get the ext name of a path.
438      * @example
439      cc.path.extname("a/b.png");//-->".png"
440      cc.path.extname("a/b.png?a=1&b=2");//-->".png"
441      cc.path.extname("a/b");//-->null
442      cc.path.extname("a/b?a=1&b=2");//-->null
443      * @param {string} pathStr
444      * @returns {*}
445      */
446     extname: function (pathStr) {
447         var temp = /(\.[^\.\/\?\\]*)(\?.*)?$/.exec(pathStr);
448         return temp ? temp[1] : null;
449     },
450 
451     /**
452      * Get the main name of a file name
453      * @param {string} fileName
454      * @returns {string}
455      */
456     mainFileName: function(fileName){
457         if(fileName){
458             var idx = fileName.lastIndexOf(".");
459             if(idx !== -1)
460                 return fileName.substring(0,idx);
461         }
462         return fileName;
463     },
464 
465     /**
466      * Get the file name of a file path.
467      * @example
468      cc.path.basename("a/b.png");//-->"b.png"
469      cc.path.basename("a/b.png?a=1&b=2");//-->"b.png"
470      cc.path.basename("a/b.png", ".png");//-->"b"
471      cc.path.basename("a/b.png?a=1&b=2", ".png");//-->"b"
472      cc.path.basename("a/b.png", ".txt");//-->"b.png"
473      * @param {string} pathStr
474      * @param {string} [extname]
475      * @returns {*}
476      */
477     basename: function (pathStr, extname) {
478         var index = pathStr.indexOf("?");
479         if (index > 0) pathStr = pathStr.substring(0, index);
480         var reg = /(\/|\\\\)([^(\/|\\\\)]+)$/g;
481         var result = reg.exec(pathStr.replace(/(\/|\\\\)$/, ""));
482         if (!result) return null;
483         var baseName = result[2];
484         if (extname && pathStr.substring(pathStr.length - extname.length).toLowerCase() === extname.toLowerCase())
485             return baseName.substring(0, baseName.length - extname.length);
486         return baseName;
487     },
488 
489     /**
490      * Get dirname of a file path.
491      * @example
492      * unix
493      cc.path.driname("a/b/c.png");//-->"a/b"
494      cc.path.driname("a/b/c.png?a=1&b=2");//-->"a/b"
495      cc.path.dirname("a/b/");//-->"a/b"
496      cc.path.dirname("c.png");//-->""
497      * windows
498      cc.path.driname("a\\b\\c.png");//-->"a\b"
499      cc.path.driname("a\\b\\c.png?a=1&b=2");//-->"a\b"
500      * @param {string} pathStr
501      * @returns {*}
502      */
503     dirname: function (pathStr) {
504         return pathStr.replace(/((.*)(\/|\\|\\\\))?(.*?\..*$)?/, '$2');
505     },
506 
507     /**
508      * Change extname of a file path.
509      * @example
510      cc.path.changeExtname("a/b.png", ".plist");//-->"a/b.plist"
511      cc.path.changeExtname("a/b.png?a=1&b=2", ".plist");//-->"a/b.plist?a=1&b=2"
512      * @param {string} pathStr
513      * @param {string} [extname]
514      * @returns {string}
515      */
516     changeExtname: function (pathStr, extname) {
517         extname = extname || "";
518         var index = pathStr.indexOf("?");
519         var tempStr = "";
520         if (index > 0) {
521             tempStr = pathStr.substring(index);
522             pathStr = pathStr.substring(0, index);
523         }
524         index = pathStr.lastIndexOf(".");
525         if (index < 0) return pathStr + extname + tempStr;
526         return pathStr.substring(0, index) + extname + tempStr;
527     },
528     /**
529      * Change file name of a file path.
530      * @example
531      cc.path.changeBasename("a/b/c.plist", "b.plist");//-->"a/b/b.plist"
532      cc.path.changeBasename("a/b/c.plist?a=1&b=2", "b.plist");//-->"a/b/b.plist?a=1&b=2"
533      cc.path.changeBasename("a/b/c.plist", ".png");//-->"a/b/c.png"
534      cc.path.changeBasename("a/b/c.plist", "b");//-->"a/b/b"
535      cc.path.changeBasename("a/b/c.plist", "b", true);//-->"a/b/b.plist"
536      * @param {String} pathStr
537      * @param {String} basename
538      * @param {Boolean} [isSameExt]
539      * @returns {string}
540      */
541     changeBasename: function (pathStr, basename, isSameExt) {
542         if (basename.indexOf(".") === 0) return this.changeExtname(pathStr, basename);
543         var index = pathStr.indexOf("?");
544         var tempStr = "";
545         var ext = isSameExt ? this.extname(pathStr) : "";
546         if (index > 0) {
547             tempStr = pathStr.substring(index);
548             pathStr = pathStr.substring(0, index);
549         }
550         index = pathStr.lastIndexOf("/");
551         index = index <= 0 ? 0 : index + 1;
552         return pathStr.substring(0, index) + basename + ext + tempStr;
553     },
554     //todo make public after verification
555     _normalize: function(url){
556         var oldUrl = url = String(url);
557 
558         //removing all ../
559         do {
560             oldUrl = url;
561             url = url.replace(this.normalizeRE, "");
562         } while(oldUrl.length !== url.length);
563         return url;
564     }
565 };
566 //+++++++++++++++++++++++++something about path end++++++++++++++++++++++++++++++++
567 
568 //+++++++++++++++++++++++++something about loader start+++++++++++++++++++++++++++
569 /**
570  * Resource loading management. Created by in CCBoot.js as a singleton
571  * cc.loader.
572  * @name cc.Loader
573  * @class
574  * @memberof cc
575  * @see cc.loader
576  */
577 
578 /**
579  * Singleton instance of cc.Loader.
580  * @name cc.loader
581  * @member {cc.Loader}
582  * @memberof cc
583  */
584 cc.loader = (function () {
585     var _jsCache = {}, //cache for js
586         _register = {}, //register of loaders
587         _langPathCache = {}, //cache for lang path
588         _aliases = {}, //aliases for res url
589         _queue = {}, // Callback queue for resources already loading
590         _urlRegExp = new RegExp(
591             "^" +
592                 // protocol identifier
593                 "(?:(?:https?|ftp)://)" +
594                 // user:pass authentication
595                 "(?:\\S+(?::\\S*)?@)?" +
596                 "(?:" +
597                     // IP address dotted notation octets
598                     // excludes loopback network 0.0.0.0
599                     // excludes reserved space >= 224.0.0.0
600                     // excludes network & broacast addresses
601                     // (first & last IP address of each class)
602                     "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" +
603                     "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" +
604                     "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" +
605                 "|" +
606                     // host name
607                     "(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)" +
608                     // domain name
609                     "(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*" +
610                     // TLD identifier
611                     "(?:\\.(?:[a-z\\u00a1-\\uffff]{2,}))" +
612                 "|" +
613                     "(?:localhost)" +
614                 ")" +
615                 // port number
616                 "(?::\\d{2,5})?" +
617                 // resource path
618                 "(?:/\\S*)?" +
619             "$", "i"
620         );
621 
622     return /** @lends cc.Loader# */{
623         /**
624          * Root path of resources.
625          * @type {String}
626          */
627         resPath: "",
628 
629         /**
630          * Root path of audio resources
631          * @type {String}
632          */
633         audioPath: "",
634 
635         /**
636          * Cache for data loaded.
637          * @type {Object}
638          */
639         cache: {},
640 
641         /**
642          * Get XMLHttpRequest.
643          * @returns {XMLHttpRequest}
644          */
645         getXMLHttpRequest: function () {
646             return window.XMLHttpRequest ? new window.XMLHttpRequest() : new ActiveXObject("MSXML2.XMLHTTP");
647         },
648 
649         //@MODE_BEGIN DEV
650 
651         _getArgs4Js: function (args) {
652             var a0 = args[0], a1 = args[1], a2 = args[2], results = ["", null, null];
653 
654             if (args.length === 1) {
655                 results[1] = a0 instanceof Array ? a0 : [a0];
656             } else if (args.length === 2) {
657                 if (typeof a1 === "function") {
658                     results[1] = a0 instanceof Array ? a0 : [a0];
659                     results[2] = a1;
660                 } else {
661                     results[0] = a0 || "";
662                     results[1] = a1 instanceof Array ? a1 : [a1];
663                 }
664             } else if (args.length === 3) {
665                 results[0] = a0 || "";
666                 results[1] = a1 instanceof Array ? a1 : [a1];
667                 results[2] = a2;
668             } else throw new Error("arguments error to load js!");
669             return results;
670         },
671 
672         isLoading: function (url) {
673             return (_queue[url] !== undefined);
674         },
675 
676         /**
677          * Load js files.
678          * If the third parameter doesn't exist, then the baseDir turns to be "".
679          *
680          * @param {string} [baseDir]   The pre path for jsList or the list of js path.
681          * @param {array} jsList    List of js path.
682          * @param {function} [cb]  Callback function
683          * @returns {*}
684          */
685         loadJs: function (baseDir, jsList, cb) {
686             var self = this,
687                 args = self._getArgs4Js(arguments);
688 
689             var preDir = args[0], list = args[1], callback = args[2];
690             if (navigator.userAgent.indexOf("Trident/5") > -1) {
691                 self._loadJs4Dependency(preDir, list, 0, callback);
692             } else {
693                 cc.async.map(list, function (item, index, cb1) {
694                     var jsPath = cc.path.join(preDir, item);
695                     if (_jsCache[jsPath]) return cb1(null);
696                     self._createScript(jsPath, false, cb1);
697                 }, callback);
698             }
699         },
700         /**
701          * Load js width loading image.
702          *
703          * @param {string} [baseDir]
704          * @param {array} jsList
705          * @param {function} [cb]
706          */
707         loadJsWithImg: function (baseDir, jsList, cb) {
708             var self = this, jsLoadingImg = self._loadJsImg(),
709                 args = self._getArgs4Js(arguments);
710             this.loadJs(args[0], args[1], function (err) {
711                 if (err) throw new Error(err);
712                 jsLoadingImg.parentNode.removeChild(jsLoadingImg);//remove loading gif
713                 if (args[2]) args[2]();
714             });
715         },
716         _createScript: function (jsPath, isAsync, cb) {
717             var d = document, self = this, s = document.createElement('script');
718             s.async = isAsync;
719             _jsCache[jsPath] = true;
720             if(cc.game.config["noCache"] && typeof jsPath === "string"){
721                 if(self._noCacheRex.test(jsPath))
722                     s.src = jsPath + "&_t=" + (new Date() - 0);
723                 else
724                     s.src = jsPath + "?_t=" + (new Date() - 0);
725             }else{
726                 s.src = jsPath;
727             }
728             s.addEventListener('load', function () {
729                 s.parentNode.removeChild(s);
730                 this.removeEventListener('load', arguments.callee, false);
731                 cb();
732             }, false);
733             s.addEventListener('error', function () {
734                 s.parentNode.removeChild(s);
735                 cb("Load " + jsPath + " failed!");
736             }, false);
737             d.body.appendChild(s);
738         },
739         _loadJs4Dependency: function (baseDir, jsList, index, cb) {
740             if (index >= jsList.length) {
741                 if (cb) cb();
742                 return;
743             }
744             var self = this;
745             self._createScript(cc.path.join(baseDir, jsList[index]), false, function (err) {
746                 if (err) return cb(err);
747                 self._loadJs4Dependency(baseDir, jsList, index + 1, cb);
748             });
749         },
750         _loadJsImg: function () {
751             var d = document, jsLoadingImg = d.getElementById("cocos2d_loadJsImg");
752             if (!jsLoadingImg) {
753                 jsLoadingImg = document.createElement('img');
754 
755                 if (cc._loadingImage)
756                     jsLoadingImg.src = cc._loadingImage;
757 
758                 var canvasNode = d.getElementById(cc.game.config["id"]);
759                 canvasNode.style.backgroundColor = "transparent";
760                 canvasNode.parentNode.appendChild(jsLoadingImg);
761 
762                 var canvasStyle = getComputedStyle ? getComputedStyle(canvasNode) : canvasNode.currentStyle;
763                 if (!canvasStyle)
764                     canvasStyle = {width: canvasNode.width, height: canvasNode.height};
765                 jsLoadingImg.style.left = canvasNode.offsetLeft + (parseFloat(canvasStyle.width) - jsLoadingImg.width) / 2 + "px";
766                 jsLoadingImg.style.top = canvasNode.offsetTop + (parseFloat(canvasStyle.height) - jsLoadingImg.height) / 2 + "px";
767                 jsLoadingImg.style.position = "absolute";
768             }
769             return jsLoadingImg;
770         },
771         //@MODE_END DEV
772 
773         /**
774          * Load a single resource as txt.
775          * @param {string} url
776          * @param {function} [cb] arguments are : err, txt
777          */
778         loadTxt: function (url, cb) {
779             if (!cc._isNodeJs) {
780                 var xhr = this.getXMLHttpRequest(),
781                     errInfo = "load " + url + " failed!";
782                 xhr.open("GET", url, true);
783                 if (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) {
784                     // IE-specific logic here
785                     xhr.setRequestHeader("Accept-Charset", "utf-8");
786                     xhr.onreadystatechange = function () {
787                         if(xhr.readyState === 4)
788                             xhr.status === 200 ? cb(null, xhr.responseText) : cb({status:xhr.status, errorMessage:errInfo}, null);
789                     };
790                 } else {
791                     if (xhr.overrideMimeType) xhr.overrideMimeType("text\/plain; charset=utf-8");
792                     xhr.onload = function () {
793                         if(xhr.readyState === 4)
794                             xhr.status === 200 ? cb(null, xhr.responseText) : cb({status:xhr.status, errorMessage:errInfo}, null);
795                     };
796                     xhr.onerror = function(){
797                         cb({status:xhr.status, errorMessage:errInfo}, null);
798                     };
799                 }
800                 xhr.send(null);
801             } else {
802                 var fs = require("fs");
803                 fs.readFile(url, function (err, data) {
804                     err ? cb(err) : cb(null, data.toString());
805                 });
806             }
807         },
808         _loadTxtSync: function (url) {
809             if (!cc._isNodeJs) {
810                 var xhr = this.getXMLHttpRequest();
811                 xhr.open("GET", url, false);
812                 if (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) {
813                     // IE-specific logic here
814                     xhr.setRequestHeader("Accept-Charset", "utf-8");
815                 } else {
816                     if (xhr.overrideMimeType) xhr.overrideMimeType("text\/plain; charset=utf-8");
817                 }
818                 xhr.send(null);
819                 if (!xhr.readyState === 4 || xhr.status !== 200) {
820                     return null;
821                 }
822                 return xhr.responseText;
823             } else {
824                 var fs = require("fs");
825                 return fs.readFileSync(url).toString();
826             }
827         },
828 
829         loadCsb: function(url, cb){
830             var xhr = new XMLHttpRequest(),
831                 errInfo = "load " + url + " failed!";
832             xhr.open("GET", url, true);
833             xhr.responseType = "arraybuffer";
834 
835             xhr.onload = function () {
836                 var arrayBuffer = xhr.response; // Note: not oReq.responseText
837                 if (arrayBuffer) {
838                     window.msg = arrayBuffer;
839                 }
840                 if(xhr.readyState === 4)
841                     xhr.status === 200 ? cb(null, xhr.response) : cb({status:xhr.status, errorMessage:errInfo}, null);
842             };
843             xhr.onerror = function(){
844                 cb({status:xhr.status, errorMessage:errInfo}, null);
845             };
846             xhr.send(null);
847         },
848 
849         /**
850          * Load a single resource as json.
851          * @param {string} url
852          * @param {function} [cb] arguments are : err, json
853          */
854         loadJson: function (url, cb) {
855             this.loadTxt(url, function (err, txt) {
856                 if (err) {
857                     cb(err);
858                 }
859                 else {
860                     try {
861                         var result = JSON.parse(txt);
862                     }
863                     catch (e) {
864                         throw new Error("parse json [" + url + "] failed : " + e);
865                         return;
866                     }
867                     cb(null, result);
868                 }
869             });
870         },
871 
872         _checkIsImageURL: function (url) {
873             var ext = /(\.png)|(\.jpg)|(\.bmp)|(\.jpeg)|(\.gif)/.exec(url);
874             return (ext != null);
875         },
876         /**
877          * Load a single image.
878          * @param {!string} url
879          * @param {object} [option]
880          * @param {function} callback
881          * @returns {Image}
882          */
883         loadImg: function (url, option, callback) {
884             var opt = {
885                 isCrossOrigin: true
886             };
887             if (callback !== undefined)
888                 opt.isCrossOrigin = option.isCrossOrigin === undefined ? opt.isCrossOrigin : option.isCrossOrigin;
889             else if (option !== undefined)
890                 callback = option;
891 
892             var img = this.getRes(url);
893             if (img) {
894                 callback && callback(null, img);
895                 return img;
896             }
897 
898             var queue = _queue[url];
899             if (queue) {
900                 queue.callbacks.push(callback);
901                 return queue.img;
902             }
903 
904             img = new Image();
905             if (opt.isCrossOrigin && location.origin !== "file://")
906                 img.crossOrigin = "Anonymous";
907 
908             var loadCallback = function () {
909                 this.removeEventListener('load', loadCallback, false);
910                 this.removeEventListener('error', errorCallback, false);
911 
912                 if (!_urlRegExp.test(url)) {
913                     cc.loader.cache[url] = img;
914                 }
915 
916                 var queue = _queue[url];
917                 if (queue) {
918                     callbacks = queue.callbacks;
919                     for (var i = 0; i < callbacks.length; ++i) {
920                         var cb = callbacks[i];
921                         if (cb) {
922                             cb(null, img);
923                         }
924                     }
925                     queue.img = null;
926                     delete _queue[url];
927                 }
928             };
929 
930             var self = this;
931             var errorCallback = function () {
932                 this.removeEventListener('error', errorCallback, false);
933 
934                 if (img.crossOrigin && img.crossOrigin.toLowerCase() === "anonymous") {
935                     opt.isCrossOrigin = false;
936                     self.release(url);
937                     cc.loader.loadImg(url, opt, callback);
938                 } else {
939                     var queue = _queue[url];
940                     if (queue) {
941                         callbacks = queue.callbacks;
942                         for (var i = 0; i < callbacks.length; ++i) {
943                             var cb = callbacks[i];
944                             if (cb) {
945                                 cb("load image failed");
946                             }
947                         }
948                         queue.img = null;
949                         delete _queue[url];
950                     }
951                 }
952             };
953 
954             _queue[url] = {
955                 img: img,
956                 callbacks: callback ? [callback] : []
957             };
958 
959             img.addEventListener("load", loadCallback);
960             img.addEventListener("error", errorCallback);
961             img.src = url;
962             return img;
963         },
964 
965         /**
966          * Iterator function to load res
967          * @param {object} item
968          * @param {number} index
969          * @param {function} [cb]
970          * @returns {*}
971          * @private
972          */
973         _loadResIterator: function (item, index, cb) {
974             var self = this, url = null;
975             var type = item.type;
976             if (type) {
977                 type = "." + type.toLowerCase();
978                 url = item.src ? item.src : item.name + type;
979             } else {
980                 url = item;
981                 type = cc.path.extname(url);
982             }
983 
984             var obj = self.getRes(url);
985             if (obj)
986                 return cb(null, obj);
987             var loader = null;
988             if (type) {
989                 loader = _register[type.toLowerCase()];
990             }
991             if (!loader) {
992                 cc.error("loader for [" + type + "] not exists!");
993                 return cb();
994             }
995             var realUrl = url;
996             if (!_urlRegExp.test(url))
997             {
998                 var basePath = loader.getBasePath ? loader.getBasePath() : self.resPath;
999                 realUrl = self.getUrl(basePath, url);
1000             }
1001 
1002             if(cc.game.config["noCache"] && typeof realUrl === "string"){
1003                 if(self._noCacheRex.test(realUrl))
1004                     realUrl += "&_t=" + (new Date() - 0);
1005                 else
1006                     realUrl += "?_t=" + (new Date() - 0);
1007             }
1008             loader.load(realUrl, url, item, function (err, data) {
1009                 if (err) {
1010                     cc.log(err);
1011                     self.cache[url] = null;
1012                     delete self.cache[url];
1013                     cb({status:520, errorMessage:err}, null);
1014                 } else {
1015                     self.cache[url] = data;
1016                     cb(null, data);
1017                 }
1018             });
1019         },
1020         _noCacheRex: /\?/,
1021 
1022         /**
1023          * Get url with basePath.
1024          * @param {string} basePath
1025          * @param {string} [url]
1026          * @returns {*}
1027          */
1028         getUrl: function (basePath, url) {
1029             var self = this, path = cc.path;
1030             if (basePath !== undefined && url === undefined) {
1031                 url = basePath;
1032                 var type = path.extname(url);
1033                 type = type ? type.toLowerCase() : "";
1034                 var loader = _register[type];
1035                 if (!loader)
1036                     basePath = self.resPath;
1037                 else
1038                     basePath = loader.getBasePath ? loader.getBasePath() : self.resPath;
1039             }
1040             url = cc.path.join(basePath || "", url);
1041             if (url.match(/[\/(\\\\)]lang[\/(\\\\)]/i)) {
1042                 if (_langPathCache[url])
1043                     return _langPathCache[url];
1044                 var extname = path.extname(url) || "";
1045                 url = _langPathCache[url] = url.substring(0, url.length - extname.length) + "_" + cc.sys.language + extname;
1046             }
1047             return url;
1048         },
1049 
1050         /**
1051          * Load resources then call the callback.
1052          * @param {string} resources
1053          * @param {function} [option] callback or trigger
1054          * @param {function|Object} [loadCallback]
1055          * @return {cc.AsyncPool}
1056          */
1057         load : function(resources, option, loadCallback){
1058             var self = this;
1059             var len = arguments.length;
1060             if(len === 0)
1061                 throw new Error("arguments error!");
1062 
1063             if(len === 3){
1064                 if(typeof option === "function"){
1065                     if(typeof loadCallback === "function")
1066                         option = {trigger : option, cb : loadCallback };
1067                     else
1068                         option = { cb : option, cbTarget : loadCallback};
1069                 }
1070             }else if(len === 2){
1071                 if(typeof option === "function")
1072                     option = {cb : option};
1073             }else if(len === 1){
1074                 option = {};
1075             }
1076 
1077             if(!(resources instanceof Array))
1078                 resources = [resources];
1079             var asyncPool = new cc.AsyncPool(
1080                 resources, 0,
1081                 function (value, index, AsyncPoolCallback, aPool) {
1082                     self._loadResIterator(value, index, function (err) {
1083                         var arr = Array.prototype.slice.call(arguments, 1);
1084                         if (option.trigger)
1085                             option.trigger.call(option.triggerTarget, arr[0], aPool.size, aPool.finishedSize);   //call trigger
1086                         AsyncPoolCallback(err, arr[0]);
1087                     });
1088                 },
1089                 option.cb, option.cbTarget);
1090             asyncPool.flow();
1091             return asyncPool;
1092         },
1093 
1094         _handleAliases: function (fileNames, cb) {
1095             var self = this;
1096             var resList = [];
1097             for (var key in fileNames) {
1098                 var value = fileNames[key];
1099                 _aliases[key] = value;
1100                 resList.push(value);
1101             }
1102             this.load(resList, cb);
1103         },
1104 
1105         /**
1106          * <p>
1107          *     Loads alias map from the contents of a filename.                                        <br/>
1108          *                                                                                                                 <br/>
1109          *     @note The plist file name should follow the format below:                                                   <br/>
1110          *     <?xml version="1.0" encoding="UTF-8"?>                                                                      <br/>
1111          *         <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">  <br/>
1112          *             <plist version="1.0">                                                                               <br/>
1113          *                 <dict>                                                                                          <br/>
1114          *                     <key>filenames</key>                                                                        <br/>
1115          *                     <dict>                                                                                      <br/>
1116          *                         <key>sounds/click.wav</key>                                                             <br/>
1117          *                         <string>sounds/click.caf</string>                                                       <br/>
1118          *                         <key>sounds/endgame.wav</key>                                                           <br/>
1119          *                         <string>sounds/endgame.caf</string>                                                     <br/>
1120          *                         <key>sounds/gem-0.wav</key>                                                             <br/>
1121          *                         <string>sounds/gem-0.caf</string>                                                       <br/>
1122          *                     </dict>                                                                                     <br/>
1123          *                     <key>metadata</key>                                                                         <br/>
1124          *                     <dict>                                                                                      <br/>
1125          *                         <key>version</key>                                                                      <br/>
1126          *                         <integer>1</integer>                                                                    <br/>
1127          *                     </dict>                                                                                     <br/>
1128          *                 </dict>                                                                                         <br/>
1129          *              </plist>                                                                                           <br/>
1130          * </p>
1131          * @param {String} url  The plist file name.
1132          * @param {Function} [callback]
1133          */
1134         loadAliases: function (url, callback) {
1135             var self = this, dict = self.getRes(url);
1136             if (!dict) {
1137                 self.load(url, function (err, results) {
1138                     self._handleAliases(results[0]["filenames"], callback);
1139                 });
1140             } else
1141                 self._handleAliases(dict["filenames"], callback);
1142         },
1143 
1144         /**
1145          * Register a resource loader into loader.
1146          * @param {string} extNames
1147          * @param {function} loader
1148          */
1149         register: function (extNames, loader) {
1150             if (!extNames || !loader) return;
1151             var self = this;
1152             if (typeof extNames === "string")
1153                 return _register[extNames.trim().toLowerCase()] = loader;
1154             for (var i = 0, li = extNames.length; i < li; i++) {
1155                 _register["." + extNames[i].trim().toLowerCase()] = loader;
1156             }
1157         },
1158 
1159         /**
1160          * Get resource data by url.
1161          * @param url
1162          * @returns {*}
1163          */
1164         getRes: function (url) {
1165             return this.cache[url] || this.cache[_aliases[url]];
1166         },
1167 
1168         /**
1169          * Get aliase by url.
1170          * @param url
1171          * @returns {*}
1172          */
1173         _getAliase: function (url) {
1174             return _aliases[url];
1175         },
1176 
1177         /**
1178          * Release the cache of resource by url.
1179          * @param url
1180          */
1181         release: function (url) {
1182             var cache = this.cache;
1183             var queue = _queue[url];
1184             if (queue) {
1185                 queue.img = null;
1186                 delete _queue[url];
1187             }
1188             delete cache[url];
1189             delete cache[_aliases[url]];
1190             delete _aliases[url];
1191         },
1192 
1193         /**
1194          * Resource cache of all resources.
1195          */
1196         releaseAll: function () {
1197             var locCache = this.cache;
1198             for (var key in locCache)
1199                 delete locCache[key];
1200             for (var key in _aliases)
1201                 delete _aliases[key];
1202         }
1203     };
1204 })();
1205 //+++++++++++++++++++++++++something about loader end+++++++++++++++++++++++++++++
1206 
1207 /**
1208  * A string tool to construct a string with format string.
1209  * for example:
1210  *      cc.formatStr("a: %d, b: %b", a, b);
1211  *      cc.formatStr(a, b, c);
1212  * @returns {String}
1213  */
1214 cc.formatStr = function(){
1215     var args = arguments;
1216     var l = args.length;
1217     if(l < 1)
1218         return "";
1219 
1220     var str = args[0];
1221     var needToFormat = true;
1222     if(typeof str === "object"){
1223         needToFormat = false;
1224     }
1225     for(var i = 1; i < l; ++i){
1226         var arg = args[i];
1227         if(needToFormat){
1228             while(true){
1229                 var result = null;
1230                 if(typeof arg === "number"){
1231                     result = str.match(/(%d)|(%s)/);
1232                     if(result){
1233                         str = str.replace(/(%d)|(%s)/, arg);
1234                         break;
1235                     }
1236                 }
1237                 result = str.match(/%s/);
1238                 if(result)
1239                     str = str.replace(/%s/, arg);
1240                 else
1241                     str += "    " + arg;
1242                 break;
1243             }
1244         }else
1245             str += "    " + arg;
1246     }
1247     return str;
1248 };
1249 
1250 
1251 //+++++++++++++++++++++++++Engine initialization function begin+++++++++++++++++++++++++++
1252 (function () {
1253 
1254 var _tmpCanvas1 = document.createElement("canvas"),
1255     _tmpCanvas2 = document.createElement("canvas");
1256 
1257 cc.create3DContext = function (canvas, opt_attribs) {
1258     var names = ["webgl", "experimental-webgl", "webkit-3d", "moz-webgl"];
1259     var context = null;
1260     for (var ii = 0; ii < names.length; ++ii) {
1261         try {
1262             context = canvas.getContext(names[ii], opt_attribs);
1263         } catch (e) {
1264         }
1265         if (context) {
1266             break;
1267         }
1268     }
1269     return context;
1270 };
1271 
1272 var _initSys = function () {
1273     /**
1274      * System variables
1275      * @namespace
1276      * @name cc.sys
1277      */
1278     cc.sys = {};
1279     var sys = cc.sys;
1280 
1281     /**
1282      * English language code
1283      * @memberof cc.sys
1284      * @name LANGUAGE_ENGLISH
1285      * @constant
1286      * @type {Number}
1287      */
1288     sys.LANGUAGE_ENGLISH = "en";
1289 
1290     /**
1291      * Chinese language code
1292      * @memberof cc.sys
1293      * @name LANGUAGE_CHINESE
1294      * @constant
1295      * @type {Number}
1296      */
1297     sys.LANGUAGE_CHINESE = "zh";
1298 
1299     /**
1300      * French language code
1301      * @memberof cc.sys
1302      * @name LANGUAGE_FRENCH
1303      * @constant
1304      * @type {Number}
1305      */
1306     sys.LANGUAGE_FRENCH = "fr";
1307 
1308     /**
1309      * Italian language code
1310      * @memberof cc.sys
1311      * @name LANGUAGE_ITALIAN
1312      * @constant
1313      * @type {Number}
1314      */
1315     sys.LANGUAGE_ITALIAN = "it";
1316 
1317     /**
1318      * German language code
1319      * @memberof cc.sys
1320      * @name LANGUAGE_GERMAN
1321      * @constant
1322      * @type {Number}
1323      */
1324     sys.LANGUAGE_GERMAN = "de";
1325 
1326     /**
1327      * Spanish language code
1328      * @memberof cc.sys
1329      * @name LANGUAGE_SPANISH
1330      * @constant
1331      * @type {Number}
1332      */
1333     sys.LANGUAGE_SPANISH = "es";
1334 
1335     /**
1336      * Spanish language code
1337      * @memberof cc.sys
1338      * @name LANGUAGE_DUTCH
1339      * @constant
1340      * @type {Number}
1341      */
1342     sys.LANGUAGE_DUTCH = "du";
1343 
1344     /**
1345      * Russian language code
1346      * @memberof cc.sys
1347      * @name LANGUAGE_RUSSIAN
1348      * @constant
1349      * @type {Number}
1350      */
1351     sys.LANGUAGE_RUSSIAN = "ru";
1352 
1353     /**
1354      * Korean language code
1355      * @memberof cc.sys
1356      * @name LANGUAGE_KOREAN
1357      * @constant
1358      * @type {Number}
1359      */
1360     sys.LANGUAGE_KOREAN = "ko";
1361 
1362     /**
1363      * Japanese language code
1364      * @memberof cc.sys
1365      * @name LANGUAGE_JAPANESE
1366      * @constant
1367      * @type {Number}
1368      */
1369     sys.LANGUAGE_JAPANESE = "ja";
1370 
1371     /**
1372      * Hungarian language code
1373      * @memberof cc.sys
1374      * @name LANGUAGE_HUNGARIAN
1375      * @constant
1376      * @type {Number}
1377      */
1378     sys.LANGUAGE_HUNGARIAN = "hu";
1379 
1380     /**
1381      * Portuguese language code
1382      * @memberof cc.sys
1383      * @name LANGUAGE_PORTUGUESE
1384      * @constant
1385      * @type {Number}
1386      */
1387     sys.LANGUAGE_PORTUGUESE = "pt";
1388 
1389     /**
1390      * Arabic language code
1391      * @memberof cc.sys
1392      * @name LANGUAGE_ARABIC
1393      * @constant
1394      * @type {Number}
1395      */
1396     sys.LANGUAGE_ARABIC = "ar";
1397 
1398     /**
1399      * Norwegian language code
1400      * @memberof cc.sys
1401      * @name LANGUAGE_NORWEGIAN
1402      * @constant
1403      * @type {Number}
1404      */
1405     sys.LANGUAGE_NORWEGIAN = "no";
1406 
1407     /**
1408      * Polish language code
1409      * @memberof cc.sys
1410      * @name LANGUAGE_POLISH
1411      * @constant
1412      * @type {Number}
1413      */
1414     sys.LANGUAGE_POLISH = "pl";
1415 
1416     /**
1417      * Unknown language code
1418      * @memberof cc.sys
1419      * @name LANGUAGE_UNKNOWN
1420      * @constant
1421      * @type {Number}
1422      */
1423     sys.LANGUAGE_UNKNOWN = "unkonwn";
1424 
1425     /**
1426      * @memberof cc.sys
1427      * @name OS_IOS
1428      * @constant
1429      * @type {string}
1430      */
1431     sys.OS_IOS = "iOS";
1432     /**
1433      * @memberof cc.sys
1434      * @name OS_ANDROID
1435      * @constant
1436      * @type {string}
1437      */
1438     sys.OS_ANDROID = "Android";
1439     /**
1440      * @memberof cc.sys
1441      * @name OS_WINDOWS
1442      * @constant
1443      * @type {string}
1444      */
1445     sys.OS_WINDOWS = "Windows";
1446     /**
1447      * @memberof cc.sys
1448      * @name OS_MARMALADE
1449      * @constant
1450      * @type {string}
1451      */
1452     sys.OS_MARMALADE = "Marmalade";
1453     /**
1454      * @memberof cc.sys
1455      * @name OS_LINUX
1456      * @constant
1457      * @type {string}
1458      */
1459     sys.OS_LINUX = "Linux";
1460     /**
1461      * @memberof cc.sys
1462      * @name OS_BADA
1463      * @constant
1464      * @type {string}
1465      */
1466     sys.OS_BADA = "Bada";
1467     /**
1468      * @memberof cc.sys
1469      * @name OS_BLACKBERRY
1470      * @constant
1471      * @type {string}
1472      */
1473     sys.OS_BLACKBERRY = "Blackberry";
1474     /**
1475      * @memberof cc.sys
1476      * @name OS_OSX
1477      * @constant
1478      * @type {string}
1479      */
1480     sys.OS_OSX = "OS X";
1481     /**
1482      * @memberof cc.sys
1483      * @name OS_WP8
1484      * @constant
1485      * @type {string}
1486      */
1487     sys.OS_WP8 = "WP8";
1488     /**
1489      * @memberof cc.sys
1490      * @name OS_WINRT
1491      * @constant
1492      * @type {string}
1493      */
1494     sys.OS_WINRT = "WINRT";
1495     /**
1496      * @memberof cc.sys
1497      * @name OS_UNKNOWN
1498      * @constant
1499      * @type {string}
1500      */
1501     sys.OS_UNKNOWN = "Unknown";
1502 
1503     /**
1504      * @memberof cc.sys
1505      * @name UNKNOWN
1506      * @constant
1507      * @default
1508      * @type {Number}
1509      */
1510     sys.UNKNOWN = -1;
1511     /**
1512      * @memberof cc.sys
1513      * @name WIN32
1514      * @constant
1515      * @default
1516      * @type {Number}
1517      */
1518     sys.WIN32 = 0;
1519     /**
1520      * @memberof cc.sys
1521      * @name LINUX
1522      * @constant
1523      * @default
1524      * @type {Number}
1525      */
1526     sys.LINUX = 1;
1527     /**
1528      * @memberof cc.sys
1529      * @name MACOS
1530      * @constant
1531      * @default
1532      * @type {Number}
1533      */
1534     sys.MACOS = 2;
1535     /**
1536      * @memberof cc.sys
1537      * @name ANDROID
1538      * @constant
1539      * @default
1540      * @type {Number}
1541      */
1542     sys.ANDROID = 3;
1543     /**
1544      * @memberof cc.sys
1545      * @name IOS
1546      * @constant
1547      * @default
1548      * @type {Number}
1549      */
1550     sys.IPHONE = 4;
1551     /**
1552      * @memberof cc.sys
1553      * @name IOS
1554      * @constant
1555      * @default
1556      * @type {Number}
1557      */
1558     sys.IPAD = 5;
1559     /**
1560      * @memberof cc.sys
1561      * @name BLACKBERRY
1562      * @constant
1563      * @default
1564      * @type {Number}
1565      */
1566     sys.BLACKBERRY = 6;
1567     /**
1568      * @memberof cc.sys
1569      * @name NACL
1570      * @constant
1571      * @default
1572      * @type {Number}
1573      */
1574     sys.NACL = 7;
1575     /**
1576      * @memberof cc.sys
1577      * @name EMSCRIPTEN
1578      * @constant
1579      * @default
1580      * @type {Number}
1581      */
1582     sys.EMSCRIPTEN = 8;
1583     /**
1584      * @memberof cc.sys
1585      * @name TIZEN
1586      * @constant
1587      * @default
1588      * @type {Number}
1589      */
1590     sys.TIZEN = 9;
1591     /**
1592      * @memberof cc.sys
1593      * @name WINRT
1594      * @constant
1595      * @default
1596      * @type {Number}
1597      */
1598     sys.WINRT = 10;
1599     /**
1600      * @memberof cc.sys
1601      * @name WP8
1602      * @constant
1603      * @default
1604      * @type {Number}
1605      */
1606     sys.WP8 = 11;
1607     /**
1608      * @memberof cc.sys
1609      * @name MOBILE_BROWSER
1610      * @constant
1611      * @default
1612      * @type {Number}
1613      */
1614     sys.MOBILE_BROWSER = 100;
1615     /**
1616      * @memberof cc.sys
1617      * @name DESKTOP_BROWSER
1618      * @constant
1619      * @default
1620      * @type {Number}
1621      */
1622     sys.DESKTOP_BROWSER = 101;
1623 
1624     sys.BROWSER_TYPE_WECHAT = "wechat";
1625     sys.BROWSER_TYPE_ANDROID = "androidbrowser";
1626     sys.BROWSER_TYPE_IE = "ie";
1627     sys.BROWSER_TYPE_QQ = "qqbrowser";
1628     sys.BROWSER_TYPE_MOBILE_QQ = "mqqbrowser";
1629     sys.BROWSER_TYPE_UC = "ucbrowser";
1630     sys.BROWSER_TYPE_360 = "360browser";
1631     sys.BROWSER_TYPE_BAIDU_APP = "baiduboxapp";
1632     sys.BROWSER_TYPE_BAIDU = "baidubrowser";
1633     sys.BROWSER_TYPE_MAXTHON = "maxthon";
1634     sys.BROWSER_TYPE_OPERA = "opera";
1635     sys.BROWSER_TYPE_OUPENG = "oupeng";
1636     sys.BROWSER_TYPE_MIUI = "miuibrowser";
1637     sys.BROWSER_TYPE_FIREFOX = "firefox";
1638     sys.BROWSER_TYPE_SAFARI = "safari";
1639     sys.BROWSER_TYPE_CHROME = "chrome";
1640     sys.BROWSER_TYPE_LIEBAO = "liebao";
1641     sys.BROWSER_TYPE_QZONE = "qzone";
1642     sys.BROWSER_TYPE_SOUGOU = "sogou";
1643     sys.BROWSER_TYPE_UNKNOWN = "unknown";
1644 
1645     /**
1646      * Is native ? This is set to be true in jsb auto.
1647      * @memberof cc.sys
1648      * @name isNative
1649      * @type {Boolean}
1650      */
1651     sys.isNative = false;
1652 
1653     var win = window, nav = win.navigator, doc = document, docEle = doc.documentElement;
1654     var ua = nav.userAgent.toLowerCase();
1655 
1656     /**
1657      * Indicate whether system is mobile system
1658      * @memberof cc.sys
1659      * @name isMobile
1660      * @type {Boolean}
1661      */
1662     sys.isMobile = ua.indexOf('mobile') !== -1 || ua.indexOf('android') !== -1;
1663 
1664     /**
1665      * Indicate the running platform
1666      * @memberof cc.sys
1667      * @name platform
1668      * @type {Number}
1669      */
1670     sys.platform = sys.isMobile ? sys.MOBILE_BROWSER : sys.DESKTOP_BROWSER;
1671 
1672     var currLanguage = nav.language;
1673     currLanguage = currLanguage ? currLanguage : nav.browserLanguage;
1674     currLanguage = currLanguage ? currLanguage.split("-")[0] : sys.LANGUAGE_ENGLISH;
1675 
1676     /**
1677      * Indicate the current language of the running system
1678      * @memberof cc.sys
1679      * @name language
1680      * @type {String}
1681      */
1682     sys.language = currLanguage;
1683 
1684     // Get the os of system
1685     var isAndroid = false, iOS = false, osVersion = '', osMainVersion = 0;
1686     var uaResult = /android (\d+(?:\.\d+)+)/i.exec(ua) || /android (\d+(?:\.\d+)+)/i.exec(nav.platform);
1687     if (uaResult) {
1688         isAndroid = true;
1689         osVersion = uaResult[1] || '';
1690         osMainVersion = parseInt(osVersion) || 0;
1691     }
1692     uaResult = /(iPad|iPhone|iPod).*OS ((\d+_?){2,3})/i.exec(ua);
1693     if (uaResult) {
1694         iOS = true;
1695         osVersion = uaResult[2] || '';
1696         osMainVersion = parseInt(osVersion) || 0;
1697     }
1698 
1699     var osName = sys.OS_UNKNOWN;
1700     if (nav.appVersion.indexOf("Win") !== -1) osName = sys.OS_WINDOWS;
1701     else if (iOS) osName = sys.OS_IOS;
1702     else if (nav.appVersion.indexOf("Mac") !== -1) osName = sys.OS_OSX;
1703     else if (nav.appVersion.indexOf("X11") !== -1 && nav.appVersion.indexOf("Linux") === -1) osName = sys.OS_UNIX;
1704     else if (isAndroid) osName = sys.OS_ANDROID;
1705     else if (nav.appVersion.indexOf("Linux") !== -1) osName = sys.OS_LINUX;
1706 
1707     /**
1708      * Indicate the running os name
1709      * @memberof cc.sys
1710      * @name os
1711      * @type {String}
1712      */
1713     sys.os = osName;
1714     /**
1715      * Indicate the running os version string
1716      * @memberof cc.sys
1717      * @name osVersion
1718      * @type {String}
1719      */
1720     sys.osVersion = osVersion;
1721     /**
1722      * Indicate the running os main version number
1723      * @memberof cc.sys
1724      * @name osMainVersion
1725      * @type {Number}
1726      */
1727     sys.osMainVersion = osMainVersion;
1728 
1729     /**
1730      * Indicate the running browser type
1731      * @memberof cc.sys
1732      * @name browserType
1733      * @type {String}
1734      */
1735     sys.browserType = sys.BROWSER_TYPE_UNKNOWN;
1736     /* Determine the browser type */
1737     (function(){
1738         var typeReg1 = /mqqbrowser|sogou|qzone|liebao|micromessenger|ucbrowser|360 aphone|360browser|baiduboxapp|baidubrowser|maxthon|mxbrowser|trident|miuibrowser/i;
1739         var typeReg2 = /qqbrowser|chrome|safari|firefox|opr|oupeng|opera/i;
1740         var browserTypes = typeReg1.exec(ua);
1741         if(!browserTypes) browserTypes = typeReg2.exec(ua);
1742         var browserType = browserTypes ? browserTypes[0] : sys.BROWSER_TYPE_UNKNOWN;
1743         if (browserType === 'micromessenger')
1744             browserType = sys.BROWSER_TYPE_WECHAT;
1745         else if (browserType === "safari" && (ua.match(/android.*applewebkit/)))
1746             browserType = sys.BROWSER_TYPE_ANDROID;
1747         else if (browserType === "trident")
1748             browserType = sys.BROWSER_TYPE_IE;
1749         else if (browserType === "360 aphone")
1750             browserType = sys.BROWSER_TYPE_360;
1751         else if (browserType === "mxbrowser")
1752             browserType = sys.BROWSER_TYPE_MAXTHON;
1753         else if (browserType === "opr")
1754             browserType = sys.BROWSER_TYPE_OPERA;
1755 
1756         sys.browserType = browserType;
1757     })();
1758 
1759     /**
1760      * Indicate the running browser version
1761      * @memberof cc.sys
1762      * @name browserVersion
1763      * @type {Number}
1764      */
1765     sys.browserVersion = "";
1766     /* Determine the browser version number */
1767     (function(){
1768         var versionReg1 = /(micromessenger|qq|mx|maxthon|baidu|sogou)(mobile)?(browser)?\/?([\d.]+)/i;
1769         var versionReg2 = /(msie |rv:|firefox|chrome|ucbrowser|oupeng|opera|opr|safari|miui)(mobile)?(browser)?\/?([\d.]+)/i;
1770         var tmp = ua.match(versionReg1);
1771         if(!tmp) tmp = ua.match(versionReg2);
1772         sys.browserVersion = tmp ? tmp[4] : "";
1773     })();
1774 
1775     var w = window.innerWidth || document.documentElement.clientWidth;
1776     var h = window.innerHeight || document.documentElement.clientHeight;
1777     var ratio = window.devicePixelRatio || 1;
1778 
1779     /**
1780      * Indicate the real pixel resolution of the whole game window
1781      * @memberof cc.sys
1782      * @name windowPixelResolution
1783      * @type {Number}
1784      */
1785     sys.windowPixelResolution = {
1786         width: ratio * w,
1787         height: ratio * h
1788     };
1789 
1790     sys._checkWebGLRenderMode = function () {
1791         if (cc._renderType !== cc.game.RENDER_TYPE_WEBGL)
1792             throw new Error("This feature supports WebGL render mode only.");
1793     };
1794 
1795     //Whether or not the Canvas BlendModes are supported.
1796     sys._supportCanvasNewBlendModes = (function(){
1797         var canvas = _tmpCanvas1;
1798         canvas.width = 1;
1799         canvas.height = 1;
1800         var context = canvas.getContext('2d');
1801         context.fillStyle = '#000';
1802         context.fillRect(0,0,1,1);
1803         context.globalCompositeOperation = 'multiply';
1804 
1805         var canvas2 = _tmpCanvas2;
1806         canvas2.width = 1;
1807         canvas2.height = 1;
1808         var context2 = canvas2.getContext('2d');
1809         context2.fillStyle = '#fff';
1810         context2.fillRect(0,0,1,1);
1811         context.drawImage(canvas2, 0, 0, 1, 1);
1812 
1813         return context.getImageData(0,0,1,1).data[0] === 0;
1814     })();
1815 
1816     // Adjust mobile css settings
1817     if (cc.sys.isMobile) {
1818         var fontStyle = document.createElement("style");
1819         fontStyle.type = "text/css";
1820         document.body.appendChild(fontStyle);
1821 
1822         fontStyle.textContent = "body,canvas,div{ -moz-user-select: none;-webkit-user-select: none;-ms-user-select: none;-khtml-user-select: none;"
1823                                 + "-webkit-tap-highlight-color:rgba(0,0,0,0);}";
1824     }
1825 
1826     /**
1827      * cc.sys.localStorage is a local storage component.
1828      * @memberof cc.sys
1829      * @name localStorage
1830      * @type {Object}
1831      */
1832     try {
1833         var localStorage = sys.localStorage = win.localStorage;
1834         localStorage.setItem("storage", "");
1835         localStorage.removeItem("storage");
1836         localStorage = null;
1837     } catch (e) {
1838         var warn = function () {
1839             cc.warn("Warning: localStorage isn't enabled. Please confirm browser cookie or privacy option");
1840         };
1841         sys.localStorage = {
1842             getItem : warn,
1843             setItem : warn,
1844             removeItem : warn,
1845             clear : warn
1846         };
1847     }
1848 
1849     var _supportCanvas = !!_tmpCanvas1.getContext("2d");
1850     var _supportWebGL = false;
1851     if (win.WebGLRenderingContext) {
1852         var tmpCanvas = document.createElement("CANVAS");
1853         try{
1854             var context = cc.create3DContext(tmpCanvas, {'stencil': true, 'preserveDrawingBuffer': true });
1855             if(context) {
1856                 _supportWebGL = true;
1857             }
1858 
1859             if (_supportWebGL && sys.os === sys.OS_ANDROID) {
1860                 switch (sys.browserType) {
1861                 case sys.BROWSER_TYPE_MOBILE_QQ:
1862                 case sys.BROWSER_TYPE_BAIDU:
1863                 case sys.BROWSER_TYPE_BAIDU_APP:
1864                     // QQ & Baidu Brwoser 6.2+ (using blink kernel)
1865                     var browserVer = parseFloat(sys.browserVersion);
1866                     if (browserVer >= 6.2) {
1867                         _supportWebGL = true;
1868                     }
1869                     else {
1870                         _supportWebGL = false;
1871                     }
1872                     break;
1873                 case sys.BROWSER_TYPE_ANDROID:
1874                     // Android 5+ default browser
1875                     if (sys.osMainVersion && sys.osMainVersion >= 5) {
1876                         _supportWebGL = true;
1877                     }
1878                     break;
1879                 case sys.BROWSER_TYPE_UNKNOWN:
1880                 case sys.BROWSER_TYPE_360:
1881                 case sys.BROWSER_TYPE_MIUI:
1882                     _supportWebGL = false;
1883                 }
1884             }
1885         }
1886         catch (e) {}
1887         tmpCanvas = null;
1888     }
1889 
1890     /**
1891      * The capabilities of the current platform
1892      * @memberof cc.sys
1893      * @name capabilities
1894      * @type {Object}
1895      */
1896     var capabilities = sys.capabilities = {
1897         "canvas": _supportCanvas,
1898         "opengl": _supportWebGL
1899     };
1900     if (docEle['ontouchstart'] !== undefined || doc['ontouchstart'] !== undefined || nav.msPointerEnabled)
1901         capabilities["touches"] = true;
1902     if (docEle['onmouseup'] !== undefined)
1903         capabilities["mouse"] = true;
1904     if (docEle['onkeyup'] !== undefined)
1905         capabilities["keyboard"] = true;
1906     if (win.DeviceMotionEvent || win.DeviceOrientationEvent)
1907         capabilities["accelerometer"] = true;
1908 
1909     /**
1910      * Forces the garbage collection, only available in JSB
1911      * @memberof cc.sys
1912      * @name garbageCollect
1913      * @function
1914      */
1915     sys.garbageCollect = function () {
1916         // N/A in cocos2d-html5
1917     };
1918 
1919     /**
1920      * Dumps rooted objects, only available in JSB
1921      * @memberof cc.sys
1922      * @name dumpRoot
1923      * @function
1924      */
1925     sys.dumpRoot = function () {
1926         // N/A in cocos2d-html5
1927     };
1928 
1929     /**
1930      * Restart the JS VM, only available in JSB
1931      * @memberof cc.sys
1932      * @name restartVM
1933      * @function
1934      */
1935     sys.restartVM = function () {
1936         // N/A in cocos2d-html5
1937     };
1938 
1939     /**
1940      * Clean a script in the JS VM, only available in JSB
1941      * @memberof cc.sys
1942      * @name cleanScript
1943      * @param {String} jsfile
1944      * @function
1945      */
1946     sys.cleanScript = function (jsfile) {
1947         // N/A in cocos2d-html5
1948     };
1949 
1950     /**
1951      * Check whether an object is valid,
1952      * In web engine, it will return true if the object exist
1953      * In native engine, it will return true if the JS object and the correspond native object are both valid
1954      * @memberof cc.sys
1955      * @name isObjectValid
1956      * @param {Object} obj
1957      * @return {boolean} Validity of the object
1958      * @function
1959      */
1960     sys.isObjectValid = function (obj) {
1961         if (obj) return true;
1962         else return false;
1963     };
1964 
1965     /**
1966      * Dump system informations
1967      * @memberof cc.sys
1968      * @name dump
1969      * @function
1970      */
1971     sys.dump = function () {
1972         var self = this;
1973         var str = "";
1974         str += "isMobile : " + self.isMobile + "\r\n";
1975         str += "language : " + self.language + "\r\n";
1976         str += "browserType : " + self.browserType + "\r\n";
1977         str += "browserVersion : " + self.browserVersion + "\r\n";
1978         str += "capabilities : " + JSON.stringify(self.capabilities) + "\r\n";
1979         str += "os : " + self.os + "\r\n";
1980         str += "osVersion : " + self.osVersion + "\r\n";
1981         str += "platform : " + self.platform + "\r\n";
1982         str += "Using " + (cc._renderType === cc.game.RENDER_TYPE_WEBGL ? "WEBGL" : "CANVAS") + " renderer." + "\r\n";
1983         cc.log(str);
1984     };
1985 
1986     /**
1987      * Open a url in browser
1988      * @memberof cc.sys
1989      * @name openURL
1990      * @param {String} url
1991      */
1992     sys.openURL = function(url){
1993         window.open(url);
1994     };
1995 };
1996 _initSys();
1997 
1998 _tmpCanvas1 = null;
1999 _tmpCanvas2 = null;
2000 
2001 //to make sure the cc.log, cc.warn, cc.error and cc.assert would not throw error before init by debugger mode.
2002 cc.log = cc.warn = cc.error = cc.assert = function () {
2003 };
2004 
2005 var _config = null,
2006     //cache for js and module that has added into jsList to be loaded.
2007     _jsAddedCache = {},
2008     _engineInitCalled = false,
2009     _engineLoadedCallback = null;
2010 
2011 cc._engineLoaded = false;
2012 
2013 function _determineRenderType(config) {
2014     var CONFIG_KEY = cc.game.CONFIG_KEY,
2015         userRenderMode = parseInt(config[CONFIG_KEY.renderMode]) || 0;
2016 
2017     // Adjust RenderType
2018     if (isNaN(userRenderMode) || userRenderMode > 2 || userRenderMode < 0)
2019         config[CONFIG_KEY.renderMode] = 0;
2020 
2021     // Determine RenderType
2022     cc._renderType = cc.game.RENDER_TYPE_CANVAS;
2023     cc._supportRender = false;
2024 
2025     if (userRenderMode === 0) {
2026         if (cc.sys.capabilities["opengl"]) {
2027             cc._renderType = cc.game.RENDER_TYPE_WEBGL;
2028             cc._supportRender = true;
2029         }
2030         else if (cc.sys.capabilities["canvas"]) {
2031             cc._renderType = cc.game.RENDER_TYPE_CANVAS;
2032             cc._supportRender = true;
2033         }
2034     }
2035     else if (userRenderMode === 1 && cc.sys.capabilities["canvas"]) {
2036         cc._renderType = cc.game.RENDER_TYPE_CANVAS;
2037         cc._supportRender = true;
2038     }
2039     else if (userRenderMode === 2 && cc.sys.capabilities["opengl"]) {
2040         cc._renderType = cc.game.RENDER_TYPE_WEBGL;
2041         cc._supportRender = true;
2042     }
2043 }
2044 
2045 function _getJsListOfModule(moduleMap, moduleName, dir) {
2046     if (_jsAddedCache[moduleName]) return null;
2047     dir = dir || "";
2048     var jsList = [];
2049     var tempList = moduleMap[moduleName];
2050     if (!tempList) throw new Error("can not find module [" + moduleName + "]");
2051     var ccPath = cc.path;
2052     for (var i = 0, li = tempList.length; i < li; i++) {
2053         var item = tempList[i];
2054         if (_jsAddedCache[item]) continue;
2055         var extname = ccPath.extname(item);
2056         if (!extname) {
2057             var arr = _getJsListOfModule(moduleMap, item, dir);
2058             if (arr) jsList = jsList.concat(arr);
2059         } else if (extname.toLowerCase() === ".js") jsList.push(ccPath.join(dir, item));
2060         _jsAddedCache[item] = 1;
2061     }
2062     return jsList;
2063 }
2064 
2065 function _afterEngineLoaded(config) {
2066     if (cc._initDebugSetting)
2067         cc._initDebugSetting(config[cc.game.CONFIG_KEY.debugMode]);
2068     cc._engineLoaded = true;
2069     cc.log(cc.ENGINE_VERSION);
2070     if (_engineLoadedCallback) _engineLoadedCallback();
2071 }
2072 
2073 function _load(config) {
2074     var self = this;
2075     var CONFIG_KEY = cc.game.CONFIG_KEY, engineDir = config[CONFIG_KEY.engineDir], loader = cc.loader;
2076 
2077     if (cc.Class) {
2078         // Single file loaded
2079         _afterEngineLoaded(config);
2080     } else {
2081         // Load cocos modules
2082         var ccModulesPath = cc.path.join(engineDir, "moduleConfig.json");
2083         loader.loadJson(ccModulesPath, function (err, modulesJson) {
2084             if (err) throw new Error(err);
2085             var modules = config["modules"] || [];
2086             var moduleMap = modulesJson["module"];
2087             var jsList = [];
2088             if (cc.sys.capabilities["opengl"] && modules.indexOf("base4webgl") < 0) modules.splice(0, 0, "base4webgl");
2089             else if (modules.indexOf("core") < 0) modules.splice(0, 0, "core");
2090             for (var i = 0, li = modules.length; i < li; i++) {
2091                 var arr = _getJsListOfModule(moduleMap, modules[i], engineDir);
2092                 if (arr) jsList = jsList.concat(arr);
2093             }
2094             cc.loader.loadJsWithImg(jsList, function (err) {
2095                 if (err) throw err;
2096                 _afterEngineLoaded(config);
2097             });
2098         });
2099     }
2100 }
2101 
2102 function _windowLoaded() {
2103     this.removeEventListener('load', _windowLoaded, false);
2104     _load(cc.game.config);
2105 }
2106 
2107 cc.initEngine = function (config, cb) {
2108     if (_engineInitCalled) {
2109         var previousCallback = _engineLoadedCallback;
2110         _engineLoadedCallback = function () {
2111             previousCallback && previousCallback();
2112             cb && cb();
2113         }
2114         return;
2115     }
2116 
2117     _engineLoadedCallback = cb;
2118 
2119     // Config uninitialized and given, initialize with it
2120     if (!cc.game.config && config) {
2121         cc.game.config = config;
2122     }
2123     // No config given and no config set before, load it
2124     else if (!cc.game.config) {
2125         cc.game._loadConfig();
2126     }
2127     config = cc.game.config;
2128 
2129     _determineRenderType(config);
2130 
2131     document.body ? _load(config) : cc._addEventListener(window, 'load', _windowLoaded, false);
2132     _engineInitCalled = true;
2133 };
2134 
2135 })();
2136 //+++++++++++++++++++++++++Engine initialization function end+++++++++++++++++++++++++++++
2137 
2138 //+++++++++++++++++++++++++something about CCGame begin+++++++++++++++++++++++++++
2139 /**
2140  * An object to boot the game.
2141  * @class
2142  * @name cc.game
2143  *
2144  */
2145 cc.game = /** @lends cc.game# */{
2146     /** 
2147      * Debug mode: No debugging. {@static}
2148      * @const {Number}
2149      * @static
2150      */
2151     DEBUG_MODE_NONE: 0,
2152     /**
2153      * Debug mode: Info, warning, error to console.
2154      * @const {Number}
2155      * @static
2156      */
2157     DEBUG_MODE_INFO: 1,
2158     /**
2159      * Debug mode: Warning, error to console.
2160      * @const {Number}
2161      * @static
2162      */
2163     DEBUG_MODE_WARN: 2,
2164     /**
2165      * Debug mode: Error to console.
2166      * @const {Number}
2167      * @static
2168      */
2169     DEBUG_MODE_ERROR: 3,
2170     /**
2171      * Debug mode: Info, warning, error to web page.
2172      * @const {Number}
2173      * @static
2174      */
2175     DEBUG_MODE_INFO_FOR_WEB_PAGE: 4,
2176     /**
2177      * Debug mode: Warning, error to web page.
2178      * @const {Number}
2179      * @static
2180      */
2181     DEBUG_MODE_WARN_FOR_WEB_PAGE: 5,
2182     /**
2183      * Debug mode: Error to web page.
2184      * @const {Number}
2185      * @static
2186      */
2187     DEBUG_MODE_ERROR_FOR_WEB_PAGE: 6,
2188 
2189     /**
2190      * Event that is fired when the game is hidden.
2191      * @constant {String}
2192      */
2193     EVENT_HIDE: "game_on_hide",
2194     /**
2195      * Event that is fired when the game is shown.
2196      * @constant {String}
2197      */
2198     EVENT_SHOW: "game_on_show",
2199     /**
2200      * Event that is fired when the game is resized.
2201      * @constant {String}
2202      */
2203     EVENT_RESIZE: "game_on_resize",
2204     /**
2205      * Event that is fired when the renderer is done being initialized.
2206      * @constant {String}
2207      */
2208     EVENT_RENDERER_INITED: "renderer_inited",
2209 
2210     /** @constant {Number} */
2211     RENDER_TYPE_CANVAS: 0,
2212     /** @constant {Number} */
2213     RENDER_TYPE_WEBGL: 1,
2214     /** @constant {Number} */
2215     RENDER_TYPE_OPENGL: 2,
2216 
2217     _eventHide: null,
2218     _eventShow: null,
2219 
2220     /**
2221      * Keys found in project.json.
2222      *
2223      * @constant
2224      * @type {Object}
2225      *
2226      * @prop {String} engineDir     - In debug mode, if you use the whole engine to develop your game, you should specify its relative path with "engineDir".
2227      * @prop {String} modules       - Defines which modules you will need in your game, it's useful only on web
2228      * @prop {String} debugMode     - Debug mode, see DEBUG_MODE_XXX constant definitions.
2229      * @prop {String} showFPS       - Left bottom corner fps information will show when "showFPS" equals true, otherwise it will be hide.
2230      * @prop {String} frameRate     - Sets the wanted frame rate for your game, but the real fps depends on your game implementation and the running environment.
2231      * @prop {String} id            - Sets the id of your canvas element on the web page, it's useful only on web.
2232      * @prop {String} renderMode    - Sets the renderer type, only useful on web, 0: Automatic, 1: Canvas, 2: WebGL
2233      * @prop {String} jsList        - Sets the list of js files in your game.
2234      */
2235     CONFIG_KEY: {
2236         width: "width",
2237         height: "height",
2238         engineDir: "engineDir",
2239         modules: "modules",
2240         debugMode: "debugMode",
2241         showFPS: "showFPS",
2242         frameRate: "frameRate",
2243         id: "id",
2244         renderMode: "renderMode",
2245         jsList: "jsList"
2246     },
2247 
2248     // states
2249     _paused: true,//whether the game is paused
2250     _prepareCalled: false,//whether the prepare function has been called
2251     _prepared: false,//whether the engine has prepared
2252     _rendererInitialized: false,
2253 
2254     _renderContext: null,
2255 
2256     _intervalId: null,//interval target of main
2257 
2258     _lastTime: null,
2259     _frameTime: null,
2260 
2261     /**
2262      * The outer frame of the game canvas, parent of cc.container
2263      * @type {Object}
2264      */
2265     frame: null,
2266     /**
2267      * The container of game canvas, equals to cc.container
2268      * @type {Object}
2269      */
2270     container: null,
2271     /**
2272      * The canvas of the game, equals to cc._canvas
2273      * @type {Object}
2274      */
2275     canvas: null,
2276 
2277     /**
2278      * Config of game
2279      * @type {Object}
2280      */
2281     config: null,
2282 
2283     /**
2284      * Callback when the scripts of engine have been load.
2285      * @type {Function|null}
2286      */
2287     onStart: null,
2288 
2289     /**
2290      * Callback when game exits.
2291      * @type {Function|null}
2292      */
2293     onStop: null,
2294 
2295 //@Public Methods
2296 
2297 //  @Game play control
2298     /**
2299      * Set frameRate of game.
2300      * @param frameRate
2301      */
2302     setFrameRate: function (frameRate) {
2303         var self = this, config = self.config, CONFIG_KEY = self.CONFIG_KEY;
2304         config[CONFIG_KEY.frameRate] = frameRate;
2305         if (self._intervalId)
2306             window.cancelAnimationFrame(self._intervalId);
2307         self._paused = true;
2308         self._setAnimFrame();
2309         self._runMainLoop();
2310     },
2311 
2312     /**
2313      * Run the game frame by frame.
2314      */
2315     step: function () {
2316         cc.director.mainLoop();
2317     },
2318 
2319     /**
2320      * Pause the game.
2321      */
2322     pause: function () {
2323         if (this._paused) return;
2324         this._paused = true;
2325         // Pause audio engine
2326         cc.audioEngine && cc.audioEngine._pausePlaying();
2327         // Pause main loop
2328         if (this._intervalId)
2329             window.cancelAnimationFrame(this._intervalId);
2330         this._intervalId = 0;
2331     },
2332 
2333     /**
2334      * Resume the game from pause.
2335      */
2336     resume: function () {
2337         if (!this._paused) return;
2338         this._paused = false;
2339         // Resume audio engine
2340         cc.audioEngine && cc.audioEngine._resumePlaying();
2341         // Resume main loop
2342         this._runMainLoop();
2343     },
2344 
2345     /**
2346      * Check whether the game is paused.
2347      */
2348     isPaused: function () {
2349         return this._paused;
2350     },
2351 
2352     /**
2353      * Restart game.
2354      */
2355     restart: function () {
2356         cc.director.popToSceneStackLevel(0);
2357         // Clean up audio
2358         cc.audioEngine && cc.audioEngine.end();
2359 
2360         cc.game.onStart();
2361     },
2362 
2363     /**
2364      * End game, it will close the game window
2365      */
2366     end: function () {
2367         close();
2368     },
2369 
2370 //  @Game loading
2371     /**
2372      * Prepare game.
2373      * @param cb
2374      */
2375     prepare: function (cb) {
2376         var self = this,
2377             config = self.config,
2378             CONFIG_KEY = self.CONFIG_KEY;
2379 
2380         this._loadConfig();
2381 
2382         // Already prepared
2383         if (this._prepared) {
2384             if (cb) cb();
2385             return;
2386         }
2387         // Prepare called, but not done yet
2388         if (this._prepareCalled) {
2389             return;
2390         }
2391         // Prepare never called and engine ready
2392         if (cc._engineLoaded) {
2393             this._prepareCalled = true;
2394 
2395             this._initRenderer(config[CONFIG_KEY.width], config[CONFIG_KEY.height]);
2396 
2397             /**
2398              * cc.view is the shared view object.
2399              * @type {cc.EGLView}
2400              * @name cc.view
2401              * @memberof cc
2402              */
2403             cc.view = cc.EGLView._getInstance();
2404 
2405             /**
2406              * @type {cc.Director}
2407              * @name cc.director
2408              * @memberof cc
2409              */
2410             cc.director = cc.Director._getInstance();
2411             if (cc.director.setOpenGLView)
2412                 cc.director.setOpenGLView(cc.view);
2413             /**
2414              * cc.winSize is the alias object for the size of the current game window.
2415              * @type {cc.Size}
2416              * @name cc.winSize
2417              * @memberof cc
2418              */
2419             cc.winSize = cc.director.getWinSize();
2420 
2421             this._initEvents();
2422 
2423             this._setAnimFrame();
2424             this._runMainLoop();
2425 
2426             // Load game scripts
2427             var jsList = config[CONFIG_KEY.jsList];
2428             if (jsList) {
2429                 cc.loader.loadJsWithImg(jsList, function (err) {
2430                     if (err) throw new Error(err);
2431                     self._prepared = true;
2432                     if (cb) cb();
2433                 });
2434             }
2435             else {
2436                 if (cb) cb();
2437             }
2438 
2439             return;
2440         }
2441 
2442         // Engine not loaded yet
2443         cc.initEngine(this.config, function () {
2444             self.prepare(cb);
2445         });
2446     },
2447 
2448     /**
2449      * Run game with configuration object and onStart function.
2450      * @param {Object|Function} [config] Pass configuration object or onStart function
2451      * @param {onStart} [onStart] onStart function to be executed after game initialized
2452      */
2453     run: function (config, onStart) {
2454         if (typeof config === 'function') {
2455             cc.game.onStart = config;
2456         }
2457         else {
2458             if (config) {
2459                 if (typeof config === 'string') {
2460                     if (!cc.game.config) this._loadConfig();
2461                     cc.game.config[cc.game.CONFIG_KEY.id] = config;
2462                 } else {
2463                     cc.game.config = config;
2464                 }
2465             }
2466             if (typeof onStart === 'function') {
2467                 cc.game.onStart = onStart;
2468             }
2469         }
2470 
2471         this.prepare(cc.game.onStart && cc.game.onStart.bind(cc.game));
2472     },
2473 
2474 //@Private Methods
2475 
2476 //  @Time ticker section
2477     _setAnimFrame: function () {
2478         this._lastTime = new Date();
2479         this._frameTime = 1000 / cc.game.config[cc.game.CONFIG_KEY.frameRate];
2480         if((cc.sys.os === cc.sys.OS_IOS && cc.sys.browserType === cc.sys.BROWSER_TYPE_WECHAT) || cc.game.config[cc.game.CONFIG_KEY.frameRate] !== 60) {
2481             window.requestAnimFrame = this._stTime;
2482             window.cancelAnimationFrame = this._ctTime;
2483         }
2484         else {
2485             window.requestAnimFrame = window.requestAnimationFrame ||
2486             window.webkitRequestAnimationFrame ||
2487             window.mozRequestAnimationFrame ||
2488             window.oRequestAnimationFrame ||
2489             window.msRequestAnimationFrame ||
2490             this._stTime;
2491             window.cancelAnimationFrame = window.cancelAnimationFrame ||
2492             window.cancelRequestAnimationFrame ||
2493             window.msCancelRequestAnimationFrame ||
2494             window.mozCancelRequestAnimationFrame ||
2495             window.oCancelRequestAnimationFrame ||
2496             window.webkitCancelRequestAnimationFrame ||
2497             window.msCancelAnimationFrame ||
2498             window.mozCancelAnimationFrame ||
2499             window.webkitCancelAnimationFrame ||
2500             window.oCancelAnimationFrame ||
2501             this._ctTime;
2502         }
2503     },
2504     _stTime: function(callback){
2505         var currTime = new Date().getTime();
2506         var timeToCall = Math.max(0, cc.game._frameTime - (currTime - cc.game._lastTime));
2507         var id = window.setTimeout(function() { callback(); },
2508             timeToCall);
2509         cc.game._lastTime = currTime + timeToCall;
2510         return id;
2511     },
2512     _ctTime: function(id){
2513         window.clearTimeout(id);
2514     },
2515     //Run game.
2516     _runMainLoop: function () {
2517         var self = this, callback, config = self.config, CONFIG_KEY = self.CONFIG_KEY,
2518             director = cc.director;
2519 
2520         director.setDisplayStats(config[CONFIG_KEY.showFPS]);
2521 
2522         callback = function () {
2523             if (!self._paused) {
2524                 director.mainLoop();
2525                 if(self._intervalId)
2526                     window.cancelAnimationFrame(self._intervalId);
2527                 self._intervalId = window.requestAnimFrame(callback);
2528             }
2529         };
2530 
2531         window.requestAnimFrame(callback);
2532         self._paused = false;
2533     },
2534 
2535 //  @Game loading section
2536     _loadConfig: function () {
2537         // Load config
2538         // Already loaded
2539         if (this.config) {
2540             this._initConfig(this.config);
2541             return;
2542         }
2543         // Load from document.ccConfig
2544         if (document["ccConfig"]) {
2545             this._initConfig(document["ccConfig"]);
2546         }
2547         // Load from project.json
2548         else {
2549             var data = {};
2550             try {
2551                 var cocos_script = document.getElementsByTagName('script');
2552                 for(var i = 0; i < cocos_script.length; i++){
2553                     var _t = cocos_script[i].getAttribute('cocos');
2554                     if(_t === '' || _t) {
2555                         break;
2556                     }
2557                 }
2558                 var _src, txt, _resPath;
2559                 if(i < cocos_script.length){
2560                     _src = cocos_script[i].src;
2561                     if(_src){
2562                         _resPath = /(.*)\//.exec(_src)[0];
2563                         cc.loader.resPath = _resPath;
2564                         _src = cc.path.join(_resPath, 'project.json');
2565                     }
2566                     txt = cc.loader._loadTxtSync(_src);
2567                 }
2568                 if(!txt){
2569                     txt = cc.loader._loadTxtSync("project.json");
2570                 }
2571                 data = JSON.parse(txt);
2572             } catch (e) {
2573                 cc.log("Failed to read or parse project.json");
2574             }
2575             this._initConfig(data);
2576         }
2577     },
2578 
2579     _initConfig: function (config) {
2580         var CONFIG_KEY = this.CONFIG_KEY,
2581             modules = config[CONFIG_KEY.modules];
2582 
2583         // Configs adjustment
2584         config[CONFIG_KEY.showFPS] = typeof config[CONFIG_KEY.showFPS] === 'undefined' ? true : config[CONFIG_KEY.showFPS];
2585         config[CONFIG_KEY.engineDir] = config[CONFIG_KEY.engineDir] || "frameworks/cocos2d-html5";
2586         if (config[CONFIG_KEY.debugMode] == null)
2587             config[CONFIG_KEY.debugMode] = 0;
2588         config[CONFIG_KEY.frameRate] = config[CONFIG_KEY.frameRate] || 60;
2589         if (config[CONFIG_KEY.renderMode] == null)
2590             config[CONFIG_KEY.renderMode] = 0;
2591         if (config[CONFIG_KEY.registerSystemEvent] == null)
2592             config[CONFIG_KEY.registerSystemEvent] = true;
2593 
2594         // Modules adjustment
2595         if (modules && modules.indexOf("core") < 0) modules.splice(0, 0, "core");
2596         modules && (config[CONFIG_KEY.modules] = modules);
2597         this.config = config;
2598     },
2599 
2600     _initRenderer: function (width, height) {
2601         // Avoid setup to be called twice.
2602         if (this._rendererInitialized) return;
2603 
2604         if (!cc._supportRender) {
2605             throw new Error("The renderer doesn't support the renderMode " + this.config[this.CONFIG_KEY.renderMode]);
2606         }
2607 
2608         var el = this.config[cc.game.CONFIG_KEY.id],
2609             win = window,
2610             element = cc.$(el) || cc.$('#' + el),
2611             localCanvas, localContainer, localConStyle;
2612 
2613         if (element.tagName === "CANVAS") {
2614             width = width || element.width;
2615             height = height || element.height;
2616 
2617             //it is already a canvas, we wrap it around with a div
2618             this.canvas = cc._canvas = localCanvas = element;
2619             this.container = cc.container = localContainer = document.createElement("DIV");
2620             if (localCanvas.parentNode)
2621                 localCanvas.parentNode.insertBefore(localContainer, localCanvas);
2622         } else {
2623             //we must make a new canvas and place into this element
2624             if (element.tagName !== "DIV") {
2625                 cc.log("Warning: target element is not a DIV or CANVAS");
2626             }
2627             width = width || element.clientWidth;
2628             height = height || element.clientHeight;
2629             this.canvas = cc._canvas = localCanvas = document.createElement("CANVAS");
2630             this.container = cc.container = localContainer = document.createElement("DIV");
2631             element.appendChild(localContainer);
2632         }
2633         localContainer.setAttribute('id', 'Cocos2dGameContainer');
2634         localContainer.appendChild(localCanvas);
2635         this.frame = (localContainer.parentNode === document.body) ? document.documentElement : localContainer.parentNode;
2636 
2637         localCanvas.addClass("gameCanvas");
2638         localCanvas.setAttribute("width", width || 480);
2639         localCanvas.setAttribute("height", height || 320);
2640         localCanvas.setAttribute("tabindex", 99);
2641         localCanvas.style.outline = "none";
2642         localConStyle = localContainer.style;
2643         localConStyle.width = (width || 480) + "px";
2644         localConStyle.height = (height || 320) + "px";
2645         localConStyle.margin = "0 auto";
2646 
2647         localConStyle.position = 'relative';
2648         localConStyle.overflow = 'hidden';
2649         localContainer.top = '100%';
2650 
2651         if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) {
2652             this._renderContext = cc._renderContext = cc.webglContext
2653              = cc.create3DContext(localCanvas, {
2654                 'stencil': true,
2655                 'preserveDrawingBuffer': true,
2656                 'antialias': !cc.sys.isMobile,
2657                 'alpha': true
2658             });
2659         }
2660         // WebGL context created successfully
2661         if (this._renderContext) {
2662             cc.renderer = cc.rendererWebGL;
2663             win.gl = this._renderContext; // global variable declared in CCMacro.js
2664             cc.renderer.init();
2665             cc.shaderCache._init();
2666             cc._drawingUtil = new cc.DrawingPrimitiveWebGL(this._renderContext);
2667             cc.textureCache._initializingRenderer();
2668             cc.glExt = {};
2669             cc.glExt.instanced_arrays = gl.getExtension("ANGLE_instanced_arrays");
2670             cc.glExt.element_uint = gl.getExtension("OES_element_index_uint");
2671         } else {
2672             cc.renderer = cc.rendererCanvas;
2673             this._renderContext = cc._renderContext = new cc.CanvasContextWrapper(localCanvas.getContext("2d"));
2674             cc._drawingUtil = cc.DrawingPrimitiveCanvas ? new cc.DrawingPrimitiveCanvas(this._renderContext) : null;
2675         }
2676 
2677         cc._gameDiv = localContainer;
2678         cc.game.canvas.oncontextmenu = function () {
2679             if (!cc._isContextMenuEnable) return false;
2680         };
2681 
2682         this.dispatchEvent(this.EVENT_RENDERER_INITED, true);
2683 
2684         this._rendererInitialized = true;
2685     },
2686 
2687     _initEvents: function () {
2688         var win = window, self = this, hidden, visibilityChange, _undef = "undefined";
2689 
2690         this._eventHide = this._eventHide || new cc.EventCustom(this.EVENT_HIDE);
2691         this._eventHide.setUserData(this);
2692         this._eventShow = this._eventShow || new cc.EventCustom(this.EVENT_SHOW);
2693         this._eventShow.setUserData(this);
2694 
2695         // register system events
2696         if (this.config[this.CONFIG_KEY.registerSystemEvent])
2697             cc.inputManager.registerSystemEvent(this.canvas);
2698 
2699         if (!cc.isUndefined(document.hidden)) {
2700             hidden = "hidden";
2701             visibilityChange = "visibilitychange";
2702         } else if (!cc.isUndefined(document.mozHidden)) {
2703             hidden = "mozHidden";
2704             visibilityChange = "mozvisibilitychange";
2705         } else if (!cc.isUndefined(document.msHidden)) {
2706             hidden = "msHidden";
2707             visibilityChange = "msvisibilitychange";
2708         } else if (!cc.isUndefined(document.webkitHidden)) {
2709             hidden = "webkitHidden";
2710             visibilityChange = "webkitvisibilitychange";
2711         }
2712 
2713         var onHidden = function () {
2714             if (cc.eventManager && cc.game._eventHide)
2715                 cc.eventManager.dispatchEvent(cc.game._eventHide);
2716         };
2717         var onShow = function () {
2718             if (cc.eventManager && cc.game._eventShow)
2719                 cc.eventManager.dispatchEvent(cc.game._eventShow);
2720         };
2721 
2722         if (hidden) {
2723             document.addEventListener(visibilityChange, function () {
2724                 if (document[hidden]) onHidden();
2725                 else onShow();
2726             }, false);
2727         } else {
2728             win.addEventListener("blur", onHidden, false);
2729             win.addEventListener("focus", onShow, false);
2730         }
2731 
2732         if(navigator.userAgent.indexOf("MicroMessenger") > -1){
2733             win.onfocus = function(){ onShow() };
2734         }
2735 
2736         if ("onpageshow" in window && "onpagehide" in window) {
2737             win.addEventListener("pagehide", onHidden, false);
2738             win.addEventListener("pageshow", onShow, false);
2739         }
2740 
2741         cc.eventManager.addCustomListener(cc.game.EVENT_HIDE, function () {
2742             cc.game.pause();
2743         });
2744         cc.eventManager.addCustomListener(cc.game.EVENT_SHOW, function () {
2745             cc.game.resume();
2746         });
2747     }
2748 };
2749 //+++++++++++++++++++++++++something about CCGame end+++++++++++++++++++++++++++++
2750 
2751 Function.prototype.bind = Function.prototype.bind || function (oThis) {
2752     if (!cc.isFunction(this)) {
2753         // closest thing possible to the ECMAScript 5
2754         // internal IsCallable function
2755         throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
2756     }
2757 
2758     var aArgs = Array.prototype.slice.call(arguments, 1),
2759         fToBind = this,
2760         fNOP = function () {},
2761         fBound = function () {
2762             return fToBind.apply(this instanceof fNOP && oThis
2763                 ? this
2764                 : oThis,
2765                 aArgs.concat(Array.prototype.slice.call(arguments)));
2766         };
2767 
2768     fNOP.prototype = this.prototype;
2769     fBound.prototype = new fNOP();
2770 
2771     return fBound;
2772 };
2773 
2774 cc._urlRegExp = new RegExp(
2775     "^" +
2776         // protocol identifier
2777         "(?:(?:https?|ftp)://)" +
2778         // user:pass authentication
2779         "(?:\\S+(?::\\S*)?@)?" +
2780         "(?:" +
2781             // IP address dotted notation octets
2782             // excludes loopback network 0.0.0.0
2783             // excludes reserved space >= 224.0.0.0
2784             // excludes network & broacast addresses
2785             // (first & last IP address of each class)
2786             "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" +
2787             "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" +
2788             "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" +
2789         "|" +
2790             // host name
2791             "(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)" +
2792             // domain name
2793             "(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*" +
2794             // TLD identifier
2795             "(?:\\.(?:[a-z\\u00a1-\\uffff]{2,}))" +
2796         "|" +
2797             "(?:localhost)" +
2798         ")" +
2799         // port number
2800         "(?::\\d{2,5})?" +
2801         // resource path
2802         "(?:/\\S*)?" +
2803     "$", "i"
2804 );
2805