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