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