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