1 /**************************************************************************** 2 Copyright (c) 2010-2012 cocos2d-x.org 3 Copyright (c) 2008-2010 Ricardo Quesada 4 Copyright (c) 2011 Zynga Inc. 5 6 http://www.cocos2d-x.org 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy 9 of this software and associated documentation files (the "Software"), to deal 10 in the Software without restriction, including without limitation the rights 11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 copies of the Software, and to permit persons to whom the Software is 13 furnished to do so, subject to the following conditions: 14 15 The above copyright notice and this permission notice shall be included in 16 all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 THE SOFTWARE. 25 ****************************************************************************/ 26 27 /** 28 * Device type 29 * @constant 30 * @type {Object} 31 */ 32 cc.TARGET_PLATFORM = { 33 WINDOWS:0, 34 LINUX:1, 35 MACOS:2, 36 ANDROID:3, 37 IPHONE:4, 38 IPAD:5, 39 BLACKBERRY:6, 40 NACL:7, 41 EMSCRIPTEN:8, 42 MOBILE_BROWSER:100, 43 PC_BROWSER:101 44 }; 45 46 /** 47 * Device oriented vertically, home button on the bottom 48 * @constant 49 * @type Number 50 */ 51 cc.ORIENTATION_PORTRAIT = 0; 52 53 /** 54 * Device oriented vertically, home button on the top 55 * @constant 56 * @type Number 57 */ 58 cc.ORIENTATION_PORTRAIT_UPSIDE_DOWN = 1; 59 60 /** 61 * Device oriented horizontally, home button on the right 62 * @constant 63 * @type Number 64 */ 65 cc.ORIENTATION_LANDSCAPE_LEFT = 2; 66 67 /** 68 * Device oriented horizontally, home button on the left 69 * @constant 70 * @type Number 71 */ 72 cc.ORIENTATION_LANDSCAPE_RIGHT = 3; 73 74 //engine render type 75 76 /** 77 * Canvas of render type 78 * @constant 79 * @type Number 80 */ 81 cc.CANVAS = 0; 82 83 /** 84 * WebGL of render type 85 * @constant 86 * @type Number 87 */ 88 cc.WEBGL = 1; 89 90 /** 91 * drawing primitive of game engine 92 * @type cc.DrawingPrimitive 93 */ 94 cc.drawingUtil = null; 95 96 /** 97 * main Canvas 2D/3D Context of game engine 98 * @type CanvasRenderingContext2D|WebGLRenderingContext 99 */ 100 cc.renderContext = null; 101 102 /** 103 * main Canvas of game engine 104 * @type HTMLCanvasElement 105 */ 106 cc.canvas = null; 107 108 /** 109 * This Div element contain all game canvas 110 * @type HTMLDivElement 111 */ 112 cc.gameDiv = null; 113 114 /** 115 * current render type of game engine 116 * @type Number 117 */ 118 cc.renderContextType = cc.CANVAS; 119 120 /** 121 * save original size of canvas, use for resize canvas 122 * @type cc.Size 123 */ 124 cc.originalCanvasSize = cc.size(0, 0); 125 126 window.requestAnimFrame = (function () { 127 return window.requestAnimationFrame || 128 window.webkitRequestAnimationFrame || 129 window.mozRequestAnimationFrame || 130 window.oRequestAnimationFrame || 131 window.msRequestAnimationFrame 132 })(); 133 134 135 if (!window.console) { 136 window.console = {}; 137 window.console.log = function () { 138 }; 139 window.console.assert = function () { 140 }; 141 } 142 143 cc.isAddedHiddenEvent = false; 144 145 /** 146 * <p> 147 * setup game main canvas,renderContext,gameDiv and drawingUtil with argument <br/> 148 * <br/> 149 * can receive follow type of arguemnt: <br/> 150 * - empty: create a canvas append to document's body, and setup other option <br/> 151 * - string: search the element by document.getElementById(), <br/> 152 * if this element is HTMLCanvasElement, set this element as main canvas of engine, and set it's ParentNode as cc.gameDiv.<br/> 153 * if this element is HTMLDivElement, set it's ParentNode to cc.gameDiv, and create a canvas as main canvas of engine. <br/> 154 * </p> 155 * @function 156 * @example 157 * //setup with null 158 * cc.setup(); 159 * 160 * // setup with HTMLCanvasElement, gameCanvas is Canvas element 161 * // declare like this: <canvas id="gameCanvas" width="800" height="450"></canvas> 162 * cc.setup("gameCanvas"); 163 * 164 * //setup with HTMLDivElement, gameDiv is Div element 165 * // declare like this: <div id="Cocos2dGameContainer" width="800" height="450"></div> 166 * cc.setup("Cocos2dGameContainer"); 167 */ 168 cc.setup = function (el, width, height) { 169 var element = cc.$(el) || cc.$('#' + el); 170 var localCanvas, localContainer, localConStyle; 171 if (element.tagName == "CANVAS") { 172 width = width || element.width; 173 height = height || element.height; 174 175 //it is already a canvas, we wrap it around with a div 176 localContainer = cc.container = cc.$new("DIV"); 177 localConStyle = localContainer.style; 178 localCanvas = cc.canvas = element; 179 localCanvas.parentNode.insertBefore(localContainer, localCanvas); 180 localCanvas.appendTo(localContainer); 181 localConStyle.width = (width || 480) + "px"; 182 localConStyle.height = (height || 320) + "px"; 183 localContainer.setAttribute('id', 'Cocos2dGameContainer'); 184 localConStyle.margin = "0 auto"; 185 localCanvas.setAttribute("width", width || 480); 186 localCanvas.setAttribute("height", height || 320); 187 } else {//we must make a new canvas and place into this element 188 if (element.tagName != "DIV") { 189 cc.log("Warning: target element is not a DIV or CANVAS"); 190 } 191 width = width || element.clientWidth; 192 height = height || element.clientHeight; 193 194 localCanvas = cc.canvas = cc.$new("CANVAS"); 195 localCanvas.addClass("gameCanvas"); 196 localCanvas.setAttribute("width", width || 480); 197 localCanvas.setAttribute("height", height || 320); 198 localContainer = cc.container = element; 199 localConStyle = localContainer.style; 200 element.appendChild(localCanvas); 201 localConStyle.width = (width || 480) + "px"; 202 localConStyle.height = (height || 320) + "px"; 203 localConStyle.margin = "0 auto"; 204 } 205 localConStyle.position = 'relative'; 206 localConStyle.overflow = 'hidden'; 207 localContainer.top = '100%'; 208 209 if(cc.__renderDoesnotSupport) 210 return; 211 212 if (cc.Browser.supportWebGL) 213 cc.renderContext = cc.webglContext = cc.create3DContext(localCanvas,{ 214 'stencil': true, 215 'preserveDrawingBuffer': true, 216 'antialias': !cc.Browser.isMobile, 217 'alpha': false}); 218 if(cc.renderContext){ 219 cc.renderContextType = cc.WEBGL; 220 window.gl = cc.renderContext; // global variable declared in CCMacro.js 221 cc.drawingUtil = new cc.DrawingPrimitiveWebGL(cc.renderContext); 222 cc.TextureCache.getInstance()._initializingRenderer(); 223 } else { 224 cc.renderContext = localCanvas.getContext("2d"); 225 cc.mainRenderContextBackup = cc.renderContext; 226 cc.renderContextType = cc.CANVAS; 227 cc.renderContext.translate(0, localCanvas.height); 228 cc.drawingUtil = cc.DrawingPrimitiveCanvas ? new cc.DrawingPrimitiveCanvas(cc.renderContext) : null; 229 } 230 231 cc.originalCanvasSize = cc.size(localCanvas.width, localCanvas.height); 232 cc.gameDiv = localContainer; 233 234 cc.log(cc.ENGINE_VERSION); 235 cc.Configuration.getInstance(); 236 237 cc.setContextMenuEnable(false); 238 239 if(cc.Browser.isMobile){ 240 cc._addUserSelectStatus(); 241 } 242 243 var isScreenHidden = false; 244 245 var hidden, visibilityChange; 246 if (typeof document.hidden !== "undefined") { 247 hidden = "hidden"; 248 visibilityChange = "visibilitychange"; 249 } else if (typeof document.mozHidden !== "undefined") { 250 hidden = "mozHidden"; 251 visibilityChange = "mozvisibilitychange"; 252 } else if (typeof document.msHidden !== "undefined") { 253 hidden = "msHidden"; 254 visibilityChange = "msvisibilitychange"; 255 } else if (typeof document.webkitHidden !== "undefined") { 256 hidden = "webkitHidden"; 257 visibilityChange = "webkitvisibilitychange"; 258 } 259 260 function handleFocus() { 261 if (!cc.AudioEngine || !isScreenHidden) return; 262 isScreenHidden = false; 263 var audioEngine = cc.AudioEngine.getInstance(); 264 audioEngine.resumeAllEffects(); 265 audioEngine.resumeMusic(); 266 } 267 268 function handleBlur() { 269 if (!cc.AudioEngine || isScreenHidden) return; 270 isScreenHidden = true; 271 var audioEngine = cc.AudioEngine.getInstance(); 272 audioEngine.pauseAllEffects(); 273 audioEngine.pauseMusic(); 274 } 275 276 function handleVisibilityChange() { 277 if (!document[hidden]) 278 handleFocus(); 279 else 280 handleBlur(); 281 } 282 283 if (typeof document.addEventListener === "undefined" || 284 typeof hidden === "undefined") { 285 cc.isAddedHiddenEvent = false; 286 window.addEventListener("focus", handleFocus, false); 287 window.addEventListener("blur", handleBlur, false); 288 } else { 289 cc.isAddedHiddenEvent = true; 290 document.addEventListener(visibilityChange, handleVisibilityChange, false); 291 } 292 293 if ("onpageshow" in window && "onpagehide" in window) { 294 window.addEventListener("pageshow", handleFocus, false); 295 window.addEventListener("pagehide", handleBlur, false); 296 } 297 298 }; 299 300 cc._addUserSelectStatus = function(){ 301 var fontStyle = document.createElement("style"); 302 fontStyle.type = "text/css"; 303 document.body.appendChild(fontStyle); 304 305 fontStyle.textContent = "body,canvas,div{ -moz-user-select: none;-webkit-user-select: none;-ms-user-select: none;-khtml-user-select: none;" 306 +"-webkit-tap-highlight-color:rgba(0,0,0,0);}"; 307 }; 308 309 cc._isContextMenuEnable = false; 310 /** 311 * enable/disable contextMenu for Canvas 312 * @param {Boolean} enabled 313 */ 314 cc.setContextMenuEnable = function (enabled) { 315 cc._isContextMenuEnable = enabled; 316 if (!cc._isContextMenuEnable) { 317 cc.canvas.oncontextmenu = function () { 318 return false; 319 }; 320 } else { 321 cc.canvas.oncontextmenu = function () { 322 }; 323 } 324 }; 325 326 /** 327 * Run main loop of game engine 328 * @class 329 * @extends cc.Class 330 */ 331 cc.Application = cc.Class.extend(/** @lends cc.Application# */{ 332 _animationInterval:null, 333 /** 334 * Constructor 335 */ 336 ctor:function () { 337 this._animationInterval = 0; 338 if(cc._sharedApplication) 339 throw "Application has been initialized"; 340 cc._sharedApplication = this; 341 }, 342 343 /** 344 * Callback by cc.Director for limit FPS. 345 * @param {Number} interval The time, which expressed in second, between current frame and next. 346 */ 347 setAnimationInterval:function (interval) { 348 this._animationInterval = interval; 349 }, 350 351 /** 352 * Get status bar rectangle in EGLView window. 353 * @param {cc.Rect} rect 354 * @deprecated 355 */ 356 statusBarFrame:function (rect) { 357 if (rect) { 358 // Windows doesn't have status bar. 359 rect = cc.rect(0, 0, 0, 0); 360 } 361 }, 362 363 getTargetPlatform:function(){ 364 return cc.Browser.isMobile ? cc.TARGET_PLATFORM.MOBILE_BROWSER : cc.TARGET_PLATFORM.PC_BROWSER; 365 }, 366 367 /** 368 * Run the message loop. 369 * @return {Number} 370 */ 371 run:function () { 372 // Initialize instance and cocos2d. 373 if (!this.applicationDidFinishLaunching()) 374 return 0; 375 376 var callback, director = cc.Director.getInstance(), w = window; 377 cc.director = director; 378 if (w.requestAnimFrame && this._animationInterval == 1 / 60) { 379 callback = function () { 380 director.mainLoop(); 381 w.requestAnimFrame(callback); 382 }; 383 //cc.log(window.requestAnimFrame); 384 w.requestAnimFrame(callback); 385 } else { 386 callback = function () { 387 director.mainLoop(); 388 }; 389 setInterval(callback, this._animationInterval * 1000); 390 } 391 return 0; 392 } 393 }); 394 395 /** 396 * Get current application instance. 397 * @return {cc.Application} Current application instance pointer. 398 */ 399 cc.Application.getInstance = function () { 400 return cc._sharedApplication; 401 }; 402 403 /** 404 * Get current language config 405 * @return {Number} Current language config 406 */ 407 cc.Application.getCurrentLanguage = function () { 408 var ret = cc.LANGUAGE_ENGLISH; 409 410 var currentLang = navigator.language; 411 if(!currentLang){ 412 currentLang = navigator.browserLanguage || navigator.userLanguage; 413 } 414 if(!currentLang){ 415 return ret; 416 } 417 418 currentLang = currentLang.substring(0,2).toLowerCase(); 419 switch (currentLang) { 420 case "cn": 421 case "zh": 422 ret = cc.LANGUAGE_CHINESE; 423 break; 424 case "fr": 425 ret = cc.LANGUAGE_FRENCH; 426 break; 427 case "it": 428 ret = cc.LANGUAGE_ITALIAN; 429 break; 430 case "de": 431 ret = cc.LANGUAGE_GERMAN; 432 break; 433 case "es": 434 ret = cc.LANGUAGE_SPANISH; 435 break; 436 case "ru": 437 ret = cc.LANGUAGE_RUSSIAN; 438 break; 439 case "ko": 440 ret = cc.LANGUAGE_KOREAN; 441 break; 442 case "ja": 443 ret = cc.LANGUAGE_JAPANESE; 444 break; 445 case "hu": 446 ret = cc.LANGUAGE_HUNGARIAN; 447 break; 448 case "pt": 449 ret = cc.LANGUAGE_PORTUGUESE; 450 break; 451 case "ar": 452 ret = cc.LANGUAGE_ARABIC; 453 break; 454 case "no": 455 ret = cc.LANGUAGE_NORWEGIAN; 456 break; 457 case "pl": 458 ret = cc.LANGUAGE_POLISH; 459 break; 460 } 461 462 return ret; 463 }; 464 465 cc._sharedApplication = null; 466