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 /** 29 * Device oriented vertically, home button on the bottom 30 * @constant 31 * @type Number 32 */ 33 cc.ORIENTATION_PORTRAIT = 0; 34 35 /** 36 * Device oriented vertically, home button on the top 37 * @constant 38 * @type Number 39 */ 40 cc.ORIENTATION_PORTRAIT_UPSIDE_DOWN = 1; 41 42 /** 43 * Device oriented horizontally, home button on the right 44 * @constant 45 * @type Number 46 */ 47 cc.ORIENTATION_LANDSCAPE_LEFT = 2; 48 49 /** 50 * Device oriented horizontally, home button on the left 51 * @constant 52 * @type Number 53 */ 54 cc.ORIENTATION_LANDSCAPE_RIGHT = 3; 55 56 //engine render type 57 58 /** 59 * Canvas of render type 60 * @constant 61 * @type Number 62 */ 63 cc.CANVAS = 0; 64 65 /** 66 * WebGL of render type 67 * @constant 68 * @type Number 69 */ 70 cc.WEBGL = 1; 71 72 /** 73 * drawing primitive of game engine 74 * @type cc.DrawingPrimitive 75 */ 76 cc.drawingUtil = null; 77 78 /** 79 * main Canvas 2D Context of game engine 80 * @type CanvasContext 81 */ 82 cc.renderContext = null; 83 84 /** 85 * main Canvas of game engine 86 * @type HTMLCanvasElement 87 */ 88 cc.canvas = null; 89 90 /** 91 * This Div element contain all game canvas 92 * @type HTMLDivElement 93 */ 94 cc.gameDiv = null; 95 96 /** 97 * current render type of game engine 98 * @type Number 99 */ 100 cc.renderContextType = cc.CANVAS; 101 102 /** 103 * save original size of canvas, use for resize canvas 104 * @type cc.Size 105 */ 106 cc.originalCanvasSize = cc.size(0, 0); 107 108 window.requestAnimFrame = (function () { 109 return window.requestAnimationFrame || 110 window.webkitRequestAnimationFrame || 111 window.mozRequestAnimationFrame || 112 window.oRequestAnimationFrame || 113 window.msRequestAnimationFrame 114 })(); 115 116 117 if (!window.console) { 118 window.console = {}; 119 window.console.log = function () { 120 }; 121 window.console.assert = function () { 122 }; 123 } 124 125 126 cc.isAddedHiddenEvent = false; 127 128 /** 129 * <p> 130 * setup game main canvas,renderContext,gameDiv and drawingUtil with argument <br/> 131 * <br/> 132 * can receive follow type of arguemnt: <br/> 133 * - empty: create a canvas append to document's body, and setup other option <br/> 134 * - string: search the element by document.getElementById(), <br/> 135 * if this element is HTMLCanvasElement, set this element as main canvas of engine, and set it's ParentNode as cc.gameDiv.<br/> 136 * if this element is HTMLDivElement, set it's ParentNode to cc.gameDiv, and create a canvas as main canvas of engine. <br/> 137 * </p> 138 * @function 139 * @example 140 * //setup with null 141 * cc.setup(); 142 * 143 * // setup with HTMLCanvasElement, gameCanvas is Canvas element 144 * // declare like this: <canvas id="gameCanvas" width="800" height="450"></canvas> 145 * cc.setup("gameCanvas"); 146 * 147 * //setup with HTMLDivElement, gameDiv is Div element 148 * // declare like this: <div id="Cocos2dGameContainer" width="800" height="450"></div> 149 * cc.setup("Cocos2dGameContainer"); 150 */ 151 cc.setup = function (el, width, height) { 152 var element = cc.$(el) || cc.$('#' + el); 153 if (element.tagName == "CANVAS") { 154 width = width || element.width; 155 height = height || element.height; 156 157 //it is already a canvas, we wrap it around with a div 158 cc.container = cc.$new("DIV"); 159 cc.canvas = element; 160 cc.canvas.parentNode.insertBefore(cc.container, cc.canvas); 161 cc.canvas.appendTo(cc.container); 162 cc.container.style.width = (width || 480) + "px"; 163 cc.container.style.height = (height || 320) + "px"; 164 cc.container.setAttribute('id', 'Cocos2dGameContainer'); 165 cc.canvas.setAttribute("width", width || 480); 166 cc.canvas.setAttribute("height", height || 320); 167 } else {//we must make a new canvas and place into this element 168 if (element.tagName != "DIV") { 169 cc.log("Warning: target element is not a DIV or CANVAS"); 170 } 171 width = width || parseInt(element.style.width); 172 height = height || parseInt(element.style.height); 173 174 cc.canvas = cc.$new("CANVAS"); 175 cc.canvas.addClass("gameCanvas"); 176 cc.canvas.setAttribute("width", width || 480); 177 cc.canvas.setAttribute("height", height || 320); 178 cc.container = element; 179 element.appendChild(cc.canvas); 180 cc.container.style.width = (width || 480) + "px"; 181 cc.container.style.height = (height || 320) + "px"; 182 } 183 cc.container.style.position = 'relative'; 184 cc.container.style.overflow = 'hidden'; 185 cc.container.top = '100%'; 186 cc.renderContext = cc.canvas.getContext("2d"); 187 cc.renderContextType = cc.CANVAS; 188 if (cc.renderContextType == cc.CANVAS) { 189 cc.renderContext.translate(0, cc.canvas.height); 190 cc.drawingUtil = new cc.DrawingPrimitiveCanvas(cc.renderContext); 191 } 192 cc.originalCanvasSize = cc.size(cc.canvas.width, cc.canvas.height); 193 cc.gameDiv = cc.container; 194 195 cc.log(cc.ENGINE_VERSION); 196 197 cc.setContextMenuEnable(false); 198 199 //binding window size 200 /* 201 cc.canvas.addEventListener("resize", function () { 202 if (!cc.firstRun) { 203 cc.Director.getInstance().addRegionToDirtyRegion(cc.rect(0, 0, cc.canvas.width, cc.canvas.height)); 204 } 205 }, true); 206 */ 207 if(cc.Browser.isMobile) 208 cc._addUserSelectStatus(); 209 210 var hidden, visibilityChange; 211 if (typeof document.hidden !== "undefined") { 212 hidden = "hidden"; 213 visibilityChange = "visibilitychange"; 214 } else if (typeof document.mozHidden !== "undefined") { 215 hidden = "mozHidden"; 216 visibilityChange = "mozvisibilitychange"; 217 } else if (typeof document.msHidden !== "undefined") { 218 hidden = "msHidden"; 219 visibilityChange = "msvisibilitychange"; 220 } else if (typeof document.webkitHidden !== "undefined") { 221 hidden = "webkitHidden"; 222 visibilityChange = "webkitvisibilitychange"; 223 } 224 225 function handleVisibilityChange() { 226 if (!document[hidden]) 227 cc.Director.getInstance()._resetLastUpdate(); 228 } 229 230 if (typeof document.addEventListener === "undefined" || 231 typeof hidden === "undefined") { 232 cc.isAddedHiddenEvent = false; 233 } else { 234 cc.isAddedHiddenEvent = true; 235 document.addEventListener(visibilityChange, handleVisibilityChange, false); 236 } 237 }; 238 239 cc._addUserSelectStatus = function(){ 240 var fontStyle = document.createElement("style"); 241 fontStyle.type = "text/css"; 242 document.body.appendChild(fontStyle); 243 244 fontStyle.textContent = "body,canvas,div{ -moz-user-select: none;-webkit-user-select: none;-ms-user-select: none;-khtml-user-select: none;" 245 +"-webkit-tap-highlight-color:rgba(0,0,0,0);}"; 246 }; 247 248 cc._isContextMenuEnable = false; 249 /** 250 * enable/disable contextMenu for Canvas 251 * @param {Boolean} enabled 252 */ 253 cc.setContextMenuEnable = function (enabled) { 254 cc._isContextMenuEnable = enabled; 255 if (!cc._isContextMenuEnable) { 256 cc.canvas.oncontextmenu = function () { 257 event.returnValue = false; 258 }; 259 } else { 260 cc.canvas.oncontextmenu = function () { 261 }; 262 } 263 }; 264 265 /** 266 * Run main loop of game engine 267 * @class 268 * @extends cc.Class 269 */ 270 cc.Application = cc.Class.extend(/** @lends cc.Application# */{ 271 /** 272 * Constructor 273 */ 274 ctor:function () { 275 this._animationInterval = 0; 276 cc.Assert(!cc._sharedApplication, "CCApplication ctor"); 277 cc._sharedApplication = this; 278 }, 279 280 /** 281 * Callback by cc.Director for limit FPS. 282 * @param {Number} interval The time, which expressed in second, between current frame and next. 283 */ 284 setAnimationInterval:function (interval) { 285 this._animationInterval = interval; 286 }, 287 288 /** 289 * Get status bar rectangle in EGLView window. 290 * @param {cc.Rect} rect 291 * @deprecated 292 */ 293 statusBarFrame:function (rect) { 294 if (rect) { 295 // Windows doesn't have status bar. 296 rect = cc.rect(0, 0, 0, 0); 297 } 298 }, 299 300 /** 301 * Run the message loop. 302 * @return {Number} 303 */ 304 run:function () { 305 // Initialize instance and cocos2d. 306 if (!this.applicationDidFinishLaunching()) { 307 return 0; 308 } 309 // TODO, need to be fixed. 310 if (window.requestAnimFrame && this._animationInterval == 1 / 60) { 311 var callback = function () { 312 cc.Director.getInstance().mainLoop(); 313 window.requestAnimFrame(callback); 314 }; 315 cc.log(window.requestAnimFrame); 316 window.requestAnimFrame(callback); 317 } 318 else { 319 var callback = function () { 320 cc.Director.getInstance().mainLoop(); 321 }; 322 setInterval(callback, this._animationInterval * 1000); 323 } 324 325 }, 326 _animationInterval:null 327 }); 328 329 /** 330 * Get current applicaiton instance. 331 * @return {cc.Application} Current application instance pointer. 332 */ 333 cc.Application.sharedApplication = function () { 334 335 cc.Assert(cc._sharedApplication, "sharedApplication"); 336 return cc._sharedApplication; 337 }; 338 339 /** 340 * Get current language config 341 * @return {Number} Current language config 342 */ 343 cc.Application.getCurrentLanguage = function () { 344 var ret = cc.LANGUAGE_ENGLISH; 345 346 var currentLang = navigator.language; 347 currentLang = currentLang.toLowerCase(); 348 switch (currentLang) { 349 case "zh-cn": 350 ret = cc.LANGUAGE_CHINESE; 351 break; 352 case "fr": 353 ret = cc.LANGUAGE_FRENCH; 354 break; 355 case "it": 356 ret = cc.LANGUAGE_ITALIAN; 357 break; 358 case "de": 359 ret = cc.LANGUAGE_GERMAN; 360 break; 361 case "es": 362 ret = cc.LANGUAGE_SPANISH; 363 break; 364 case "ru": 365 ret = cc.LANGUAGE_RUSSIAN; 366 break; 367 } 368 369 return ret; 370 }; 371 372 cc._sharedApplication = null; 373