mirror of
https://github.com/tiennm99/fbird.git
synced 2026-06-17 14:48:18 +00:00
2900 lines
91 KiB
JavaScript
Vendored
2900 lines
91 KiB
JavaScript
Vendored
/****************************************************************************
|
|
Copyright (c) 2011-2012 cocos2d-x.org
|
|
Copyright (c) 2013-2015 Chukong Technologies Inc.
|
|
|
|
http://www.cocos2d-x.org
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
THE SOFTWARE.
|
|
****************************************************************************/
|
|
|
|
/**
|
|
* The main namespace of Cocos2d-JS, all engine core classes, functions, properties and constants are defined in this namespace
|
|
* @namespace
|
|
* @name cc
|
|
*/
|
|
var cc = cc || {};
|
|
cc._tmp = cc._tmp || {};
|
|
cc._LogInfos = {};
|
|
|
|
var _p = window;
|
|
/** @expose */
|
|
_p.gl;
|
|
/** @expose */
|
|
_p.WebGLRenderingContext;
|
|
/** @expose */
|
|
_p.DeviceOrientationEvent;
|
|
/** @expose */
|
|
_p.DeviceMotionEvent;
|
|
/** @expose */
|
|
_p.AudioContext;
|
|
if (!_p.AudioContext) {
|
|
/** @expose */
|
|
_p.webkitAudioContext;
|
|
}
|
|
/** @expose */
|
|
_p.mozAudioContext;
|
|
_p = Object.prototype;
|
|
/** @expose */
|
|
_p._super;
|
|
/** @expose */
|
|
_p.ctor;
|
|
_p = null;
|
|
|
|
/**
|
|
* drawing primitive of game engine
|
|
* @type {cc.DrawingPrimitive}
|
|
*/
|
|
cc._drawingUtil = null;
|
|
|
|
/**
|
|
* main Canvas 2D/3D Context of game engine
|
|
* @type {CanvasRenderingContext2D|WebGLRenderingContext}
|
|
*/
|
|
cc._renderContext = null;
|
|
cc._supportRender = false;
|
|
|
|
/**
|
|
* Main canvas of game engine
|
|
* @type {HTMLCanvasElement}
|
|
*/
|
|
cc._canvas = null;
|
|
|
|
/**
|
|
* The element contains the game canvas
|
|
* @type {HTMLDivElement}
|
|
*/
|
|
cc.container = null;
|
|
cc._gameDiv = null;
|
|
|
|
window.ENABLE_IMAEG_POOL = true;
|
|
|
|
/**
|
|
* Iterate over an object or an array, executing a function for each matched element.
|
|
* @param {object|array} obj
|
|
* @param {function} iterator
|
|
* @param {object} [context]
|
|
*/
|
|
cc.each = function (obj, iterator, context) {
|
|
if (!obj)
|
|
return;
|
|
if (obj instanceof Array) {
|
|
for (var i = 0, li = obj.length; i < li; i++) {
|
|
if (iterator.call(context, obj[i], i) === false)
|
|
return;
|
|
}
|
|
} else {
|
|
for (var key in obj) {
|
|
if (iterator.call(context, obj[key], key) === false)
|
|
return;
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Copy all of the properties in source objects to target object and return the target object.
|
|
* @param {object} target
|
|
* @param {object} *sources
|
|
* @returns {object}
|
|
*/
|
|
cc.extend = function (target) {
|
|
var sources = arguments.length >= 2 ? Array.prototype.slice.call(arguments, 1) : [];
|
|
|
|
cc.each(sources, function (src) {
|
|
for (var key in src) {
|
|
if (src.hasOwnProperty(key)) {
|
|
target[key] = src[key];
|
|
}
|
|
}
|
|
});
|
|
return target;
|
|
};
|
|
|
|
/**
|
|
* Another way to subclass: Using Google Closure.
|
|
* The following code was copied + pasted from goog.base / goog.inherits
|
|
* @function
|
|
* @param {Function} childCtor
|
|
* @param {Function} parentCtor
|
|
*/
|
|
cc.inherits = function (childCtor, parentCtor) {
|
|
function tempCtor() {}
|
|
tempCtor.prototype = parentCtor.prototype;
|
|
childCtor.superClass_ = parentCtor.prototype;
|
|
childCtor.prototype = new tempCtor();
|
|
childCtor.prototype.constructor = childCtor;
|
|
|
|
// Copy "static" method, but doesn't generate subclasses.
|
|
// for( var i in parentCtor ) {
|
|
// childCtor[ i ] = parentCtor[ i ];
|
|
// }
|
|
};
|
|
|
|
/**
|
|
* Check the obj whether is function or not
|
|
* @param {*} obj
|
|
* @returns {boolean}
|
|
*/
|
|
cc.isFunction = function (obj) {
|
|
return typeof obj === 'function';
|
|
};
|
|
|
|
/**
|
|
* Check the obj whether is number or not
|
|
* @param {*} obj
|
|
* @returns {boolean}
|
|
*/
|
|
cc.isNumber = function (obj) {
|
|
return typeof obj === 'number' || Object.prototype.toString.call(obj) === '[object Number]';
|
|
};
|
|
|
|
/**
|
|
* Check the obj whether is string or not
|
|
* @param {*} obj
|
|
* @returns {boolean}
|
|
*/
|
|
cc.isString = function (obj) {
|
|
return typeof obj === 'string' || Object.prototype.toString.call(obj) === '[object String]';
|
|
};
|
|
|
|
/**
|
|
* Check the obj whether is array or not
|
|
* @param {*} obj
|
|
* @returns {boolean}
|
|
*/
|
|
cc.isArray = function (obj) {
|
|
return Array.isArray(obj) ||
|
|
(typeof obj === 'object' && Object.prototype.toString.call(obj) === '[object Array]');
|
|
};
|
|
|
|
/**
|
|
* Check the obj whether is undefined or not
|
|
* @param {*} obj
|
|
* @returns {boolean}
|
|
*/
|
|
cc.isUndefined = function (obj) {
|
|
return typeof obj === 'undefined';
|
|
};
|
|
|
|
/**
|
|
* Check the obj whether is object or not
|
|
* @param {*} obj
|
|
* @returns {boolean}
|
|
*/
|
|
cc.isObject = function (obj) {
|
|
return typeof obj === "object" && Object.prototype.toString.call(obj) === '[object Object]';
|
|
};
|
|
|
|
/**
|
|
* Check the url whether cross origin
|
|
* @param {String} url
|
|
* @returns {boolean}
|
|
*/
|
|
cc.isCrossOrigin = function (url) {
|
|
if (!url) {
|
|
cc.log("invalid URL");
|
|
return false;
|
|
}
|
|
var startIndex = url.indexOf("://");
|
|
if (startIndex === -1)
|
|
return false;
|
|
|
|
var endIndex = url.indexOf("/", startIndex + 3);
|
|
var urlOrigin = (endIndex === -1) ? url : url.substring(0, endIndex);
|
|
return urlOrigin !== location.origin;
|
|
};
|
|
|
|
//+++++++++++++++++++++++++something about async begin+++++++++++++++++++++++++++++++
|
|
/**
|
|
* Async Pool class, a helper of cc.async
|
|
* @param {Object|Array} srcObj
|
|
* @param {Number} limit the limit of parallel number
|
|
* @param {function} iterator
|
|
* @param {function} onEnd
|
|
* @param {object} target
|
|
* @constructor
|
|
*/
|
|
cc.AsyncPool = function (srcObj, limit, iterator, onEnd, target) {
|
|
var self = this;
|
|
self._finished = false;
|
|
self._srcObj = srcObj;
|
|
self._limit = limit;
|
|
self._pool = [];
|
|
self._iterator = iterator;
|
|
self._iteratorTarget = target;
|
|
self._onEnd = onEnd;
|
|
self._onEndTarget = target;
|
|
self._results = srcObj instanceof Array ? [] : {};
|
|
self._errors = srcObj instanceof Array ? [] : {};
|
|
|
|
cc.each(srcObj, function (value, index) {
|
|
self._pool.push({index: index, value: value});
|
|
});
|
|
|
|
self.size = self._pool.length;
|
|
self.finishedSize = 0;
|
|
self._workingSize = 0;
|
|
|
|
self._limit = self._limit || self.size;
|
|
|
|
self.onIterator = function (iterator, target) {
|
|
self._iterator = iterator;
|
|
self._iteratorTarget = target;
|
|
};
|
|
|
|
self.onEnd = function (endCb, endCbTarget) {
|
|
self._onEnd = endCb;
|
|
self._onEndTarget = endCbTarget;
|
|
};
|
|
|
|
self._handleItem = function () {
|
|
var self = this;
|
|
if (self._pool.length === 0 || self._workingSize >= self._limit)
|
|
return; //return directly if the array's length = 0 or the working size great equal limit number
|
|
|
|
var item = self._pool.shift();
|
|
var value = item.value, index = item.index;
|
|
self._workingSize++;
|
|
self._iterator.call(self._iteratorTarget, value, index,
|
|
function (err, result) {
|
|
if (self._finished) {
|
|
return;
|
|
}
|
|
|
|
if (err) {
|
|
self._errors[this.index] = err;
|
|
}
|
|
else {
|
|
self._results[this.index] = result;
|
|
}
|
|
|
|
self.finishedSize++;
|
|
self._workingSize--;
|
|
if (self.finishedSize === self.size) {
|
|
var errors = self._errors.length === 0 ? null : self._errors;
|
|
self.onEnd(errors, self._results);
|
|
return;
|
|
}
|
|
self._handleItem();
|
|
}.bind(item),
|
|
self);
|
|
};
|
|
|
|
self.flow = function () {
|
|
var self = this;
|
|
if (self._pool.length === 0) {
|
|
if (self._onEnd)
|
|
self._onEnd.call(self._onEndTarget, null, []);
|
|
return;
|
|
}
|
|
for (var i = 0; i < self._limit; i++)
|
|
self._handleItem();
|
|
};
|
|
|
|
self.onEnd = function(errors, results) {
|
|
self._finished = true;
|
|
if (self._onEnd) {
|
|
var selector = self._onEnd;
|
|
var target = self._onEndTarget;
|
|
self._onEnd = null;
|
|
self._onEndTarget = null;
|
|
selector.call(target, errors, results);
|
|
}
|
|
};
|
|
};
|
|
|
|
/**
|
|
* @class
|
|
*/
|
|
cc.async = /** @lends cc.async# */{
|
|
/**
|
|
* Do tasks series.
|
|
* @param {Array|Object} tasks
|
|
* @param {function} [cb] callback
|
|
* @param {Object} [target]
|
|
* @return {cc.AsyncPool}
|
|
*/
|
|
series: function (tasks, cb, target) {
|
|
var asyncPool = new cc.AsyncPool(tasks, 1, function (func, index, cb1) {
|
|
func.call(target, cb1);
|
|
}, cb, target);
|
|
asyncPool.flow();
|
|
return asyncPool;
|
|
},
|
|
|
|
/**
|
|
* Do tasks parallel.
|
|
* @param {Array|Object} tasks
|
|
* @param {function} cb callback
|
|
* @param {Object} [target]
|
|
* @return {cc.AsyncPool}
|
|
*/
|
|
parallel: function (tasks, cb, target) {
|
|
var asyncPool = new cc.AsyncPool(tasks, 0, function (func, index, cb1) {
|
|
func.call(target, cb1);
|
|
}, cb, target);
|
|
asyncPool.flow();
|
|
return asyncPool;
|
|
},
|
|
|
|
/**
|
|
* Do tasks waterfall.
|
|
* @param {Array|Object} tasks
|
|
* @param {function} cb callback
|
|
* @param {Object} [target]
|
|
* @return {cc.AsyncPool}
|
|
*/
|
|
waterfall: function (tasks, cb, target) {
|
|
var args = [];
|
|
var lastResults = [null];//the array to store the last results
|
|
var asyncPool = new cc.AsyncPool(tasks, 1,
|
|
function (func, index, cb1) {
|
|
args.push(function (err) {
|
|
args = Array.prototype.slice.call(arguments, 1);
|
|
if (tasks.length - 1 === index) lastResults = lastResults.concat(args);//while the last task
|
|
cb1.apply(null, arguments);
|
|
});
|
|
func.apply(target, args);
|
|
}, function (err) {
|
|
if (!cb)
|
|
return;
|
|
if (err)
|
|
return cb.call(target, err);
|
|
cb.apply(target, lastResults);
|
|
});
|
|
asyncPool.flow();
|
|
return asyncPool;
|
|
},
|
|
|
|
/**
|
|
* Do tasks by iterator.
|
|
* @param {Array|Object} tasks
|
|
* @param {function|Object} iterator
|
|
* @param {function} [callback]
|
|
* @param {Object} [target]
|
|
* @return {cc.AsyncPool}
|
|
*/
|
|
map: function (tasks, iterator, callback, target) {
|
|
var locIterator = iterator;
|
|
if (typeof(iterator) === "object") {
|
|
callback = iterator.cb;
|
|
target = iterator.iteratorTarget;
|
|
locIterator = iterator.iterator;
|
|
}
|
|
var asyncPool = new cc.AsyncPool(tasks, 0, locIterator, callback, target);
|
|
asyncPool.flow();
|
|
return asyncPool;
|
|
},
|
|
|
|
/**
|
|
* Do tasks by iterator limit.
|
|
* @param {Array|Object} tasks
|
|
* @param {Number} limit
|
|
* @param {function} iterator
|
|
* @param {function} cb callback
|
|
* @param {Object} [target]
|
|
*/
|
|
mapLimit: function (tasks, limit, iterator, cb, target) {
|
|
var asyncPool = new cc.AsyncPool(tasks, limit, iterator, cb, target);
|
|
asyncPool.flow();
|
|
return asyncPool;
|
|
}
|
|
};
|
|
//+++++++++++++++++++++++++something about async end+++++++++++++++++++++++++++++++++
|
|
|
|
//+++++++++++++++++++++++++something about path begin++++++++++++++++++++++++++++++++
|
|
/**
|
|
* @class
|
|
*/
|
|
cc.path = /** @lends cc.path# */{
|
|
normalizeRE: /[^\.\/]+\/\.\.\//,
|
|
|
|
/**
|
|
* Join strings to be a path.
|
|
* @example
|
|
cc.path.join("a", "b.png");//-->"a/b.png"
|
|
cc.path.join("a", "b", "c.png");//-->"a/b/c.png"
|
|
cc.path.join("a", "b");//-->"a/b"
|
|
cc.path.join("a", "b", "/");//-->"a/b/"
|
|
cc.path.join("a", "b/", "/");//-->"a/b/"
|
|
* @returns {string}
|
|
*/
|
|
join: function () {
|
|
var l = arguments.length;
|
|
var result = "";
|
|
for (var i = 0; i < l; i++) {
|
|
result = (result + (result === "" ? "" : "/") + arguments[i]).replace(/(\/|\\\\)$/, "");
|
|
}
|
|
return result;
|
|
},
|
|
|
|
/**
|
|
* Get the ext name of a path.
|
|
* @example
|
|
cc.path.extname("a/b.png");//-->".png"
|
|
cc.path.extname("a/b.png?a=1&b=2");//-->".png"
|
|
cc.path.extname("a/b");//-->null
|
|
cc.path.extname("a/b?a=1&b=2");//-->null
|
|
* @param {string} pathStr
|
|
* @returns {*}
|
|
*/
|
|
extname: function (pathStr) {
|
|
var temp = /(\.[^\.\/\?\\]*)(\?.*)?$/.exec(pathStr);
|
|
return temp ? temp[1] : null;
|
|
},
|
|
|
|
/**
|
|
* Get the main name of a file name
|
|
* @param {string} fileName
|
|
* @returns {string}
|
|
*/
|
|
mainFileName: function (fileName) {
|
|
if (fileName) {
|
|
var idx = fileName.lastIndexOf(".");
|
|
if (idx !== -1)
|
|
return fileName.substring(0, idx);
|
|
}
|
|
return fileName;
|
|
},
|
|
|
|
/**
|
|
* Get the file name of a file path.
|
|
* @example
|
|
cc.path.basename("a/b.png");//-->"b.png"
|
|
cc.path.basename("a/b.png?a=1&b=2");//-->"b.png"
|
|
cc.path.basename("a/b.png", ".png");//-->"b"
|
|
cc.path.basename("a/b.png?a=1&b=2", ".png");//-->"b"
|
|
cc.path.basename("a/b.png", ".txt");//-->"b.png"
|
|
* @param {string} pathStr
|
|
* @param {string} [extname]
|
|
* @returns {*}
|
|
*/
|
|
basename: function (pathStr, extname) {
|
|
var index = pathStr.indexOf("?");
|
|
if (index > 0) pathStr = pathStr.substring(0, index);
|
|
var reg = /(\/|\\\\)([^(\/|\\\\)]+)$/g;
|
|
var result = reg.exec(pathStr.replace(/(\/|\\\\)$/, ""));
|
|
if (!result) return null;
|
|
var baseName = result[2];
|
|
if (extname && pathStr.substring(pathStr.length - extname.length).toLowerCase() === extname.toLowerCase())
|
|
return baseName.substring(0, baseName.length - extname.length);
|
|
return baseName;
|
|
},
|
|
|
|
/**
|
|
* Get dirname of a file path.
|
|
* @example
|
|
* unix
|
|
cc.path.driname("a/b/c.png");//-->"a/b"
|
|
cc.path.driname("a/b/c.png?a=1&b=2");//-->"a/b"
|
|
cc.path.dirname("a/b/");//-->"a/b"
|
|
cc.path.dirname("c.png");//-->""
|
|
* windows
|
|
cc.path.driname("a\\b\\c.png");//-->"a\b"
|
|
cc.path.driname("a\\b\\c.png?a=1&b=2");//-->"a\b"
|
|
* @param {string} pathStr
|
|
* @returns {*}
|
|
*/
|
|
dirname: function (pathStr) {
|
|
return pathStr.replace(/((.*)(\/|\\|\\\\))?(.*?\..*$)?/, '$2');
|
|
},
|
|
|
|
/**
|
|
* Change extname of a file path.
|
|
* @example
|
|
cc.path.changeExtname("a/b.png", ".plist");//-->"a/b.plist"
|
|
cc.path.changeExtname("a/b.png?a=1&b=2", ".plist");//-->"a/b.plist?a=1&b=2"
|
|
* @param {string} pathStr
|
|
* @param {string} [extname]
|
|
* @returns {string}
|
|
*/
|
|
changeExtname: function (pathStr, extname) {
|
|
extname = extname || "";
|
|
var index = pathStr.indexOf("?");
|
|
var tempStr = "";
|
|
if (index > 0) {
|
|
tempStr = pathStr.substring(index);
|
|
pathStr = pathStr.substring(0, index);
|
|
}
|
|
index = pathStr.lastIndexOf(".");
|
|
if (index < 0) return pathStr + extname + tempStr;
|
|
return pathStr.substring(0, index) + extname + tempStr;
|
|
},
|
|
/**
|
|
* Change file name of a file path.
|
|
* @example
|
|
cc.path.changeBasename("a/b/c.plist", "b.plist");//-->"a/b/b.plist"
|
|
cc.path.changeBasename("a/b/c.plist?a=1&b=2", "b.plist");//-->"a/b/b.plist?a=1&b=2"
|
|
cc.path.changeBasename("a/b/c.plist", ".png");//-->"a/b/c.png"
|
|
cc.path.changeBasename("a/b/c.plist", "b");//-->"a/b/b"
|
|
cc.path.changeBasename("a/b/c.plist", "b", true);//-->"a/b/b.plist"
|
|
* @param {String} pathStr
|
|
* @param {String} basename
|
|
* @param {Boolean} [isSameExt]
|
|
* @returns {string}
|
|
*/
|
|
changeBasename: function (pathStr, basename, isSameExt) {
|
|
if (basename.indexOf(".") === 0) return this.changeExtname(pathStr, basename);
|
|
var index = pathStr.indexOf("?");
|
|
var tempStr = "";
|
|
var ext = isSameExt ? this.extname(pathStr) : "";
|
|
if (index > 0) {
|
|
tempStr = pathStr.substring(index);
|
|
pathStr = pathStr.substring(0, index);
|
|
}
|
|
index = pathStr.lastIndexOf("/");
|
|
index = index <= 0 ? 0 : index + 1;
|
|
return pathStr.substring(0, index) + basename + ext + tempStr;
|
|
},
|
|
//todo make public after verification
|
|
_normalize: function (url) {
|
|
var oldUrl = url = String(url);
|
|
|
|
//removing all ../
|
|
do {
|
|
oldUrl = url;
|
|
url = url.replace(this.normalizeRE, "");
|
|
} while (oldUrl.length !== url.length);
|
|
return url;
|
|
}
|
|
};
|
|
//+++++++++++++++++++++++++something about path end++++++++++++++++++++++++++++++++
|
|
|
|
//+++++++++++++++++++++++++something about loader start+++++++++++++++++++++++++++
|
|
/**
|
|
* Resource loading management. Created by in CCBoot.js as a singleton
|
|
* cc.loader.
|
|
* @name cc.Loader
|
|
* @class
|
|
* @memberof cc
|
|
* @see cc.loader
|
|
*/
|
|
|
|
var imagePool = {
|
|
_pool: new Array(10),
|
|
_MAX: 10,
|
|
_smallImg: "data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=",
|
|
|
|
count: 0,
|
|
get: function () {
|
|
if (this.count > 0) {
|
|
this.count--;
|
|
var result = this._pool[this.count];
|
|
this._pool[this.count] = null;
|
|
return result;
|
|
}
|
|
else {
|
|
return new Image();
|
|
}
|
|
},
|
|
put: function (img) {
|
|
var pool = this._pool;
|
|
if (img instanceof HTMLImageElement && this.count < this._MAX) {
|
|
img.src = this._smallImg;
|
|
pool[this.count] = img;
|
|
this.count++;
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Singleton instance of cc.Loader.
|
|
* @name cc.loader
|
|
* @member {cc.Loader}
|
|
* @memberof cc
|
|
*/
|
|
cc.loader = (function () {
|
|
var _jsCache = {}, //cache for js
|
|
_register = {}, //register of loaders
|
|
_langPathCache = {}, //cache for lang path
|
|
_aliases = {}, //aliases for res url
|
|
_queue = {}, // Callback queue for resources already loading
|
|
_urlRegExp = new RegExp("^(?:https?|ftp)://\\S*$", "i");
|
|
|
|
return /** @lends cc.Loader# */{
|
|
/**
|
|
* Root path of resources.
|
|
* @type {String}
|
|
*/
|
|
resPath: "",
|
|
|
|
/**
|
|
* Root path of audio resources
|
|
* @type {String}
|
|
*/
|
|
audioPath: "",
|
|
|
|
/**
|
|
* Cache for data loaded.
|
|
* @type {Object}
|
|
*/
|
|
cache: {},
|
|
|
|
/**
|
|
* Get XMLHttpRequest.
|
|
* @returns {XMLHttpRequest}
|
|
*/
|
|
getXMLHttpRequest: function () {
|
|
var xhr = window.XMLHttpRequest ? new window.XMLHttpRequest() : new ActiveXObject("MSXML2.XMLHTTP");
|
|
xhr.timeout = 10000;
|
|
if (xhr.ontimeout === undefined) {
|
|
xhr._timeoutId = -1;
|
|
}
|
|
return xhr;
|
|
},
|
|
|
|
//@MODE_BEGIN DEV
|
|
|
|
_getArgs4Js: function (args) {
|
|
var a0 = args[0], a1 = args[1], a2 = args[2], results = ["", null, null];
|
|
|
|
if (args.length === 1) {
|
|
results[1] = a0 instanceof Array ? a0 : [a0];
|
|
} else if (args.length === 2) {
|
|
if (typeof a1 === "function") {
|
|
results[1] = a0 instanceof Array ? a0 : [a0];
|
|
results[2] = a1;
|
|
} else {
|
|
results[0] = a0 || "";
|
|
results[1] = a1 instanceof Array ? a1 : [a1];
|
|
}
|
|
} else if (args.length === 3) {
|
|
results[0] = a0 || "";
|
|
results[1] = a1 instanceof Array ? a1 : [a1];
|
|
results[2] = a2;
|
|
} else throw new Error("arguments error to load js!");
|
|
return results;
|
|
},
|
|
|
|
isLoading: function (url) {
|
|
return (_queue[url] !== undefined);
|
|
},
|
|
|
|
/**
|
|
* Load js files.
|
|
* If the third parameter doesn't exist, then the baseDir turns to be "".
|
|
*
|
|
* @param {string} [baseDir] The pre path for jsList or the list of js path.
|
|
* @param {array} jsList List of js path.
|
|
* @param {function} [cb] Callback function
|
|
* @returns {*}
|
|
*/
|
|
loadJs: function (baseDir, jsList, cb) {
|
|
var self = this,
|
|
args = self._getArgs4Js(arguments);
|
|
|
|
var preDir = args[0], list = args[1], callback = args[2];
|
|
if (navigator.userAgent.indexOf("Trident/5") > -1) {
|
|
self._loadJs4Dependency(preDir, list, 0, callback);
|
|
} else {
|
|
cc.async.map(list, function (item, index, cb1) {
|
|
var jsPath = cc.path.join(preDir, item);
|
|
if (_jsCache[jsPath]) return cb1(null);
|
|
self._createScript(jsPath, false, cb1);
|
|
}, callback);
|
|
}
|
|
},
|
|
/**
|
|
* Load js width loading image.
|
|
*
|
|
* @param {string} [baseDir]
|
|
* @param {array} jsList
|
|
* @param {function} [cb]
|
|
*/
|
|
loadJsWithImg: function (baseDir, jsList, cb) {
|
|
var self = this, jsLoadingImg = self._loadJsImg(),
|
|
args = self._getArgs4Js(arguments);
|
|
this.loadJs(args[0], args[1], function (err) {
|
|
if (err) throw new Error(err);
|
|
jsLoadingImg.parentNode.removeChild(jsLoadingImg);//remove loading gif
|
|
if (args[2]) args[2]();
|
|
});
|
|
},
|
|
_createScript: function (jsPath, isAsync, cb) {
|
|
var d = document, self = this, s = document.createElement('script');
|
|
s.async = isAsync;
|
|
_jsCache[jsPath] = true;
|
|
if (cc.game.config["noCache"] && typeof jsPath === "string") {
|
|
if (self._noCacheRex.test(jsPath))
|
|
s.src = jsPath + "&_t=" + (new Date() - 0);
|
|
else
|
|
s.src = jsPath + "?_t=" + (new Date() - 0);
|
|
} else {
|
|
s.src = jsPath;
|
|
}
|
|
s.addEventListener('load', function () {
|
|
s.parentNode.removeChild(s);
|
|
this.removeEventListener('load', arguments.callee, false);
|
|
cb();
|
|
}, false);
|
|
s.addEventListener('error', function () {
|
|
s.parentNode.removeChild(s);
|
|
cb("Load " + jsPath + " failed!");
|
|
}, false);
|
|
d.body.appendChild(s);
|
|
},
|
|
_loadJs4Dependency: function (baseDir, jsList, index, cb) {
|
|
if (index >= jsList.length) {
|
|
if (cb) cb();
|
|
return;
|
|
}
|
|
var self = this;
|
|
self._createScript(cc.path.join(baseDir, jsList[index]), false, function (err) {
|
|
if (err) return cb(err);
|
|
self._loadJs4Dependency(baseDir, jsList, index + 1, cb);
|
|
});
|
|
},
|
|
_loadJsImg: function () {
|
|
var d = document, jsLoadingImg = d.getElementById("cocos2d_loadJsImg");
|
|
if (!jsLoadingImg) {
|
|
jsLoadingImg = document.createElement('img');
|
|
|
|
if (cc._loadingImage)
|
|
jsLoadingImg.src = cc._loadingImage;
|
|
|
|
var canvasNode = d.getElementById(cc.game.config["id"]);
|
|
canvasNode.style.backgroundColor = "transparent";
|
|
canvasNode.parentNode.appendChild(jsLoadingImg);
|
|
|
|
var canvasStyle = getComputedStyle ? getComputedStyle(canvasNode) : canvasNode.currentStyle;
|
|
if (!canvasStyle)
|
|
canvasStyle = {width: canvasNode.width, height: canvasNode.height};
|
|
jsLoadingImg.style.left = canvasNode.offsetLeft + (parseFloat(canvasStyle.width) - jsLoadingImg.width) / 2 + "px";
|
|
jsLoadingImg.style.top = canvasNode.offsetTop + (parseFloat(canvasStyle.height) - jsLoadingImg.height) / 2 + "px";
|
|
jsLoadingImg.style.position = "absolute";
|
|
}
|
|
return jsLoadingImg;
|
|
},
|
|
//@MODE_END DEV
|
|
|
|
/**
|
|
* Load a single resource as txt.
|
|
* @param {string} url
|
|
* @param {function} [cb] arguments are : err, txt
|
|
*/
|
|
loadTxt: function (url, cb) {
|
|
if (!cc._isNodeJs) {
|
|
var xhr = this.getXMLHttpRequest(),
|
|
errInfo = "load " + url + " failed!";
|
|
xhr.open("GET", url, true);
|
|
if (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) {
|
|
// IE-specific logic here
|
|
xhr.setRequestHeader("Accept-Charset", "utf-8");
|
|
xhr.onreadystatechange = function () {
|
|
if (xhr.readyState === 4)
|
|
(xhr.status === 200||xhr.status === 0) ? cb(null, xhr.responseText) : cb({status:xhr.status, errorMessage:errInfo}, null);
|
|
};
|
|
} else {
|
|
if (xhr.overrideMimeType) xhr.overrideMimeType("text\/plain; charset=utf-8");
|
|
var loadCallback = function () {
|
|
xhr.removeEventListener('load', loadCallback);
|
|
xhr.removeEventListener('error', errorCallback);
|
|
if (xhr._timeoutId >= 0) {
|
|
clearTimeout(xhr._timeoutId);
|
|
}
|
|
else {
|
|
xhr.removeEventListener('timeout', timeoutCallback);
|
|
}
|
|
if (xhr.readyState === 4) {
|
|
(xhr.status === 200||xhr.status === 0) ? cb(null, xhr.responseText) : cb({status:xhr.status, errorMessage:errInfo}, null);
|
|
}
|
|
};
|
|
var errorCallback = function () {
|
|
xhr.removeEventListener('load', loadCallback);
|
|
xhr.removeEventListener('error', errorCallback);
|
|
if (xhr._timeoutId >= 0) {
|
|
clearTimeout(xhr._timeoutId);
|
|
}
|
|
else {
|
|
xhr.removeEventListener('timeout', timeoutCallback);
|
|
}
|
|
cb({status: xhr.status, errorMessage: errInfo}, null);
|
|
};
|
|
var timeoutCallback = function () {
|
|
xhr.removeEventListener('load', loadCallback);
|
|
xhr.removeEventListener('error', errorCallback);
|
|
if (xhr._timeoutId >= 0) {
|
|
clearTimeout(xhr._timeoutId);
|
|
}
|
|
else {
|
|
xhr.removeEventListener('timeout', timeoutCallback);
|
|
}
|
|
cb({status: xhr.status, errorMessage: "Request timeout: " + errInfo}, null);
|
|
};
|
|
xhr.addEventListener('load', loadCallback);
|
|
xhr.addEventListener('error', errorCallback);
|
|
if (xhr.ontimeout === undefined) {
|
|
xhr._timeoutId = setTimeout(function () {
|
|
timeoutCallback();
|
|
}, xhr.timeout);
|
|
}
|
|
else {
|
|
xhr.addEventListener('timeout', timeoutCallback);
|
|
}
|
|
}
|
|
xhr.send(null);
|
|
} else {
|
|
var fs = require("fs");
|
|
fs.readFile(url, function (err, data) {
|
|
err ? cb(err) : cb(null, data.toString());
|
|
});
|
|
}
|
|
},
|
|
|
|
loadCsb: function(url, cb){
|
|
var xhr = cc.loader.getXMLHttpRequest(),
|
|
errInfo = "load " + url + " failed!";
|
|
xhr.open("GET", url, true);
|
|
xhr.responseType = "arraybuffer";
|
|
|
|
var loadCallback = function () {
|
|
xhr.removeEventListener('load', loadCallback);
|
|
xhr.removeEventListener('error', errorCallback);
|
|
if (xhr._timeoutId >= 0) {
|
|
clearTimeout(xhr._timeoutId);
|
|
}
|
|
else {
|
|
xhr.removeEventListener('timeout', timeoutCallback);
|
|
}
|
|
var arrayBuffer = xhr.response; // Note: not oReq.responseText
|
|
if (arrayBuffer) {
|
|
window.msg = arrayBuffer;
|
|
}
|
|
if (xhr.readyState === 4) {
|
|
(xhr.status === 200||xhr.status === 0) ? cb(null, xhr.response) : cb({status:xhr.status, errorMessage:errInfo}, null);
|
|
}
|
|
};
|
|
var errorCallback = function(){
|
|
xhr.removeEventListener('load', loadCallback);
|
|
xhr.removeEventListener('error', errorCallback);
|
|
if (xhr._timeoutId >= 0) {
|
|
clearTimeout(xhr._timeoutId);
|
|
}
|
|
else {
|
|
xhr.removeEventListener('timeout', timeoutCallback);
|
|
}
|
|
cb({status:xhr.status, errorMessage:errInfo}, null);
|
|
};
|
|
var timeoutCallback = function () {
|
|
xhr.removeEventListener('load', loadCallback);
|
|
xhr.removeEventListener('error', errorCallback);
|
|
if (xhr._timeoutId >= 0) {
|
|
clearTimeout(xhr._timeoutId);
|
|
}
|
|
else {
|
|
xhr.removeEventListener('timeout', timeoutCallback);
|
|
}
|
|
cb({status: xhr.status, errorMessage: "Request timeout: " + errInfo}, null);
|
|
};
|
|
xhr.addEventListener('load', loadCallback);
|
|
xhr.addEventListener('error', errorCallback);
|
|
if (xhr.ontimeout === undefined) {
|
|
xhr._timeoutId = setTimeout(function () {
|
|
timeoutCallback();
|
|
}, xhr.timeout);
|
|
}
|
|
else {
|
|
xhr.addEventListener('timeout', timeoutCallback);
|
|
}
|
|
xhr.send(null);
|
|
},
|
|
|
|
/**
|
|
* Load a single resource as json.
|
|
* @param {string} url
|
|
* @param {function} [cb] arguments are : err, json
|
|
*/
|
|
loadJson: function (url, cb) {
|
|
this.loadTxt(url, function (err, txt) {
|
|
if (err) {
|
|
cb(err);
|
|
}
|
|
else {
|
|
try {
|
|
var result = JSON.parse(txt);
|
|
}
|
|
catch (e) {
|
|
throw new Error("parse json [" + url + "] failed : " + e);
|
|
return;
|
|
}
|
|
cb(null, result);
|
|
}
|
|
});
|
|
},
|
|
|
|
_checkIsImageURL: function (url) {
|
|
var ext = /(\.png)|(\.jpg)|(\.bmp)|(\.jpeg)|(\.gif)/.exec(url);
|
|
return (ext != null);
|
|
},
|
|
/**
|
|
* Load a single image.
|
|
* @param {!string} url
|
|
* @param {object} [option]
|
|
* @param {function} callback
|
|
* @returns {Image}
|
|
*/
|
|
loadImg: function (url, option, callback, img) {
|
|
var opt = {
|
|
isCrossOrigin: true
|
|
};
|
|
if (callback !== undefined)
|
|
opt.isCrossOrigin = option.isCrossOrigin === undefined ? opt.isCrossOrigin : option.isCrossOrigin;
|
|
else if (option !== undefined)
|
|
callback = option;
|
|
|
|
var texture = this.getRes(url);
|
|
if (texture) {
|
|
callback && callback(null, texture);
|
|
return null;
|
|
}
|
|
|
|
var queue = _queue[url];
|
|
if (queue) {
|
|
queue.callbacks.push(callback);
|
|
return queue.img;
|
|
}
|
|
|
|
img = img || imagePool.get();
|
|
if (opt.isCrossOrigin && location.origin !== "file://")
|
|
img.crossOrigin = "Anonymous";
|
|
else
|
|
img.crossOrigin = null;
|
|
|
|
var loadCallback = function () {
|
|
this.removeEventListener('load', loadCallback, false);
|
|
this.removeEventListener('error', errorCallback, false);
|
|
|
|
var queue = _queue[url];
|
|
if (queue) {
|
|
var callbacks = queue.callbacks;
|
|
for (var i = 0; i < callbacks.length; ++i) {
|
|
var cb = callbacks[i];
|
|
if (cb) {
|
|
cb(null, img);
|
|
}
|
|
}
|
|
queue.img = null;
|
|
delete _queue[url];
|
|
}
|
|
|
|
if (window.ENABLE_IMAEG_POOL && cc._renderType === cc.game.RENDER_TYPE_WEBGL) {
|
|
imagePool.put(img);
|
|
}
|
|
};
|
|
|
|
var self = this;
|
|
var errorCallback = function () {
|
|
this.removeEventListener('load', loadCallback, false);
|
|
this.removeEventListener('error', errorCallback, false);
|
|
|
|
if (window.location.protocol !== 'https:' && img.crossOrigin && img.crossOrigin.toLowerCase() === "anonymous") {
|
|
opt.isCrossOrigin = false;
|
|
self.release(url);
|
|
cc.loader.loadImg(url, opt, callback, img);
|
|
} else {
|
|
var queue = _queue[url];
|
|
if (queue) {
|
|
var callbacks = queue.callbacks;
|
|
for (var i = 0; i < callbacks.length; ++i) {
|
|
var cb = callbacks[i];
|
|
if (cb) {
|
|
cb("load image failed");
|
|
}
|
|
}
|
|
queue.img = null;
|
|
delete _queue[url];
|
|
}
|
|
|
|
if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) {
|
|
imagePool.put(img);
|
|
}
|
|
}
|
|
};
|
|
|
|
_queue[url] = {
|
|
img: img,
|
|
callbacks: callback ? [callback] : []
|
|
};
|
|
|
|
img.addEventListener("load", loadCallback);
|
|
img.addEventListener("error", errorCallback);
|
|
img.src = url;
|
|
return img;
|
|
},
|
|
|
|
/**
|
|
* Iterator function to load res
|
|
* @param {object} item
|
|
* @param {number} index
|
|
* @param {function} [cb]
|
|
* @returns {*}
|
|
* @private
|
|
*/
|
|
_loadResIterator: function (item, index, cb) {
|
|
var self = this, url = null;
|
|
var type = item.type;
|
|
if (type) {
|
|
type = "." + type.toLowerCase();
|
|
url = item.src ? item.src : item.name + type;
|
|
} else {
|
|
url = item;
|
|
type = cc.path.extname(url);
|
|
}
|
|
|
|
var obj = self.getRes(url);
|
|
if (obj)
|
|
return cb(null, obj);
|
|
var loader = null;
|
|
if (type) {
|
|
loader = _register[type.toLowerCase()];
|
|
}
|
|
if (!loader) {
|
|
cc.error("loader for [" + type + "] doesn't exist!");
|
|
return cb();
|
|
}
|
|
var realUrl = url;
|
|
if (!_urlRegExp.test(url)) {
|
|
var basePath = loader.getBasePath ? loader.getBasePath() : self.resPath;
|
|
realUrl = self.getUrl(basePath, url);
|
|
}
|
|
|
|
if (cc.game.config["noCache"] && typeof realUrl === "string") {
|
|
if (self._noCacheRex.test(realUrl))
|
|
realUrl += "&_t=" + (new Date() - 0);
|
|
else
|
|
realUrl += "?_t=" + (new Date() - 0);
|
|
}
|
|
loader.load(realUrl, url, item, function (err, data) {
|
|
if (err) {
|
|
cc.log(err);
|
|
self.cache[url] = null;
|
|
delete self.cache[url];
|
|
cb({status: 520, errorMessage: err}, null);
|
|
} else {
|
|
self.cache[url] = data;
|
|
cb(null, data);
|
|
}
|
|
});
|
|
},
|
|
_noCacheRex: /\?/,
|
|
|
|
/**
|
|
* Get url with basePath.
|
|
* @param {string} basePath
|
|
* @param {string} [url]
|
|
* @returns {*}
|
|
*/
|
|
getUrl: function (basePath, url) {
|
|
var self = this, path = cc.path;
|
|
if (basePath !== undefined && url === undefined) {
|
|
url = basePath;
|
|
var type = path.extname(url);
|
|
type = type ? type.toLowerCase() : "";
|
|
var loader = _register[type];
|
|
if (!loader)
|
|
basePath = self.resPath;
|
|
else
|
|
basePath = loader.getBasePath ? loader.getBasePath() : self.resPath;
|
|
}
|
|
url = cc.path.join(basePath || "", url);
|
|
if (url.match(/[\/(\\\\)]lang[\/(\\\\)]/i)) {
|
|
if (_langPathCache[url])
|
|
return _langPathCache[url];
|
|
var extname = path.extname(url) || "";
|
|
url = _langPathCache[url] = url.substring(0, url.length - extname.length) + "_" + cc.sys.language + extname;
|
|
}
|
|
return url;
|
|
},
|
|
|
|
/**
|
|
* Load resources then call the callback.
|
|
* @param {string} resources
|
|
* @param {function} [option] callback or trigger
|
|
* @param {function|Object} [loadCallback]
|
|
* @return {cc.AsyncPool}
|
|
*/
|
|
load: function (resources, option, loadCallback) {
|
|
var self = this;
|
|
var len = arguments.length;
|
|
if (len === 0)
|
|
throw new Error("arguments error!");
|
|
|
|
if (len === 3) {
|
|
if (typeof option === "function") {
|
|
if (typeof loadCallback === "function")
|
|
option = {trigger: option, cb: loadCallback};
|
|
else
|
|
option = {cb: option, cbTarget: loadCallback};
|
|
}
|
|
} else if (len === 2) {
|
|
if (typeof option === "function")
|
|
option = {cb: option};
|
|
} else if (len === 1) {
|
|
option = {};
|
|
}
|
|
|
|
if (!(resources instanceof Array))
|
|
resources = [resources];
|
|
var asyncPool = new cc.AsyncPool(
|
|
resources, cc.CONCURRENCY_HTTP_REQUEST_COUNT,
|
|
function (value, index, AsyncPoolCallback, aPool) {
|
|
self._loadResIterator(value, index, function (err) {
|
|
var arr = Array.prototype.slice.call(arguments, 1);
|
|
if (option.trigger)
|
|
option.trigger.call(option.triggerTarget, arr[0], aPool.size, aPool.finishedSize); //call trigger
|
|
AsyncPoolCallback(err, arr[0]);
|
|
});
|
|
},
|
|
option.cb, option.cbTarget);
|
|
asyncPool.flow();
|
|
return asyncPool;
|
|
},
|
|
|
|
_handleAliases: function (fileNames, cb) {
|
|
var self = this;
|
|
var resList = [];
|
|
for (var key in fileNames) {
|
|
var value = fileNames[key];
|
|
_aliases[key] = value;
|
|
resList.push(value);
|
|
}
|
|
this.load(resList, cb);
|
|
},
|
|
|
|
/**
|
|
* <p>
|
|
* Loads alias map from the contents of a filename. <br/>
|
|
* <br/>
|
|
* @note The plist file name should follow the format below: <br/>
|
|
* <?xml version="1.0" encoding="UTF-8"?> <br/>
|
|
* <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <br/>
|
|
* <plist version="1.0"> <br/>
|
|
* <dict> <br/>
|
|
* <key>filenames</key> <br/>
|
|
* <dict> <br/>
|
|
* <key>sounds/click.wav</key> <br/>
|
|
* <string>sounds/click.caf</string> <br/>
|
|
* <key>sounds/endgame.wav</key> <br/>
|
|
* <string>sounds/endgame.caf</string> <br/>
|
|
* <key>sounds/gem-0.wav</key> <br/>
|
|
* <string>sounds/gem-0.caf</string> <br/>
|
|
* </dict> <br/>
|
|
* <key>metadata</key> <br/>
|
|
* <dict> <br/>
|
|
* <key>version</key> <br/>
|
|
* <integer>1</integer> <br/>
|
|
* </dict> <br/>
|
|
* </dict> <br/>
|
|
* </plist> <br/>
|
|
* </p>
|
|
* @param {String} url The plist file name.
|
|
* @param {Function} [callback]
|
|
*/
|
|
loadAliases: function (url, callback) {
|
|
var self = this, dict = self.getRes(url);
|
|
if (!dict) {
|
|
self.load(url, function (err, results) {
|
|
self._handleAliases(results[0]["filenames"], callback);
|
|
});
|
|
} else
|
|
self._handleAliases(dict["filenames"], callback);
|
|
},
|
|
|
|
/**
|
|
* Register a resource loader into loader.
|
|
* @param {string} extNames
|
|
* @param {function} loader
|
|
*/
|
|
register: function (extNames, loader) {
|
|
if (!extNames || !loader) return;
|
|
var self = this;
|
|
if (typeof extNames === "string")
|
|
return _register[extNames.trim().toLowerCase()] = loader;
|
|
for (var i = 0, li = extNames.length; i < li; i++) {
|
|
_register["." + extNames[i].trim().toLowerCase()] = loader;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Get resource data by url.
|
|
* @param url
|
|
* @returns {*}
|
|
*/
|
|
getRes: function (url) {
|
|
return this.cache[url] || this.cache[_aliases[url]];
|
|
},
|
|
|
|
/**
|
|
* Get aliase by url.
|
|
* @param url
|
|
* @returns {*}
|
|
*/
|
|
_getAliase: function (url) {
|
|
return _aliases[url];
|
|
},
|
|
|
|
/**
|
|
* Release the cache of resource by url.
|
|
* @param url
|
|
*/
|
|
release: function (url) {
|
|
var cache = this.cache;
|
|
var queue = _queue[url];
|
|
if (queue) {
|
|
queue.img = null;
|
|
delete _queue[url];
|
|
}
|
|
delete cache[url];
|
|
delete cache[_aliases[url]];
|
|
delete _aliases[url];
|
|
},
|
|
|
|
/**
|
|
* Resource cache of all resources.
|
|
*/
|
|
releaseAll: function () {
|
|
var locCache = this.cache;
|
|
for (var key in locCache)
|
|
delete locCache[key];
|
|
for (var key in _aliases)
|
|
delete _aliases[key];
|
|
}
|
|
};
|
|
})();
|
|
//+++++++++++++++++++++++++something about loader end+++++++++++++++++++++++++++++
|
|
|
|
/**
|
|
* A string tool to construct a string with format string.
|
|
* for example:
|
|
* cc.formatStr("a: %d, b: %b", a, b);
|
|
* cc.formatStr(a, b, c);
|
|
* @returns {String}
|
|
*/
|
|
cc.formatStr = function () {
|
|
var args = arguments;
|
|
var l = args.length;
|
|
if (l < 1)
|
|
return "";
|
|
|
|
var str = args[0];
|
|
var needToFormat = true;
|
|
if (typeof str === "object") {
|
|
needToFormat = false;
|
|
}
|
|
for (var i = 1; i < l; ++i) {
|
|
var arg = args[i];
|
|
if (needToFormat) {
|
|
while (true) {
|
|
var result = null;
|
|
if (typeof arg === "number") {
|
|
result = str.match(/(%d)|(%s)/);
|
|
if (result) {
|
|
str = str.replace(/(%d)|(%s)/, arg);
|
|
break;
|
|
}
|
|
}
|
|
result = str.match(/%s/);
|
|
if (result)
|
|
str = str.replace(/%s/, arg);
|
|
else
|
|
str += " " + arg;
|
|
break;
|
|
}
|
|
} else
|
|
str += " " + arg;
|
|
}
|
|
return str;
|
|
};
|
|
|
|
|
|
//+++++++++++++++++++++++++Engine initialization function begin+++++++++++++++++++++++++++
|
|
(function () {
|
|
|
|
var _tmpCanvas1 = document.createElement("canvas"),
|
|
_tmpCanvas2 = document.createElement("canvas");
|
|
|
|
cc.create3DContext = function (canvas, opt_attribs) {
|
|
var names = ["webgl", "experimental-webgl", "webkit-3d", "moz-webgl"];
|
|
var context = null;
|
|
for (var ii = 0; ii < names.length; ++ii) {
|
|
try {
|
|
context = canvas.getContext(names[ii], opt_attribs);
|
|
} catch (e) {
|
|
}
|
|
if (context) {
|
|
break;
|
|
}
|
|
}
|
|
return context;
|
|
};
|
|
|
|
var _initSys = function () {
|
|
/**
|
|
* System variables
|
|
* @namespace
|
|
* @name cc.sys
|
|
*/
|
|
cc.sys = {};
|
|
var sys = cc.sys;
|
|
|
|
/**
|
|
* English language code
|
|
* @memberof cc.sys
|
|
* @name LANGUAGE_ENGLISH
|
|
* @constant
|
|
* @type {Number}
|
|
*/
|
|
sys.LANGUAGE_ENGLISH = "en";
|
|
|
|
/**
|
|
* Chinese language code
|
|
* @memberof cc.sys
|
|
* @name LANGUAGE_CHINESE
|
|
* @constant
|
|
* @type {Number}
|
|
*/
|
|
sys.LANGUAGE_CHINESE = "zh";
|
|
|
|
/**
|
|
* French language code
|
|
* @memberof cc.sys
|
|
* @name LANGUAGE_FRENCH
|
|
* @constant
|
|
* @type {Number}
|
|
*/
|
|
sys.LANGUAGE_FRENCH = "fr";
|
|
|
|
/**
|
|
* Italian language code
|
|
* @memberof cc.sys
|
|
* @name LANGUAGE_ITALIAN
|
|
* @constant
|
|
* @type {Number}
|
|
*/
|
|
sys.LANGUAGE_ITALIAN = "it";
|
|
|
|
/**
|
|
* German language code
|
|
* @memberof cc.sys
|
|
* @name LANGUAGE_GERMAN
|
|
* @constant
|
|
* @type {Number}
|
|
*/
|
|
sys.LANGUAGE_GERMAN = "de";
|
|
|
|
/**
|
|
* Spanish language code
|
|
* @memberof cc.sys
|
|
* @name LANGUAGE_SPANISH
|
|
* @constant
|
|
* @type {Number}
|
|
*/
|
|
sys.LANGUAGE_SPANISH = "es";
|
|
|
|
/**
|
|
* Spanish language code
|
|
* @memberof cc.sys
|
|
* @name LANGUAGE_DUTCH
|
|
* @constant
|
|
* @type {Number}
|
|
*/
|
|
sys.LANGUAGE_DUTCH = "du";
|
|
|
|
/**
|
|
* Russian language code
|
|
* @memberof cc.sys
|
|
* @name LANGUAGE_RUSSIAN
|
|
* @constant
|
|
* @type {Number}
|
|
*/
|
|
sys.LANGUAGE_RUSSIAN = "ru";
|
|
|
|
/**
|
|
* Korean language code
|
|
* @memberof cc.sys
|
|
* @name LANGUAGE_KOREAN
|
|
* @constant
|
|
* @type {Number}
|
|
*/
|
|
sys.LANGUAGE_KOREAN = "ko";
|
|
|
|
/**
|
|
* Japanese language code
|
|
* @memberof cc.sys
|
|
* @name LANGUAGE_JAPANESE
|
|
* @constant
|
|
* @type {Number}
|
|
*/
|
|
sys.LANGUAGE_JAPANESE = "ja";
|
|
|
|
/**
|
|
* Hungarian language code
|
|
* @memberof cc.sys
|
|
* @name LANGUAGE_HUNGARIAN
|
|
* @constant
|
|
* @type {Number}
|
|
*/
|
|
sys.LANGUAGE_HUNGARIAN = "hu";
|
|
|
|
/**
|
|
* Portuguese language code
|
|
* @memberof cc.sys
|
|
* @name LANGUAGE_PORTUGUESE
|
|
* @constant
|
|
* @type {Number}
|
|
*/
|
|
sys.LANGUAGE_PORTUGUESE = "pt";
|
|
|
|
/**
|
|
* Arabic language code
|
|
* @memberof cc.sys
|
|
* @name LANGUAGE_ARABIC
|
|
* @constant
|
|
* @type {Number}
|
|
*/
|
|
sys.LANGUAGE_ARABIC = "ar";
|
|
|
|
/**
|
|
* Norwegian language code
|
|
* @memberof cc.sys
|
|
* @name LANGUAGE_NORWEGIAN
|
|
* @constant
|
|
* @type {Number}
|
|
*/
|
|
sys.LANGUAGE_NORWEGIAN = "no";
|
|
|
|
/**
|
|
* Polish language code
|
|
* @memberof cc.sys
|
|
* @name LANGUAGE_POLISH
|
|
* @constant
|
|
* @type {Number}
|
|
*/
|
|
sys.LANGUAGE_POLISH = "pl";
|
|
|
|
/**
|
|
* Unknown language code
|
|
* @memberof cc.sys
|
|
* @name LANGUAGE_UNKNOWN
|
|
* @constant
|
|
* @type {Number}
|
|
*/
|
|
sys.LANGUAGE_UNKNOWN = "unkonwn";
|
|
|
|
/**
|
|
* @memberof cc.sys
|
|
* @name OS_IOS
|
|
* @constant
|
|
* @type {string}
|
|
*/
|
|
sys.OS_IOS = "iOS";
|
|
/**
|
|
* @memberof cc.sys
|
|
* @name OS_ANDROID
|
|
* @constant
|
|
* @type {string}
|
|
*/
|
|
sys.OS_ANDROID = "Android";
|
|
/**
|
|
* @memberof cc.sys
|
|
* @name OS_WINDOWS
|
|
* @constant
|
|
* @type {string}
|
|
*/
|
|
sys.OS_WINDOWS = "Windows";
|
|
/**
|
|
* @memberof cc.sys
|
|
* @name OS_MARMALADE
|
|
* @constant
|
|
* @type {string}
|
|
*/
|
|
sys.OS_MARMALADE = "Marmalade";
|
|
/**
|
|
* @memberof cc.sys
|
|
* @name OS_LINUX
|
|
* @constant
|
|
* @type {string}
|
|
*/
|
|
sys.OS_LINUX = "Linux";
|
|
/**
|
|
* @memberof cc.sys
|
|
* @name OS_BADA
|
|
* @constant
|
|
* @type {string}
|
|
*/
|
|
sys.OS_BADA = "Bada";
|
|
/**
|
|
* @memberof cc.sys
|
|
* @name OS_BLACKBERRY
|
|
* @constant
|
|
* @type {string}
|
|
*/
|
|
sys.OS_BLACKBERRY = "Blackberry";
|
|
/**
|
|
* @memberof cc.sys
|
|
* @name OS_OSX
|
|
* @constant
|
|
* @type {string}
|
|
*/
|
|
sys.OS_OSX = "OS X";
|
|
/**
|
|
* @memberof cc.sys
|
|
* @name OS_WP8
|
|
* @constant
|
|
* @type {string}
|
|
*/
|
|
sys.OS_WP8 = "WP8";
|
|
/**
|
|
* @memberof cc.sys
|
|
* @name OS_WINRT
|
|
* @constant
|
|
* @type {string}
|
|
*/
|
|
sys.OS_WINRT = "WINRT";
|
|
/**
|
|
* @memberof cc.sys
|
|
* @name OS_UNKNOWN
|
|
* @constant
|
|
* @type {string}
|
|
*/
|
|
sys.OS_UNKNOWN = "Unknown";
|
|
|
|
/**
|
|
* @memberof cc.sys
|
|
* @name UNKNOWN
|
|
* @constant
|
|
* @default
|
|
* @type {Number}
|
|
*/
|
|
sys.UNKNOWN = -1;
|
|
/**
|
|
* @memberof cc.sys
|
|
* @name WIN32
|
|
* @constant
|
|
* @default
|
|
* @type {Number}
|
|
*/
|
|
sys.WIN32 = 0;
|
|
/**
|
|
* @memberof cc.sys
|
|
* @name LINUX
|
|
* @constant
|
|
* @default
|
|
* @type {Number}
|
|
*/
|
|
sys.LINUX = 1;
|
|
/**
|
|
* @memberof cc.sys
|
|
* @name MACOS
|
|
* @constant
|
|
* @default
|
|
* @type {Number}
|
|
*/
|
|
sys.MACOS = 2;
|
|
/**
|
|
* @memberof cc.sys
|
|
* @name ANDROID
|
|
* @constant
|
|
* @default
|
|
* @type {Number}
|
|
*/
|
|
sys.ANDROID = 3;
|
|
/**
|
|
* @memberof cc.sys
|
|
* @name IOS
|
|
* @constant
|
|
* @default
|
|
* @type {Number}
|
|
*/
|
|
sys.IPHONE = 4;
|
|
/**
|
|
* @memberof cc.sys
|
|
* @name IOS
|
|
* @constant
|
|
* @default
|
|
* @type {Number}
|
|
*/
|
|
sys.IPAD = 5;
|
|
/**
|
|
* @memberof cc.sys
|
|
* @name BLACKBERRY
|
|
* @constant
|
|
* @default
|
|
* @type {Number}
|
|
*/
|
|
sys.BLACKBERRY = 6;
|
|
/**
|
|
* @memberof cc.sys
|
|
* @name NACL
|
|
* @constant
|
|
* @default
|
|
* @type {Number}
|
|
*/
|
|
sys.NACL = 7;
|
|
/**
|
|
* @memberof cc.sys
|
|
* @name EMSCRIPTEN
|
|
* @constant
|
|
* @default
|
|
* @type {Number}
|
|
*/
|
|
sys.EMSCRIPTEN = 8;
|
|
/**
|
|
* @memberof cc.sys
|
|
* @name TIZEN
|
|
* @constant
|
|
* @default
|
|
* @type {Number}
|
|
*/
|
|
sys.TIZEN = 9;
|
|
/**
|
|
* @memberof cc.sys
|
|
* @name WINRT
|
|
* @constant
|
|
* @default
|
|
* @type {Number}
|
|
*/
|
|
sys.WINRT = 10;
|
|
/**
|
|
* @memberof cc.sys
|
|
* @name WP8
|
|
* @constant
|
|
* @default
|
|
* @type {Number}
|
|
*/
|
|
sys.WP8 = 11;
|
|
/**
|
|
* @memberof cc.sys
|
|
* @name MOBILE_BROWSER
|
|
* @constant
|
|
* @default
|
|
* @type {Number}
|
|
*/
|
|
sys.MOBILE_BROWSER = 100;
|
|
/**
|
|
* @memberof cc.sys
|
|
* @name DESKTOP_BROWSER
|
|
* @constant
|
|
* @default
|
|
* @type {Number}
|
|
*/
|
|
sys.DESKTOP_BROWSER = 101;
|
|
|
|
sys.BROWSER_TYPE_WECHAT = "wechat";
|
|
sys.BROWSER_TYPE_ANDROID = "androidbrowser";
|
|
sys.BROWSER_TYPE_IE = "ie";
|
|
sys.BROWSER_TYPE_QQ_APP = "qq"; // QQ App
|
|
sys.BROWSER_TYPE_QQ = "qqbrowser";
|
|
sys.BROWSER_TYPE_MOBILE_QQ = "mqqbrowser";
|
|
sys.BROWSER_TYPE_UC = "ucbrowser";
|
|
sys.BROWSER_TYPE_360 = "360browser";
|
|
sys.BROWSER_TYPE_BAIDU_APP = "baiduboxapp";
|
|
sys.BROWSER_TYPE_BAIDU = "baidubrowser";
|
|
sys.BROWSER_TYPE_MAXTHON = "maxthon";
|
|
sys.BROWSER_TYPE_OPERA = "opera";
|
|
sys.BROWSER_TYPE_OUPENG = "oupeng";
|
|
sys.BROWSER_TYPE_MIUI = "miuibrowser";
|
|
sys.BROWSER_TYPE_FIREFOX = "firefox";
|
|
sys.BROWSER_TYPE_SAFARI = "safari";
|
|
sys.BROWSER_TYPE_CHROME = "chrome";
|
|
sys.BROWSER_TYPE_LIEBAO = "liebao";
|
|
sys.BROWSER_TYPE_QZONE = "qzone";
|
|
sys.BROWSER_TYPE_SOUGOU = "sogou";
|
|
sys.BROWSER_TYPE_UNKNOWN = "unknown";
|
|
|
|
/**
|
|
* Is native ? This is set to be true in jsb auto.
|
|
* @memberof cc.sys
|
|
* @name isNative
|
|
* @type {Boolean}
|
|
*/
|
|
sys.isNative = false;
|
|
|
|
var win = window, nav = win.navigator, doc = document, docEle = doc.documentElement;
|
|
var ua = nav.userAgent.toLowerCase();
|
|
|
|
/**
|
|
* Indicate whether system is mobile system
|
|
* @memberof cc.sys
|
|
* @name isMobile
|
|
* @type {Boolean}
|
|
*/
|
|
sys.isMobile = /mobile|android|iphone|ipad/.test(ua);
|
|
|
|
/**
|
|
* Indicate the running platform
|
|
* @memberof cc.sys
|
|
* @name platform
|
|
* @type {Number}
|
|
*/
|
|
sys.platform = sys.isMobile ? sys.MOBILE_BROWSER : sys.DESKTOP_BROWSER;
|
|
|
|
var currLanguage = nav.language;
|
|
currLanguage = currLanguage ? currLanguage : nav.browserLanguage;
|
|
currLanguage = currLanguage ? currLanguage.split("-")[0] : sys.LANGUAGE_ENGLISH;
|
|
|
|
/**
|
|
* Indicate the current language of the running system
|
|
* @memberof cc.sys
|
|
* @name language
|
|
* @type {String}
|
|
*/
|
|
sys.language = currLanguage;
|
|
|
|
// Get the os of system
|
|
var isAndroid = false, iOS = false, osVersion = '', osMainVersion = 0;
|
|
var uaResult = /android (\d+(?:\.\d+)+)/i.exec(ua) || /android (\d+(?:\.\d+)+)/i.exec(nav.platform);
|
|
if (uaResult) {
|
|
isAndroid = true;
|
|
osVersion = uaResult[1] || '';
|
|
osMainVersion = parseInt(osVersion) || 0;
|
|
}
|
|
uaResult = /(iPad|iPhone|iPod).*OS ((\d+_?){2,3})/i.exec(ua);
|
|
if (uaResult) {
|
|
iOS = true;
|
|
osVersion = uaResult[2] || '';
|
|
osMainVersion = parseInt(osVersion) || 0;
|
|
}
|
|
else if (/(iPhone|iPad|iPod)/.exec(nav.platform)) {
|
|
iOS = true;
|
|
osVersion = '';
|
|
osMainVersion = 0;
|
|
}
|
|
|
|
var osName = sys.OS_UNKNOWN;
|
|
if (nav.appVersion.indexOf("Win") !== -1) osName = sys.OS_WINDOWS;
|
|
else if (iOS) osName = sys.OS_IOS;
|
|
else if (nav.appVersion.indexOf("Mac") !== -1) osName = sys.OS_OSX;
|
|
else if (nav.appVersion.indexOf("X11") !== -1 && nav.appVersion.indexOf("Linux") === -1) osName = sys.OS_UNIX;
|
|
else if (isAndroid) osName = sys.OS_ANDROID;
|
|
else if (nav.appVersion.indexOf("Linux") !== -1) osName = sys.OS_LINUX;
|
|
|
|
/**
|
|
* Indicate the running os name
|
|
* @memberof cc.sys
|
|
* @name os
|
|
* @type {String}
|
|
*/
|
|
sys.os = osName;
|
|
/**
|
|
* Indicate the running os version string
|
|
* @memberof cc.sys
|
|
* @name osVersion
|
|
* @type {String}
|
|
*/
|
|
sys.osVersion = osVersion;
|
|
/**
|
|
* Indicate the running os main version number
|
|
* @memberof cc.sys
|
|
* @name osMainVersion
|
|
* @type {Number}
|
|
*/
|
|
sys.osMainVersion = osMainVersion;
|
|
|
|
/**
|
|
* Indicate the running browser type
|
|
* @memberof cc.sys
|
|
* @name browserType
|
|
* @type {String}
|
|
*/
|
|
sys.browserType = sys.BROWSER_TYPE_UNKNOWN;
|
|
/* Determine the browser type */
|
|
(function(){
|
|
var typeReg1 = /micromessenger|mqqbrowser|sogou|qzone|liebao|ucbrowser|360 aphone|360browser|baiduboxapp|baidubrowser|maxthon|mxbrowser|trident|miuibrowser/i;
|
|
var typeReg2 = /qqbrowser|qq|chrome|safari|firefox|opr|oupeng|opera/i;
|
|
var browserTypes = typeReg1.exec(ua);
|
|
if(!browserTypes) browserTypes = typeReg2.exec(ua);
|
|
var browserType = browserTypes ? browserTypes[0] : sys.BROWSER_TYPE_UNKNOWN;
|
|
if (browserType === 'micromessenger')
|
|
browserType = sys.BROWSER_TYPE_WECHAT;
|
|
else if (browserType === "safari" && isAndroid)
|
|
browserType = sys.BROWSER_TYPE_ANDROID;
|
|
else if (browserType === "trident")
|
|
browserType = sys.BROWSER_TYPE_IE;
|
|
else if (browserType === "360 aphone")
|
|
browserType = sys.BROWSER_TYPE_360;
|
|
else if (browserType === "mxbrowser")
|
|
browserType = sys.BROWSER_TYPE_MAXTHON;
|
|
else if (browserType === "opr")
|
|
browserType = sys.BROWSER_TYPE_OPERA;
|
|
|
|
sys.browserType = browserType;
|
|
})();
|
|
|
|
/**
|
|
* Indicate the running browser version
|
|
* @memberof cc.sys
|
|
* @name browserVersion
|
|
* @type {String}
|
|
*/
|
|
sys.browserVersion = "";
|
|
/* Determine the browser version number */
|
|
(function(){
|
|
var versionReg1 = /(mqqbrowser|micromessenger|sogou|qzone|liebao|maxthon|mxbrowser|baidu)(mobile)?(browser)?\/?([\d.]+)/i;
|
|
var versionReg2 = /(msie |rv:|firefox|chrome|ucbrowser|qq|oupeng|opera|opr|safari|miui)(mobile)?(browser)?\/?([\d.]+)/i;
|
|
var tmp = ua.match(versionReg1);
|
|
if(!tmp) tmp = ua.match(versionReg2);
|
|
sys.browserVersion = tmp ? tmp[4] : "";
|
|
})();
|
|
|
|
var w = window.innerWidth || document.documentElement.clientWidth;
|
|
var h = window.innerHeight || document.documentElement.clientHeight;
|
|
var ratio = window.devicePixelRatio || 1;
|
|
|
|
/**
|
|
* Indicate the real pixel resolution of the whole game window
|
|
* @memberof cc.sys
|
|
* @name windowPixelResolution
|
|
* @type {Size}
|
|
*/
|
|
sys.windowPixelResolution = {
|
|
width: ratio * w,
|
|
height: ratio * h
|
|
};
|
|
|
|
sys._checkWebGLRenderMode = function () {
|
|
if (cc._renderType !== cc.game.RENDER_TYPE_WEBGL)
|
|
throw new Error("This feature supports WebGL render mode only.");
|
|
};
|
|
|
|
//Whether or not the Canvas BlendModes are supported.
|
|
sys._supportCanvasNewBlendModes = (function(){
|
|
var canvas = _tmpCanvas1;
|
|
canvas.width = 1;
|
|
canvas.height = 1;
|
|
var context = canvas.getContext('2d');
|
|
context.fillStyle = '#000';
|
|
context.fillRect(0, 0, 1, 1);
|
|
context.globalCompositeOperation = 'multiply';
|
|
|
|
var canvas2 = _tmpCanvas2;
|
|
canvas2.width = 1;
|
|
canvas2.height = 1;
|
|
var context2 = canvas2.getContext('2d');
|
|
context2.fillStyle = '#fff';
|
|
context2.fillRect(0, 0, 1, 1);
|
|
context.drawImage(canvas2, 0, 0, 1, 1);
|
|
|
|
return context.getImageData(0, 0, 1, 1).data[0] === 0;
|
|
})();
|
|
|
|
// Adjust mobile css settings
|
|
if (cc.sys.isMobile) {
|
|
var fontStyle = document.createElement("style");
|
|
fontStyle.type = "text/css";
|
|
document.body.appendChild(fontStyle);
|
|
|
|
fontStyle.textContent = "body,canvas,div{ -moz-user-select: none;-webkit-user-select: none;-ms-user-select: none;-khtml-user-select: none;"
|
|
+ "-webkit-tap-highlight-color:rgba(0,0,0,0);}";
|
|
}
|
|
|
|
/**
|
|
* cc.sys.localStorage is a local storage component.
|
|
* @memberof cc.sys
|
|
* @name localStorage
|
|
* @type {Object}
|
|
*/
|
|
try {
|
|
var localStorage = sys.localStorage = win.localStorage;
|
|
localStorage.setItem("storage", "");
|
|
localStorage.removeItem("storage");
|
|
localStorage = null;
|
|
} catch (e) {
|
|
var warn = function () {
|
|
cc.warn("Warning: localStorage isn't enabled. Please confirm browser cookie or privacy option");
|
|
};
|
|
sys.localStorage = {
|
|
getItem : warn,
|
|
setItem : warn,
|
|
removeItem : warn,
|
|
clear : warn
|
|
};
|
|
}
|
|
|
|
var _supportCanvas = !!_tmpCanvas1.getContext("2d");
|
|
var _supportWebGL = false;
|
|
if (win.WebGLRenderingContext) {
|
|
var tmpCanvas = document.createElement("CANVAS");
|
|
try{
|
|
var context = cc.create3DContext(tmpCanvas);
|
|
if (context) {
|
|
_supportWebGL = true;
|
|
}
|
|
|
|
if (_supportWebGL && sys.os === sys.OS_IOS && sys.osMainVersion === 9) {
|
|
// Not activating WebGL in iOS 9 UIWebView because it may crash when entering background
|
|
if (!window.indexedDB) {
|
|
_supportWebGL = false;
|
|
}
|
|
}
|
|
|
|
if (_supportWebGL && sys.os === sys.OS_ANDROID) {
|
|
var browserVer = parseFloat(sys.browserVersion);
|
|
switch (sys.browserType) {
|
|
case sys.BROWSER_TYPE_MOBILE_QQ:
|
|
case sys.BROWSER_TYPE_BAIDU:
|
|
case sys.BROWSER_TYPE_BAIDU_APP:
|
|
// QQ & Baidu Brwoser 6.2+ (using blink kernel)
|
|
if (browserVer >= 6.2) {
|
|
_supportWebGL = true;
|
|
}
|
|
else {
|
|
_supportWebGL = false;
|
|
}
|
|
break;
|
|
case sys.BROWSER_TYPE_CHROME:
|
|
// Chrome on android supports WebGL from v.30
|
|
if(browserVer >= 30.0) {
|
|
_supportWebGL = true;
|
|
} else {
|
|
_supportWebGL = false;
|
|
}
|
|
break;
|
|
case sys.BROWSER_TYPE_ANDROID:
|
|
// Android 5+ default browser
|
|
if (sys.osMainVersion && sys.osMainVersion >= 5) {
|
|
_supportWebGL = true;
|
|
}
|
|
break;
|
|
case sys.BROWSER_TYPE_UNKNOWN:
|
|
case sys.BROWSER_TYPE_360:
|
|
case sys.BROWSER_TYPE_MIUI:
|
|
case sys.BROWSER_TYPE_UC:
|
|
_supportWebGL = false;
|
|
}
|
|
}
|
|
}
|
|
catch (e) {}
|
|
tmpCanvas = null;
|
|
}
|
|
|
|
/**
|
|
* The capabilities of the current platform
|
|
* @memberof cc.sys
|
|
* @name capabilities
|
|
* @type {Object}
|
|
*/
|
|
var capabilities = sys.capabilities = {
|
|
"canvas": _supportCanvas,
|
|
"opengl": _supportWebGL
|
|
};
|
|
if (docEle['ontouchstart'] !== undefined || doc['ontouchstart'] !== undefined || nav.msPointerEnabled)
|
|
capabilities["touches"] = true;
|
|
if (docEle['onmouseup'] !== undefined)
|
|
capabilities["mouse"] = true;
|
|
if (docEle['onkeyup'] !== undefined)
|
|
capabilities["keyboard"] = true;
|
|
if (win.DeviceMotionEvent || win.DeviceOrientationEvent)
|
|
capabilities["accelerometer"] = true;
|
|
|
|
/**
|
|
* Forces the garbage collection, only available in JSB
|
|
* @memberof cc.sys
|
|
* @name garbageCollect
|
|
* @function
|
|
*/
|
|
sys.garbageCollect = function () {
|
|
// N/A in cocos2d-html5
|
|
};
|
|
|
|
/**
|
|
* Dumps rooted objects, only available in JSB
|
|
* @memberof cc.sys
|
|
* @name dumpRoot
|
|
* @function
|
|
*/
|
|
sys.dumpRoot = function () {
|
|
// N/A in cocos2d-html5
|
|
};
|
|
|
|
/**
|
|
* Restart the JS VM, only available in JSB
|
|
* @memberof cc.sys
|
|
* @name restartVM
|
|
* @function
|
|
*/
|
|
sys.restartVM = function () {
|
|
// N/A in cocos2d-html5
|
|
};
|
|
|
|
/**
|
|
* Clean a script in the JS VM, only available in JSB
|
|
* @memberof cc.sys
|
|
* @name cleanScript
|
|
* @param {String} jsfile
|
|
* @function
|
|
*/
|
|
sys.cleanScript = function (jsfile) {
|
|
// N/A in cocos2d-html5
|
|
};
|
|
|
|
/**
|
|
* Check whether an object is valid,
|
|
* In web engine, it will return true if the object exist
|
|
* In native engine, it will return true if the JS object and the correspond native object are both valid
|
|
* @memberof cc.sys
|
|
* @name isObjectValid
|
|
* @param {Object} obj
|
|
* @return {boolean} Validity of the object
|
|
* @function
|
|
*/
|
|
sys.isObjectValid = function (obj) {
|
|
if (obj) return true;
|
|
else return false;
|
|
};
|
|
|
|
/**
|
|
* Dump system informations
|
|
* @memberof cc.sys
|
|
* @name dump
|
|
* @function
|
|
*/
|
|
sys.dump = function () {
|
|
var self = this;
|
|
var str = "";
|
|
str += "isMobile : " + self.isMobile + "\r\n";
|
|
str += "language : " + self.language + "\r\n";
|
|
str += "browserType : " + self.browserType + "\r\n";
|
|
str += "browserVersion : " + self.browserVersion + "\r\n";
|
|
str += "capabilities : " + JSON.stringify(self.capabilities) + "\r\n";
|
|
str += "os : " + self.os + "\r\n";
|
|
str += "osVersion : " + self.osVersion + "\r\n";
|
|
str += "platform : " + self.platform + "\r\n";
|
|
str += "Using " + (cc._renderType === cc.game.RENDER_TYPE_WEBGL ? "WEBGL" : "CANVAS") + " renderer." + "\r\n";
|
|
cc.log(str);
|
|
};
|
|
|
|
/**
|
|
* Open a url in browser
|
|
* @memberof cc.sys
|
|
* @name openURL
|
|
* @param {String} url
|
|
*/
|
|
sys.openURL = function(url){
|
|
window.open(url);
|
|
};
|
|
|
|
/**
|
|
* Get the number of milliseconds elapsed since 1 January 1970 00:00:00 UTC.
|
|
* @memberof cc.sys
|
|
* @name now
|
|
* @return {Number}
|
|
*/
|
|
sys.now = function () {
|
|
if (Date.now) {
|
|
return Date.now();
|
|
}
|
|
else {
|
|
return +(new Date);
|
|
}
|
|
};
|
|
};
|
|
_initSys();
|
|
|
|
_tmpCanvas1 = null;
|
|
_tmpCanvas2 = null;
|
|
|
|
//to make sure the cc.log, cc.warn, cc.error and cc.assert would not throw error before init by debugger mode.
|
|
cc.log = cc.warn = cc.error = cc.assert = function () {
|
|
};
|
|
|
|
var _config = null,
|
|
//cache for js and module that has added into jsList to be loaded.
|
|
_jsAddedCache = {},
|
|
_engineInitCalled = false,
|
|
_engineLoadedCallback = null;
|
|
|
|
cc._engineLoaded = false;
|
|
|
|
function _determineRenderType(config) {
|
|
var CONFIG_KEY = cc.game.CONFIG_KEY,
|
|
userRenderMode = parseInt(config[CONFIG_KEY.renderMode]) || 0;
|
|
|
|
// Adjust RenderType
|
|
if (isNaN(userRenderMode) || userRenderMode > 2 || userRenderMode < 0)
|
|
config[CONFIG_KEY.renderMode] = 0;
|
|
|
|
// Determine RenderType
|
|
cc._renderType = cc.game.RENDER_TYPE_CANVAS;
|
|
cc._supportRender = false;
|
|
|
|
if (userRenderMode === 0) {
|
|
if (cc.sys.capabilities["opengl"]) {
|
|
cc._renderType = cc.game.RENDER_TYPE_WEBGL;
|
|
cc._supportRender = true;
|
|
}
|
|
else if (cc.sys.capabilities["canvas"]) {
|
|
cc._renderType = cc.game.RENDER_TYPE_CANVAS;
|
|
cc._supportRender = true;
|
|
}
|
|
}
|
|
else if (userRenderMode === 1 && cc.sys.capabilities["canvas"]) {
|
|
cc._renderType = cc.game.RENDER_TYPE_CANVAS;
|
|
cc._supportRender = true;
|
|
}
|
|
else if (userRenderMode === 2 && cc.sys.capabilities["opengl"]) {
|
|
cc._renderType = cc.game.RENDER_TYPE_WEBGL;
|
|
cc._supportRender = true;
|
|
}
|
|
}
|
|
|
|
function _getJsListOfModule(moduleMap, moduleName, dir) {
|
|
if (_jsAddedCache[moduleName]) return null;
|
|
dir = dir || "";
|
|
var jsList = [];
|
|
var tempList = moduleMap[moduleName];
|
|
if (!tempList) throw new Error("can not find module [" + moduleName + "]");
|
|
var ccPath = cc.path;
|
|
for (var i = 0, li = tempList.length; i < li; i++) {
|
|
var item = tempList[i];
|
|
if (_jsAddedCache[item]) continue;
|
|
var extname = ccPath.extname(item);
|
|
if (!extname) {
|
|
var arr = _getJsListOfModule(moduleMap, item, dir);
|
|
if (arr) jsList = jsList.concat(arr);
|
|
} else if (extname.toLowerCase() === ".js") jsList.push(ccPath.join(dir, item));
|
|
_jsAddedCache[item] = 1;
|
|
}
|
|
return jsList;
|
|
}
|
|
|
|
function _afterEngineLoaded(config) {
|
|
if (cc._initDebugSetting)
|
|
cc._initDebugSetting(config[cc.game.CONFIG_KEY.debugMode]);
|
|
cc._engineLoaded = true;
|
|
console.log(cc.ENGINE_VERSION);
|
|
if (_engineLoadedCallback) _engineLoadedCallback();
|
|
}
|
|
|
|
function _load(config) {
|
|
var self = this;
|
|
var CONFIG_KEY = cc.game.CONFIG_KEY, engineDir = config[CONFIG_KEY.engineDir], loader = cc.loader;
|
|
|
|
if (cc.Class) {
|
|
// Single file loaded
|
|
_afterEngineLoaded(config);
|
|
} else {
|
|
// Load cocos modules
|
|
var ccModulesPath = cc.path.join(engineDir, "moduleConfig.json");
|
|
loader.loadJson(ccModulesPath, function (err, modulesJson) {
|
|
if (err) throw new Error(err);
|
|
var modules = config["modules"] || [];
|
|
var moduleMap = modulesJson["module"];
|
|
var jsList = [];
|
|
if (cc.sys.capabilities["opengl"] && modules.indexOf("base4webgl") < 0) modules.splice(0, 0, "base4webgl");
|
|
else if (modules.indexOf("core") < 0) modules.splice(0, 0, "core");
|
|
for (var i = 0, li = modules.length; i < li; i++) {
|
|
var arr = _getJsListOfModule(moduleMap, modules[i], engineDir);
|
|
if (arr) jsList = jsList.concat(arr);
|
|
}
|
|
cc.loader.loadJsWithImg(jsList, function (err) {
|
|
if (err) throw err;
|
|
_afterEngineLoaded(config);
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
function _windowLoaded() {
|
|
this.removeEventListener('load', _windowLoaded, false);
|
|
_load(cc.game.config);
|
|
}
|
|
|
|
cc.initEngine = function (config, cb) {
|
|
if (_engineInitCalled) {
|
|
var previousCallback = _engineLoadedCallback;
|
|
_engineLoadedCallback = function () {
|
|
previousCallback && previousCallback();
|
|
cb && cb();
|
|
}
|
|
return;
|
|
}
|
|
|
|
_engineLoadedCallback = cb;
|
|
|
|
// Config uninitialized and given, initialize with it
|
|
if (!cc.game.config && config) {
|
|
cc.game.config = config;
|
|
}
|
|
// No config given and no config set before, load it
|
|
else if (!cc.game.config) {
|
|
cc.game._loadConfig();
|
|
}
|
|
config = cc.game.config;
|
|
|
|
_determineRenderType(config);
|
|
|
|
document.body ? _load(config) : cc._addEventListener(window, 'load', _windowLoaded, false);
|
|
_engineInitCalled = true;
|
|
};
|
|
|
|
})();
|
|
//+++++++++++++++++++++++++Engine initialization function end+++++++++++++++++++++++++++++
|
|
|
|
//+++++++++++++++++++++++++something about CCGame begin+++++++++++++++++++++++++++
|
|
/**
|
|
* An object to boot the game.
|
|
* @class
|
|
* @name cc.game
|
|
*
|
|
*/
|
|
cc.game = /** @lends cc.game# */{
|
|
/**
|
|
* Debug mode: No debugging. {@static}
|
|
* @const {Number}
|
|
* @static
|
|
*/
|
|
DEBUG_MODE_NONE: 0,
|
|
/**
|
|
* Debug mode: Info, warning, error to console.
|
|
* @const {Number}
|
|
* @static
|
|
*/
|
|
DEBUG_MODE_INFO: 1,
|
|
/**
|
|
* Debug mode: Warning, error to console.
|
|
* @const {Number}
|
|
* @static
|
|
*/
|
|
DEBUG_MODE_WARN: 2,
|
|
/**
|
|
* Debug mode: Error to console.
|
|
* @const {Number}
|
|
* @static
|
|
*/
|
|
DEBUG_MODE_ERROR: 3,
|
|
/**
|
|
* Debug mode: Info, warning, error to web page.
|
|
* @const {Number}
|
|
* @static
|
|
*/
|
|
DEBUG_MODE_INFO_FOR_WEB_PAGE: 4,
|
|
/**
|
|
* Debug mode: Warning, error to web page.
|
|
* @const {Number}
|
|
* @static
|
|
*/
|
|
DEBUG_MODE_WARN_FOR_WEB_PAGE: 5,
|
|
/**
|
|
* Debug mode: Error to web page.
|
|
* @const {Number}
|
|
* @static
|
|
*/
|
|
DEBUG_MODE_ERROR_FOR_WEB_PAGE: 6,
|
|
|
|
/**
|
|
* Event that is fired when the game is hidden.
|
|
* @constant {String}
|
|
*/
|
|
EVENT_HIDE: "game_on_hide",
|
|
/**
|
|
* Event that is fired when the game is shown.
|
|
* @constant {String}
|
|
*/
|
|
EVENT_SHOW: "game_on_show",
|
|
/**
|
|
* Event that is fired when the game is resized.
|
|
* @constant {String}
|
|
*/
|
|
EVENT_RESIZE: "game_on_resize",
|
|
/**
|
|
* Event that is fired when the renderer is done being initialized.
|
|
* @constant {String}
|
|
*/
|
|
EVENT_RENDERER_INITED: "renderer_inited",
|
|
|
|
/** @constant {Number} */
|
|
RENDER_TYPE_CANVAS: 0,
|
|
/** @constant {Number} */
|
|
RENDER_TYPE_WEBGL: 1,
|
|
/** @constant {Number} */
|
|
RENDER_TYPE_OPENGL: 2,
|
|
|
|
_eventHide: null,
|
|
_eventShow: null,
|
|
|
|
/**
|
|
* Keys found in project.json.
|
|
*
|
|
* @constant
|
|
* @type {Object}
|
|
*
|
|
* @prop {String} engineDir - In debug mode, if you use the whole engine to develop your game, you should specify its relative path with "engineDir".
|
|
* @prop {String} modules - Defines which modules you will need in your game, it's useful only on web
|
|
* @prop {String} debugMode - Debug mode, see DEBUG_MODE_XXX constant definitions.
|
|
* @prop {String} exposeClassName - Expose class name to chrome debug tools
|
|
* @prop {String} showFPS - Left bottom corner fps information will show when "showFPS" equals true, otherwise it will be hide.
|
|
* @prop {String} frameRate - Sets the wanted frame rate for your game, but the real fps depends on your game implementation and the running environment.
|
|
* @prop {String} id - Sets the id of your canvas element on the web page, it's useful only on web.
|
|
* @prop {String} renderMode - Sets the renderer type, only useful on web, 0: Automatic, 1: Canvas, 2: WebGL
|
|
* @prop {String} jsList - Sets the list of js files in your game.
|
|
*/
|
|
CONFIG_KEY: {
|
|
width: "width",
|
|
height: "height",
|
|
engineDir: "engineDir",
|
|
modules: "modules",
|
|
debugMode: "debugMode",
|
|
exposeClassName: "exposeClassName",
|
|
showFPS: "showFPS",
|
|
frameRate: "frameRate",
|
|
id: "id",
|
|
renderMode: "renderMode",
|
|
jsList: "jsList"
|
|
},
|
|
|
|
// states
|
|
_paused: true,//whether the game is paused
|
|
_configLoaded: false,//whether config loaded
|
|
_prepareCalled: false,//whether the prepare function has been called
|
|
_prepared: false,//whether the engine has prepared
|
|
_rendererInitialized: false,
|
|
|
|
_renderContext: null,
|
|
|
|
_intervalId: null,//interval target of main
|
|
|
|
_lastTime: null,
|
|
_frameTime: null,
|
|
|
|
/**
|
|
* The outer frame of the game canvas, parent of cc.container
|
|
* @type {Object}
|
|
*/
|
|
frame: null,
|
|
/**
|
|
* The container of game canvas, equals to cc.container
|
|
* @type {Object}
|
|
*/
|
|
container: null,
|
|
/**
|
|
* The canvas of the game, equals to cc._canvas
|
|
* @type {Object}
|
|
*/
|
|
canvas: null,
|
|
|
|
/**
|
|
* Config of game
|
|
* @type {Object}
|
|
*/
|
|
config: null,
|
|
|
|
/**
|
|
* Callback when the scripts of engine have been load.
|
|
* @type {Function|null}
|
|
*/
|
|
onStart: null,
|
|
|
|
/**
|
|
* Callback when game exits.
|
|
* @type {Function|null}
|
|
*/
|
|
onStop: null,
|
|
|
|
//@Public Methods
|
|
|
|
// @Game play control
|
|
/**
|
|
* Set frameRate of game.
|
|
* @param frameRate
|
|
*/
|
|
setFrameRate: function (frameRate) {
|
|
var self = this, config = self.config, CONFIG_KEY = self.CONFIG_KEY;
|
|
config[CONFIG_KEY.frameRate] = frameRate;
|
|
if (self._intervalId)
|
|
window.cancelAnimationFrame(self._intervalId);
|
|
self._intervalId = 0;
|
|
self._paused = true;
|
|
self._setAnimFrame();
|
|
self._runMainLoop();
|
|
},
|
|
|
|
/**
|
|
* Run the game frame by frame.
|
|
*/
|
|
step: function () {
|
|
cc.director.mainLoop();
|
|
},
|
|
|
|
/**
|
|
* Pause the game.
|
|
*/
|
|
pause: function () {
|
|
if (this._paused) return;
|
|
this._paused = true;
|
|
// Pause audio engine
|
|
if (cc.audioEngine) {
|
|
cc.audioEngine._pausePlaying();
|
|
}
|
|
// Pause main loop
|
|
if (this._intervalId)
|
|
window.cancelAnimationFrame(this._intervalId);
|
|
this._intervalId = 0;
|
|
},
|
|
|
|
/**
|
|
* Resume the game from pause.
|
|
*/
|
|
resume: function () {
|
|
if (!this._paused) return;
|
|
this._paused = false;
|
|
// Resume audio engine
|
|
if (cc.audioEngine) {
|
|
cc.audioEngine._resumePlaying();
|
|
}
|
|
// Resume main loop
|
|
this._runMainLoop();
|
|
},
|
|
|
|
/**
|
|
* Check whether the game is paused.
|
|
*/
|
|
isPaused: function () {
|
|
return this._paused;
|
|
},
|
|
|
|
/**
|
|
* Restart game.
|
|
*/
|
|
restart: function () {
|
|
cc.director.popToSceneStackLevel(0);
|
|
// Clean up audio
|
|
cc.audioEngine && cc.audioEngine.end();
|
|
|
|
cc.game.onStart();
|
|
},
|
|
|
|
/**
|
|
* End game, it will close the game window
|
|
*/
|
|
end: function () {
|
|
close();
|
|
},
|
|
|
|
// @Game loading
|
|
/**
|
|
* Prepare game.
|
|
* @param cb
|
|
*/
|
|
prepare: function (cb) {
|
|
var self = this,
|
|
config = self.config,
|
|
CONFIG_KEY = self.CONFIG_KEY;
|
|
|
|
// Config loaded
|
|
if (!this._configLoaded) {
|
|
this._loadConfig(function () {
|
|
self.prepare(cb);
|
|
});
|
|
return;
|
|
}
|
|
|
|
// Already prepared
|
|
if (this._prepared) {
|
|
if (cb) cb();
|
|
return;
|
|
}
|
|
// Prepare called, but not done yet
|
|
if (this._prepareCalled) {
|
|
return;
|
|
}
|
|
// Prepare never called and engine ready
|
|
if (cc._engineLoaded) {
|
|
this._prepareCalled = true;
|
|
|
|
this._initRenderer(config[CONFIG_KEY.width], config[CONFIG_KEY.height]);
|
|
|
|
/**
|
|
* cc.view is the shared view object.
|
|
* @type {cc.EGLView}
|
|
* @name cc.view
|
|
* @memberof cc
|
|
*/
|
|
cc.view = cc.EGLView._getInstance();
|
|
|
|
/**
|
|
* @type {cc.Director}
|
|
* @name cc.director
|
|
* @memberof cc
|
|
*/
|
|
cc.director = cc.Director._getInstance();
|
|
if (cc.director.setOpenGLView)
|
|
cc.director.setOpenGLView(cc.view);
|
|
/**
|
|
* cc.winSize is the alias object for the size of the current game window.
|
|
* @type {cc.Size}
|
|
* @name cc.winSize
|
|
* @memberof cc
|
|
*/
|
|
cc.winSize = cc.director.getWinSize();
|
|
|
|
this._initEvents();
|
|
|
|
this._setAnimFrame();
|
|
this._runMainLoop();
|
|
|
|
// Load game scripts
|
|
var jsList = config[CONFIG_KEY.jsList];
|
|
if (jsList) {
|
|
cc.loader.loadJsWithImg(jsList, function (err) {
|
|
if (err) throw new Error(err);
|
|
self._prepared = true;
|
|
if (cb) cb();
|
|
});
|
|
}
|
|
else {
|
|
if (cb) cb();
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
// Engine not loaded yet
|
|
cc.initEngine(this.config, function () {
|
|
self.prepare(cb);
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Run game with configuration object and onStart function.
|
|
* @param {Object|Function} [config] Pass configuration object or onStart function
|
|
* @param {onStart} [onStart] onStart function to be executed after game initialized
|
|
*/
|
|
run: function (config, onStart) {
|
|
if (typeof config === 'function') {
|
|
cc.game.onStart = config;
|
|
}
|
|
else {
|
|
if (config) {
|
|
if (typeof config === 'string') {
|
|
if (!cc.game.config) this._loadConfig();
|
|
cc.game.config[cc.game.CONFIG_KEY.id] = config;
|
|
} else {
|
|
cc.game.config = config;
|
|
}
|
|
}
|
|
if (typeof onStart === 'function') {
|
|
cc.game.onStart = onStart;
|
|
}
|
|
}
|
|
|
|
this.prepare(cc.game.onStart && cc.game.onStart.bind(cc.game));
|
|
},
|
|
|
|
//@Private Methods
|
|
|
|
// @Time ticker section
|
|
_setAnimFrame: function () {
|
|
this._lastTime = new Date();
|
|
var frameRate = cc.game.config[cc.game.CONFIG_KEY.frameRate];
|
|
this._frameTime = 1000 / frameRate;
|
|
if (frameRate !== 60 && frameRate !== 30) {
|
|
window.requestAnimFrame = this._stTime;
|
|
window.cancelAnimationFrame = this._ctTime;
|
|
}
|
|
else {
|
|
window.requestAnimFrame = window.requestAnimationFrame ||
|
|
window.webkitRequestAnimationFrame ||
|
|
window.mozRequestAnimationFrame ||
|
|
window.oRequestAnimationFrame ||
|
|
window.msRequestAnimationFrame ||
|
|
this._stTime;
|
|
window.cancelAnimationFrame = window.cancelAnimationFrame ||
|
|
window.cancelRequestAnimationFrame ||
|
|
window.msCancelRequestAnimationFrame ||
|
|
window.mozCancelRequestAnimationFrame ||
|
|
window.oCancelRequestAnimationFrame ||
|
|
window.webkitCancelRequestAnimationFrame ||
|
|
window.msCancelAnimationFrame ||
|
|
window.mozCancelAnimationFrame ||
|
|
window.webkitCancelAnimationFrame ||
|
|
window.oCancelAnimationFrame ||
|
|
this._ctTime;
|
|
}
|
|
},
|
|
_stTime: function (callback) {
|
|
var currTime = new Date().getTime();
|
|
var timeToCall = Math.max(0, cc.game._frameTime - (currTime - cc.game._lastTime));
|
|
var id = window.setTimeout(function() { callback(); },
|
|
timeToCall);
|
|
cc.game._lastTime = currTime + timeToCall;
|
|
return id;
|
|
},
|
|
_ctTime: function (id) {
|
|
window.clearTimeout(id);
|
|
},
|
|
//Run game.
|
|
_runMainLoop: function () {
|
|
var self = this, callback, config = self.config, CONFIG_KEY = self.CONFIG_KEY,
|
|
director = cc.director,
|
|
skip = true, frameRate = config[CONFIG_KEY.frameRate];
|
|
|
|
director.setDisplayStats(config[CONFIG_KEY.showFPS]);
|
|
|
|
callback = function () {
|
|
if (!self._paused) {
|
|
if (frameRate === 30) {
|
|
if (skip = !skip) {
|
|
self._intervalId = window.requestAnimFrame(callback);
|
|
return;
|
|
}
|
|
}
|
|
|
|
director.mainLoop();
|
|
self._intervalId = window.requestAnimFrame(callback);
|
|
}
|
|
};
|
|
|
|
self._intervalId = window.requestAnimFrame(callback);
|
|
self._paused = false;
|
|
},
|
|
|
|
// @Game loading section
|
|
_loadConfig: function (cb) {
|
|
// Load config
|
|
var config = this.config || document["ccConfig"];
|
|
// Already loaded or Load from document.ccConfig
|
|
if (config) {
|
|
this._initConfig(config);
|
|
cb && cb();
|
|
}
|
|
// Load from project.json
|
|
else {
|
|
var cocos_script = document.getElementsByTagName('script');
|
|
for (var i = 0; i < cocos_script.length; i++) {
|
|
var _t = cocos_script[i].getAttribute('cocos');
|
|
if (_t === '' || _t) {
|
|
break;
|
|
}
|
|
}
|
|
var self = this;
|
|
var loaded = function (err, txt) {
|
|
var data = JSON.parse(txt);
|
|
self._initConfig(data);
|
|
cb && cb();
|
|
};
|
|
var _src, txt, _resPath;
|
|
if (i < cocos_script.length) {
|
|
_src = cocos_script[i].src;
|
|
if (_src) {
|
|
_resPath = /(.*)\//.exec(_src)[0];
|
|
cc.loader.resPath = _resPath;
|
|
_src = cc.path.join(_resPath, 'project.json');
|
|
}
|
|
cc.loader.loadTxt(_src, loaded);
|
|
}
|
|
if (!txt) {
|
|
cc.loader.loadTxt("project.json", loaded);
|
|
}
|
|
}
|
|
},
|
|
|
|
_initConfig: function (config) {
|
|
var CONFIG_KEY = this.CONFIG_KEY,
|
|
modules = config[CONFIG_KEY.modules];
|
|
|
|
// Configs adjustment
|
|
config[CONFIG_KEY.showFPS] = typeof config[CONFIG_KEY.showFPS] === 'undefined' ? true : config[CONFIG_KEY.showFPS];
|
|
config[CONFIG_KEY.engineDir] = config[CONFIG_KEY.engineDir] || "frameworks/cocos2d-html5";
|
|
if (config[CONFIG_KEY.debugMode] == null)
|
|
config[CONFIG_KEY.debugMode] = 0;
|
|
config[CONFIG_KEY.exposeClassName] = !!config[CONFIG_KEY.exposeClassName];
|
|
config[CONFIG_KEY.frameRate] = config[CONFIG_KEY.frameRate] || 60;
|
|
if (config[CONFIG_KEY.renderMode] == null)
|
|
config[CONFIG_KEY.renderMode] = 0;
|
|
if (config[CONFIG_KEY.registerSystemEvent] == null)
|
|
config[CONFIG_KEY.registerSystemEvent] = true;
|
|
|
|
// Modules adjustment
|
|
if (modules && modules.indexOf("core") < 0) modules.splice(0, 0, "core");
|
|
modules && (config[CONFIG_KEY.modules] = modules);
|
|
this.config = config;
|
|
this._configLoaded = true;
|
|
},
|
|
|
|
_initRenderer: function (width, height) {
|
|
// Avoid setup to be called twice.
|
|
if (this._rendererInitialized) return;
|
|
|
|
if (!cc._supportRender) {
|
|
throw new Error("The renderer doesn't support the renderMode " + this.config[this.CONFIG_KEY.renderMode]);
|
|
}
|
|
|
|
var el = this.config[cc.game.CONFIG_KEY.id],
|
|
win = window,
|
|
element = cc.$(el) || cc.$('#' + el),
|
|
localCanvas, localContainer, localConStyle;
|
|
|
|
if (element.tagName === "CANVAS") {
|
|
width = width || element.width;
|
|
height = height || element.height;
|
|
|
|
//it is already a canvas, we wrap it around with a div
|
|
this.canvas = cc._canvas = localCanvas = element;
|
|
this.container = cc.container = localContainer = document.createElement("DIV");
|
|
if (localCanvas.parentNode)
|
|
localCanvas.parentNode.insertBefore(localContainer, localCanvas);
|
|
} else {
|
|
//we must make a new canvas and place into this element
|
|
if (element.tagName !== "DIV") {
|
|
cc.log("Warning: target element is not a DIV or CANVAS");
|
|
}
|
|
width = width || element.clientWidth;
|
|
height = height || element.clientHeight;
|
|
this.canvas = cc._canvas = localCanvas = cc.$(document.createElement("CANVAS"));
|
|
this.container = cc.container = localContainer = document.createElement("DIV");
|
|
element.appendChild(localContainer);
|
|
}
|
|
localContainer.setAttribute('id', 'Cocos2dGameContainer');
|
|
localContainer.appendChild(localCanvas);
|
|
this.frame = (localContainer.parentNode === document.body) ? document.documentElement : localContainer.parentNode;
|
|
|
|
localCanvas.addClass("gameCanvas");
|
|
localCanvas.setAttribute("width", width || 480);
|
|
localCanvas.setAttribute("height", height || 320);
|
|
localCanvas.setAttribute("tabindex", 99);
|
|
|
|
if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) {
|
|
this._renderContext = cc._renderContext = cc.webglContext
|
|
= cc.create3DContext(localCanvas, {
|
|
'stencil': true,
|
|
'alpha': false
|
|
});
|
|
}
|
|
// WebGL context created successfully
|
|
if (this._renderContext) {
|
|
cc.renderer = cc.rendererWebGL;
|
|
win.gl = this._renderContext; // global variable declared in CCMacro.js
|
|
cc.renderer.init();
|
|
cc._drawingUtil = new cc.DrawingPrimitiveWebGL(this._renderContext);
|
|
cc.textureCache._initializingRenderer();
|
|
cc.glExt = {};
|
|
cc.glExt.instanced_arrays = win.gl.getExtension("ANGLE_instanced_arrays");
|
|
cc.glExt.element_uint = win.gl.getExtension("OES_element_index_uint");
|
|
} else {
|
|
cc._renderType = cc.game.RENDER_TYPE_CANVAS;
|
|
cc.renderer = cc.rendererCanvas;
|
|
this._renderContext = cc._renderContext = new cc.CanvasContextWrapper(localCanvas.getContext("2d"));
|
|
cc._drawingUtil = cc.DrawingPrimitiveCanvas ? new cc.DrawingPrimitiveCanvas(this._renderContext) : null;
|
|
}
|
|
|
|
cc._gameDiv = localContainer;
|
|
cc.game.canvas.oncontextmenu = function () {
|
|
if (!cc._isContextMenuEnable) return false;
|
|
};
|
|
|
|
this.dispatchEvent(this.EVENT_RENDERER_INITED, true);
|
|
|
|
this._rendererInitialized = true;
|
|
},
|
|
|
|
_initEvents: function () {
|
|
var win = window, hidden;
|
|
|
|
this._eventHide = this._eventHide || new cc.EventCustom(this.EVENT_HIDE);
|
|
this._eventHide.setUserData(this);
|
|
this._eventShow = this._eventShow || new cc.EventCustom(this.EVENT_SHOW);
|
|
this._eventShow.setUserData(this);
|
|
|
|
// register system events
|
|
if (this.config[this.CONFIG_KEY.registerSystemEvent])
|
|
cc.inputManager.registerSystemEvent(this.canvas);
|
|
|
|
if (!cc.isUndefined(document.hidden)) {
|
|
hidden = "hidden";
|
|
} else if (!cc.isUndefined(document.mozHidden)) {
|
|
hidden = "mozHidden";
|
|
} else if (!cc.isUndefined(document.msHidden)) {
|
|
hidden = "msHidden";
|
|
} else if (!cc.isUndefined(document.webkitHidden)) {
|
|
hidden = "webkitHidden";
|
|
}
|
|
|
|
var changeList = [
|
|
"visibilitychange",
|
|
"mozvisibilitychange",
|
|
"msvisibilitychange",
|
|
"webkitvisibilitychange",
|
|
"qbrowserVisibilityChange"
|
|
];
|
|
var onHidden = function () {
|
|
if (cc.eventManager && cc.game._eventHide)
|
|
cc.eventManager.dispatchEvent(cc.game._eventHide);
|
|
};
|
|
var onShow = function () {
|
|
if (cc.eventManager && cc.game._eventShow)
|
|
cc.eventManager.dispatchEvent(cc.game._eventShow);
|
|
};
|
|
|
|
if (hidden) {
|
|
for (var i=0; i<changeList.length; i++) {
|
|
document.addEventListener(changeList[i], function (event) {
|
|
var visible = document[hidden];
|
|
// QQ App
|
|
visible = visible || event["hidden"];
|
|
if (visible) onHidden();
|
|
else onShow();
|
|
}, false);
|
|
}
|
|
} else {
|
|
win.addEventListener("blur", onHidden, false);
|
|
win.addEventListener("focus", onShow, false);
|
|
}
|
|
|
|
if (navigator.userAgent.indexOf("MicroMessenger") > -1) {
|
|
win.onfocus = function(){ onShow() };
|
|
}
|
|
|
|
if ("onpageshow" in window && "onpagehide" in window) {
|
|
win.addEventListener("pagehide", onHidden, false);
|
|
win.addEventListener("pageshow", onShow, false);
|
|
}
|
|
|
|
cc.eventManager.addCustomListener(cc.game.EVENT_HIDE, function () {
|
|
cc.game.pause();
|
|
});
|
|
cc.eventManager.addCustomListener(cc.game.EVENT_SHOW, function () {
|
|
cc.game.resume();
|
|
});
|
|
}
|
|
};
|
|
//+++++++++++++++++++++++++something about CCGame end+++++++++++++++++++++++++++++
|
|
|
|
Function.prototype.bind = Function.prototype.bind || function (oThis) {
|
|
if (!cc.isFunction(this)) {
|
|
// closest thing possible to the ECMAScript 5
|
|
// internal IsCallable function
|
|
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
|
|
}
|
|
|
|
var aArgs = Array.prototype.slice.call(arguments, 1),
|
|
fToBind = this,
|
|
fNOP = function () {},
|
|
fBound = function () {
|
|
return fToBind.apply(this instanceof fNOP && oThis
|
|
? this
|
|
: oThis,
|
|
aArgs.concat(Array.prototype.slice.call(arguments)));
|
|
};
|
|
|
|
fNOP.prototype = this.prototype;
|
|
fBound.prototype = new fNOP();
|
|
|
|
return fBound;
|
|
};
|