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