phaser/Phaser/Stage.ts

436 lines
13 KiB
TypeScript
Raw Normal View History

2013-04-18 13:16:18 +00:00
/// <reference path="Phaser.ts" />
2013-04-12 16:19:56 +00:00
/// <reference path="Game.ts" />
2013-08-06 02:14:48 +00:00
/// <reference path="display/CSS3Filters.ts" />
/// <reference path="system/StageScaleMode.ts" />
/// <reference path="system/screens/BootScreen.ts" />
/// <reference path="system/screens/PauseScreen.ts" />
/// <reference path="system/screens/OrientationScreen.ts" />
2013-04-12 16:19:56 +00:00
2013-04-18 13:16:18 +00:00
/**
2013-04-18 15:49:08 +00:00
* Phaser - Stage
*
* The Stage is the canvas on which everything is displayed. This class handles display within the web browser, focus handling,
* resizing, scaling and pause/boot screens.
2013-04-18 13:16:18 +00:00
*/
2013-04-12 16:19:56 +00:00
2013-04-18 13:16:18 +00:00
module Phaser {
2013-04-12 16:19:56 +00:00
2013-04-18 13:16:18 +00:00
export class Stage {
2013-04-12 16:19:56 +00:00
/**
* Stage constructor
*
* Create a new <code>Stage</code> with specific width and height.
*
* @param parent {number} ID of parent DOM element.
* @param width {number} Width of the stage.
* @param height {number} Height of the stage.
*/
2013-04-18 13:16:18 +00:00
constructor(game: Game, parent: string, width: number, height: number) {
2013-04-12 16:19:56 +00:00
this.game = game;
2013-04-12 16:19:56 +00:00
2013-04-18 13:16:18 +00:00
this.canvas = <HTMLCanvasElement> document.createElement('canvas');
this.canvas.width = width;
this.canvas.height = height;
2013-04-12 16:19:56 +00:00
if ((parent !== '' || parent !== null) && document.getElementById(parent))
2013-04-18 13:16:18 +00:00
{
document.getElementById(parent).appendChild(this.canvas);
document.getElementById(parent).style.overflow = 'hidden';
}
else
{
document.body.appendChild(this.canvas);
}
2013-04-12 16:19:56 +00:00
// Consume default actions on the canvas
this.canvas.style.msTouchAction = 'none';
2013-05-16 01:36:58 +00:00
this.canvas.style['ms-touch-action'] = 'none';
this.canvas.style['touch-action'] = 'none';
this.canvas.style.backgroundColor = 'rgb(0,0,0)';
this.canvas.oncontextmenu = function(event) { event.preventDefault(); };
2013-04-18 13:16:18 +00:00
this.context = this.canvas.getContext('2d');
2013-04-12 16:19:56 +00:00
2013-08-06 02:14:48 +00:00
this.css3 = new Phaser.Display.CSS3Filters(this.canvas);
2013-04-18 13:16:18 +00:00
this.scaleMode = StageScaleMode.NO_SCALE;
this.scale = new StageScaleMode(this.game, width, height);
2013-04-18 13:16:18 +00:00
this.getOffset(this.canvas);
this.bounds = new Rectangle(this.offset.x, this.offset.y, width, height);
this.aspectRatio = width / height;
document.addEventListener('visibilitychange', (event) => this.visibilityChange(event), false);
document.addEventListener('webkitvisibilitychange', (event) => this.visibilityChange(event), false);
document.addEventListener('pagehide', (event) => this.visibilityChange(event), false);
document.addEventListener('pageshow', (event) => this.visibilityChange(event), false);
2013-04-18 13:16:18 +00:00
window.onblur = (event) => this.visibilityChange(event);
window.onfocus = (event) => this.visibilityChange(event);
}
/**
* Local reference to Game.
*/
public game: Game;
2013-05-11 22:51:50 +00:00
/**
* Background color of the stage (defaults to black). Set via the public backgroundColor property.
* @type {string}
*/
private _backgroundColor: string = 'rgb(0,0,0)';
2013-05-11 22:51:50 +00:00
/**
* This will be displayed when Phaser is started without any default functions or State
* @type {BootScreen}
*/
public bootScreen;
2013-05-11 22:51:50 +00:00
/**
* This will be displayed whenever the game loses focus or the player switches to another browser tab.
* @type {PauseScreen}
*/
public pauseScreen;
/**
* This will be displayed whenever the device is turned to an unsupported orientation.
* @type {OrientationScreen}
*/
public orientationScreen;
2013-04-12 16:19:56 +00:00
/**
* Controls the CSS3 Filters applied to the Stages canvas object.
2013-08-06 02:14:48 +00:00
* @type {Phaser.Display.CSS3Filters}
*/
2013-08-06 02:14:48 +00:00
public css3: Phaser.Display.CSS3Filters;
/**
* Bound of this stage.
2013-05-28 20:38:37 +00:00
* @type {Rectangle}
*/
2013-05-28 20:38:37 +00:00
public bounds: Rectangle;
2013-05-11 22:51:50 +00:00
/**
* Asperct ratio, thus: width / height.
* @type {number}
*/
2013-04-18 13:16:18 +00:00
public aspectRatio: number;
2013-05-11 22:51:50 +00:00
/**
* Clear the whole stage every frame? (Default to true)
* @type {boolean}
*/
2013-08-08 10:34:33 +00:00
public clear: boolean = true;
2013-05-11 22:51:50 +00:00
/**
* Canvas element used by engine.
* @type {HTMLCanvasElement}
*/
2013-04-18 13:16:18 +00:00
public canvas: HTMLCanvasElement;
2013-05-11 22:51:50 +00:00
/**
* Render context of stage's canvas.
* @type {CanvasRenderingContext2D}
*/
2013-04-18 13:16:18 +00:00
public context: CanvasRenderingContext2D;
2013-05-11 22:51:50 +00:00
/**
* Do not use pause screen when game is paused?
* (Default to false, aka always use PauseScreen)
* @type {boolean}
*/
2013-08-08 10:34:33 +00:00
public disablePauseScreen: boolean = false;
2013-05-11 22:51:50 +00:00
/**
* Do not use boot screen when engine starts?
* (Default to false, aka always use BootScreen)
* @type {boolean}
*/
2013-08-08 10:34:33 +00:00
public disableBootScreen: boolean = false;
2013-05-11 22:51:50 +00:00
/**
* Offset from this stage to the canvas element.
2013-05-16 01:36:58 +00:00
* @type {MicroPoint}
*/
2013-05-28 20:38:37 +00:00
public offset: Point;
2013-05-11 22:51:50 +00:00
/**
* This object manages scaling of the game, see(StageScaleMode).
* @type {StageScaleMode}
*/
2013-04-18 13:16:18 +00:00
public scale: StageScaleMode;
2013-05-11 22:51:50 +00:00
/**
* Which mode will the game be scaled.
* Available: StageScaleMode.EXACT_FIT, StageScaleMode.NO_SCALE, StageScaleMode.SHOW_ALL.
* @type {number}
*/
2013-04-18 13:16:18 +00:00
public scaleMode: number;
2013-08-01 21:21:03 +00:00
/**
* If set to true the game will never pause when the browser or browser tab loses focuses
* @type {boolean}
*/
2013-08-08 10:34:33 +00:00
public disableVisibilityChange: boolean = false;
2013-08-01 21:21:03 +00:00
/**
* Stage boot
*/
public boot() {
this.bootScreen = new BootScreen(this.game);
this.pauseScreen = new PauseScreen(this.game, this.width, this.height);
this.orientationScreen = new OrientationScreen(this.game);
this.scale.setScreenSize(true);
}
/**
* Update stage for rendering. This will handle scaling, clearing
* and PauseScreen/BootScreen updating and rendering.
*/
2013-04-18 13:16:18 +00:00
public update() {
this.scale.update();
this.context.setTransform(1, 0, 0, 1, 0, 0);
if (this.clear || (this.game.paused && this.disablePauseScreen == false))
2013-04-18 13:16:18 +00:00
{
if (this.game.device.patchAndroidClearRectBug)
{
this.context.fillStyle = 'rgb(0,0,0)';
this.context.fillRect(0, 0, this.width, this.height);
}
else
{
this.context.clearRect(0, 0, this.width, this.height);
}
2013-04-18 13:16:18 +00:00
}
if (this.game.paused && this.scale.incorrectOrientation)
{
this.orientationScreen.update();
this.orientationScreen.render();
return;
}
if (this.game.isRunning == false && this.disableBootScreen == false)
{
this.bootScreen.update();
this.bootScreen.render();
}
2013-04-12 16:19:56 +00:00
if (this.game.paused && this.disablePauseScreen == false)
{
this.pauseScreen.update();
this.pauseScreen.render();
}
2013-04-12 16:19:56 +00:00
2013-04-18 13:16:18 +00:00
}
2013-04-12 16:19:56 +00:00
/**
* This method is called when the canvas elements visibility is changed.
*/
2013-04-18 13:16:18 +00:00
private visibilityChange(event) {
2013-08-01 21:21:03 +00:00
if (this.disableVisibilityChange)
{
return;
}
if (event.type == 'pagehide' || event.type == 'blur' || document['hidden'] == true || document['webkitHidden'] == true)
2013-04-18 13:16:18 +00:00
{
if (this.game.paused == false)
{
2013-05-22 23:01:58 +00:00
this.pauseGame();
}
2013-04-18 13:16:18 +00:00
}
else
2013-04-18 13:16:18 +00:00
{
if (this.game.paused == true)
{
2013-05-22 23:01:58 +00:00
this.resumeGame();
}
2013-04-18 13:16:18 +00:00
}
2013-04-12 16:19:56 +00:00
}
2013-04-18 13:16:18 +00:00
2013-08-08 10:34:33 +00:00
public enableOrientationCheck(forceLandscape: boolean, forcePortrait: boolean, imageKey: string = '') {
this.scale.forceLandscape = forceLandscape;
this.scale.forcePortrait = forcePortrait;
this.orientationScreen.enable(forceLandscape, forcePortrait, imageKey);
if (forceLandscape || forcePortrait)
{
if ((this.scale.isLandscape && forcePortrait) || (this.scale.isPortrait && forceLandscape))
{
// They are in the wrong orientation right now
this.game.paused = true;
this.scale.incorrectOrientation = true;
}
else
{
this.scale.incorrectOrientation = false;
}
}
}
public setImageRenderingCrisp() {
this.canvas.style['image-rendering'] = 'crisp-edges';
this.canvas.style['image-rendering'] = '-moz-crisp-edges';
this.canvas.style['image-rendering'] = '-webkit-optimize-contrast';
this.canvas.style['-ms-interpolation-mode'] = 'nearest-neighbor';
}
2013-05-22 23:01:58 +00:00
public pauseGame() {
this.game.paused = true;
if (this.disablePauseScreen == false && this.pauseScreen)
{
this.pauseScreen.onPaused();
}
2013-05-22 23:01:58 +00:00
this.saveCanvasValues();
2013-08-06 02:14:48 +00:00
2013-05-22 23:01:58 +00:00
}
public resumeGame() {
if (this.disablePauseScreen == false && this.pauseScreen)
{
this.pauseScreen.onResume();
}
2013-05-22 23:01:58 +00:00
this.restoreCanvasValues();
2013-08-06 02:14:48 +00:00
this.game.paused = false;
2013-05-22 23:01:58 +00:00
}
/**
* Get the DOM offset values of the given element
*/
2013-08-08 10:34:33 +00:00
public getOffset(element, populateOffset: boolean = true): Point {
2013-04-12 16:19:56 +00:00
2013-04-18 13:16:18 +00:00
var box = element.getBoundingClientRect();
2013-04-12 16:19:56 +00:00
2013-04-18 13:16:18 +00:00
var clientTop = element.clientTop || document.body.clientTop || 0;
var clientLeft = element.clientLeft || document.body.clientLeft || 0;
var scrollTop = window.pageYOffset || element.scrollTop || document.body.scrollTop;
var scrollLeft = window.pageXOffset || element.scrollLeft || document.body.scrollLeft;
2013-04-12 16:19:56 +00:00
if (populateOffset)
{
this.offset = new Point(box.left + scrollLeft - clientLeft, box.top + scrollTop - clientTop);
return this.offset;
}
else
{
return new Point(box.left + scrollLeft - clientLeft, box.top + scrollTop - clientTop);
}
2013-04-12 16:19:56 +00:00
2013-04-18 13:16:18 +00:00
}
2013-04-12 16:19:56 +00:00
/**
* Canvas strokeStyle.
* @type {string}
*/
2013-04-18 13:16:18 +00:00
public strokeStyle: string;
2013-05-11 22:51:50 +00:00
/**
* Canvas lineWidth.
* @type {number}
*/
2013-04-18 13:16:18 +00:00
public lineWidth: number;
2013-05-11 22:51:50 +00:00
/**
* Canvas fillStyle.
* @type {string}
*/
2013-04-18 13:16:18 +00:00
public fillStyle: string;
2013-04-12 16:19:56 +00:00
/**
* Save current canvas properties (strokeStyle, lineWidth and fillStyle) for later using.
*/
2013-04-18 13:16:18 +00:00
public saveCanvasValues() {
2013-04-12 16:19:56 +00:00
2013-04-18 13:16:18 +00:00
this.strokeStyle = this.context.strokeStyle;
this.lineWidth = this.context.lineWidth;
this.fillStyle = this.context.fillStyle;
2013-04-12 16:19:56 +00:00
2013-04-18 13:16:18 +00:00
}
2013-04-12 16:19:56 +00:00
/**
* Restore current canvas values (strokeStyle, lineWidth and fillStyle) with saved values.
*/
2013-04-18 13:16:18 +00:00
public restoreCanvasValues() {
2013-04-12 16:19:56 +00:00
2013-04-18 13:16:18 +00:00
this.context.strokeStyle = this.strokeStyle;
this.context.lineWidth = this.lineWidth;
this.context.fillStyle = this.fillStyle;
2013-04-12 16:19:56 +00:00
if (this.game.device.patchAndroidClearRectBug)
2013-08-06 02:14:48 +00:00
{
this.context.fillStyle = 'rgb(0,0,0)';
this.context.fillRect(0, 0, this.width, this.height);
}
else
{
this.context.clearRect(0, 0, this.width, this.height);
}
2013-04-18 13:16:18 +00:00
}
2013-04-12 16:19:56 +00:00
2013-04-18 13:16:18 +00:00
public set backgroundColor(color: string) {
2013-08-06 02:14:48 +00:00
2013-04-18 13:16:18 +00:00
this.canvas.style.backgroundColor = color;
this._backgroundColor = color;
2013-08-06 02:14:48 +00:00
2013-04-18 13:16:18 +00:00
}
2013-04-12 16:19:56 +00:00
2013-04-18 13:16:18 +00:00
public get backgroundColor(): string {
return this._backgroundColor;
2013-04-18 13:16:18 +00:00
}
2013-04-12 16:19:56 +00:00
2013-04-18 13:16:18 +00:00
public get x(): number {
return this.bounds.x;
}
2013-04-12 16:19:56 +00:00
2013-04-18 13:16:18 +00:00
public get y(): number {
return this.bounds.y;
}
2013-04-12 16:19:56 +00:00
2013-04-18 13:16:18 +00:00
public get width(): number {
return this.bounds.width;
}
2013-04-12 16:19:56 +00:00
2013-04-18 13:16:18 +00:00
public get height(): number {
return this.bounds.height;
}
2013-04-12 16:19:56 +00:00
2013-04-18 13:16:18 +00:00
public get centerX(): number {
return this.bounds.halfWidth;
}
2013-04-12 16:19:56 +00:00
2013-04-18 13:16:18 +00:00
public get centerY(): number {
return this.bounds.halfHeight;
}
2013-04-12 16:19:56 +00:00
2013-04-18 13:16:18 +00:00
public get randomX(): number {
return Math.round(Math.random() * this.bounds.width);
}
2013-04-12 16:19:56 +00:00
2013-04-18 13:16:18 +00:00
public get randomY(): number {
return Math.round(Math.random() * this.bounds.height);
}
2013-04-12 16:19:56 +00:00
2013-04-18 13:16:18 +00:00
}
2013-04-12 16:19:56 +00:00
}