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