Added FullScreen API support and fixed numerous StageScaleMode issues.

This commit is contained in:
Richard Davey
2013-05-14 03:37:38 +01:00
parent 8fc31ed83b
commit ce7bfd1fc2
37 changed files with 11227 additions and 2853 deletions
+51 -14
View File
@@ -58,16 +58,19 @@ module Phaser {
* @type {number}
*/
public static STYLE_LOCKON: number = 0;
/**
* Camera "follow" style preset: camera deadzone is narrow but tall.
* @type {number}
*/
public static STYLE_PLATFORMER: number = 1;
/**
* Camera "follow" style preset: camera deadzone is a medium-size square around the focus object.
* @type {number}
*/
public static STYLE_TOPDOWN: number = 2;
/**
* Camera "follow" style preset: camera deadzone is a small square around the focus object.
* @type {number}
@@ -78,31 +81,37 @@ module Phaser {
* Identity of this camera.
*/
public ID: number;
/**
* Camera view rectangle in world coordinate.
* @type {Rectangle}
*/
public worldView: Rectangle;
/**
* How many sprites will be rendered by this camera.
* @type {number}
*/
public totalSpritesRendered: number;
/**
* Scale factor of the camera.
* @type {MicroPoint}
*/
public scale: MicroPoint = new MicroPoint(1, 1);
/**
* Scrolling factor.
* @type {MicroPoint}
*/
public scroll: MicroPoint = new MicroPoint(0, 0);
/**
* Camera bounds.
* @type {Rectangle}
*/
public bounds: Rectangle = null;
/**
* Sprite moving inside this rectangle will not cause camera moving.
* @type {Rectangle}
@@ -111,32 +120,47 @@ module Phaser {
// Camera Border
public disableClipping: bool = false;
/**
* Whether render border of this camera or not. (default is false)
* @type {boolean}
*/
public showBorder: bool = false;
/**
* Color of border of this camera. (in css color string)
* @type {string}
*/
public borderColor: string = 'rgb(255,255,255)';
// Camera Background Color
/**
* Whethor camera background invisible or not.
* Whether the camera background is opaque or not. If set to true the Camera is filled with
* the value of Camera.backgroundColor every frame.
* @type {boolean}
*/
public opaque: bool = true;
public opaque: bool = false;
/**
* Clears the camera every frame using a canvas clearRect call (default to true).
* Note that this erases anything below the camera as well, so do not use it in conjuction with a camera
* that uses alpha or that needs to be able to manage opacity. Equally if Camera.opaque is set to true
* then set Camera.clear to false to save rendering time.
* By default the Stage will clear itself every frame, so be sure not to double-up clear calls.
* @type {boolean}
*/
public clear: bool = false;
/**
* Background color in css color string.
* @type {string}
*/
private _bgColor: string = 'rgb(0,0,0)';
/**
* Background texture to be rendered if background is visible.
*/
private _bgTexture;
/**
* Background texture repeat style. (default is 'repeat')
* @type {string}
@@ -149,16 +173,19 @@ module Phaser {
* @type {boolean}
*/
public showShadow: bool = false;
/**
* Color of shadow, in css color string.
* @type {string}
*/
public shadowColor: string = 'rgb(0,0,0)';
/**
* Blur factor of shadow.
* @type {number}
*/
public shadowBlur: number = 10;
/**
* Offset of the shadow from camera's position.
* @type {MicroPoint}
@@ -170,6 +197,7 @@ module Phaser {
* @type {boolean}
*/
public visible: bool = true;
/**
* Alpha of the camera. (everything rendered to this camera will be affected)
* @type {number}
@@ -181,6 +209,7 @@ module Phaser {
* @type {number}
*/
public inputX: number = 0;
/**
* The y position of the current input event in world coordinates.
* @type {number}
@@ -373,13 +402,13 @@ module Phaser {
return;
}
//if (this._rotation !== 0 || this._clip || this.scale.x !== 1 || this.scale.y !== 1)
//{
//this._game.stage.context.save();
//}
if (this._rotation !== 0 || this._clip || this.scale.x !== 1 || this.scale.y !== 1)
{
this._game.stage.context.save();
}
// It may be safer/quicker to just save the context every frame regardless (needs testing on mobile)
this._game.stage.context.save();
// It may be safer/quicker to just save the context every frame regardless (needs testing on mobile - sucked on Android 2.x)
//this._game.stage.context.save();
this.fx.preRender(this, this._stageX, this._stageY, this.worldView.width, this.worldView.height);
@@ -392,7 +421,7 @@ module Phaser {
this._sy = this._stageY;
// Shadow
if (this.showShadow)
if (this.showShadow == true)
{
this._game.stage.context.shadowColor = this.shadowColor;
this._game.stage.context.shadowBlur = this.shadowBlur;
@@ -418,6 +447,11 @@ module Phaser {
this._game.stage.context.translate(-(this._sx + this.worldView.halfWidth), -(this._sy + this.worldView.halfHeight));
}
if (this.clear == true)
{
this._game.stage.context.clearRect(this._sx, this._sy, this.worldView.width, this.worldView.height);
}
// Background
if (this.opaque == true)
{
@@ -434,7 +468,7 @@ module Phaser {
}
// Shadow off
if (this.showShadow)
if (this.showShadow == true)
{
this._game.stage.context.shadowBlur = 0;
this._game.stage.context.shadowOffsetX = 0;
@@ -444,7 +478,7 @@ module Phaser {
this.fx.render(this, this._stageX, this._stageY, this.worldView.width, this.worldView.height);
// Clip the camera so we don't get sprites appearing outside the edges
if (this._clip && this.disableClipping == false)
if (this._clip == true && this.disableClipping == false)
{
this._game.stage.context.beginPath();
this._game.stage.context.rect(this._sx, this._sy, this.worldView.width, this.worldView.height);
@@ -454,7 +488,7 @@ module Phaser {
this._game.world.group.render(this, this._sx, this._sy);
if (this.showBorder)
if (this.showBorder == true)
{
this._game.stage.context.strokeStyle = this.borderColor;
this._game.stage.context.lineWidth = 1;
@@ -475,7 +509,10 @@ module Phaser {
this._game.stage.context.translate(0, 0);
}
this._game.stage.context.restore();
if (this._rotation !== 0 || this._clip || this.scale.x !== 1 || this.scale.y !== 1)
{
this._game.stage.context.restore();
}
if (this.alpha !== 1)
{
+31 -65
View File
@@ -15,10 +15,10 @@ module Phaser {
* @param {Any} callback
* @return {RequestAnimationFrame} This object.
*/
constructor(callback, callbackContext) {
constructor(game: Game, callback) {
this._callback = callback;
this._callbackContext = callbackContext;
this._game = game;
this.callback = callback;
var vendors = ['ms', 'moz', 'webkit', 'o'];
@@ -33,24 +33,16 @@ module Phaser {
}
/**
*
* @property _callback
* @type Any
* @private
**/
private _callback;
private _callbackContext;
* Local private reference to game.
*/
private _game: Game;
/**
*
* @method callback
* @param {Any} callback
* The function to be called each frame. Will be called in the context of _game
* @property callback
* @type Any
**/
public setCallback(callback) {
this._callback = callback;
}
public callback;
/**
*
@@ -86,30 +78,10 @@ module Phaser {
**/
public isUsingRAF(): bool {
if (this._isSetTimeOut === true)
{
return false;
}
else
{
return true;
}
return this._isSetTimeOut === true;
}
/**
*
* @property lastTime
* @type Number
**/
public lastTime: number = 0;
/**
*
* @property currentTime
* @type Number
**/
public currentTime: number = 0;
/**
*
* @property isRunning
@@ -118,7 +90,7 @@ module Phaser {
public isRunning: bool = false;
/**
*
* Starts the requestAnimatioFrame running or setTimeout if unavailable in browser
* @method start
* @param {Any} [callback]
**/
@@ -126,7 +98,7 @@ module Phaser {
if (callback)
{
this._callback = callback;
this.callback = callback;
}
if (!window.requestAnimationFrame)
@@ -137,7 +109,7 @@ module Phaser {
else
{
this._isSetTimeOut = false;
window.requestAnimationFrame(() => this.RAFUpdate());
window.requestAnimationFrame(() => this.RAFUpdate(0));
}
this.isRunning = true;
@@ -145,7 +117,7 @@ module Phaser {
}
/**
*
* Stops the requestAnimationFrame from running
* @method stop
**/
public stop() {
@@ -163,44 +135,38 @@ module Phaser {
}
public RAFUpdate() {
/**
* The update method for the requestAnimationFrame
* @method RAFUpdate
**/
public RAFUpdate(time: number) {
// Not in IE8 (but neither is RAF) also doesn't use a high performance timer (window.performance.now)
this.currentTime = Date.now();
this._game.time.update(time);
if (this._callback)
if (this.callback)
{
this._callback.call(this._callbackContext);
this.callback.call(this._game);
}
var timeToCall: number = Math.max(0, 16 - (this.currentTime - this.lastTime));
window.requestAnimationFrame(() => this.RAFUpdate());
this.lastTime = this.currentTime + timeToCall;
window.requestAnimationFrame((time) => this.RAFUpdate(time));
}
/**
*
* The update method for the setTimeout
* @method SetTimeoutUpdate
**/
public SetTimeoutUpdate() {
// Not in IE8
this.currentTime = Date.now();
this._game.time.update(Date.now());
if (this._callback)
this._timeOutID = window.setTimeout(() => this.SetTimeoutUpdate(), 16.7);
if (this.callback)
{
this._callback.call(this._callbackContext);
this.callback.call(this._game);
}
var timeToCall: number = Math.max(0, 16 - (this.currentTime - this.lastTime));
this._timeOutID = window.setTimeout(() => this.SetTimeoutUpdate(), timeToCall);
this.lastTime = this.currentTime + timeToCall;
}
}
+175 -18
View File
@@ -5,7 +5,7 @@
*
* This class controls the scaling of your game. On mobile devices it will also remove the URL bar and allow
* you to maintain proportion and aspect ratio.
* It is based on a technique taken from Viewporter v2.0 by Zynga Inc. http://github.com/zynga/viewporter
* The resizing method is based on a technique taken from Viewporter v2.0 by Zynga Inc. http://github.com/zynga/viewporter
*/
module Phaser {
@@ -19,9 +19,27 @@ module Phaser {
this._game = game;
this.orientation = window['orientation'];
this.enterLandscape = new Phaser.Signal();
this.enterPortrait = new Phaser.Signal();
if (window['orientation'])
{
this.orientation = window['orientation'];
}
else
{
if (window.outerWidth > window.outerHeight)
{
this.orientation = 90;
}
else
{
this.orientation = 0;
}
}
window.addEventListener('orientationchange', (event) => this.checkOrientation(event), false);
window.addEventListener('resize', (event) => this.checkResize(event), false);
}
@@ -29,6 +47,7 @@ module Phaser {
* Local private reference to game.
*/
private _game: Game;
/**
* Stage height when start the game.
* @type {number}
@@ -55,11 +74,38 @@ module Phaser {
*/
public static SHOW_ALL: number = 2;
/**
* Minimum width the canvas should be scaled to (in pixels)
* @type {number}
*/
public minWidth: number = null;
/**
* Maximum width the canvas should be scaled to (in pixels).
* If null it will scale to whatever width the browser can handle.
* @type {number}
*/
public maxWidth: number = null;
/**
* Minimum height the canvas should be scaled to (in pixels)
* @type {number}
*/
public minHeight: number = null;
/**
* Maximum height the canvas should be scaled to (in pixels).
* If null it will scale to whatever height the browser can handle.
* @type {number}
*/
public maxHeight: number = null;
/**
* Width of the stage after calculation.
* @type {number}
*/
public width: number = 0;
/**
* Height of the stage after calculation.
* @type {number}
@@ -67,11 +113,78 @@ module Phaser {
public height: number = 0;
/**
* Game orientation angel.
* Window orientation angle (90 and -90 are landscape, 0 is portrait)
* @type {number}
*/
public orientation;
public orientation: number;
/**
* A Signal that is dispatched when the device enters landscape mode from portrait
* @type {Signal}
*/
public enterLandscape: Phaser.Signal;
/**
* A Signal that is dispatched when the device enters portrait mode from landscape
* @type {Signal}
*/
public enterPortrait: Phaser.Signal;
public get isFullScreen(): bool {
if (document['fullscreenElement'] === null|| document['mozFullScreenElement'] === null|| document['webkitFullscreenElement'] === null)
{
return false;
}
return true;
}
public startFullScreen() {
if (this.isFullScreen)
{
return;
}
var element = this._game.stage.canvas;
if (element['requestFullScreen'])
{
element['requestFullScreen']();
}
else if(element['mozRequestFullScreen'])
{
element['mozRequestFullScreen']();
}
else if (element['webkitRequestFullScreen'])
{
element['webkitRequestFullScreen']();
}
}
public stopFullScreen() {
if (document['cancelFullScreen'])
{
document['cancelFullScreen']();
}
else if (document['mozCancelFullScreen'])
{
document['mozCancelFullScreen']();
}
else if (document['webkitCancelFullScreen'])
{
document['webkitCancelFullScreen']();
}
}
/**
* The core update loop, called by Phaser.Stage
*/
public update() {
if (this._game.stage.scaleMode !== StageScaleMode.NO_SCALE && (window.innerWidth !== this.width || window.innerHeight !== this.height))
@@ -81,19 +194,63 @@ module Phaser {
}
public get isPortrait(): bool {
return this.orientation == 0;
}
public get isLandscape(): bool {
return window['orientation'] === 90 || window['orientation'] === -90;
return this.orientation === 90 || this.orientation === -90;
}
/**
* Check whether game orientation the same as window's. Update orientation if not equal.
* Handle window.orientationchange events
*/
private checkOrientation(event) {
if (window['orientation'] !== this.orientation)
this.orientation = window['orientation'];
if (this.isLandscape)
{
this.enterLandscape.dispatch(this.orientation);
}
else
{
this.enterPortrait.dispatch(this.orientation);
}
if (this._game.stage.scaleMode !== StageScaleMode.NO_SCALE)
{
this.refresh();
}
}
/**
* Handle window.resize events
*/
private checkResize(event) {
if (window.outerWidth > window.outerHeight)
{
this.orientation = 90;
}
else
{
this.orientation = 0;
}
if (this.isLandscape)
{
this.enterLandscape.dispatch(this.orientation);
}
else
{
this.enterPortrait.dispatch(this.orientation);
}
if (this._game.stage.scaleMode !== StageScaleMode.NO_SCALE)
{
this.refresh();
this.orientation = window['orientation'];
}
}
@@ -129,7 +286,7 @@ module Phaser {
}
/**
* Set screen size automatically based on stage's scaleMode.
* Set screen size automatically based on the scaleMode.
*/
private setScreenSize() {
@@ -154,18 +311,18 @@ module Phaser {
if (this._game.stage.scaleMode == StageScaleMode.EXACT_FIT)
{
if (this._game.stage.maxScaleX && window.innerWidth > this._game.stage.maxScaleX)
if (this.maxWidth && window.innerWidth > this.maxWidth)
{
this.width = this._game.stage.maxScaleX;
this.width = this.maxWidth;
}
else
{
this.width = window.innerWidth;
}
if (this._game.stage.maxScaleY && window.innerHeight > this._game.stage.maxScaleY)
if (this.maxHeight && window.innerHeight > this.maxHeight)
{
this.height = this._game.stage.maxScaleY;
this.height = this.maxHeight;
}
else
{
@@ -173,20 +330,20 @@ module Phaser {
}
}
else if (this._game.stage.scaleMode == StageScaleMode.SHOW_ALL)
{
{
var multiplier = Math.min((window.innerHeight / this._game.stage.height), (window.innerWidth / this._game.stage.width));
this.width = Math.round(this._game.stage.width * multiplier);
this.height = Math.round(this._game.stage.height * multiplier);
if (this._game.stage.maxScaleX && this.width > this._game.stage.maxScaleX)
if (this.maxWidth && this.width > this.maxWidth)
{
this.width = this._game.stage.maxScaleX;
this.width = this.maxWidth;
}
if (this._game.stage.maxScaleY && this.height > this._game.stage.maxScaleY)
if (this.maxHeight && this.height > this.maxHeight)
{
this.height = this._game.stage.maxScaleY;
this.height = this.maxHeight;
}
}
+8
View File
@@ -48,11 +48,13 @@ module Phaser {
* Local private reference to game.
*/
private _game: Phaser.Game;
/**
* Manager of this tween.
* @type {Phaser.TweenManager}
*/
private _manager: Phaser.TweenManager;
/**
* Reference to the target object.
* @type {object}
@@ -65,11 +67,13 @@ module Phaser {
* @type {object}
*/
private _valuesStart = {};
/**
* End values container.
* @type {object}
*/
private _valuesEnd = {};
/**
* How long this tween will perform.
* @type {number}
@@ -77,12 +81,14 @@ module Phaser {
private _duration = 1000;
private _delayTime = 0;
private _startTime = null;
/**
* Easing function which actually updating this tween.
* @type {function}
*/
private _easingFunction;
private _interpolationFunction;
/**
* Contains chained tweens.
* @type {Tweens[]}
@@ -94,11 +100,13 @@ module Phaser {
* @type {Phaser.Signal}
*/
public onStart: Phaser.Signal;
/**
* Signal to be dispatched when this tween updating.
* @type {Phaser.Signal}
*/
public onUpdate: Phaser.Signal;
/**
* Signal to be dispatched when this tween completed.
* @type {Phaser.Signal}
+14
View File
@@ -1,5 +1,6 @@
/// <reference path="../../Game.ts" />
/// <reference path="../../Signal.ts" />
/// <reference path="MSPointer.ts" />
/**
* Phaser - Input
@@ -18,6 +19,7 @@ module Phaser {
this.mouse = new Mouse(this._game);
this.keyboard = new Keyboard(this._game);
this.touch = new Touch(this._game);
this.mspointer = new MSPointer(this._game);
this.onDown = new Phaser.Signal();
this.onUp = new Phaser.Signal();
@@ -31,22 +33,31 @@ module Phaser {
* @type {Mouse}
*/
public mouse: Mouse;
/**
*
* @type {Keyboard}
*/
public keyboard: Keyboard;
/**
*
* @type {Touch}
*/
public touch: Touch;
/**
*
* @type {MSPointer}
*/
public mspointer: MSPointer;
/**
*
* @type {Number}
*/
public x: number = 0;
/**
*
* @type {Number}
@@ -58,6 +69,7 @@ module Phaser {
* @type {Number}
*/
public scaleX: number = 1;
/**
*
* @type {Number}
@@ -69,6 +81,7 @@ module Phaser {
* @type {Number}
*/
public worldX: number = 0;
/**
*
* @type {Number}
@@ -80,6 +93,7 @@ module Phaser {
* @type {Phaser.Signal}
*/
public onDown: Phaser.Signal;
/**
*
* @type {Phaser.Signal}
+326
View File
@@ -0,0 +1,326 @@
/// <reference path="../../Game.ts" />
/// <reference path="Finger.ts" />
/**
* Phaser - MSPointer
*
* The MSPointer class handles touch interactions with the game and the resulting Finger objects.
* It will work only in Internet Explorer 10 and Windows Store or Windows Phone 8 apps using JavaScript.
* http://msdn.microsoft.com/en-us/library/ie/hh673557(v=vs.85).aspx
*
*
* @todo Gestures (pinch, zoom, swipe)
*/
module Phaser {
export class MSPointer {
/**
* Constructor
* @param {Game} game.
* @return {MSPointer} This object.
*/
constructor(game: Game) {
this._game = game;
this.finger1 = new Finger(this._game);
this.finger2 = new Finger(this._game);
this.finger3 = new Finger(this._game);
this.finger4 = new Finger(this._game);
this.finger5 = new Finger(this._game);
this.finger6 = new Finger(this._game);
this.finger7 = new Finger(this._game);
this.finger8 = new Finger(this._game);
this.finger9 = new Finger(this._game);
this.finger10 = new Finger(this._game);
this._fingers = [this.finger1, this.finger2, this.finger3, this.finger4, this.finger5, this.finger6, this.finger7, this.finger8, this.finger9, this.finger10];
this.touchDown = new Signal();
this.touchUp = new Signal();
this.start();
}
/**
*
* @property _game
* @type Game
* @private
**/
private _game: Game;
/**
*
* @property x
* @type Number
**/
public x: number = 0;
/**
*
* @property y
* @type Number
**/
public y: number = 0;
/**
*
* @property _fingers
* @type Array
* @private
**/
private _fingers: Finger[];
/**
*
* @property finger1
* @type Finger
**/
public finger1: Finger;
/**
*
* @property finger2
* @type Finger
**/
public finger2: Finger;
/**
*
* @property finger3
* @type Finger
**/
public finger3: Finger;
/**
*
* @property finger4
* @type Finger
**/
public finger4: Finger;
/**
*
* @property finger5
* @type Finger
**/
public finger5: Finger;
/**
*
* @property finger6
* @type Finger
**/
public finger6: Finger;
/**
*
* @property finger7
* @type Finger
**/
public finger7: Finger;
/**
*
* @property finger8
* @type Finger
**/
public finger8: Finger;
/**
*
* @property finger9
* @type Finger
**/
public finger9: Finger;
/**
*
* @property finger10
* @type Finger
**/
public finger10: Finger;
/**
*
* @property latestFinger
* @type Finger
**/
public latestFinger: Finger;
/**
*
* @property isDown
* @type Boolean
**/
public isDown: bool = false;
/**
*
* @property isUp
* @type Boolean
**/
public isUp: bool = true;
public touchDown: Signal;
public touchUp: Signal;
/**
*
* @method start
*/
public start() {
if (navigator.msMaxTouchPoints)
{
this._game.stage.canvas.addEventListener('MSPointerDown', (event) => this.onPointerDown(event), false);
this._game.stage.canvas.addEventListener('MSPointerMove', (event) => this.onPointerMove(event), false);
this._game.stage.canvas.addEventListener('MSPointerUp', (event) => this.onPointerUp(event), false);
}
}
/**
*
* @method onPointerDown
* @param {Any} event
**/
private onPointerDown(event) {
event.preventDefault();
for (var f = 0; f < this._fingers.length; f++)
{
if (this._fingers[f].active === false)
{
event.identifier = event.pointerId;
this._fingers[f].start(event);
this.x = this._fingers[f].x;
this.y = this._fingers[f].y;
this._game.input.x = this.x * this._game.input.scaleX;
this._game.input.y = this.y * this._game.input.scaleY;
this.touchDown.dispatch(this._fingers[f].x, this._fingers[f].y, this._fingers[f].timeDown, this._fingers[f].timeUp, this._fingers[f].duration);
this._game.input.onDown.dispatch(this._game.input.x, this._game.input.y, this._fingers[f].timeDown);
this.isDown = true;
this.isUp = false;
break;
}
}
}
/**
*
* @method onPointerMove
* @param {Any} event
**/
private onPointerMove(event) {
event.preventDefault();
for (var f = 0; f < this._fingers.length; f++)
{
if (this._fingers[f].identifier === event.pointerId &&
this._fingers[f].active === true)
{
event.identifier = event.pointerId;
this._fingers[f].move(event);
this.x = this._fingers[f].x;
this.y = this._fingers[f].y;
this._game.input.x = this.x * this._game.input.scaleX;
this._game.input.y = this.y * this._game.input.scaleY;
break;
}
}
}
/**
*
* @method onPointerUp
* @param {Any} event
**/
private onPointerUp(event) {
event.preventDefault();
for (var f = 0; f < this._fingers.length; f++)
{
if (this._fingers[f].identifier === event.pointerId)
{
event.identifier = event.pointerId;
this._fingers[f].stop(event);
this.x = this._fingers[f].x;
this.y = this._fingers[f].y;
this._game.input.x = this.x * this._game.input.scaleX;
this._game.input.y = this.y * this._game.input.scaleY;
this.touchUp.dispatch(this._fingers[f].x, this._fingers[f].y, this._fingers[f].timeDown, this._fingers[f].timeUp, this._fingers[f].duration);
this._game.input.onUp.dispatch(this._game.input.x, this._game.input.y, this._fingers[f].timeUp);
this.isDown = false;
this.isUp = true;
break;
}
}
}
/**
*
* @method calculateDistance
* @param {Finger} finger1
* @param {Finger} finger2
**/
public calculateDistance(finger1: Finger, finger2: Finger) {
}
/**
*
* @method calculateAngle
* @param {Finger} finger1
* @param {Finger} finger2
**/
public calculateAngle(finger1: Finger, finger2: Finger) {
}
/**
*
* @method checkOverlap
* @param {Finger} finger1
* @param {Finger} finger2
**/
public checkOverlap(finger1: Finger, finger2: Finger) {
}
/**
*
* @method update
*/
public update() {
}
/**
*
* @method stop
*/
public stop() {
}
/**
*
* @method reset
**/
public reset() {
this.isDown = false;
this.isUp = false;
}
}
}