51 Commits
Author SHA1 Message Date
Richard Davey 4ef0750c07 Prep before branch 2013-05-24 01:40:56 +01:00
Richard Davey 67bf221073 Updates 2013-05-23 21:47:29 +01:00
Richard Davey 94add2ea6e Updated Loader so it no longer checks if the animation data is valid, passes that control to the AnimationLoader. Also fixed camera bounds check in Sprite. 2013-05-23 15:45:04 +01:00
Richard Davey c7485301ca Added Starling/Sparrow XML Texture Atlas format support. 2013-05-23 03:08:57 +01:00
Richard Davey c5ace72180 Updated every test to use the new GameObjectFactory syntax 2013-05-23 00:36:53 +01:00
Richard Davey bd54460e80 Added the GameObjectManager 2013-05-23 00:01:58 +01:00
Richard Davey e2141c91a6 Added VerletManager and lots of new tests 2013-05-21 04:12:54 +01:00
Richard Davey 0b2d818ba8 CollisionMask up and running 2013-05-20 06:21:12 +01:00
Richard Davey 05cc32fbc9 Added final logo and start of CollisionMask 2013-05-19 14:01:11 +01:00
Richard Davey 53aa43566e Updated DynamicTexture.setPixel, added GameMath.shuffleArray, fixed Animation.frame and created a few new tests 2013-05-18 03:05:28 +01:00
Richard Davey 55568592b5 Lots of updates across input, rendering and grouping 2013-05-17 06:49:43 +01:00
Richard Davey a6e8436e6d Massive input overhaul continued 2013-05-16 21:34:24 +01:00
Richard Davey 3cdd2baff0 New Input handler implemented. 2013-05-16 02:36:58 +01:00
Richard Davey ce7bfd1fc2 Added FullScreen API support and fixed numerous StageScaleMode issues. 2013-05-14 03:37:38 +01:00
Richard Davey 8fc31ed83b Doc formatting 2013-05-11 23:51:50 +01:00
Sean 1c311a73df Simply add type info to jsdoc of these classs. 2013-05-12 00:26:30 +08:00
Richard Davey 0adbf1d92f Adding more docs :) 2013-05-10 16:31:19 +01:00
Richard Davey aaaaf7ede3 Preparing for doc merge 2013-05-10 16:31:19 +01:00
SeanandRichard Davey 77582fb1ed Re-format optional parameters. 2013-05-10 16:31:18 +01:00
SeanandRichard Davey 2a8447f64e Add some type info to Emitter class. 2013-05-10 16:31:18 +01:00
SeanandRichard Davey deb37e9a90 Finish document for DynamicTexture, Loader, GeomSprite, Sprite, Camera. 2013-05-10 16:31:17 +01:00
SeanandRichard Davey ca932038fb Finish document for ScrollRegion, ScrollZone, Tilemap, Device, TilemapLayer. 2013-05-10 16:31:16 +01:00
SeanandRichard Davey 00ef200914 Finish document for Time, Tween, Animation, AnimationLoader, Frame. 2013-05-10 16:31:16 +01:00
SeanandRichard Davey e88c48641d Finish document for AnimationManager, Tile, FrameData, BootScreen, PauseScreen. 2013-05-10 16:31:15 +01:00
SeanandRichard Davey 1052df6660 Finish documents for Cache, CameraManager, Game, SoundManager, Sound. 2013-05-10 16:31:15 +01:00
SeanandRichard Davey 4be5a10e44 Finish documents for GameObject, World, TweenManager, State, Stage. 2013-05-10 16:31:14 +01:00
SeanandRichard Davey 5cf8b846f8 Finish another 10 classes' document. 2013-05-10 16:31:14 +01:00
SeanandRichard Davey 9da64e6baf Finish document for AnimationManager, CameraManager, SoundManager and TweenManager class. 2013-05-10 16:31:13 +01:00
SeanandRichard Davey 98693cb418 Finish document for Cache, Game, Stage, State and World class. 2013-05-10 16:31:12 +01:00
HackManiacandRichard Davey b1a33cc593 Extended Gruntfile to create phaser-fx.js and phaser-fx.amd.js including declarations 2013-05-10 16:31:12 +01:00
Richard Davey b5b5a99dce Preparing for 0.9.6 work 2013-05-02 20:54:28 +01:00
Richard Davey be982b4322 Updated readme and new minified build 2013-05-02 14:03:41 +01:00
Richard Davey 493380a51e Updated readme for official release. 2013-05-02 05:20:01 +01:00
Richard Davey 0a08e1ae0e Removed un-needed file and added SoundManager fix. 2013-05-02 05:16:16 +01:00
Richard Davey e39073d07b Updated readme 2013-05-02 05:02:05 +01:00
Richard Davey 54a5e6477c Lots of new tile map commands and tests. 2013-05-02 05:01:34 +01:00
Richard Davey 2a5b6ef12a Large Tilemap collision overhaul. Proper callback support, optimised collision checks and lots more. 2013-05-02 03:37:45 +01:00
Richard Davey e62b300a25 Added Camera Mirror FX and test case. 2013-05-02 01:02:06 +01:00
Richard Davey 7d98a1bb9d New FXManager system and Camera FX now in place. 2013-05-01 04:10:21 +01:00
Richard Davey c5cccf3283 Large refactoring of the pause and boot screens in Stage and various other small fixes 2013-04-29 02:41:19 +01:00
Richard Davey 9f23c378a1 0.9.4 release 2013-04-28 22:10:12 +01:00
Richard Davey b6f8a3fba6 Final 0.9.4 release 2013-04-28 22:10:11 +01:00
Richard Davey cb9cb6e894 Github Bug Fixes 2013-04-28 22:04:37 +01:00
Richard Davey e948f1e3be Fixed daft issue in Camera and fully implemented tilemap collision. 2013-04-28 22:04:36 +01:00
Richard Davey 4c21ac0d87 Tilemap collision is now working but all Camera following seems to be broken as a result. Awesome. 2013-04-28 22:04:36 +01:00
Richard Davey db9b8ec370 Merge pull request #11 from HackManiac/amd
Automatic creation of UMD wrapped variant of Phaser
2013-04-28 13:37:09 -07:00
HackManiacandDaniel Wippermann f66e0e9254 Automatic creation of UMD wrapped variant of Phaser 2013-04-26 16:35:32 +02:00
Richard Davey 2087b2d76e tidying up 2013-04-26 00:24:58 +01:00
Richard Davey b2e1434f5e Tilemap collision working but needs speeding up 2013-04-25 20:05:56 +01:00
Richard Davey b8ab13fec8 Getting tilemap collision up and running 2013-04-25 01:55:56 +01:00
Richard Davey 53d8e4da2e Fixed Game.boot syntax error. 2013-04-24 09:37:29 +01:00
381 changed files with 83539 additions and 6348 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 531 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 809 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

+84 -11
View File
@@ -2,7 +2,43 @@ module.exports = function (grunt) {
grunt.loadNpmTasks('grunt-typescript');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-copy');
var wrapPhaserInUmd = function(content, isAddon) {
var replacement = [
'(function (root, factory) {',
' if (typeof exports === \'object\') {',
' module.exports = factory();',
' } else if (typeof define === \'function\' && define.amd) {',
' define(factory);',
' } else {',
' root.Phaser = factory();',
' }',
'}(this, function () {',
content,
'return Phaser;',
'}));'
];
return replacement.join('\n');
};
var wrapAddonInUmd = function(content) {
var replacement = [
'(function (root, factory) {',
' if (typeof exports === \'object\') {',
' module.exports = factory(require(\'phaser\'));',
' } else if (typeof define === \'function\' && define.amd) {',
' define([\'phaser\'], factory);',
' } else {',
' factory(root.Phaser);',
' }',
'}(this, function (Phaser) {',
content,
'return Phaser;',
'}));'
];
return replacement.join('\n');
};
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
typescript: {
@@ -10,22 +46,59 @@ module.exports = function (grunt) {
src: ['Phaser/**/*.ts'],
dest: 'build/phaser.js',
options: {
target: 'ES5'
target: 'ES5',
declaration: true,
comments: true
}
},
fx: {
src: ['SpecialFX/**/*.ts'],
dest: 'build/phaser-fx.js',
options: {
target: 'ES5',
declaration: true,
comments: true
}
}
},
copy: {
main: {
files: [{
src: 'build/phaser.js',
dest: 'Tests/phaser.js'
}]
},
fx: {
files: [{
src: 'build/phaser-fx.js',
dest: 'Tests/phaser-fx.js'
}]
},
mainAmd: {
files: [{
src: 'build/phaser.js',
dest: 'build/phaser.amd.js'
}],
options: {
processContent: wrapPhaserInUmd
}
},
fxAmd: {
files: [{
src: 'build/phaser-fx.js',
dest: 'build/phaser-fx.amd.js'
}],
options: {
processContent: wrapAddonInUmd
}
}
},
copy: {
main: {
files: [
{src: 'build/phaser.js', dest: 'Tests/phaser.js'}
]}
},
watch: {
files: '**/*.ts',
tasks: ['typescript', 'copy']
}
});
grunt.registerTask('default', ['watch']);
grunt.registerTask('default', ['typescript', 'copy', 'watch']);
}
+28
View File
@@ -0,0 +1,28 @@
/// <reference path="Game.d.ts" />
/// <reference path="gameobjects/Sprite.d.ts" />
/// <reference path="system/animation/Animation.d.ts" />
/// <reference path="system/animation/AnimationLoader.d.ts" />
/// <reference path="system/animation/Frame.d.ts" />
/// <reference path="system/animation/FrameData.d.ts" />
module Phaser {
class AnimationManager {
constructor(game: Game, parent: Sprite);
private _game;
private _parent;
private _anims;
private _frameIndex;
private _frameData;
public currentAnim: Animation;
public currentFrame: Frame;
public loadFrameData(frameData: FrameData): void;
public add(name: string, frames?: any[], frameRate?: number, loop?: bool, useNumericIndex?: bool): void;
private validateFrames(frames, useNumericIndex);
public play(name: string, frameRate?: number, loop?: bool): void;
public stop(name: string): void;
public update(): void;
public frameData : FrameData;
public frameTotal : number;
public frame : number;
public frameName : string;
}
}
+96 -8
View File
@@ -16,6 +16,12 @@ module Phaser {
export class AnimationManager {
/**
* AnimationManager constructor
* Create a new <code>AnimationManager</code>.
*
* @param parent {Sprite} Owner sprite of this manager.
*/
constructor(game: Game, parent: Sprite) {
this._game = game;
@@ -24,16 +30,47 @@ module Phaser {
}
/**
* Local private reference to game.
*/
private _game: Game;
/**
* Local private reference to its owner sprite.
*/
private _parent: Sprite;
/**
* Animation key-value container.
*/
private _anims: {};
/**
* Index of current frame.
* @type {number}
*/
private _frameIndex: number;
/**
* Data contains animation frames.
* @type {FrameData}
*/
private _frameData: FrameData = null;
/**
* Keeps track of the current animation being played.
*/
public currentAnim: Animation;
/**
* Keeps track of the current frame of animation.
*/
public currentFrame: Frame = null;
/**
* Load animation frame data.
* @param frameData Data to be loaded.
*/
public loadFrameData(frameData: FrameData) {
this._frameData = frameData;
@@ -42,7 +79,16 @@ module Phaser {
}
public add(name: string, frames: any[] = null, frameRate: number = 60, loop: bool = false, useNumericIndex: bool = true) {
/**
* Add a new animation.
* @param name {string} What this animation should be called (e.g. "run").
* @param frames {any[]} An array of numbers/strings indicating what frames to play in what order (e.g. [1, 2, 3] or ['run0', 'run1', run2]).
* @param frameRate {number} The speed in frames per second that the animation should play at (e.g. 60 fps).
* @param loop {boolean} Whether or not the animation is looped or just plays once.
* @param useNumericIndex {boolean} Use number indexes instead of string indexes?
* @return {Animation} The Animation that was created
*/
public add(name: string, frames: any[] = null, frameRate: number = 60, loop: bool = false, useNumericIndex: bool = true): Animation {
if (this._frameData == null)
{
@@ -72,8 +118,16 @@ module Phaser {
this.currentAnim = this._anims[name];
this.currentFrame = this.currentAnim.currentFrame;
return this._anims[name];
}
/**
* Check whether the frames is valid.
* @param frames {any[]} Frames to be validated.
* @param useNumericIndex {boolean} Does these frames use number indexes or string indexes?
* @return {boolean} True if they're valid, otherwise return false.
*/
private validateFrames(frames: any[], useNumericIndex: bool): bool {
for (var i = 0; i < frames.length; i++)
@@ -98,6 +152,12 @@ module Phaser {
}
/**
* Play animation with specific name.
* @param name {string} The string name of the animation you want to play.
* @param frameRate {number} FrameRate you want to specify instead of using default.
* @param loop {boolean} Whether or not the animation is looped or just plays once.
*/
public play(name: string, frameRate?: number = null, loop?: bool) {
if (this._anims[name])
@@ -118,6 +178,10 @@ module Phaser {
}
/**
* Stop animation by name.
* Current animation will be automatically set to the stopped one.
*/
public stop(name: string) {
if (this._anims[name])
@@ -128,13 +192,16 @@ module Phaser {
}
/**
* Update animation and parent sprite's bounds.
*/
public update() {
if (this.currentAnim && this.currentAnim.update() == true)
{
this.currentFrame = this.currentAnim.currentFrame;
this._parent.bounds.width = this.currentFrame.width;
this._parent.bounds.height = this.currentFrame.height;
this._parent.frameBounds.width = this.currentFrame.width;
this._parent.frameBounds.height = this.currentFrame.height;
}
}
@@ -144,7 +211,15 @@ module Phaser {
}
public get frameTotal(): number {
return this._frameData.total;
if (this._frameData)
{
return this._frameData.total;
}
else
{
return -1;
}
}
public get frame(): number {
@@ -157,8 +232,8 @@ module Phaser {
{
this.currentFrame = this._frameData.getFrame(value);
this._parent.bounds.width = this.currentFrame.width;
this._parent.bounds.height = this.currentFrame.height;
this._parent.frameBounds.width = this.currentFrame.width;
this._parent.frameBounds.height = this.currentFrame.height;
this._frameIndex = value;
}
@@ -174,13 +249,26 @@ module Phaser {
{
this.currentFrame = this._frameData.getFrameByName(value);
this._parent.bounds.width = this.currentFrame.width;
this._parent.bounds.height = this.currentFrame.height;
this._parent.frameBounds.width = this.currentFrame.width;
this._parent.frameBounds.height = this.currentFrame.height;
this._frameIndex = this.currentFrame.index;
}
}
/**
* Removes all related references
*/
public destroy() {
this._anims = {};
this._frameData = null;
this._frameIndex = 0;
this.currentAnim = null;
this.currentFrame = null;
}
}
}
+23
View File
@@ -0,0 +1,23 @@
/// <reference path="Game.d.ts" />
module Phaser {
class Basic {
constructor(game: Game);
public _game: Game;
public name: string;
public ID: number;
public isGroup: bool;
public exists: bool;
public active: bool;
public visible: bool;
public alive: bool;
public ignoreDrawDebug: bool;
public destroy(): void;
public preUpdate(): void;
public update(): void;
public postUpdate(): void;
public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number): void;
public kill(): void;
public revive(): void;
public toString(): string;
}
}
+14 -2
View File
@@ -23,6 +23,8 @@ module Phaser {
this.visible = true;
this.alive = true;
this.isGroup = false;
this.ignoreGlobalUpdate = false;
this.ignoreGlobalRender = false;
this.ignoreDrawDebug = false;
}
@@ -70,6 +72,16 @@ module Phaser {
*/
public alive: bool;
/**
* Setting this to true will prevent the object from being updated during the main game loop (you will have to call update on it yourself)
*/
public ignoreGlobalUpdate: bool;
/**
* Setting this to true will prevent the object from being rendered during the main game loop (you will have to call render on it yourself)
*/
public ignoreGlobalRender: bool;
/**
* Setting this to true will prevent the object from appearing
* when the visual debug mode in the debugger overlay is toggled on.
@@ -93,7 +105,7 @@ module Phaser {
* Override this to update your class's position and appearance.
* This is where most of your game rules and behavioral code will go.
*/
public update() {
public update(forceUpdate?: bool = false) {
}
/**
@@ -102,7 +114,7 @@ module Phaser {
public postUpdate() {
}
public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number) {
public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number, forceRender?: bool = false) {
}
/**
+26
View File
@@ -0,0 +1,26 @@
/// <reference path="Game.d.ts" />
module Phaser {
class Cache {
constructor(game: Game);
private _game;
private _canvases;
private _images;
private _sounds;
private _text;
public addCanvas(key: string, canvas: HTMLCanvasElement, context: CanvasRenderingContext2D): void;
public addSpriteSheet(key: string, url: string, data, frameWidth: number, frameHeight: number, frameMax: number): void;
public addTextureAtlas(key: string, url: string, data, jsonData): void;
public addImage(key: string, url: string, data): void;
public addSound(key: string, url: string, data): void;
public decodedSound(key: string, data): void;
public addText(key: string, url: string, data): void;
public getCanvas(key: string);
public getImage(key: string);
public getFrameData(key: string): FrameData;
public getSound(key: string);
public isSoundDecoded(key: string): bool;
public isSpriteSheet(key: string): bool;
public getText(key: string);
public destroy(): void;
}
}
+116 -2
View File
@@ -11,6 +11,9 @@ module Phaser {
export class Cache {
/**
* Cache constructor
*/
constructor(game: Game) {
this._game = game;
@@ -22,19 +25,53 @@ module Phaser {
}
/**
* Local private reference to game.
*/
private _game: Game;
/**
* Canvas key-value container.
* @type {object}
*/
private _canvases;
/**
* Image key-value container.
* @type {object}
*/
private _images;
/**
* Sound key-value container.
* @type {object}
*/
private _sounds;
/**
* Text key-value container.
* @type {object}
*/
private _text;
/**
* Add a new canvas.
* @param key {string} Asset key for this canvas.
* @param canvas {HTMLCanvasElement} Canvas DOM element.
* @param context {CanvasRenderingContext2D} Render context of this canvas.
*/
public addCanvas(key: string, canvas: HTMLCanvasElement, context: CanvasRenderingContext2D) {
this._canvases[key] = { canvas: canvas, context: context };
}
/**
* Add a new sprite sheet.
* @param key {string} Asset key for the sprite sheet.
* @param url {string} URL of this sprite sheet file.
* @param data {object} Extra sprite sheet data.
* @param frameWidth {number} Width of the sprite sheet.
* @param frameHeight {number} Height of the sprite sheet.
* @param frameMax {number} How many frames stored in the sprite sheet.
*/
public addSpriteSheet(key: string, url: string, data, frameWidth: number, frameHeight: number, frameMax: number) {
this._images[key] = { url: url, data: data, spriteSheet: true, frameWidth: frameWidth, frameHeight: frameHeight };
@@ -42,25 +79,58 @@ module Phaser {
}
public addTextureAtlas(key: string, url: string, data, jsonData) {
/**
* Add a new texture atlas.
* @param key {string} Asset key for the texture atlas.
* @param url {string} URL of this texture atlas file.
* @param data {object} Extra texture atlas data.
* @param atlasData {object} Texture atlas frames data.
*/
public addTextureAtlas(key: string, url: string, data, atlasData, format) {
this._images[key] = { url: url, data: data, spriteSheet: true };
this._images[key].frameData = AnimationLoader.parseJSONData(this._game, jsonData);
if (format == Phaser.Loader.TEXTURE_ATLAS_JSON_ARRAY)
{
this._images[key].frameData = AnimationLoader.parseJSONData(this._game, atlasData);
}
else if (format == Phaser.Loader.TEXTURE_ATLAS_XML_STARLING)
{
this._images[key].frameData = AnimationLoader.parseXMLData(this._game, atlasData, format);
}
}
/**
* Add a new image.
* @param key {string} Asset key for the image.
* @param url {string} URL of this image file.
* @param data {object} Extra image data.
*/
public addImage(key: string, url: string, data) {
this._images[key] = { url: url, data: data, spriteSheet: false };
}
/**
* Add a new sound.
* @param key {string} Asset key for the sound.
* @param url {string} URL of this sound file.
* @param data {object} Extra sound data.
*/
public addSound(key: string, url: string, data) {
this._sounds[key] = { url: url, data: data, decoded: false };
}
/**
* Add a new decoded sound.
* @param key {string} Asset key for the sound.
* @param url {string} URL of this sound file.
* @param data {object} Extra sound data.
*/
public decodedSound(key: string, data) {
this._sounds[key].data = data;
@@ -68,12 +138,23 @@ module Phaser {
}
/**
* Add a new text data.
* @param key {string} Asset key for the text data.
* @param url {string} URL of this text data file.
* @param data {object} Extra text data.
*/
public addText(key: string, url: string, data) {
this._text[key] = { url: url, data: data };
}
/**
* Get canvas by key.
* @param key Asset key of the canvas you want.
* @return {object} The canvas you want.
*/
public getCanvas(key: string) {
if (this._canvases[key])
@@ -85,6 +166,11 @@ module Phaser {
}
/**
* Get image data by key.
* @param key Asset key of the image you want.
* @return {object} The image data you want.
*/
public getImage(key: string) {
if (this._images[key])
@@ -96,6 +182,11 @@ module Phaser {
}
/**
* Get frame data by key.
* @param key Asset key of the frame data you want.
* @return {object} The frame data you want.
*/
public getFrameData(key: string): FrameData {
if (this._images[key] && this._images[key].spriteSheet == true)
@@ -107,6 +198,11 @@ module Phaser {
}
/**
* Get sound data by key.
* @param key Asset key of the sound you want.
* @return {object} The sound data you want.
*/
public getSound(key: string) {
if (this._sounds[key])
@@ -118,6 +214,11 @@ module Phaser {
}
/**
* Check whether an asset is decoded sound.
* @param key Asset key of the sound you want.
* @return {object} The sound data you want.
*/
public isSoundDecoded(key: string): bool {
if (this._sounds[key])
@@ -127,6 +228,11 @@ module Phaser {
}
/**
* Check whether an asset is sprite sheet.
* @param key Asset key of the sprite sheet you want.
* @return {object} The sprite sheet data you want.
*/
public isSpriteSheet(key: string): bool {
if (this._images[key])
@@ -136,6 +242,11 @@ module Phaser {
}
/**
* Get text data by key.
* @param key Asset key of the text data you want.
* @return {object} The text data you want.
*/
public getText(key: string) {
if (this._text[key])
@@ -147,6 +258,9 @@ module Phaser {
}
/**
* Clean up cache memory.
*/
public destroy() {
for (var item in this._canvases)
+17
View File
@@ -0,0 +1,17 @@
/// <reference path="Game.d.ts" />
/// <reference path="system/Camera.d.ts" />
module Phaser {
class CameraManager {
constructor(game: Game, x: number, y: number, width: number, height: number);
private _game;
private _cameras;
private _cameraInstance;
public current: Camera;
public getAll(): Camera[];
public update(): void;
public render(): void;
public addCamera(x: number, y: number, width: number, height: number): Camera;
public removeCamera(id: number): bool;
public destroy(): void;
}
}
+52 -3
View File
@@ -6,15 +6,21 @@
*
* Your game only has one CameraManager instance and it's responsible for looking after, creating and destroying
* all of the cameras in the world.
*
* TODO: If the Camera is larger than the Stage size then the rotation offset isn't correct
* TODO: Texture Repeat doesn't scroll, because it's part of the camera not the world, need to think about this more
*/
module Phaser {
export class CameraManager {
/**
* CameraManager constructor
* This will create a new <code>Camera</code> with position and size.
*
* @param x {number} X Position of the created camera.
* @param y {number} y Position of the created camera.
* @param width {number} Width of the created camera.
* @param height {number} Height of the created camera.
*/
constructor(game: Game, x: number, y: number, width: number, height: number) {
this._game = game;
@@ -25,24 +31,58 @@ module Phaser {
}
/**
* Local private reference to Game.
*/
private _game: Game;
/**
* Local container for storing cameras.
*/
private _cameras: Camera[];
/**
* Local helper stores index of next created camera.
*/
private _cameraInstance: number = 0;
/**
* Currently used camera.
*/
public current: Camera;
/**
* Get all the cameras.
*
* @returns {Camera[]} An array contains all the cameras.
*/
public getAll(): Camera[] {
return this._cameras;
}
/**
* Update cameras.
*/
public update() {
this._cameras.forEach((camera) => camera.update());
}
/**
* Render cameras.
*/
public render() {
this._cameras.forEach((camera) => camera.render());
}
/**
* Create a new camera with specific position and size.
*
* @param x {number} X position of the new camera.
* @param y {number} Y position of the new camera.
* @param width {number} Width of the new camera.
* @param height {number} Height of the new camera.
* @returns {Camera} The newly created camera object.
*/
public addCamera(x: number, y: number, width: number, height: number): Camera {
var newCam: Camera = new Camera(this._game, this._cameraInstance, x, y, width, height);
@@ -55,6 +95,12 @@ module Phaser {
}
/**
* Remove a new camera with its id.
*
* @param id {number} ID of the camera you want to remove.
* @returns {boolean} True if successfully removed the camera, otherwise return false.
*/
public removeCamera(id: number): bool {
for (var c = 0; c < this._cameras.length; c++)
@@ -76,6 +122,9 @@ module Phaser {
}
/**
* Clean up memory.
*/
public destroy() {
this._cameras.length = 0;
+53
View File
@@ -0,0 +1,53 @@
/// <reference path="Game.d.ts" />
/// <reference path="geom/Point.d.ts" />
/// <reference path="geom/Rectangle.d.ts" />
/// <reference path="geom/Quad.d.ts" />
/// <reference path="geom/Circle.d.ts" />
/// <reference path="geom/Line.d.ts" />
/// <reference path="geom/IntersectResult.d.ts" />
/// <reference path="system/QuadTree.d.ts" />
module Phaser {
class Collision {
constructor(game: Game);
private _game;
static LEFT: number;
static RIGHT: number;
static UP: number;
static DOWN: number;
static NONE: number;
static CEILING: number;
static FLOOR: number;
static WALL: number;
static ANY: number;
static OVERLAP_BIAS: number;
static TILE_OVERLAP: bool;
static _tempBounds: Quad;
static lineToLine(line1: Line, line2: Line, output?: IntersectResult): IntersectResult;
static lineToLineSegment(line: Line, seg: Line, output?: IntersectResult): IntersectResult;
static lineToRawSegment(line: Line, x1: number, y1: number, x2: number, y2: number, output?: IntersectResult): IntersectResult;
static lineToRay(line1: Line, ray: Line, output?: IntersectResult): IntersectResult;
static lineToCircle(line: Line, circle: Circle, output?: IntersectResult): IntersectResult;
static lineToRectangle(line: Line, rect: Rectangle, output?: IntersectResult): IntersectResult;
static lineSegmentToLineSegment(line1: Line, line2: Line, output?: IntersectResult): IntersectResult;
static lineSegmentToRay(line: Line, ray: Line, output?: IntersectResult): IntersectResult;
static lineSegmentToCircle(seg: Line, circle: Circle, output?: IntersectResult): IntersectResult;
static lineSegmentToRectangle(seg: Line, rect: Rectangle, output?: IntersectResult): IntersectResult;
static rayToRectangle(ray: Line, rect: Rectangle, output?: IntersectResult): IntersectResult;
static rayToLineSegment(rayX1, rayY1, rayX2, rayY2, lineX1, lineY1, lineX2, lineY2, output?: IntersectResult): IntersectResult;
static pointToRectangle(point, rect: Rectangle, output?: IntersectResult): IntersectResult;
static rectangleToRectangle(rect1: Rectangle, rect2: Rectangle, output?: IntersectResult): IntersectResult;
static rectangleToCircle(rect: Rectangle, circle: Circle, output?: IntersectResult): IntersectResult;
static circleToCircle(circle1: Circle, circle2: Circle, output?: IntersectResult): IntersectResult;
static circleToRectangle(circle: Circle, rect: Rectangle, output?: IntersectResult): IntersectResult;
static circleContainsPoint(circle: Circle, point, output?: IntersectResult): IntersectResult;
public overlap(object1?: Basic, object2?: Basic, notifyCallback?, processCallback?): bool;
static separate(object1, object2): bool;
static separateTile(object: GameObject, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool, collideUp: bool, collideDown: bool): bool;
static separateTileX(object: GameObject, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool): bool;
static separateTileY(object: GameObject, x: number, y: number, width: number, height: number, mass: number, collideUp: bool, collideDown: bool): bool;
static separateX(object1, object2): bool;
static separateY(object1, object2): bool;
static distance(x1: number, y1: number, x2: number, y2: number): number;
static distanceSquared(x1: number, y1: number, x2: number, y2: number): number;
}
}
+1196 -387
View File
File diff suppressed because it is too large Load Diff
+32
View File
@@ -0,0 +1,32 @@
/// <reference path="Game.d.ts" />
module Phaser {
class DynamicTexture {
constructor(game: Game, width: number, height: number);
private _game;
private _sx;
private _sy;
private _sw;
private _sh;
private _dx;
private _dy;
private _dw;
private _dh;
public bounds: Rectangle;
public canvas: HTMLCanvasElement;
public context: CanvasRenderingContext2D;
public getPixel(x: number, y: number): number;
public getPixel32(x: number, y: number): number;
public getPixels(rect: Rectangle): ImageData;
public setPixel(x: number, y: number, color: number): void;
public setPixel32(x: number, y: number, color: number): void;
public setPixels(rect: Rectangle, input): void;
public fillRect(rect: Rectangle, color: number): void;
public pasteImage(key: string, frame?: number, destX?: number, destY?: number, destWidth?: number, destHeight?: number): void;
public copyPixels(sourceTexture: DynamicTexture, sourceRect: Rectangle, destPoint: Point): void;
public clear(): void;
public width : number;
public height : number;
private getColor32(alpha, red, green, blue);
private getColor(red, green, blue);
}
}
+125 -24
View File
@@ -13,6 +13,14 @@ module Phaser {
export class DynamicTexture {
/**
* DynamicTexture constructor
* Create a new <code>DynamicTexture</code>.
*
* @param game {Phaser.Game} Current game instance.
* @param width {number} Init width of this texture.
* @param height {number} Init height of this texture.
*/
constructor(game: Game, width: number, height: number) {
this._game = game;
@@ -26,6 +34,9 @@ module Phaser {
}
/**
* Local private reference to game.
*/
private _game: Game;
private _sx: number = 0;
@@ -39,10 +50,30 @@ module Phaser {
// Input / Output nodes?
/**
* Bound of this texture with width and height info.
* @type {Rectangle}
*/
public bounds: Rectangle;
/**
* This class is actually a wrapper of canvas.
* @type {HTMLCanvasElement}
*/
public canvas: HTMLCanvasElement;
/**
* Canvas context of this object.
* @type {CanvasRenderingContext2D}
*/
public context: CanvasRenderingContext2D;
/**
* Get a color of a specific pixel.
* @param x {number} X position of the pixel in this texture.
* @param y {number} Y position of the pixel in this texture.
* @return {number} A native color value integer (format: 0xRRGGBB)
*/
public getPixel(x: number, y: number): number {
//r = imageData.data[0];
@@ -55,6 +86,12 @@ module Phaser {
}
/**
* Get a color of a specific pixel (including alpha value).
* @param x {number} X position of the pixel in this texture.
* @param y {number} Y position of the pixel in this texture.
* @return A native color value integer (format: 0xAARRGGBB)
*/
public getPixel32(x: number, y: number) {
var imageData = this.context.getImageData(x, y, 1, 1);
@@ -63,20 +100,36 @@ module Phaser {
}
// Returns a CanvasPixelArray
/**
* Get pixels in array in a specific rectangle.
* @param rect {Rectangle} The specific rectangle.
* @returns {array} CanvasPixelArray.
*/
public getPixels(rect: Rectangle) {
return this.context.getImageData(rect.x, rect.y, rect.width, rect.height);
}
public setPixel(x: number, y: number, color: number) {
/**
* Set color of a specific pixel.
* @param x {number} X position of the target pixel.
* @param y {number} Y position of the target pixel.
* @param color {number} Native integer with color value. (format: 0xRRGGBB)
*/
public setPixel(x: number, y: number, color: string) {
this.context.fillStyle = color;
this.context.fillRect(x, y, 1, 1);
}
/**
* Set color (with alpha) of a specific pixel.
* @param x {number} X position of the target pixel.
* @param y {number} Y position of the target pixel.
* @param color {number} Native integer with color value. (format: 0xAARRGGBB)
*/
public setPixel32(x: number, y: number, color: number) {
this.context.fillStyle = color;
@@ -84,12 +137,22 @@ module Phaser {
}
/**
* Set image data to a specific rectangle.
* @param rect {Rectangle} Target rectangle.
* @param input {object} Source image data.
*/
public setPixels(rect: Rectangle, input) {
this.context.putImageData(input, rect.x, rect.y);
}
/**
* Fill a given rectangle with specific color.
* @param rect {Rectangle} Target rectangle you want to fill.
* @param color {number} A native number with color value. (format: 0xRRGGBB)
*/
public fillRect(rect: Rectangle, color: number) {
this.context.fillStyle = color;
@@ -97,6 +160,9 @@ module Phaser {
}
/**
*
*/
public pasteImage(key: string, frame?: number = -1, destX?: number = 0, destY?: number = 0, destWidth?: number = null, destHeight?: number = null) {
var texture = null;
@@ -138,21 +204,27 @@ module Phaser {
if (texture != null)
{
this.context.drawImage(
texture, // Source Image
this._sx, // Source X (location within the source image)
this._sy, // Source Y
this._sw, // Source Width
this._sh, // Source Height
this._dx, // Destination X (where on the canvas it'll be drawn)
this._dy, // Destination Y
this._dw, // Destination Width (always same as Source Width unless scaled)
this._dh // Destination Height (always same as Source Height unless scaled)
texture, // Source Image
this._sx, // Source X (location within the source image)
this._sy, // Source Y
this._sw, // Source Width
this._sh, // Source Height
this._dx, // Destination X (where on the canvas it'll be drawn)
this._dy, // Destination Y
this._dw, // Destination Width (always same as Source Width unless scaled)
this._dh // Destination Height (always same as Source Height unless scaled)
);
}
}
// TODO - Add in support for: alphaBitmapData: BitmapData = null, alphaPoint: Point = null, mergeAlpha: bool = false
/**
* Copy pixel from another DynamicTexture to this texture.
* @param sourceTexture {DynamicTexture} Source texture object.
* @param sourceRect {Rectangle} The specific region rectangle to be copied to this in the source.
* @param destPoint {Point} Top-left point the target image data will be paste at.
*/
public copyPixels(sourceTexture: DynamicTexture, sourceRect: Rectangle, destPoint: Point) {
// Swap for drawImage if the sourceRect is the same size as the sourceTexture to avoid a costly getImageData call
@@ -167,12 +239,41 @@ module Phaser {
}
/**
* Given an array of GameObjects it will update each of them so that their canvas/contexts reference this DynamicTexture
* @param objects {Array} An array of GameObjects, or objects that inherit from it such as Sprites
*/
public assignCanvasToGameObjects(objects: GameObject[]) {
for (var i = 0; i < objects.length; i++)
{
objects[i].canvas = this.canvas;
objects[i].context = this.context;
}
}
/**
* Clear the whole canvas.
*/
public clear() {
this.context.clearRect(0, 0, this.bounds.width, this.bounds.height);
}
/**
* Renders this DynamicTexture to the Stage at the given x/y coordinates
*
* @param x {number} The X coordinate to render on the stage to (given in screen coordinates, not world)
* @param y {number} The Y coordinate to render on the stage to (given in screen coordinates, not world)
*/
public render(x?: number = 0, y?: number = 0) {
this._game.stage.context.drawImage(this.canvas, x, y);
}
public get width(): number {
return this.bounds.width;
}
@@ -183,13 +284,13 @@ module Phaser {
/**
* Given an alpha and 3 color values this will return an integer representation of it
*
* @param alpha The Alpha value (between 0 and 255)
* @param red The Red channel value (between 0 and 255)
* @param green The Green channel value (between 0 and 255)
* @param blue The Blue channel value (between 0 and 255)
*
* @return A native color value integer (format: 0xAARRGGBB)
*
* @param alpha {number} The Alpha value (between 0 and 255)
* @param red {number} The Red channel value (between 0 and 255)
* @param green {number} The Green channel value (between 0 and 255)
* @param blue {number} The Blue channel value (between 0 and 255)
*
* @return A native color value integer (format: 0xAARRGGBB)
*/
private getColor32(alpha: number, red: number, green: number, blue: number): number {
@@ -199,12 +300,12 @@ module Phaser {
/**
* Given 3 color values this will return an integer representation of it
*
* @param red The Red channel value (between 0 and 255)
* @param green The Green channel value (between 0 and 255)
* @param blue The Blue channel value (between 0 and 255)
*
* @return A native color value integer (format: 0xRRGGBB)
*
* @param red {number} The Red channel value (between 0 and 255)
* @param green {number} The Green channel value (between 0 and 255)
* @param blue {number} The Blue channel value (between 0 and 255)
*
* @return A native color value integer (format: 0xRRGGBB)
*/
private getColor(red: number, green: number, blue: number): number {
+18
View File
@@ -0,0 +1,18 @@
/// <reference path="Game.d.ts" />
module Phaser {
class FXManager {
constructor(game: Game);
private _fx;
private _length;
private _game;
public active: bool;
public visible: bool;
public add(effect): any;
public preUpdate(): void;
public postUpdate(): void;
public preRender(camera: Camera, cameraX: number, cameraY: number, cameraWidth: number, cameraHeight: number): void;
public render(camera: Camera, cameraX: number, cameraY: number, cameraWidth: number, cameraHeight: number): void;
public postRender(camera: Camera, cameraX: number, cameraY: number, cameraWidth: number, cameraHeight: number): void;
public destroy(): void;
}
}
+232
View File
@@ -0,0 +1,232 @@
/// <reference path="Game.ts" />
/**
* Phaser - FXManager
*
* The FXManager controls all special effects applied to game objects such as Cameras.
*/
module Phaser {
export class FXManager {
constructor(game: Game, parent) {
this._game = game;
this._parent = parent;
this._fx = [];
this.active = true;
this.visible = true;
}
/**
* The essential reference to the main game object.
*/
private _game: Game;
/**
* A reference to the object that owns this FXManager instance.
*/
private _parent;
/**
* The array in which we keep all of the registered FX
*/
private _fx;
/**
* Holds the size of the _fx array
*/
private _length: number;
/**
* Controls whether any of the FX have preUpdate, update or postUpdate called
*/
public active: bool;
/**
* Controls whether any of the FX have preRender, render or postRender called
*/
public visible: bool;
/**
* Adds a new FX to the FXManager.
* The effect must be an object with at least one of the following methods: preUpdate, postUpdate, preRender, render or postRender.
* A new instance of the effect will be created and a reference to Game will be passed to the object constructor.
* @param {object} effect
* @return {any}
*/
public add(effect): any {
var result: bool = false;
var newEffect = { effect: {}, preUpdate: false, postUpdate: false, preRender: false, render: false, postRender: false };
if (typeof effect === 'function')
{
newEffect.effect = new effect(this._game, this._parent);
}
else
{
throw new Error("Invalid object given to Phaser.FXManager.add");
}
// Check for methods now to avoid having to do this every loop
if (typeof newEffect.effect['preUpdate'] === 'function')
{
newEffect.preUpdate = true;
result = true;
}
if (typeof newEffect.effect['postUpdate'] === 'function')
{
newEffect.postUpdate = true;
result = true;
}
if (typeof newEffect.effect['preRender'] === 'function')
{
newEffect.preRender = true;
result = true;
}
if (typeof newEffect.effect['render'] === 'function')
{
newEffect.render = true;
result = true;
}
if (typeof newEffect.effect['postRender'] === 'function')
{
newEffect.postRender = true;
result = true;
}
if (result == true)
{
this._length = this._fx.push(newEffect);
return newEffect.effect;
}
else
{
return result;
}
}
/**
* Pre-update is called at the start of the objects update cycle, before any other updates have taken place.
*/
public preUpdate() {
if (this.active)
{
for (var i = 0; i < this._length; i++)
{
if (this._fx[i].preUpdate)
{
this._fx[i].effect.preUpdate();
}
}
}
}
/**
* Post-update is called at the end of the objects update cycle, after other update logic has taken place.
*/
public postUpdate() {
if (this.active)
{
for (var i = 0; i < this._length; i++)
{
if (this._fx[i].postUpdate)
{
this._fx[i].effect.postUpdate();
}
}
}
}
/**
* Pre-render is called at the start of the object render cycle, before any transforms have taken place.
* It happens directly AFTER a canvas context.save has happened if added to a Camera.
* @param {Camera} camera
* @param {number} cameraX
* @param {number} cameraY
* @param {number} cameraWidth
* @param {number} cameraHeight
*/
public preRender(camera:Camera, cameraX: number, cameraY: number, cameraWidth: number, cameraHeight: number) {
if (this.visible)
{
for (var i = 0; i < this._length; i++)
{
if (this._fx[i].preRender)
{
this._fx[i].effect.preRender(camera, cameraX, cameraY, cameraWidth, cameraHeight);
}
}
}
}
/**
* render is called during the objects render cycle, right after all transforms have finished, but before any children/image data is rendered.
* @param {Camera} camera
* @param {number} cameraX
* @param {number} cameraY
* @param {number} cameraWidth
* @param {number} cameraHeight
*/
public render(camera:Camera, cameraX: number, cameraY: number, cameraWidth: number, cameraHeight: number) {
if (this.visible)
{
for (var i = 0; i < this._length; i++)
{
if (this._fx[i].preRender)
{
this._fx[i].effect.preRender(camera, cameraX, cameraY, cameraWidth, cameraHeight);
}
}
}
}
/**
* Post-render is called during the objects render cycle, after the children/image data has been rendered.
* It happens directly BEFORE a canvas context.restore has happened if added to a Camera.
*/
public postRender(camera:Camera, cameraX: number, cameraY: number, cameraWidth: number, cameraHeight: number) {
if (this.visible)
{
for (var i = 0; i < this._length; i++)
{
if (this._fx[i].postRender)
{
this._fx[i].effect.postRender(camera, cameraX, cameraY, cameraWidth, cameraHeight);
}
}
}
}
/**
* Clear down this FXManager and null out references
*/
public destroy() {
this._game = null;
this._fx = null;
}
}
}
+88
View File
@@ -0,0 +1,88 @@
/// <reference path="AnimationManager.d.ts" />
/// <reference path="Basic.d.ts" />
/// <reference path="Cache.d.ts" />
/// <reference path="CameraManager.d.ts" />
/// <reference path="Collision.d.ts" />
/// <reference path="DynamicTexture.d.ts" />
/// <reference path="FXManager.d.ts" />
/// <reference path="GameMath.d.ts" />
/// <reference path="Group.d.ts" />
/// <reference path="Loader.d.ts" />
/// <reference path="Motion.d.ts" />
/// <reference path="Signal.d.ts" />
/// <reference path="SignalBinding.d.ts" />
/// <reference path="SoundManager.d.ts" />
/// <reference path="Stage.d.ts" />
/// <reference path="Time.d.ts" />
/// <reference path="TweenManager.d.ts" />
/// <reference path="World.d.ts" />
/// <reference path="system/Device.d.ts" />
/// <reference path="system/RandomDataGenerator.d.ts" />
/// <reference path="system/RequestAnimationFrame.d.ts" />
/// <reference path="system/input/Input.d.ts" />
/// <reference path="system/input/Keyboard.d.ts" />
/// <reference path="system/input/Mouse.d.ts" />
/// <reference path="system/input/Touch.d.ts" />
/// <reference path="gameobjects/Emitter.d.ts" />
/// <reference path="gameobjects/GameObject.d.ts" />
/// <reference path="gameobjects/GeomSprite.d.ts" />
/// <reference path="gameobjects/Particle.d.ts" />
/// <reference path="gameobjects/Sprite.d.ts" />
/// <reference path="gameobjects/Tilemap.d.ts" />
/// <reference path="gameobjects/ScrollZone.d.ts" />
module Phaser {
class Game {
constructor(callbackContext, parent?: string, width?: number, height?: number, initCallback?, createCallback?, updateCallback?, renderCallback?);
private _raf;
private _maxAccumulation;
private _accumulator;
private _step;
private _loadComplete;
private _paused;
private _pendingState;
public callbackContext;
public onInitCallback;
public onCreateCallback;
public onUpdateCallback;
public onRenderCallback;
public onPausedCallback;
public cache: Cache;
public collision: Collision;
public input: Input;
public loader: Loader;
public math: GameMath;
public motion: Motion;
public sound: SoundManager;
public stage: Stage;
public time: Time;
public tweens: TweenManager;
public world: World;
public rnd: RandomDataGenerator;
public device: Device;
public isBooted: bool;
public isRunning: bool;
private boot(parent, width, height);
private loadComplete();
private bootLoop();
private pausedLoop();
private loop();
private startState();
public setCallbacks(initCallback?, createCallback?, updateCallback?, renderCallback?): void;
public switchState(state, clearWorld?: bool, clearCache?: bool): void;
public destroy(): void;
public paused : bool;
public framerate : number;
public createCamera(x: number, y: number, width: number, height: number): Camera;
public createGeomSprite(x: number, y: number): GeomSprite;
public createSprite(x: number, y: number, key?: string): Sprite;
public createDynamicTexture(width: number, height: number): DynamicTexture;
public createGroup(MaxSize?: number): Group;
public createParticle(): Particle;
public createEmitter(x?: number, y?: number, size?: number): Emitter;
public createScrollZone(key: string, x?: number, y?: number, width?: number, height?: number): ScrollZone;
public createTilemap(key: string, mapData: string, format: number, resizeWorld?: bool, tileWidth?: number, tileHeight?: number): Tilemap;
public createTween(obj): Tween;
public collide(objectOrGroup1?: Basic, objectOrGroup2?: Basic, notifyCallback?): bool;
public camera : Camera;
}
}
+311 -86
View File
@@ -4,7 +4,9 @@
/// <reference path="CameraManager.ts" />
/// <reference path="Collision.ts" />
/// <reference path="DynamicTexture.ts" />
/// <reference path="FXManager.ts" />
/// <reference path="GameMath.ts" />
/// <reference path="GameObjectFactory.ts" />
/// <reference path="Group.ts" />
/// <reference path="Loader.ts" />
/// <reference path="Motion.ts" />
@@ -14,13 +16,16 @@
/// <reference path="Stage.ts" />
/// <reference path="Time.ts" />
/// <reference path="TweenManager.ts" />
/// <reference path="VerletManager.ts" />
/// <reference path="World.ts" />
/// <reference path="geom/Vector2.ts" />
/// <reference path="system/Device.ts" />
/// <reference path="system/RandomDataGenerator.ts" />
/// <reference path="system/RequestAnimationFrame.ts" />
/// <reference path="system/input/Input.ts" />
/// <reference path="system/input/Keyboard.ts" />
/// <reference path="system/input/Mouse.ts" />
/// <reference path="system/input/MSPointer.ts" />
/// <reference path="system/input/Touch.ts" />
/// <reference path="gameobjects/Emitter.ts" />
/// <reference path="gameobjects/GameObject.ts" />
@@ -33,25 +38,44 @@
/**
* Phaser - Game
*
* This is where the magic happens. The Game object is the heart of your game,
* This is where the magic happens. The Game object is the heart of your game,
* providing quick access to common functions and handling the boot process.
*
* "Hell, there are no rules here - we're trying to accomplish something."
* Thomas A. Edison
*/
module Phaser {
export class Game {
constructor(callbackContext, parent?: string = '', width?: number = 800, height?: number = 600, initCallback = null, createCallback = null, updateCallback = null, renderCallback = null) {
/**
* Game constructor
*
* Instantiate a new <code>Phaser.Game</code> object.
*
* @param callbackContext Which context will the callbacks be called with.
* @param parent {string} ID of its parent DOM element.
* @param width {number} The width of your game in game pixels.
* @param height {number} The height of your game in game pixels.
* @param initCallback {function} Init callback invoked when init default screen.
* @param createCallback {function} Create callback invoked when create default screen.
* @param updateCallback {function} Update callback invoked when update default screen.
* @param renderCallback {function} Render callback invoked when render default screen.
* @param destroyCallback {function} Destroy callback invoked when state is destroyed.
*/
constructor(callbackContext, parent?: string = '', width?: number = 800, height?: number = 600, initCallback = null, createCallback = null, updateCallback = null, renderCallback = null, destroyCallback = null) {
this.callbackContext = callbackContext;
this.onInitCallback = initCallback;
this.onCreateCallback = createCallback;
this.onUpdateCallback = updateCallback;
this.onRenderCallback = renderCallback;
this.onDestroyCallback = destroyCallback;
if (document.readyState === 'complete' || document.readyState === 'interactive')
{
setTimeout((parent, width, height) => this.boot(parent, width, height));
setTimeout(() => this.boot(parent, width, height));
}
else
{
@@ -61,39 +85,202 @@ module Phaser {
}
private _raf: RequestAnimationFrame;
/**
* Game loop trigger wrapper.
*/
public _raf: RequestAnimationFrame;
/**
* Max allowable accumulation.
* @type {number}
*/
private _maxAccumulation: number = 32;
/**
* Total number of milliseconds elapsed since last update loop.
* @type {number}
*/
private _accumulator: number = 0;
/**
* Milliseconds of time per step of the game loop.
* @type {number}
*/
private _step: number = 0;
/**
* Whether loader complete loading or not.
* @type {boolean}
*/
private _loadComplete: bool = false;
/**
* Game is paused?
* @type {boolean}
*/
private _paused: bool = false;
/**
* The state to be switched to in the next frame.
* @type {State}
*/
private _pendingState = null;
// Event callbacks
/**
* The current State object (defaults to null)
* @type {State}
*/
public state = null;
/**
* Context for calling the callbacks.
*/
public callbackContext;
/**
* This will be called when init states. (loading assets...)
* @type {function}
*/
public onInitCallback = null;
/**
* This will be called when create states. (setup states...)
* @type {function}
*/
public onCreateCallback = null;
/**
* This will be called when update states.
* @type {function}
*/
public onUpdateCallback = null;
/**
* This will be called when render states.
* @type {function}
*/
public onRenderCallback = null;
/**
* This will be called when states paused.
* @type {function}
*/
public onPausedCallback = null;
public camera: Camera; // quick reference to the default created camera, access the rest via .world
/**
* This will be called when the state is destroyed (i.e. swapping to a new state)
* @type {function}
*/
public onDestroyCallback = null;
/**
* Reference to the GameObject Factory.
* @type {GameObjectFactory}
*/
public add: GameObjectFactory;
/**
* Reference to the assets cache.
* @type {Cache}
*/
public cache: Cache;
/**
* Reference to the collision helper.
* @type {Collision}
*/
public collision: Collision;
/**
* Reference to the input manager
* @type {Input}
*/
public input: Input;
/**
* Reference to the assets loader.
* @type {Loader}
*/
public loader: Loader;
/**
* Reference to the math helper.
* @type {GameMath}
*/
public math: GameMath;
/**
* Reference to the motion helper.
* @type {Motion}
*/
public motion: Motion;
/**
* Reference to the sound manager.
* @type {SoundManager}
*/
public sound: SoundManager;
/**
* Reference to the stage.
* @type {Stage}
*/
public stage: Stage;
/**
* Reference to game clock.
* @type {Time}
*/
public time: Time;
/**
* Reference to the tween manager.
* @type {TweenManager}
*/
public tweens: TweenManager;
/**
* Reference to the verlet manager.
* @type {VerletManager}
*/
public verlet: Phaser.Verlet.VerletManager;
/**
* Reference to the world.
* @type {World}
*/
public world: World;
/**
* Instance of repeatable random data generator helper.
* @type {RandomDataGenerator}
*/
public rnd: RandomDataGenerator;
/**
* Contains device information and capabilities.
* @type {Device}
*/
public device: Device;
/**
* Whether the game engine is booted, aka available.
* @type {boolean}
*/
public isBooted: bool = false;
/**
* Is game running or paused?
* @type {boolean}
*/
public isRunning: bool = false;
/**
* Initialize engine sub modules and start the game.
* @param parent {string} ID of parent Dom element.
* @param width {number} Width of the game screen.
* @param height {number} Height of the game screen.
*/
private boot(parent: string, width: number, height: number) {
if (this.isBooted == true)
@@ -112,6 +299,7 @@ module Phaser {
this.math = new GameMath(this);
this.stage = new Stage(this, parent, width, height);
this.world = new World(this, width, height);
this.add = new GameObjectFactory(this);
this.sound = new SoundManager(this);
this.cache = new Cache(this);
this.collision = new Collision(this);
@@ -120,21 +308,23 @@ module Phaser {
this.tweens = new TweenManager(this);
this.input = new Input(this);
this.rnd = new RandomDataGenerator([(Date.now() * Math.random()).toString()]);
this.verlet = new Phaser.Verlet.VerletManager(this, width, height);
this.framerate = 60;
this.isBooted = true;
this.input.start();
// Display the default game screen?
if (this.onInitCallback == null && this.onCreateCallback == null && this.onUpdateCallback == null && this.onRenderCallback == null && this._pendingState == null)
{
this.isBooted = false;
this.stage.drawInitScreen();
this._raf = new RequestAnimationFrame(this, this.bootLoop);
}
else
{
this.isBooted = true;
this.isRunning = true;
this._loadComplete = false;
this._raf = new RequestAnimationFrame(this.loop, this);
this._raf = new RequestAnimationFrame(this, this.loop);
if (this._pendingState)
{
@@ -151,32 +341,52 @@ module Phaser {
}
/**
* Called when the loader has finished after init was run.
*/
private loadComplete() {
// Called when the loader has finished after init was run
this._loadComplete = true;
}
private loop() {
/**
* Game loop method will be called when it's booting.
*/
private bootLoop() {
this.time.update();
this.tweens.update();
if (this._paused == true)
{
if (this.onPausedCallback !== null)
{
this.onPausedCallback.call(this.callbackContext);
}
return;
}
this.input.update();
this.stage.update();
}
/**
* Game loop method will be called when it's paused.
*/
private pausedLoop() {
this.tweens.update();
this.input.update();
this.stage.update();
if (this.onPausedCallback !== null)
{
this.onPausedCallback.call(this.callbackContext);
}
}
/**
* Game loop method will be called when it's running.
*/
private loop() {
this.tweens.update();
this.input.update();
this.stage.update();
this.verlet.update();
this._accumulator += this.time.delta;
if (this._accumulator > this._maxAccumulation)
@@ -205,6 +415,9 @@ module Phaser {
}
/**
* Start current state.
*/
private startState() {
if (this.onInitCallback !== null)
@@ -237,15 +450,30 @@ module Phaser {
}
public setCallbacks(initCallback = null, createCallback = null, updateCallback = null, renderCallback = null) {
/**
* Set all state callbacks (init, create, update, render).
* @param initCallback {function} Init callback invoked when init state.
* @param createCallback {function} Create callback invoked when create state.
* @param updateCallback {function} Update callback invoked when update state.
* @param renderCallback {function} Render callback invoked when render state.
* @param destroyCallback {function} Destroy callback invoked when state is destroyed.
*/
public setCallbacks(initCallback = null, createCallback = null, updateCallback = null, renderCallback = null, destroyCallback = null) {
this.onInitCallback = initCallback;
this.onCreateCallback = createCallback;
this.onUpdateCallback = updateCallback;
this.onRenderCallback = renderCallback;
this.onDestroyCallback = destroyCallback;
}
/**
* Switch to a new State.
* @param state {State} The state you want to switch to.
* @param [clearWorld] {boolean} clear everything in the world? (Default to true)
* @param [clearCache] {boolean} clear asset cache? (Default to false and ONLY available when clearWorld=true)
*/
public switchState(state, clearWorld: bool = true, clearCache: bool = false) {
if (this.isBooted == false)
@@ -254,47 +482,61 @@ module Phaser {
return;
}
// Destroy current state?
if (this.onDestroyCallback !== null)
{
this.onDestroyCallback.call(this.callbackContext);
}
this.input.reset(true);
// Prototype?
if (typeof state === 'function')
{
state = new state(this);
this.state = new state(this);
}
// Ok, have we got the right functions?
if (state['create'] || state['update'])
if (this.state['create'] || this.state['update'])
{
this.callbackContext = state;
this.callbackContext = this.state;
this.onInitCallback = null;
this.onCreateCallback = null;
this.onUpdateCallback = null;
this.onRenderCallback = null;
this.onPausedCallback = null;
this.onDestroyCallback = null;
// Bingo, let's set them up
if (state['init'])
if (this.state['init'])
{
this.onInitCallback = state['init'];
this.onInitCallback = this.state['init'];
}
if (state['create'])
if (this.state['create'])
{
this.onCreateCallback = state['create'];
this.onCreateCallback = this.state['create'];
}
if (state['update'])
if (this.state['update'])
{
this.onUpdateCallback = state['update'];
this.onUpdateCallback = this.state['update'];
}
if (state['render'])
if (this.state['render'])
{
this.onRenderCallback = state['render'];
this.onRenderCallback = this.state['render'];
}
if (state['paused'])
if (this.state['paused'])
{
this.onPausedCallback = state['paused'];
this.onPausedCallback = this.state['paused'];
}
if (this.state['destroy'])
{
this.onDestroyCallback = this.state['destroy'];
}
if (clearWorld)
@@ -313,13 +555,14 @@ module Phaser {
}
else
{
throw Error("Invalid State object given. Must contain at least a create or update function.");
return;
throw new Error("Invalid State object given. Must contain at least a create or update function.");
}
}
// Nuke the whole game from orbit
/**
* Nuke the whole game from orbit
*/
public destroy() {
this.callbackContext = null;
@@ -328,7 +571,7 @@ module Phaser {
this.onUpdateCallback = null;
this.onRenderCallback = null;
this.onPausedCallback = null;
this.camera = null;
this.onDestroyCallback = null;
this.cache = null;
this.input = null;
this.loader = null;
@@ -349,12 +592,22 @@ module Phaser {
if (value == true && this._paused == false)
{
this._paused = true;
this._raf.callback = this.pausedLoop;
}
else if (value == false && this._paused == true)
{
this._paused = false;
this.time.time = Date.now();
//this.time.time = window.performance.now ? (performance.now() + performance.timing.navigationStart) : Date.now();
this.input.reset();
if (this.isRunning == false)
{
this._raf.callback = this.bootLoop;
}
else
{
this._raf.callback = this.loop;
}
}
}
@@ -374,50 +627,22 @@ module Phaser {
}
// Handy Proxy methods
public createCamera(x: number, y: number, width: number, height: number): Camera {
return this.world.createCamera(x, y, width, height);
/**
* Checks for overlaps between two objects using the world QuadTree. Can be GameObject vs. GameObject, GameObject vs. Group or Group vs. Group.
* Note: Does not take the objects scrollFactor into account. All overlaps are check in world space.
* @param object1 The first GameObject or Group to check. If null the world.group is used.
* @param object2 The second GameObject or Group to check.
* @param notifyCallback A callback function that is called if the objects overlap. The two objects will be passed to this function in the same order in which you passed them to Collision.overlap.
* @param processCallback A callback function that lets you perform additional checks against the two objects if they overlap. If this is set then notifyCallback will only be called if processCallback returns true.
* @param context The context in which the callbacks will be called
* @returns {boolean} true if the objects overlap, otherwise false.
*/
public collide(objectOrGroup1: Basic = null, objectOrGroup2: Basic = null, notifyCallback = null, context? = this.callbackContext): bool {
return this.collision.overlap(objectOrGroup1, objectOrGroup2, notifyCallback, Collision.separate, context);
}
public createGeomSprite(x: number, y: number): GeomSprite {
return this.world.createGeomSprite(x, y);
}
public createSprite(x: number, y: number, key?: string = ''): Sprite {
return this.world.createSprite(x, y, key);
}
public createDynamicTexture(width: number, height: number): DynamicTexture {
return this.world.createDynamicTexture(width, height);
}
public createGroup(MaxSize?: number = 0): Group {
return this.world.createGroup(MaxSize);
}
public createParticle(): Particle {
return this.world.createParticle();
}
public createEmitter(x?: number = 0, y?: number = 0, size?: number = 0): Emitter {
return this.world.createEmitter(x, y, size);
}
public createScrollZone(key: string, x?: number = 0, y?: number = 0, width?: number = 0, height?: number = 0): ScrollZone {
return this.world.createScrollZone(key, x, y, width, height);
}
public createTilemap(key: string, mapData: string, format: number, resizeWorld: bool = true, tileWidth?: number = 0, tileHeight?: number = 0): Tilemap {
return this.world.createTilemap(key, mapData, format, resizeWorld, tileWidth, tileHeight);
}
public createTween(obj): Tween {
return this.tweens.create(obj);
}
public collide(ObjectOrGroup1: Basic = null, ObjectOrGroup2: Basic = null, NotifyCallback = null): bool {
return this.collision.overlap(ObjectOrGroup1, ObjectOrGroup2, NotifyCallback, Collision.separate);
public get camera(): Camera {
return this.world.cameras.current;
}
}
+110
View File
@@ -0,0 +1,110 @@
/// <reference path="Game.d.ts" />
module Phaser {
class GameMath {
constructor(game: Game);
private _game;
static PI: number;
static PI_2: number;
static PI_4: number;
static PI_8: number;
static PI_16: number;
static TWO_PI: number;
static THREE_PI_2: number;
static E: number;
static LN10: number;
static LN2: number;
static LOG10E: number;
static LOG2E: number;
static SQRT1_2: number;
static SQRT2: number;
static DEG_TO_RAD: number;
static RAD_TO_DEG: number;
static B_16: number;
static B_31: number;
static B_32: number;
static B_48: number;
static B_53: number;
static B_64: number;
static ONE_THIRD: number;
static TWO_THIRDS: number;
static ONE_SIXTH: number;
static COS_PI_3: number;
static SIN_2PI_3: number;
static CIRCLE_ALPHA: number;
static ON: bool;
static OFF: bool;
static SHORT_EPSILON: number;
static PERC_EPSILON: number;
static EPSILON: number;
static LONG_EPSILON: number;
public cosTable: any[];
public sinTable: any[];
public fuzzyEqual(a: number, b: number, epsilon?: number): bool;
public fuzzyLessThan(a: number, b: number, epsilon?: number): bool;
public fuzzyGreaterThan(a: number, b: number, epsilon?: number): bool;
public fuzzyCeil(val: number, epsilon?: number): number;
public fuzzyFloor(val: number, epsilon?: number): number;
public average(...args: any[]): number;
public slam(value: number, target: number, epsilon?: number): number;
public percentageMinMax(val: number, max: number, min?: number): number;
public sign(n: number): number;
public truncate(n: number): number;
public shear(n: number): number;
public wrap(val: number, max: number, min?: number): number;
public arithWrap(value: number, max: number, min?: number): number;
public clamp(input: number, max: number, min?: number): number;
public snapTo(input: number, gap: number, start?: number): number;
public snapToFloor(input: number, gap: number, start?: number): number;
public snapToCeil(input: number, gap: number, start?: number): number;
public snapToInArray(input: number, arr: number[], sort?: bool): number;
public roundTo(value: number, place?: number, base?: number): number;
public floorTo(value: number, place?: number, base?: number): number;
public ceilTo(value: number, place?: number, base?: number): number;
public interpolateFloat(a: number, b: number, weight: number): number;
public radiansToDegrees(angle: number): number;
public degreesToRadians(angle: number): number;
public angleBetween(x1: number, y1: number, x2: number, y2: number): number;
public normalizeAngle(angle: number, radians?: bool): number;
public nearestAngleBetween(a1: number, a2: number, radians?: bool): number;
public normalizeAngleToAnother(dep: number, ind: number, radians?: bool): number;
public normalizeAngleAfterAnother(dep: number, ind: number, radians?: bool): number;
public normalizeAngleBeforeAnother(dep: number, ind: number, radians?: bool): number;
public interpolateAngles(a1: number, a2: number, weight: number, radians?: bool, ease?): number;
public logBaseOf(value: number, base: number): number;
public GCD(m: number, n: number): number;
public LCM(m: number, n: number): number;
public factorial(value: number): number;
public gammaFunction(value: number): number;
public fallingFactorial(base: number, exp: number): number;
public risingFactorial(base: number, exp: number): number;
public binCoef(n: number, k: number): number;
public risingBinCoef(n: number, k: number): number;
public chanceRoll(chance?: number): bool;
public maxAdd(value: number, amount: number, max: number): number;
public minSub(value: number, amount: number, min: number): number;
public wrapValue(value: number, amount: number, max: number): number;
public randomSign(): number;
public isOdd(n: number): bool;
public isEven(n: number): bool;
public wrapAngle(angle: number): number;
public angleLimit(angle: number, min: number, max: number): number;
public linearInterpolation(v, k);
public bezierInterpolation(v, k): number;
public catmullRomInterpolation(v, k);
public linear(p0, p1, t);
public bernstein(n, i): number;
public catmullRom(p0, p1, p2, p3, t);
public difference(a: number, b: number): number;
public globalSeed: number;
public random(): number;
public srand(Seed: number): number;
public getRandom(Objects, StartIndex?: number, Length?: number);
public floor(Value: number): number;
public ceil(Value: number): number;
public sinCosGenerator(length: number, sinAmplitude?: number, cosAmplitude?: number, frequency?: number): any[];
public shiftSinTable(): number;
public shiftCosTable(): number;
public vectorLength(dx: number, dy: number): number;
public dotProduct(ax: number, ay: number, bx: number, by: number): number;
}
}
+137 -75
View File
@@ -152,7 +152,7 @@ module Phaser {
/**
* force a value within the boundaries of two values
*
*
* if max < min, min is returned
*/
public clamp(input: number, max: number, min: number = 0): number {
@@ -161,12 +161,12 @@ module Phaser {
/**
* Snap a value to nearest grid slice, using rounding.
*
*
* example if you have an interval gap of 5 and a position of 12... you will snap to 10. Where as 14 will snap to 15
*
*
* @param input - the value to snap
* @param gap - the interval gap of the grid
* @param start - optional starting offset for gap
* @param [start] - optional starting offset for gap
*/
public snapTo(input: number, gap: number, start: number = 0): number {
if (gap == 0) return input;
@@ -178,12 +178,12 @@ module Phaser {
/**
* Snap a value to nearest grid slice, using floor.
*
*
* example if you have an interval gap of 5 and a position of 12... you will snap to 10. As will 14 snap to 10... but 16 will snap to 15
*
*
* @param input - the value to snap
* @param gap - the interval gap of the grid
* @param start - optional starting offset for gap
* @param [start] - optional starting offset for gap
*/
public snapToFloor(input: number, gap: number, start: number = 0): number {
if (gap == 0) return input;
@@ -195,12 +195,12 @@ module Phaser {
/**
* Snap a value to nearest grid slice, using ceil.
*
*
* example if you have an interval gap of 5 and a position of 12... you will snap to 15. As will 14 will snap to 15... but 16 will snap to 20
*
*
* @param input - the value to snap
* @param gap - the interval gap of the grid
* @param start - optional starting offset for gap
* @param [start] - optional starting offset for gap
*/
public snapToCeil(input: number, gap: number, start: number = 0): number {
if (gap == 0) return input;
@@ -231,17 +231,17 @@ module Phaser {
/**
* roundTo some place comparative to a 'base', default is 10 for decimal place
*
*
* 'place' is represented by the power applied to 'base' to get that place
*
*
* @param value - the value to round
* @param place - the place to round to
* @param base - the base to round in... default is 10 for decimal
*
*
* e.g.
*
*
* 2000/7 ~= 285.714285714285714285714 ~= (bin)100011101.1011011011011011
*
*
* roundTo(2000/7,3) == 0
* roundTo(2000/7,2) == 300
* roundTo(2000/7,1) == 290
@@ -251,7 +251,7 @@ module Phaser {
* roundTo(2000/7,-3) == 285.714
* roundTo(2000/7,-4) == 285.7143
* roundTo(2000/7,-5) == 285.71429
*
*
* roundTo(2000/7,3,2) == 288 -- 100100000
* roundTo(2000/7,2,2) == 284 -- 100011100
* roundTo(2000/7,1,2) == 286 -- 100011110
@@ -261,8 +261,8 @@ module Phaser {
* roundTo(2000/7,-3,2) == 285.75 -- 100011101.11
* roundTo(2000/7,-4,2) == 285.6875 -- 100011101.1011
* roundTo(2000/7,-5,2) == 285.71875 -- 100011101.10111
*
* note what occurs when we round to the 3rd space (8ths place), 100100000, this is to be assumed
*
* note what occurs when we round to the 3rd space (8ths place), 100100000, this is to be assumed
* because we are rounding 100011.1011011011011011 which rounds up.
*/
public roundTo(value: number, place: number = 0, base: number = 10): number {
@@ -336,7 +336,7 @@ module Phaser {
/**
* normalizes independent and then sets dep to the nearest value respective to independent
*
*
* for instance if dep=-170 and ind=170 then 190 will be returned as an alternative to -170
*/
public normalizeAngleToAnother(dep: number, ind: number, radians: bool = true): number {
@@ -345,7 +345,7 @@ module Phaser {
/**
* normalize independent and dependent and then set dependent to an angle relative to 'after/clockwise' independent
*
*
* for instance dep=-170 and ind=170, then 190 will be reutrned as alternative to -170
*/
public normalizeAngleAfterAnother(dep: number, ind: number, radians: bool = true): number {
@@ -356,7 +356,7 @@ module Phaser {
/**
* normalizes indendent and dependent and then sets dependent to an angle relative to 'before/counterclockwise' independent
*
*
* for instance dep = 190 and ind = 170, then -170 will be returned as an alternative to 190
*/
public normalizeAngleBeforeAnother(dep: number, ind: number, radians: bool = true): number {
@@ -378,17 +378,17 @@ module Phaser {
/**
* Compute the logarithm of any value of any base
*
* a logarithm is the exponent that some constant (base) would have to be raised to
*
* a logarithm is the exponent that some constant (base) would have to be raised to
* to be equal to value.
*
*
* i.e.
* 4 ^ x = 16
* can be rewritten as to solve for x
* logB4(16) = x
* which with this function would be
* which with this function would be
* LoDMath.logBaseOf(16,4)
*
*
* which would return 2, because 4^2 = 16
*/
public logBaseOf(value: number, base: number): number {
@@ -434,9 +434,9 @@ module Phaser {
/**
* Factorial - N!
*
*
* simple product series
*
*
* by definition:
* 0! == 1
*/
@@ -455,7 +455,7 @@ module Phaser {
/**
* gamma function
*
*
* defined: gamma(N) == (N - 1)!
*/
public gammaFunction(value: number): number {
@@ -464,9 +464,9 @@ module Phaser {
/**
* falling factorial
*
*
* defined: (N)! / (N - x)!
*
*
* written subscript: (N)x OR (base)exp
*/
public fallingFactorial(base: number, exp: number): number {
@@ -475,9 +475,9 @@ module Phaser {
/**
* rising factorial
*
*
* defined: (N + x - 1)! / (N - 1)!
*
*
* written superscript N^(x) OR base^(exp)
*/
public risingFactorial(base: number, exp: number): number {
@@ -487,7 +487,7 @@ module Phaser {
/**
* binomial coefficient
*
*
* defined: N! / (k!(N-k)!)
* reduced: N! / (N-k)! == (N)k (fallingfactorial)
* reduced: (N)k / k!
@@ -498,10 +498,10 @@ module Phaser {
/**
* rising binomial coefficient
*
* as one can notice in the analysis of binCoef(...) that
* binCoef is the (N)k divided by k!. Similarly rising binCoef
* is merely N^(k) / k!
*
* as one can notice in the analysis of binCoef(...) that
* binCoef is the (N)k divided by k!. Similarly rising binCoef
* is merely N^(k) / k!
*/
public risingBinCoef(n: number, k: number): number {
return this.risingFactorial(n, k) / this.factorial(k);
@@ -542,7 +542,7 @@ module Phaser {
/**
* Adds the given amount to the value, but never lets the value go over the specified maximum
*
*
* @param value The value to add the amount to
* @param amount The amount to add to the value
* @param max The maximum the value is allowed to be
@@ -563,7 +563,7 @@ module Phaser {
/**
* Subtracts the given amount from the value, but never lets the value go below the specified minimum
*
*
* @param value The base value
* @param amount The amount to subtract from the base value
* @param min The minimum the value is allowed to be
@@ -584,7 +584,7 @@ module Phaser {
/**
* Adds value to amount and ensures that the result always stays between 0 and max, by wrapping the value around.
* <p>Values must be positive integers, and are passed through Math.abs</p>
*
*
* @param value The value to add the amount to
* @param amount The amount to add to the value
* @param max The maximum the value is allowed to be
@@ -606,7 +606,7 @@ module Phaser {
/**
* Randomly returns either a 1 or -1
*
*
* @return 1 or -1
*/
public randomSign(): number {
@@ -615,9 +615,9 @@ module Phaser {
/**
* Returns true if the number given is odd.
*
*
* @param n The number to check
*
*
* @return True if the given number is odd. False if the given number is even.
*/
public isOdd(n: number): bool {
@@ -635,9 +635,9 @@ module Phaser {
/**
* Returns true if the number given is even.
*
*
* @param n The number to check
*
*
* @return True if the given number is even. False if the given number is odd.
*/
public isEven(n: number): bool {
@@ -656,9 +656,9 @@ module Phaser {
/**
* Keeps an angle value between -180 and +180<br>
* Should be called whenever the angle is updated on the Sprite to stop it from going insane.
*
*
* @param angle The angle value to check
*
*
* @return The new angle value, returns the same as the input angle if it was within bounds
*/
public wrapAngle(angle: number): number {
@@ -685,11 +685,11 @@ module Phaser {
/**
* Keeps an angle value between the given min and max values
*
*
* @param angle The angle value to check. Must be between -180 and +180
* @param min The minimum angle that is allowed (must be -180 or greater)
* @param max The maximum angle that is allowed (must be 180 or less)
*
*
* @return The new angle value, returns the same as the input angle if it was within bounds
*/
public angleLimit(angle: number, min: number, max: number): number {
@@ -832,7 +832,7 @@ module Phaser {
/**
* Generates a random number. Deterministic, meaning safe
* to use if you want to record replays in random environments.
*
*
* @return A <code>Number</code> between 0 and 1.
*/
public random(): number {
@@ -841,9 +841,9 @@ module Phaser {
/**
* Generates a random number based on the seed provided.
*
*
* @param Seed A number between 0 and 1, used to generate a predictable random number (very optional).
*
*
* @return A <code>Number</code> between 0 and 1.
*/
public srand(Seed: number): number {
@@ -855,29 +855,27 @@ module Phaser {
/**
* Fetch a random entry from the given array.
* Will return null if random selection is missing, or array has no entries.
* <code>G.getRandom()</code> is deterministic and safe for use with replays/recordings.
* HOWEVER, <code>U.getRandom()</code> is NOT deterministic and unsafe for use with replays/recordings.
*
* @param Objects An array of objects.
* @param StartIndex Optional offset off the front of the array. Default value is 0, or the beginning of the array.
* @param Length Optional restriction on the number of values you want to randomly select from.
*
*
* @param objects An array of objects.
* @param startIndex Optional offset off the front of the array. Default value is 0, or the beginning of the array.
* @param length Optional restriction on the number of values you want to randomly select from.
*
* @return The random object that was selected.
*/
public getRandom(Objects, StartIndex: number = 0, Length: number = 0) {
public getRandom(objects, startIndex: number = 0, length: number = 0) {
if (Objects != null)
if (objects != null)
{
var l: number = Length;
var l: number = length;
if ((l == 0) || (l > Objects.length - StartIndex))
if ((l == 0) || (l > objects.length - startIndex))
{
l = Objects.length - StartIndex;
l = objects.length - startIndex;
}
if (l > 0)
{
return Objects[StartIndex + Math.floor(Math.random() * l)];
return objects[startIndex + Math.floor(Math.random() * l)];
}
}
@@ -887,9 +885,9 @@ module Phaser {
/**
* Round down to the next whole number. E.g. floor(1.7) == 1, and floor(-2.7) == -2.
*
*
* @param Value Any number.
*
*
* @return The rounded value of that number.
*/
public floor(Value: number): number {
@@ -899,9 +897,9 @@ module Phaser {
/**
* Round up to the next whole number. E.g. ceil(1.3) == 2, and ceil(-2.3) == -3.
*
*
* @param Value Any number.
*
*
* @return The rounded value of that number.
*/
public ceil(Value: number): number {
@@ -979,25 +977,25 @@ module Phaser {
/**
* Finds the length of the given vector
*
*
* @param dx
* @param dy
*
*
* @return
*/
public vectorLength(dx:number, dy:number):number
{
return Math.sqrt(dx * dx + dy * dy);
}
/**
* Finds the dot product value of two vectors
*
*
* @param ax Vector X
* @param ay Vector Y
* @param bx Vector X
* @param by Vector Y
*
*
* @return Dot product
*/
public dotProduct(ax:number, ay:number, bx:number, by:number):number
@@ -1005,6 +1003,70 @@ module Phaser {
return ax * bx + ay * by;
}
/**
* Shuffles the data in the given array into a new order
* @param array The array to shuffle
* @return The array
*/
public shuffleArray(array) {
for (var i = array.length - 1; i > 0; i--)
{
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
/**
* Returns the distance from this Point object to the given Point object.
* @method distanceFrom
* @param {Point} target - The destination Point object.
* @param {Boolean} round - Round the distance to the nearest integer (default false)
* @return {Number} The distance between this Point object and the destination Point object.
**/
public static distanceBetween(x1: number, y1: number, x2: number, y2: number): number {
var dx = x1 - x2;
var dy = y1 - y2;
return Math.sqrt(dx * dx + dy * dy);
}
/**
* Rotates the point around the x/y coordinates given to the desired angle and distance
* @param point {Object} Any object with exposed x and y properties
* @param x {number} The x coordinate of the anchor point
* @param y {number} The y coordinate of the anchor point
* @param {Number} angle The angle in radians (unless asDegrees is true) to return the point from.
* @param {Boolean} asDegrees Is the given angle in radians (false) or degrees (true)?
* @param {Number} distance An optional distance constraint between the point and the anchor
* @return The modified point object
*/
public rotatePoint(point, x1: number, y1: number, angle: number, asDegrees: bool = false, distance?:number = null) {
if (asDegrees)
{
angle = angle * GameMath.DEG_TO_RAD;
}
// Get distance from origin to the point
if (distance === null)
{
distance = Math.sqrt(((x1 - point.x) * (x1 - point.x)) + ((y1 - point.y) * (y1 - point.y)));
}
point.x = x1 + distance * Math.cos(angle);
point.y = y1 + distance * Math.sin(angle);
return point;
}
}
+219
View File
@@ -0,0 +1,219 @@
/// <reference path="Game.ts" />
/**
* Phaser - GameObjectFactory
*
* A quick way to create new world objects and add existing objects to the current world.
*/
module Phaser {
export class GameObjectFactory {
/**
* GameObjectFactory constructor
* @param game {Game} A reference to the current Game.
*/
constructor(game: Phaser.Game) {
this._game = game;
this._world = this._game.world;
}
/**
* Local private reference to Game
*/
private _game: Phaser.Game;
/**
* Local private reference to World
*/
private _world: Phaser.World;
/**
* Create a new camera with specific position and size.
*
* @param x {number} X position of the new camera.
* @param y {number} Y position of the new camera.
* @param width {number} Width of the new camera.
* @param height {number} Height of the new camera.
* @returns {Camera} The newly created camera object.
*/
public camera(x: number, y: number, width: number, height: number): Camera {
return this._world.createCamera(x, y, width, height);
}
/**
* Create a new GeomSprite with specific position.
*
* @param x {number} X position of the new geom sprite.
* @param y {number} Y position of the new geom sprite.
* @returns {GeomSprite} The newly created geom sprite object.
*/
public geomSprite(x: number, y: number): GeomSprite {
return this._world.createGeomSprite(x, y);
}
/**
* Create a new Sprite with specific position and sprite sheet key.
*
* @param x {number} X position of the new sprite.
* @param y {number} Y position of the new sprite.
* @param key {string} Optional, key for the sprite sheet you want it to use.
* @returns {Sprite} The newly created sprite object.
*/
public sprite(x: number, y: number, key?: string = ''): Sprite {
return this._world.createSprite(x, y, key);
}
/**
* Create a new DynamicTexture with specific size.
*
* @param width {number} Width of the texture.
* @param height {number} Height of the texture.
* @returns {DynamicTexture} The newly created dynamic texture object.
*/
public dynamicTexture(width: number, height: number): DynamicTexture {
return this._world.createDynamicTexture(width, height);
}
/**
* Create a new object container.
*
* @param maxSize {number} Optional, capacity of this group.
* @returns {Group} The newly created group.
*/
public group(maxSize?: number = 0): Group {
return this._world.createGroup(maxSize);
}
/**
* Create a new Particle.
*
* @return {Particle} The newly created particle object.
*/
public particle(): Particle {
return this._world.createParticle();
}
/**
* Create a new Emitter.
*
* @param x {number} Optional, x position of the emitter.
* @param y {number} Optional, y position of the emitter.
* @param size {number} Optional, size of this emitter.
* @return {Emitter} The newly created emitter object.
*/
public emitter(x?: number = 0, y?: number = 0, size?: number = 0): Emitter {
return this._world.createEmitter(x, y, size);
}
/**
* Create a new ScrollZone object with image key, position and size.
*
* @param key {string} Key to a image you wish this object to use.
* @param x {number} X position of this object.
* @param y {number} Y position of this object.
* @param width number} Width of this object.
* @param height {number} Height of this object.
* @returns {ScrollZone} The newly created scroll zone object.
*/
public scrollZone(key: string, x?: number = 0, y?: number = 0, width?: number = 0, height?: number = 0): ScrollZone {
return this._world.createScrollZone(key, x, y, width, height);
}
/**
* Create a new Tilemap.
*
* @param key {string} Key for tileset image.
* @param mapData {string} Data of this tilemap.
* @param format {number} Format of map data. (Tilemap.FORMAT_CSV or Tilemap.FORMAT_TILED_JSON)
* @param [resizeWorld] {boolean} resize the world to make same as tilemap?
* @param [tileWidth] {number} width of each tile.
* @param [tileHeight] {number} height of each tile.
* @return {Tilemap} The newly created tilemap object.
*/
public tilemap(key: string, mapData: string, format: number, resizeWorld: bool = true, tileWidth?: number = 0, tileHeight?: number = 0): Tilemap {
return this._world.createTilemap(key, mapData, format, resizeWorld, tileWidth, tileHeight);
}
/**
* Create a tween object for a specific object.
*
* @param obj Object you wish the tween will affect.
* @return {Phaser.Tween} The newly created tween object.
*/
public tween(obj): Tween {
return this._game.tweens.create(obj);
}
/**
* Add an existing Sprite to the current world.
* Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
*
* @param sprite The Sprite to add to the Game World
* @return {Phaser.Sprite} The Sprite object
*/
public existingSprite(sprite: Sprite): Sprite {
return this._world.group.add(sprite);
}
/**
* Add an existing GeomSprite to the current world.
* Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
*
* @param sprite The GeomSprite to add to the Game World
* @return {Phaser.GeomSprite} The GeomSprite object
*/
public existingGeomSprite(sprite: GeomSprite): GeomSprite {
return this._world.group.add(sprite);
}
/**
* Add an existing Emitter to the current world.
* Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
*
* @param emitter The Emitter to add to the Game World
* @return {Phaser.Emitter} The Emitter object
*/
public existingEmitter(emitter: Emitter): Emitter {
return this._world.group.add(emitter);
}
/**
* Add an existing ScrollZone to the current world.
* Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
*
* @param scrollZone The ScrollZone to add to the Game World
* @return {Phaser.ScrollZone} The ScrollZone object
*/
public existingScrollZone(scrollZone: ScrollZone): ScrollZone {
return this._world.group.add(scrollZone);
}
/**
* Add an existing Tilemap to the current world.
* Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
*
* @param tilemap The Tilemap to add to the Game World
* @return {Phaser.Tilemap} The Tilemap object
*/
public existingTilemap(tilemap: Tilemap): Tilemap {
return this._world.group.add(tilemap);
}
/**
* Add an existing Tween to the current world.
* Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
*
* @param tween The Tween to add to the Game World
* @return {Phaser.Tween} The Tween object
*/
public existingTween(tween: Tween): Tween {
return this._game.tweens.add(tween);
}
}
}
+39
View File
@@ -0,0 +1,39 @@
/// <reference path="Basic.d.ts" />
/// <reference path="Game.d.ts" />
module Phaser {
class Group extends Basic {
constructor(game: Game, MaxSize?: number);
static ASCENDING: number;
static DESCENDING: number;
public members: Basic[];
public length: number;
private _maxSize;
private _marker;
private _sortIndex;
private _sortOrder;
public destroy(): void;
public update(): void;
public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number): void;
public maxSize : number;
public add(Object: Basic): Basic;
public recycle(ObjectClass?);
public remove(Object: Basic, Splice?: bool): Basic;
public replace(OldObject: Basic, NewObject: Basic): Basic;
public sort(Index?: string, Order?: number): void;
public setAll(VariableName: string, Value: Object, Recurse?: bool): void;
public callAll(FunctionName: string, Recurse?: bool): void;
public forEach(callback, recursive?: bool): void;
public forEachAlive(context, callback, recursive?: bool): void;
public getFirstAvailable(ObjectClass?);
public getFirstNull(): number;
public getFirstExtant(): Basic;
public getFirstAlive(): Basic;
public getFirstDead(): Basic;
public countLiving(): number;
public countDead(): number;
public getRandom(StartIndex?: number, Length?: number): Basic;
public clear(): void;
public kill(): void;
public sortHandler(Obj1: Basic, Obj2: Basic): number;
}
}
+214 -87
View File
@@ -5,7 +5,6 @@
* Phaser - Group
*
* This class is used for organising, updating and sorting game objects.
*
*/
module Phaser {
@@ -22,9 +21,31 @@ module Phaser {
this._maxSize = MaxSize;
this._marker = 0;
this._sortIndex = null;
this.cameraBlacklist = [];
}
/**
* Internal tracker for the maximum capacity of the group.
* Default is 0, or no max capacity.
*/
private _maxSize: number;
/**
* Internal helper variable for recycling objects a la <code>Emitter</code>.
*/
private _marker: number;
/**
* Helper for sort.
*/
private _sortIndex: string;
/**
* Helper for sort.
*/
private _sortOrder: number;
/**
* Use with <code>sort()</code> to sort in ascending order.
*/
@@ -48,25 +69,62 @@ module Phaser {
public length: number;
/**
* Internal tracker for the maximum capacity of the group.
* Default is 0, or no max capacity.
* You can set a globalCompositeOperation that will be applied before the render method is called on this Groups children.
* This is useful if you wish to apply an effect like 'lighten' to a whole group of children as it saves doing it one-by-one.
* If this value is set it will call a canvas context save and restore before and after the render pass.
* Set to null to disable.
*/
private _maxSize: number;
public globalCompositeOperation: string = null;
/**
* Internal helper variable for recycling objects a la <code>Emitter</code>.
* You can set an alpha value on this Group that will be applied before the render method is called on this Groups children.
* This is useful if you wish to alpha a whole group of children as it saves doing it one-by-one.
* Set to 0 to disable.
*/
private _marker: number;
public alpha: number = 0;
/**
* Helper for sort.
* An Array of Cameras to which this Group, or any of its children, won't render
* @type {Array}
*/
private _sortIndex: string;
public cameraBlacklist: number[];
/**
* Helper for sort.
* If you do not wish this object to be visible to a specific camera, pass the camera here.
*
* @param camera {Camera} The specific camera.
*/
public hideFromCamera(camera: Camera) {
if (this.cameraBlacklist.indexOf(camera.ID) == -1)
{
this.cameraBlacklist.push(camera.ID);
}
}
/**
* Make this object only visible to a specific camera.
*
* @param camera {Camera} The camera you wish it to be visible.
*/
public showToCamera(camera: Camera) {
if (this.cameraBlacklist.indexOf(camera.ID) !== -1)
{
this.cameraBlacklist.slice(this.cameraBlacklist.indexOf(camera.ID), 1);
}
}
/**
* This clears the camera black list, making the GameObject visible to all cameras.
*/
private _sortOrder: number;
public clearCameraList() {
this.cameraBlacklist.length = 0;
}
/**
* Override this function to handle any deleting or "shutdown" type operations you might need,
@@ -99,7 +157,12 @@ module Phaser {
/**
* Automatically goes through and calls update on everything you added.
*/
public update() {
public update(forceUpdate?: bool = false) {
if (this.ignoreGlobalUpdate && forceUpdate == false)
{
return;
}
var basic: Basic;
var i: number = 0;
@@ -108,10 +171,10 @@ module Phaser {
{
basic = this.members[i++];
if ((basic != null) && basic.exists && basic.active)
if ((basic != null) && basic.exists && basic.active && basic.ignoreGlobalUpdate == false)
{
basic.preUpdate();
basic.update();
basic.update(forceUpdate);
basic.postUpdate();
}
}
@@ -120,7 +183,29 @@ module Phaser {
/**
* Automatically goes through and calls render on everything you added.
*/
public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number) {
public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number, forceRender?: bool = false) {
if (this.cameraBlacklist.indexOf(camera.ID) !== -1)
{
return;
}
if (this.ignoreGlobalRender && forceRender == false)
{
return;
}
if (this.globalCompositeOperation)
{
this._game.stage.context.save();
this._game.stage.context.globalCompositeOperation = this.globalCompositeOperation;
}
if (this.alpha > 0)
{
var prevAlpha: number = this._game.stage.context.globalAlpha;
this._game.stage.context.globalAlpha = this.alpha;
}
var basic: Basic;
var i: number = 0;
@@ -129,11 +214,21 @@ module Phaser {
{
basic = this.members[i++];
if ((basic != null) && basic.exists && basic.visible)
if ((basic != null) && basic.exists && basic.visible && basic.ignoreGlobalRender == false)
{
basic.render(camera, cameraOffsetX, cameraOffsetY);
basic.render(camera, cameraOffsetX, cameraOffsetY, forceRender);
}
}
if (this.alpha > 0)
{
this._game.stage.context.globalAlpha = prevAlpha;
}
if (this.globalCompositeOperation)
{
this._game.stage.context.restore();
}
}
/**
@@ -179,7 +274,7 @@ module Phaser {
}
/**
* Adds a new <code>Basic</code> subclass (Basic, Basic, Enemy, etc) to the group.
* Adds a new <code>Basic</code> subclass (Basic, GameObject, Sprite, etc) to the group.
* Group will try to replace a null member of the array first.
* Failing that, Group will add it to the end of the member array,
* assuming there is room for it, and doubling the size of the array if necessary.
@@ -187,11 +282,10 @@ module Phaser {
* <p>WARNING: If the group has a maxSize that has already been met,
* the object will NOT be added to the group!</p>
*
* @param Object The object you want to add to the group.
*
* @return The same <code>Basic</code> object that was passed in.
* @param {Basic} Object The object you want to add to the group.
* @return {Basic} The same <code>Basic</code> object that was passed in.
*/
public add(Object: Basic) {
public add(Object: Basic): any {
//Don't bother adding an object twice.
if (this.members.indexOf(Object) >= 0)
@@ -252,26 +346,26 @@ module Phaser {
/**
* Recycling is designed to help you reuse game objects without always re-allocating or "newing" them.
*
*
* <p>If you specified a maximum size for this group (like in Emitter),
* then recycle will employ what we're calling "rotating" recycling.
* Recycle() will first check to see if the group is at capacity yet.
* If group is not yet at capacity, recycle() returns a new object.
* If the group IS at capacity, then recycle() just returns the next object in line.</p>
*
*
* <p>If you did NOT specify a maximum size for this group,
* then recycle() will employ what we're calling "grow-style" recycling.
* Recycle() will return either the first object with exists == false,
* or, finding none, add a new object to the array,
* doubling the size of the array if necessary.</p>
*
*
* <p>WARNING: If this function needs to create a new object,
* and no object class was provided, it will return null
* instead of a valid object!</p>
*
* @param ObjectClass The class type you want to recycle (e.g. Basic, EvilRobot, etc). Do NOT "new" the class in the parameter!
*
* @return A reference to the object that was created. Don't forget to cast it back to the Class you want (e.g. myObject = myGroup.recycle(myObjectClass) as myObjectClass;).
*
* @param {class} ObjectClass The class type you want to recycle (e.g. Basic, EvilRobot, etc). Do NOT "new" the class in the parameter!
*
* @return {any} A reference to the object that was created. Don't forget to cast it back to the Class you want (e.g. myObject = myGroup.recycle(myObjectClass) as myObjectClass;).
*/
public recycle(ObjectClass = null) {
@@ -320,22 +414,22 @@ module Phaser {
/**
* Removes an object from the group.
*
* @param Object The <code>Basic</code> you want to remove.
* @param Splice Whether the object should be cut from the array entirely or not.
*
* @return The removed object.
*
* @param {Basic} object The <code>Basic</code> you want to remove.
* @param {boolean} splice Whether the object should be cut from the array entirely or not.
*
* @return {Basic} The removed object.
*/
public remove(Object: Basic, Splice: bool = false): Basic {
public remove(object: Basic, splice: bool = false): Basic {
var index: number = this.members.indexOf(Object);
var index: number = this.members.indexOf(object);
if ((index < 0) || (index >= this.members.length))
{
return null;
}
if (Splice)
if (splice)
{
this.members.splice(index, 1);
this.length--;
@@ -345,30 +439,30 @@ module Phaser {
this.members[index] = null;
}
return Object;
return object;
}
/**
* Replaces an existing <code>Basic</code> with a new one.
*
* @param OldObject The object you want to replace.
* @param NewObject The new object you want to use instead.
*
* @return The new object.
*
* @param {Basic} oldObject The object you want to replace.
* @param {Basic} newObject The new object you want to use instead.
*
* @return {Basic} The new object.
*/
public replace(OldObject: Basic, NewObject: Basic): Basic {
public replace(oldObject: Basic, newObject: Basic): Basic {
var index: number = this.members.indexOf(OldObject);
var index: number = this.members.indexOf(oldObject);
if ((index < 0) || (index >= this.members.length))
{
return null;
}
this.members[index] = NewObject;
this.members[index] = newObject;
return NewObject;
return newObject;
}
@@ -378,24 +472,24 @@ module Phaser {
* <code>myGroup.sort("y",Group.ASCENDING)</code> at the bottom of your
* <code>State.update()</code> override. To sort all existing objects after
* a big explosion or bomb attack, you might call <code>myGroup.sort("exists",Group.DESCENDING)</code>.
*
* @param Index The <code>string</code> name of the member variable you want to sort on. Default value is "y".
* @param Order A <code>Group</code> constant that defines the sort order. Possible values are <code>Group.ASCENDING</code> and <code>Group.DESCENDING</code>. Default value is <code>Group.ASCENDING</code>.
*
* @param {string} index The <code>string</code> name of the member variable you want to sort on. Default value is "y".
* @param {number} order A <code>Group</code> constant that defines the sort order. Possible values are <code>Group.ASCENDING</code> and <code>Group.DESCENDING</code>. Default value is <code>Group.ASCENDING</code>.
*/
public sort(Index: string = "y", Order: number = Group.ASCENDING) {
public sort(index: string = "y", order: number = Group.ASCENDING) {
this._sortIndex = Index;
this._sortOrder = Order;
this._sortIndex = index;
this._sortOrder = order;
this.members.sort(this.sortHandler);
}
/**
* Go through and set the specified variable to the specified value on all members of the group.
*
* @param VariableName The string representation of the variable name you want to modify, for example "visible" or "scrollFactor".
* @param Value The value you want to assign to that variable.
* @param Recurse Default value is true, meaning if <code>setAll()</code> encounters a member that is a group, it will call <code>setAll()</code> on that group rather than modifying its variable.
*
* @param {string} VariableName The string representation of the variable name you want to modify, for example "visible" or "scrollFactor".
* @param {Object} Value The value you want to assign to that variable.
* @param {boolean} Recurse Default value is true, meaning if <code>setAll()</code> encounters a member that is a group, it will call <code>setAll()</code> on that group rather than modifying its variable.
*/
public setAll(VariableName: string, Value: Object, Recurse: bool = true) {
@@ -423,9 +517,9 @@ module Phaser {
/**
* Go through and call the specified function on all members of the group.
* Currently only works on functions that have no required parameters.
*
* @param FunctionName The string representation of the function you want to call on each object, for example "kill()" or "init()".
* @param Recurse Default value is true, meaning if <code>callAll()</code> encounters a member that is a group, it will call <code>callAll()</code> on that group rather than calling the group's function.
*
* @param {string} FunctionName The string representation of the function you want to call on each object, for example "kill()" or "init()".
* @param {boolean} Recurse Default value is true, meaning if <code>callAll()</code> encounters a member that is a group, it will call <code>callAll()</code> on that group rather than calling the group's function.
*/
public callAll(FunctionName: string, Recurse: bool = true) {
@@ -450,7 +544,11 @@ module Phaser {
}
}
public forEach(callback, Recurse: bool = false) {
/**
* @param {function} callback
* @param {boolean} recursive
*/
public forEach(callback, recursive: bool = false) {
var basic;
var i: number = 0;
@@ -461,7 +559,7 @@ module Phaser {
if (basic != null)
{
if (Recurse && (basic.isGroup == true))
if (recursive && (basic.isGroup == true))
{
basic.forEach(callback, true);
}
@@ -474,13 +572,42 @@ module Phaser {
}
/**
* @param {any} context
* @param {function} callback
* @param {boolean} recursive
*/
public forEachAlive(context, callback, recursive: bool = false) {
var basic;
var i: number = 0;
while (i < this.length)
{
basic = this.members[i++];
if (basic != null && basic.alive)
{
if (recursive && (basic.isGroup == true))
{
basic.forEachAlive(context, callback, true);
}
else
{
callback.call(context, basic);
}
}
}
}
/**
* Call this function to retrieve the first object with exists == false in the group.
* This is handy for recycling in general, e.g. respawning enemies.
*
* @param ObjectClass An optional parameter that lets you narrow the results to instances of this particular class.
*
* @return A <code>Basic</code> currently flagged as not existing.
*
* @param {any} [ObjectClass] An optional parameter that lets you narrow the results to instances of this particular class.
*
* @return {any} A <code>Basic</code> currently flagged as not existing.
*/
public getFirstAvailable(ObjectClass = null) {
@@ -504,8 +631,8 @@ module Phaser {
/**
* Call this function to retrieve the first index set to 'null'.
* Returns -1 if no index stores a null object.
*
* @return An <code>int</code> indicating the first null slot in the group.
*
* @return {number} An <code>int</code> indicating the first null slot in the group.
*/
public getFirstNull(): number {
@@ -532,8 +659,8 @@ module Phaser {
/**
* Call this function to retrieve the first object with exists == true in the group.
* This is handy for checking if everything's wiped out, or choosing a squad leader, etc.
*
* @return A <code>Basic</code> currently flagged as existing.
*
* @return {Basic} A <code>Basic</code> currently flagged as existing.
*/
public getFirstExtant(): Basic {
@@ -557,8 +684,8 @@ module Phaser {
/**
* Call this function to retrieve the first object with dead == false in the group.
* This is handy for checking if everything's wiped out, or choosing a squad leader, etc.
*
* @return A <code>Basic</code> currently flagged as not dead.
*
* @return {Basic} A <code>Basic</code> currently flagged as not dead.
*/
public getFirstAlive(): Basic {
@@ -582,8 +709,8 @@ module Phaser {
/**
* Call this function to retrieve the first object with dead == true in the group.
* This is handy for checking if everything's wiped out, or choosing a squad leader, etc.
*
* @return A <code>Basic</code> currently flagged as dead.
*
* @return {Basic} A <code>Basic</code> currently flagged as dead.
*/
public getFirstDead(): Basic {
@@ -606,8 +733,8 @@ module Phaser {
/**
* Call this function to find out how many members of the group are not dead.
*
* @return The number of <code>Basic</code>s flagged as not dead. Returns -1 if group is empty.
*
* @return {number} The number of <code>Basic</code>s flagged as not dead. Returns -1 if group is empty.
*/
public countLiving(): number {
@@ -639,8 +766,8 @@ module Phaser {
/**
* Call this function to find out how many members of the group are dead.
*
* @return The number of <code>Basic</code>s flagged as dead. Returns -1 if group is empty.
*
* @return {number} The number of <code>Basic</code>s flagged as dead. Returns -1 if group is empty.
*/
public countDead(): number {
@@ -672,11 +799,11 @@ module Phaser {
/**
* Returns a member at random from the group.
*
* @param StartIndex Optional offset off the front of the array. Default value is 0, or the beginning of the array.
* @param Length Optional restriction on the number of values you want to randomly select from.
*
* @return A <code>Basic</code> from the members list.
*
* @param {number} StartIndex Optional offset off the front of the array. Default value is 0, or the beginning of the array.
* @param {number} Length Optional restriction on the number of values you want to randomly select from.
*
* @return {Basic} A <code>Basic</code> from the members list.
*/
public getRandom(StartIndex: number = 0, Length: number = 0): Basic {
@@ -719,11 +846,11 @@ module Phaser {
/**
* Helper function for the sort process.
*
* @param Obj1 The first object being sorted.
* @param Obj2 The second object being sorted.
*
* @return An integer value: -1 (Obj1 before Obj2), 0 (same), or 1 (Obj1 after Obj2).
*
* @param {Basic} Obj1 The first object being sorted.
* @param {Basic} Obj2 The second object being sorted.
*
* @return {number} An integer value: -1 (Obj1 before Obj2), 0 (same), or 1 (Obj1 after Obj2).
*/
public sortHandler(Obj1: Basic, Obj2: Basic): number {
+34
View File
@@ -0,0 +1,34 @@
/// <reference path="Game.d.ts" />
module Phaser {
class Loader {
constructor(game: Game, callback);
private _game;
private _keys;
private _fileList;
private _gameCreateComplete;
private _onComplete;
private _onFileLoad;
private _progressChunk;
private _xhr;
private _queueSize;
public hasLoaded: bool;
public progress: number;
public reset(): void;
public queueSize : number;
public addImageFile(key: string, url: string): void;
public addSpriteSheet(key: string, url: string, frameWidth: number, frameHeight: number, frameMax?: number): void;
public addTextureAtlas(key: string, url: string, jsonURL?: string, jsonData?): void;
public addAudioFile(key: string, url: string): void;
public addTextFile(key: string, url: string): void;
public removeFile(key: string): void;
public removeAll(): void;
public load(onFileLoadCallback?, onCompleteCallback?): void;
private loadFile();
private fileError(key);
private fileComplete(key);
private jsonLoadComplete(key);
private jsonLoadError(key);
private nextFile(previousKey, success);
private checkKeyExists(key);
}
}
+237 -34
View File
@@ -11,6 +11,12 @@ module Phaser {
export class Loader {
/**
* Loader constructor
*
* @param game {Phaser.Game} Current game instance.
* @param callback {function} This will be called when assets completely loaded.
*/
constructor(game: Game, callback) {
this._game = game;
@@ -22,19 +28,70 @@ module Phaser {
}
/**
* Local private reference to game.
*/
private _game: Game;
/**
* Array stors assets keys. So you can get that asset by its unique key.
*/
private _keys: string[];
/**
* Contains all the assets file infos.
*/
private _fileList;
/**
* Game initialial assets loading callback.
*/
private _gameCreateComplete;
private _onComplete;
private _onFileLoad;
/**
* Indicates assets loading progress. (from 0 to 100)
* @type {number}
*/
private _progressChunk: number;
private _xhr: XMLHttpRequest;
/**
* Length of assets queue.
* @type {number}
*/
private _queueSize: number;
/**
* True if game is completely loaded.
* @type {boolean}
*/
public hasLoaded: bool;
/**
* Loading progress (from 0 to 1)
* @type {number}
*/
public progress: number;
/**
* The crossOrigin value applied to loaded images
* @type {string}
*/
public crossOrigin: string = '';
/**
* TextureAtlas data format constants
*/
public static TEXTURE_ATLAS_JSON_ARRAY: number = 0;
public static TEXTURE_ATLAS_JSON_HASH: number = 1;
public static TEXTURE_ATLAS_XML_STARLING: number = 2;
/**
* Reset loader, this will remove all loaded assets.
*/
public reset() {
this._queueSize = 0;
}
@@ -45,6 +102,11 @@ module Phaser {
}
/**
* Add a new image asset loading request with key and url.
* @param key {string} Unique asset key of this image file.
* @param url {string} URL of image file.
*/
public addImageFile(key: string, url: string) {
if (this.checkKeyExists(key) === false)
@@ -56,6 +118,14 @@ module Phaser {
}
/**
* Add a new sprite sheet loading request.
* @param key {string} Unique asset key of the sheet file.
* @param url {string} URL of sheet file.
* @param frameWidth {number} Width of each single frame.
* @param frameHeight {number} Height of each single frame.
* @param frameMax {number} How many frames in this sprite sheet.
*/
public addSpriteSheet(key: string, url: string, frameWidth: number, frameHeight: number, frameMax?: number = -1) {
if (this.checkKeyExists(key) === false)
@@ -67,40 +137,78 @@ module Phaser {
}
public addTextureAtlas(key: string, url: string, jsonURL?: string = null, jsonData? = null) {
/**
* Add a new texture atlas loading request.
* @param key {string} Unique asset key of the texture atlas file.
* @param textureURL {string} The url of the texture atlas image file.
* @param [atlasURL] {string} The url of the texture atlas data file (json/xml)
* @param [atlasData] {object} A JSON or XML data object.
* @param [format] {number} A value describing the format of the data.
*/
public addTextureAtlas(key: string, textureURL: string, atlasURL?: string = null, atlasData? = null, format?:number = Loader.TEXTURE_ATLAS_JSON_ARRAY) {
if (this.checkKeyExists(key) === false)
{
if (jsonURL !== null)
if (atlasURL !== null)
{
// A URL to a json file has been given
// A URL to a json/xml file has been given
this._queueSize++;
this._fileList[key] = { type: 'textureatlas', key: key, url: url, data: null, jsonURL: jsonURL, jsonData: null, error: false, loaded: false };
this._fileList[key] = { type: 'textureatlas', key: key, url: textureURL, atlasURL: atlasURL, data: null, format: format, error: false, loaded: false };
this._keys.push(key);
}
else
{
// A json string or object has been given
if (typeof jsonData === 'string')
if (format == Loader.TEXTURE_ATLAS_JSON_ARRAY)
{
var data = JSON.parse(jsonData);
// Malformed?
if (data['frames'])
// A json string or object has been given
if (typeof atlasData === 'string')
{
this._queueSize++;
this._fileList[key] = { type: 'textureatlas', key: key, url: url, data: null, jsonURL: null, jsonData: data['frames'], error: false, loaded: false };
this._keys.push(key);
atlasData = JSON.parse(atlasData);
}
this._queueSize++;
this._fileList[key] = { type: 'textureatlas', key: key, url: textureURL, data: null, atlasURL: null, atlasData: atlasData['frames'], format: format, error: false, loaded: false };
this._keys.push(key);
}
else
else if (format == Loader.TEXTURE_ATLAS_XML_STARLING)
{
// Malformed?
if (jsonData['frames'])
// An xml string or object has been given
if (typeof atlasData === 'string')
{
this._queueSize++;
this._fileList[key] = { type: 'textureatlas', key: key, url: url, data: null, jsonURL: null, jsonData: jsonData['frames'], error: false, loaded: false };
this._keys.push(key);
var xml;
try
{
if (window['DOMParser'])
{
var domparser = new DOMParser();
xml = domparser.parseFromString(atlasData, "text/xml");
}
else
{
xml = new ActiveXObject("Microsoft.XMLDOM");
xml.async = 'false';
xml.loadXML(atlasData);
}
}
catch (e)
{
xml = undefined;
}
if (!xml || !xml.documentElement || xml.getElementsByTagName("parsererror").length)
{
throw new Error("Phaser.Loader. Invalid Texture Atlas XML given");
}
else
{
atlasData = xml;
}
}
this._queueSize++;
this._fileList[key] = { type: 'textureatlas', key: key, url: textureURL, data: null, atlasURL: null, atlasData: atlasData, format: format, error: false, loaded: false };
this._keys.push(key);
}
}
@@ -109,6 +217,11 @@ module Phaser {
}
/**
* Add a new audio file loading request.
* @param key {string} Unique asset key of the audio file.
* @param url {string} URL of audio file.
*/
public addAudioFile(key: string, url: string) {
if (this.checkKeyExists(key) === false)
@@ -120,6 +233,11 @@ module Phaser {
}
/**
* Add a new text file loading request.
* @param key {string} Unique asset key of the text file.
* @param url {string} URL of text file.
*/
public addTextFile(key: string, url: string) {
if (this.checkKeyExists(key) === false)
@@ -131,18 +249,30 @@ module Phaser {
}
/**
* Remove loading request of a file.
* @param key {string} Key of the file you want to remove.
*/
public removeFile(key: string) {
delete this._fileList[key];
}
/**
* Remove all file loading requests.
*/
public removeAll() {
this._fileList = {};
}
/**
* Load assets.
* @param onFileLoadCallback {function} Called when each file loaded successfully.
* @param onCompleteCallback {function} Called when all assets completely loaded.
*/
public load(onFileLoadCallback = null, onCompleteCallback = null) {
this.progress = 0;
@@ -176,6 +306,9 @@ module Phaser {
}
/**
* Load files. Private method ONLY used by loader.
*/
private loadFile() {
var file = this._fileList[this._keys.pop()];
@@ -191,6 +324,7 @@ module Phaser {
file.data.name = file.key;
file.data.onload = () => this.fileComplete(file.key);
file.data.onerror = () => this.fileError(file.key);
file.data.crossOrigin = this.crossOrigin;
file.data.src = file.url;
break;
@@ -213,6 +347,10 @@ module Phaser {
}
/**
* Error occured when load a file.
* @param key {string} Key of the error loading file.
*/
private fileError(key: string) {
this._fileList[key].loaded = true;
@@ -222,6 +360,10 @@ module Phaser {
}
/**
* Called when a file is successfully loaded.
* @param key {string} Key of the successfully loaded file.
*/
private fileComplete(key: string) {
this._fileList[key].loaded = true;
@@ -240,18 +382,27 @@ module Phaser {
break;
case 'textureatlas':
if (file.jsonURL == null)
if (file.atlasURL == null)
{
this._game.cache.addTextureAtlas(file.key, file.url, file.data, file.jsonData);
this._game.cache.addTextureAtlas(file.key, file.url, file.data, file.atlasData, file.format);
}
else
{
// Load the JSON before carrying on with the next file
// Load the JSON or XML before carrying on with the next file
loadNext = false;
this._xhr.open("GET", file.jsonURL, true);
this._xhr.open("GET", file.atlasURL, true);
this._xhr.responseType = "text";
this._xhr.onload = () => this.jsonLoadComplete(file.key);
this._xhr.onerror = () => this.jsonLoadError(file.key);
if (file.format == Loader.TEXTURE_ATLAS_JSON_ARRAY)
{
this._xhr.onload = () => this.jsonLoadComplete(file.key);
}
else if (file.format == Loader.TEXTURE_ATLAS_XML_STARLING)
{
this._xhr.onload = () => this.xmlLoadComplete(file.key);
}
this._xhr.onerror = () => this.dataLoadError(file.key);
this._xhr.send();
}
break;
@@ -274,36 +425,83 @@ module Phaser {
}
/**
* Successfully loaded a JSON file.
* @param key {string} Key of the loaded JSON file.
*/
private jsonLoadComplete(key: string) {
var data = JSON.parse(this._xhr.response);
var file = this._fileList[key];
// Malformed?
if (data['frames'])
{
var file = this._fileList[key];
this._game.cache.addTextureAtlas(file.key, file.url, file.data, data['frames']);
}
this._game.cache.addTextureAtlas(file.key, file.url, file.data, data['frames'], file.format);
this.nextFile(key, true);
}
private jsonLoadError(key: string) {
/**
* Error occured when load a JSON.
* @param key {string} Key of the error loading JSON file.
*/
private dataLoadError(key: string) {
var file = this._fileList[key];
file.error = true;
this.nextFile(key, true);
}
private xmlLoadComplete(key: string) {
var atlasData = this._xhr.response;
var xml;
try
{
if (window['DOMParser'])
{
var domparser = new DOMParser();
xml = domparser.parseFromString(atlasData, "text/xml");
}
else
{
xml = new ActiveXObject("Microsoft.XMLDOM");
xml.async = 'false';
xml.loadXML(atlasData);
}
}
catch (e)
{
xml = undefined;
}
if (!xml || !xml.documentElement || xml.getElementsByTagName("parsererror").length)
{
throw new Error("Phaser.Loader. Invalid Texture Atlas XML given");
}
var file = this._fileList[key];
this._game.cache.addTextureAtlas(file.key, file.url, file.data, xml, file.format);
this.nextFile(key, true);
}
/**
* Handle loading next file.
* @param previousKey {string} Key of previous loaded asset.
* @param success {boolean} Whether the previous asset loaded successfully or not.
*/
private nextFile(previousKey: string, success: bool) {
this.progress = Math.round(this.progress + this._progressChunk);
if (this.progress > 1)
if (this.progress > 100)
{
this.progress = 1;
this.progress = 100;
}
if (this._onFileLoad)
@@ -329,6 +527,11 @@ module Phaser {
}
/**
* Check whether asset exists with a specific key.
* @param key {string} Key of the asset you want to check.
* @return {boolean} Return true if exists, otherwise return false.
*/
private checkKeyExists(key: string): bool {
if (this._fileList[key])
+23
View File
@@ -0,0 +1,23 @@
/// <reference path="Game.d.ts" />
/// <reference path="gameobjects/GameObject.d.ts" />
module Phaser {
class Motion {
constructor(game: Game);
private _game;
public computeVelocity(Velocity: number, Acceleration?: number, Drag?: number, Max?: number): number;
public velocityFromAngle(angle: number, speed: number): Point;
public moveTowardsObject(source: GameObject, dest: GameObject, speed?: number, maxTime?: number): void;
public accelerateTowardsObject(source: GameObject, dest: GameObject, speed: number, xSpeedMax: number, ySpeedMax: number): void;
public moveTowardsMouse(source: GameObject, speed?: number, maxTime?: number): void;
public accelerateTowardsMouse(source: GameObject, speed: number, xSpeedMax: number, ySpeedMax: number): void;
public moveTowardsPoint(source: GameObject, target: Point, speed?: number, maxTime?: number): void;
public accelerateTowardsPoint(source: GameObject, target: Point, speed: number, xSpeedMax: number, ySpeedMax: number): void;
public distanceBetween(a: GameObject, b: GameObject): number;
public distanceToPoint(a: GameObject, target: Point): number;
public distanceToMouse(a: GameObject): number;
public angleBetweenPoint(a: GameObject, target: Point, asDegrees?: bool): number;
public angleBetween(a: GameObject, b: GameObject, asDegrees?: bool): number;
public velocityFromFacing(parent: GameObject, speed: number): Point;
public angleBetweenMouse(a: GameObject, asDegrees?: bool): number;
}
}
+104 -104
View File
@@ -21,13 +21,13 @@ module Phaser {
/**
* A tween-like function that takes a starting velocity and some other factors and returns an altered velocity.
*
* @param Velocity Any component of velocity (e.g. 20).
* @param Acceleration Rate at which the velocity is changing.
* @param Drag Really kind of a deceleration, this is how much the velocity changes if Acceleration is not set.
* @param Max An absolute value cap for the velocity.
*
* @return The altered Velocity value.
*
* @param {number} Velocity Any component of velocity (e.g. 20).
* @param {number} Acceleration Rate at which the velocity is changing.
* @param {number} Drag Really kind of a deceleration, this is how much the velocity changes if Acceleration is not set.
* @param {number} Max An absolute value cap for the velocity.
*
* @return {number} The altered Velocity value.
*/
public computeVelocity(Velocity: number, Acceleration: number = 0, Drag: number = 0, Max: number = 10000): number {
@@ -71,11 +71,11 @@ module Phaser {
/**
* Given the angle and speed calculate the velocity and return it as a Point
*
* @param angle The angle (in degrees) calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative)
* @param speed The speed it will move, in pixels per second sq
*
* @return A Point where Point.x contains the velocity x value and Point.y contains the velocity y value
*
* @param {number} angle The angle (in degrees) calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative)
* @param {number} speed The speed it will move, in pixels per second sq
*
* @return {Point} A Point where Point.x contains the velocity x value and Point.y contains the velocity y value
*/
public velocityFromAngle(angle: number, speed: number): Point {
@@ -97,24 +97,24 @@ module Phaser {
* The source object doesn't stop moving automatically should it ever reach the destination coordinates.<br>
* If you need the object to accelerate, see accelerateTowardsObject() instead
* Note: Doesn't take into account acceleration, maxVelocity or drag (if you set drag or acceleration too high this object may not move at all)
*
* @param source The Sprite on which the velocity will be set
* @param dest The Sprite where the source object will move to
* @param speed The speed it will move, in pixels per second (default is 60 pixels/sec)
* @param maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms
*
* @param {GameObject} source The Sprite on which the velocity will be set
* @param {GameObject} dest The Sprite where the source object will move to
* @param {number} speed The speed it will move, in pixels per second (default is 60 pixels/sec)
* @param {number} maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms
*/
public moveTowardsObject(source:GameObject, dest:GameObject, speed:number= 60, maxTime:number = 0)
{
var a:number = this.angleBetween(source, dest);
if (maxTime > 0)
{
var d:number = this.distanceBetween(source, dest);
// We know how many pixels we need to move, but how fast?
speed = d / (maxTime / 1000);
}
source.velocity.x = Math.cos(a) * speed;
source.velocity.y = Math.sin(a) * speed;
@@ -124,23 +124,23 @@ module Phaser {
* Sets the x/y acceleration on the source Sprite so it will move towards the destination Sprite at the speed given (in pixels per second)<br>
* You must give a maximum speed value, beyond which the Sprite won't go any faster.<br>
* If you don't need acceleration look at moveTowardsObject() instead.
*
* @param source The Sprite on which the acceleration will be set
* @param dest The Sprite where the source object will move towards
* @param speed The speed it will accelerate in pixels per second
* @param xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally
* @param ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically
*
* @param {GameObject} source The Sprite on which the acceleration will be set
* @param {GameObject} dest The Sprite where the source object will move towards
* @param {number} speed The speed it will accelerate in pixels per second
* @param {number} xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally
* @param {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically
*/
public accelerateTowardsObject(source:GameObject, dest:GameObject, speed:number, xSpeedMax:number, ySpeedMax:number)
{
var a:number = this.angleBetween(source, dest);
source.velocity.x = 0;
source.velocity.y = 0;
source.acceleration.x = Math.cos(a) * speed;
source.acceleration.y = Math.sin(a) * speed;
source.maxVelocity.x = xSpeedMax;
source.maxVelocity.y = ySpeedMax;
@@ -151,23 +151,23 @@ module Phaser {
* If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds.<br>
* Timings are approximate due to the way Flash timers work, and irrespective of SWF frame rate. Allow for a variance of +- 50ms.<br>
* The source object doesn't stop moving automatically should it ever reach the destination coordinates.<br>
*
* @param source The Sprite to move
* @param speed The speed it will move, in pixels per second (default is 60 pixels/sec)
* @param maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms
*
* @param {GameObject} source The Sprite to move
* @param {number} speed The speed it will move, in pixels per second (default is 60 pixels/sec)
* @param {number} maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms
*/
public moveTowardsMouse(source:GameObject, speed:number = 60, maxTime:number = 0)
{
var a:number = this.angleBetweenMouse(source);
if (maxTime > 0)
{
var d:number = this.distanceToMouse(source);
// We know how many pixels we need to move, but how fast?
speed = d / (maxTime / 1000);
}
source.velocity.x = Math.cos(a) * speed;
source.velocity.y = Math.sin(a) * speed;
@@ -177,22 +177,22 @@ module Phaser {
* Sets the x/y acceleration on the source Sprite so it will move towards the mouse coordinates at the speed given (in pixels per second)<br>
* You must give a maximum speed value, beyond which the Sprite won't go any faster.<br>
* If you don't need acceleration look at moveTowardsMouse() instead.
*
* @param source The Sprite on which the acceleration will be set
* @param speed The speed it will accelerate in pixels per second
* @param xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally
* @param ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically
*
* @param {GameObject} source The Sprite on which the acceleration will be set
* @param {number} speed The speed it will accelerate in pixels per second
* @param {number} xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally
* @param {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically
*/
public accelerateTowardsMouse(source:GameObject, speed:number, xSpeedMax:number, ySpeedMax:number)
{
var a:number = this.angleBetweenMouse(source);
source.velocity.x = 0;
source.velocity.y = 0;
source.acceleration.x = Math.cos(a) * speed;
source.acceleration.y = Math.sin(a) * speed;
source.maxVelocity.x = xSpeedMax;
source.maxVelocity.y = ySpeedMax;
}
@@ -202,24 +202,24 @@ module Phaser {
* If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds.<br>
* Timings are approximate due to the way Flash timers work, and irrespective of SWF frame rate. Allow for a variance of +- 50ms.<br>
* The source object doesn't stop moving automatically should it ever reach the destination coordinates.<br>
*
* @param source The Sprite to move
* @param target The Point coordinates to move the source Sprite towards
* @param speed The speed it will move, in pixels per second (default is 60 pixels/sec)
* @param maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms
*
* @param {GameObject} source The Sprite to move
* @param {Point} target The Point coordinates to move the source Sprite towards
* @param {number} speed The speed it will move, in pixels per second (default is 60 pixels/sec)
* @param {number} maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms
*/
public moveTowardsPoint(source:GameObject, target:Point, speed:number = 60, maxTime:number = 0)
{
var a:number = this.angleBetweenPoint(source, target);
if (maxTime > 0)
{
var d:number = this.distanceToPoint(source, target);
// We know how many pixels we need to move, but how fast?
speed = d / (maxTime / 1000);
}
source.velocity.x = Math.cos(a) * speed;
source.velocity.y = Math.sin(a) * speed;
}
@@ -228,87 +228,87 @@ module Phaser {
* Sets the x/y acceleration on the source Sprite so it will move towards the target coordinates at the speed given (in pixels per second)<br>
* You must give a maximum speed value, beyond which the Sprite won't go any faster.<br>
* If you don't need acceleration look at moveTowardsPoint() instead.
*
* @param source The Sprite on which the acceleration will be set
* @param target The Point coordinates to move the source Sprite towards
* @param speed The speed it will accelerate in pixels per second
* @param xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally
* @param ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically
*
* @param {GameObject} source The Sprite on which the acceleration will be set
* @param {Point} target The Point coordinates to move the source Sprite towards
* @param {number} speed The speed it will accelerate in pixels per second
* @param {number} xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally
* @param {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically
*/
public accelerateTowardsPoint(source:GameObject, target:Point, speed:number, xSpeedMax:number, ySpeedMax:number)
{
var a:number = this.angleBetweenPoint(source, target);
source.velocity.x = 0;
source.velocity.y = 0;
source.acceleration.x = Math.cos(a) * speed;
source.acceleration.y = Math.sin(a) * speed;
source.maxVelocity.x = xSpeedMax;
source.maxVelocity.y = ySpeedMax;
}
/**
* Find the distance (in pixels, rounded) between two Sprites, taking their origin into account
*
* @param a The first Sprite
* @param b The second Sprite
* @return int Distance (in pixels)
*
* @param {GameObject} a The first Sprite
* @param {GameObject} b The second Sprite
* @return {number} int Distance (in pixels)
*/
public distanceBetween(a:GameObject, b:GameObject):number
{
var dx:number = (a.x + a.origin.x) - (b.x + b.origin.x);
var dy:number = (a.y + a.origin.y) - (b.y + b.origin.y);
return this._game.math.vectorLength(dx, dy);
}
/**
* Find the distance (in pixels, rounded) from an Sprite to the given Point, taking the source origin into account
*
* @param a The Sprite
* @param target The Point
* @return int Distance (in pixels)
*
* @param {GameObject} a The Sprite
* @param {Point} target The Point
* @return {number} Distance (in pixels)
*/
public distanceToPoint(a:GameObject, target:Point):number
{
var dx:number = (a.x + a.origin.x) - (target.x);
var dy:number = (a.y + a.origin.y) - (target.y);
return this._game.math.vectorLength(dx, dy);
}
/**
* Find the distance (in pixels, rounded) from the object x/y and the mouse x/y
*
* @param a The Sprite to test against
* @return int The distance between the given sprite and the mouse coordinates
*
* @param {GameObject} a Sprite to test against
* @return {number} The distance between the given sprite and the mouse coordinates
*/
public distanceToMouse(a:GameObject):number
{
var dx: number = (a.x + a.origin.x) - this._game.input.x;
var dy: number = (a.y + a.origin.y) - this._game.input.y;
return this._game.math.vectorLength(dx, dy);
}
/**
* Find the angle (in radians) between an Sprite and an Point. The source sprite takes its x/y and origin into account.
* The angle is calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative)
*
* @param a The Sprite to test from
* @param target The Point to angle the Sprite towards
* @param asDegrees If you need the value in degrees instead of radians, set to true
*
* @return Number The angle (in radians unless asDegrees is true)
*
* @param {GameObject} a The Sprite to test from
* @param {Point} target The Point to angle the Sprite towards
* @param {boolean} asDegrees If you need the value in degrees instead of radians, set to true
*
* @return {number} The angle (in radians unless asDegrees is true)
*/
public angleBetweenPoint(a:GameObject, target:Point, asDegrees:bool = false):number
{
var dx:number = (target.x) - (a.x + a.origin.x);
var dy:number = (target.y) - (a.y + a.origin.y);
if (asDegrees)
{
return this._game.math.radiansToDegrees(Math.atan2(dy, dx));
@@ -322,18 +322,18 @@ module Phaser {
/**
* Find the angle (in radians) between the two Sprite, taking their x/y and origin into account.
* The angle is calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative)
*
* @param a The Sprite to test from
* @param b The Sprite to test to
* @param asDegrees If you need the value in degrees instead of radians, set to true
*
* @return Number The angle (in radians unless asDegrees is true)
*
* @param {GameObject} a The Sprite to test from
* @param {GameObject} b The Sprite to test to
* @param {boolean} asDegrees If you need the value in degrees instead of radians, set to true
*
* @return {number} The angle (in radians unless asDegrees is true)
*/
public angleBetween(a:GameObject, b:GameObject, asDegrees:bool = false):number
{
var dx:number = (b.x + b.origin.x) - (a.x + a.origin.x);
var dy:number = (b.y + b.origin.y) - (a.y + a.origin.y);
if (asDegrees)
{
return this._game.math.radiansToDegrees(Math.atan2(dy, dx));
@@ -346,16 +346,16 @@ module Phaser {
/**
* Given the GameObject and speed calculate the velocity and return it as an Point based on the direction the sprite is facing
*
* @param parent The Sprite to get the facing value from
* @param speed The speed it will move, in pixels per second sq
*
* @return An Point where Point.x contains the velocity x value and Point.y contains the velocity y value
*
* @param {GameObject} parent The Sprite to get the facing value from
* @param {number} speed The speed it will move, in pixels per second sq
*
* @return {Point} An Point where Point.x contains the velocity x value and Point.y contains the velocity y value
*/
public velocityFromFacing(parent:GameObject, speed:number):Point
{
var a:number;
if (parent.facing == Collision.LEFT)
{
a = this._game.math.degreesToRadians(180);
@@ -372,28 +372,28 @@ module Phaser {
{
a = this._game.math.degreesToRadians(90);
}
return new Point(Math.cos(a) * speed, Math.sin(a) * speed);
}
/**
* Find the angle (in radians) between an Sprite and the mouse, taking their x/y and origin into account.
* The angle is calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative)
*
* @param a The Object to test from
* @param asDegrees If you need the value in degrees instead of radians, set to true
*
* @return Number The angle (in radians unless asDegrees is true)
*
* @param {GameObject} a The Object to test from
* @param {boolean} asDegrees If you need the value in degrees instead of radians, set to true
*
* @return {number} The angle (in radians unless asDegrees is true)
*/
public angleBetweenMouse(a:GameObject, asDegrees:bool = false):number
{
// In order to get the angle between the object and mouse, we need the objects screen coordinates (rather than world coordinates)
var p:MicroPoint = a.getScreenXY();
var dx:number = a._game.input.x - p.x;
var dy:number = a._game.input.y - p.y;
if (asDegrees)
{
return this._game.math.radiansToDegrees(Math.atan2(dy, dx));
+70 -4
View File
@@ -47,12 +47,14 @@
<TypeScriptIncludeComments>true</TypeScriptIncludeComments>
<TypeScriptSourceMap>false</TypeScriptSourceMap>
<TypeScriptOutFile>../build/phaser.js</TypeScriptOutFile>
<TypeScriptGeneratesDeclarations>true</TypeScriptGeneratesDeclarations>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<TypeScriptTarget>ES5</TypeScriptTarget>
<TypeScriptIncludeComments>false</TypeScriptIncludeComments>
<TypeScriptSourceMap>false</TypeScriptSourceMap>
<TypeScriptOutFile>../build/phaser.js</TypeScriptOutFile>
<TypeScriptGeneratesDeclarations>true</TypeScriptGeneratesDeclarations>
</PropertyGroup>
<ItemGroup>
<Folder Include="plugins\" />
@@ -67,12 +69,20 @@
<Content Include="DynamicTexture.js">
<DependentUpon>DynamicTexture.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="FXManager.ts" />
<Content Include="FXManager.js">
<DependentUpon>FXManager.ts</DependentUpon>
</Content>
<Content Include="Game.js">
<DependentUpon>Game.ts</DependentUpon>
</Content>
<Content Include="GameMath.js">
<DependentUpon>GameMath.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="GameObjectFactory.ts" />
<Content Include="GameObjectFactory.js">
<DependentUpon>GameObjectFactory.ts</DependentUpon>
</Content>
<Content Include="gameobjects\Emitter.js">
<DependentUpon>Emitter.ts</DependentUpon>
</Content>
@@ -99,9 +109,33 @@
<Content Include="gameobjects\Tilemap.js">
<DependentUpon>Tilemap.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="verlet\AngleConstraint.ts" />
<TypeScriptCompile Include="VerletManager.ts" />
<TypeScriptCompile Include="geom\Polygon.ts" />
<Content Include="geom\Polygon.js">
<DependentUpon>Polygon.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="geom\Response.ts" />
<Content Include="geom\Response.js">
<DependentUpon>Response.ts</DependentUpon>
</Content>
<Content Include="VerletManager.js">
<DependentUpon>VerletManager.ts</DependentUpon>
</Content>
<Content Include="verlet\AngleConstraint.js">
<DependentUpon>AngleConstraint.ts</DependentUpon>
</Content>
<Content Include="geom\Circle.js">
<DependentUpon>Circle.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="verlet\DistanceConstraint.ts" />
<TypeScriptCompile Include="verlet\Composite.ts" />
<Content Include="verlet\Composite.js">
<DependentUpon>Composite.ts</DependentUpon>
</Content>
<Content Include="verlet\DistanceConstraint.js">
<DependentUpon>DistanceConstraint.ts</DependentUpon>
</Content>
<Content Include="geom\IntersectResult.js">
<DependentUpon>IntersectResult.ts</DependentUpon>
</Content>
@@ -112,6 +146,14 @@
<Content Include="geom\MicroPoint.js">
<DependentUpon>MicroPoint.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="verlet\PinConstraint.ts" />
<TypeScriptCompile Include="verlet\Particle.ts" />
<Content Include="verlet\Particle.js">
<DependentUpon>Particle.ts</DependentUpon>
</Content>
<Content Include="verlet\PinConstraint.js">
<DependentUpon>PinConstraint.ts</DependentUpon>
</Content>
<Content Include="geom\Point.js">
<DependentUpon>Point.ts</DependentUpon>
</Content>
@@ -122,9 +164,37 @@
<Content Include="geom\Rectangle.js">
<DependentUpon>Rectangle.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="geom\Vector2.ts" />
<Content Include="geom\Vector2.js">
<DependentUpon>Vector2.ts</DependentUpon>
</Content>
<Content Include="SoundManager.js">
<DependentUpon>SoundManager.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="system\screens\PauseScreen.ts" />
<TypeScriptCompile Include="system\screens\BootScreen.ts" />
<TypeScriptCompile Include="system\input\MSPointer.ts" />
<TypeScriptCompile Include="system\input\Gestures.ts" />
<TypeScriptCompile Include="system\CollisionMask.ts" />
<Content Include="system\CollisionMask.js">
<DependentUpon>CollisionMask.ts</DependentUpon>
</Content>
<Content Include="system\input\Gestures.js">
<DependentUpon>Gestures.ts</DependentUpon>
</Content>
<Content Include="system\input\MSPointer.js">
<DependentUpon>MSPointer.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="system\input\Pointer.ts" />
<Content Include="system\input\Pointer.js">
<DependentUpon>Pointer.ts</DependentUpon>
</Content>
<Content Include="system\screens\BootScreen.js">
<DependentUpon>BootScreen.ts</DependentUpon>
</Content>
<Content Include="system\screens\PauseScreen.js">
<DependentUpon>PauseScreen.ts</DependentUpon>
</Content>
<Content Include="system\Sound.js">
<DependentUpon>Sound.ts</DependentUpon>
</Content>
@@ -215,9 +285,6 @@
<Content Include="system\easing\Sinusoidal.js">
<DependentUpon>Sinusoidal.ts</DependentUpon>
</Content>
<Content Include="system\input\Finger.js">
<DependentUpon>Finger.ts</DependentUpon>
</Content>
<Content Include="system\input\Input.js">
<DependentUpon>Input.ts</DependentUpon>
</Content>
@@ -234,7 +301,6 @@
<TypeScriptCompile Include="system\input\Mouse.ts" />
<TypeScriptCompile Include="system\input\Keyboard.ts" />
<TypeScriptCompile Include="system\input\Input.ts" />
<TypeScriptCompile Include="system\input\Finger.ts" />
<TypeScriptCompile Include="system\easing\Sinusoidal.ts" />
<TypeScriptCompile Include="system\easing\Quintic.ts" />
<TypeScriptCompile Include="system\easing\Quartic.ts" />
+3
View File
@@ -0,0 +1,3 @@
module Phaser {
var VERSION: string;
}
+3 -3
View File
@@ -1,13 +1,13 @@
/**
* Phaser
*
* v0.9.3 - April 24th 2013
* v0.9.6 - May 21st 2013
*
* A small and feature-packed 2D canvas game framework born from the firey pits of Flixel and Kiwi.
*
* Richard Davey (@photonstorm)
*
* Many thanks to Adam Saltsman (@ADAMATOMIC) for the original Flixel AS3 code on which Phaser is based.
* Many thanks to Adam Saltsman (@ADAMATOMIC) for releasing Flixel on which Phaser took a lot of inspiration.
*
* "If you want your children to be intelligent, read them fairy tales."
* "If you want them to be more intelligent, read them more fairy tales."
@@ -16,6 +16,6 @@
module Phaser {
export var VERSION: string = 'Phaser version 0.9.3';
export var VERSION: string = 'Phaser version 0.9.6';
}
+26
View File
@@ -0,0 +1,26 @@
/// <reference path="SignalBinding.d.ts" />
module Phaser {
class Signal {
private _bindings;
private _prevParams;
static VERSION: string;
public memorize: bool;
private _shouldPropagate;
public active: bool;
public validateListener(listener, fnName): void;
private _registerListener(listener, isOnce, listenerContext, priority);
private _addBinding(binding);
private _indexOfListener(listener, context);
public has(listener, context?: any): bool;
public add(listener, listenerContext?: any, priority?: number): SignalBinding;
public addOnce(listener, listenerContext?: any, priority?: number): SignalBinding;
public remove(listener, context?: any);
public removeAll(): void;
public getNumListeners(): number;
public halt(): void;
public dispatch(...paramsArr: any[]): void;
public forget(): void;
public dispose(): void;
public toString(): string;
}
}
+10 -7
View File
@@ -211,7 +211,7 @@ module Phaser {
if (i !== -1)
{
this._bindings[i]._destroy(); //no reason to a SignalBinding exist if it isn't attached to a signal
this._bindings[i]._destroy();
this._bindings.splice(i, 1);
}
@@ -224,14 +224,17 @@ module Phaser {
*/
public removeAll() {
var n: number = this._bindings.length;
while (n--)
if (this._bindings)
{
this._bindings[n]._destroy();
}
var n: number = this._bindings.length;
this._bindings.length = 0;
while (n--)
{
this._bindings[n]._destroy();
}
this._bindings.length = 0;
}
}
+21
View File
@@ -0,0 +1,21 @@
/// <reference path="Signal.d.ts" />
module Phaser {
class SignalBinding {
constructor(signal: Signal, listener, isOnce: bool, listenerContext, priority?: number);
private _listener;
private _isOnce;
public context;
private _signal;
public priority: number;
public active: bool;
public params;
public execute(paramsArr?: any[]);
public detach();
public isBound(): bool;
public isOnce(): bool;
public getListener();
public getSignal(): Signal;
public _destroy(): void;
public toString(): string;
}
}
+16
View File
@@ -0,0 +1,16 @@
/// <reference path="Game.d.ts" />
/// <reference path="system/Sound.d.ts" />
module Phaser {
class SoundManager {
constructor(game: Game);
private _game;
private _context;
private _gainNode;
private _volume;
public mute(): void;
public unmute(): void;
public volume : number;
public decode(key: string, callback?, sound?: Sound): void;
public play(key: string, volume?: number, loop?: bool): Sound;
}
}
+39 -1
View File
@@ -11,6 +11,10 @@ module Phaser {
export class SoundManager {
/**
* SoundManager constructor
* Create a new <code>SoundManager</code>.
*/
constructor(game: Game) {
this._game = game;
@@ -36,18 +40,39 @@ module Phaser {
}
/**
* Local private reference to game.
*/
private _game: Game;
/**
* Reference to AudioContext instance.
*/
private _context = null;
/**
* Gain node created from audio context.
*/
private _gainNode;
/**
* Volume of sounds.
* @type {number}
*/
private _volume: number;
/**
* Mute sounds.
*/
public mute() {
this._gainNode.gain.value = 0;
}
/**
* Enable sounds.
*/
public unmute() {
this._gainNode.gain.value = this._volume;
@@ -65,6 +90,12 @@ module Phaser {
return this._volume;
}
/**
* Decode a sound with its assets key.
* @param key {string} Assets key of the sound to be decoded.
* @param callback {function} This will be invoked when finished decoding.
* @param [sound] {Sound} its bufer will be set to decoded data.
*/
public decode(key: string, callback = null, sound?: Sound = null) {
var soundData = this._game.cache.getSound(key);
@@ -90,6 +121,13 @@ module Phaser {
}
/**
* Play a sound with its assets key.
* @param key {string} Assets key of the sound you want to play.
* @param [volume] {number} volume of the sound you want to play.
* @param [loop] {boolean} loop when it finished playing? (Default to false)
* @return {Sound} The playing sound object.
*/
public play(key: string, volume?: number = 1, loop?: bool = false): Sound {
if (this._context === null)
@@ -111,7 +149,7 @@ module Phaser {
var tempSound: Sound = new Sound(this._context, this._gainNode, null, volume, loop);
// this is an async process, so we can return the Sound object anyway, it just won't be playing yet
this.decode(key, () => this.play(key), tempSound);
this.decode(key, () => tempSound.play(), tempSound);
return tempSound;
}
+47
View File
@@ -0,0 +1,47 @@
/// <reference path="Phaser.d.ts" />
/// <reference path="Game.d.ts" />
/// <reference path="system/StageScaleMode.d.ts" />
/// <reference path="system/screens/BootScreen.d.ts" />
/// <reference path="system/screens/PauseScreen.d.ts" />
module Phaser {
class Stage {
constructor(game: Game, parent: string, width: number, height: number);
private _game;
private _bgColor;
private _bootScreen;
private _pauseScreen;
static ORIENTATION_LANDSCAPE: number;
static ORIENTATION_PORTRAIT: number;
public bounds: Rectangle;
public aspectRatio: number;
public clear: bool;
public canvas: HTMLCanvasElement;
public context: CanvasRenderingContext2D;
public disablePauseScreen: bool;
public disableBootScreen: bool;
public offset: Point;
public scale: StageScaleMode;
public scaleMode: number;
public minScaleX: number;
public maxScaleX: number;
public minScaleY: number;
public maxScaleY: number;
public update(): void;
private visibilityChange(event);
private getOffset(element);
public strokeStyle: string;
public lineWidth: number;
public fillStyle: string;
public saveCanvasValues(): void;
public restoreCanvasValues(): void;
public backgroundColor : string;
public x : number;
public y : number;
public width : number;
public height : number;
public centerX : number;
public centerY : number;
public randomX : number;
public randomY : number;
}
}
+157 -77
View File
@@ -1,6 +1,8 @@
/// <reference path="Phaser.ts" />
/// <reference path="Game.ts" />
/// <reference path="system/StageScaleMode.ts" />
/// <reference path="system/screens/BootScreen.ts" />
/// <reference path="system/screens/PauseScreen.ts" />
/**
* Phaser - Stage
@@ -13,6 +15,15 @@ module Phaser {
export class Stage {
/**
* 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.
*/
constructor(game: Game, parent: string, width: number, height: number) {
this._game = game;
@@ -33,45 +44,119 @@ module Phaser {
// Consume default actions on the canvas
this.canvas.style.msTouchAction = 'none';
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(); };
this.context = this.canvas.getContext('2d');
this.offset = this.getOffset(this.canvas);
this.bounds = new Rectangle(this.offset.x, this.offset.y, width, height);
this.bounds = new Quad(this.offset.x, this.offset.y, width, height);
this.aspectRatio = width / height;
this.scaleMode = StageScaleMode.NO_SCALE;
this.scale = new StageScaleMode(this._game);
//document.addEventListener('visibilitychange', (event) => this.visibilityChange(event), false);
//document.addEventListener('webkitvisibilitychange', (event) => this.visibilityChange(event), false);
this._bootScreen = new BootScreen(this._game);
this._pauseScreen = new PauseScreen(this._game, width, height);
document.addEventListener('visibilitychange', (event) => this.visibilityChange(event), false);
document.addEventListener('webkitvisibilitychange', (event) => this.visibilityChange(event), false);
window.onblur = (event) => this.visibilityChange(event);
window.onfocus = (event) => this.visibilityChange(event);
}
/**
* Local private reference to game.
*/
private _game: Game;
private _bgColor: string;
/**
* Background color of the stage (defaults to black)
* @type {string}
*/
private _bgColor: string = 'rgb(0,0,0)';
public static ORIENTATION_LANDSCAPE: number = 0;
public static ORIENTATION_PORTRAIT: number = 1;
/**
* This will be displayed when Phaser is started without any default functions or State
* @type {BootScreen}
*/
private _bootScreen;
public bounds: Rectangle;
/**
* This will be displayed whenever the game loses focus or the player switches to another browser tab.
* @type {PauseScreen}
*/
private _pauseScreen;
/**
* Bound of this stage.
* @type {Quad}
*/
public bounds: Quad;
/**
* Asperct ratio, thus: width / height.
* @type {number}
*/
public aspectRatio: number;
/**
* Clear the whole stage every frame? (Default to true)
* @type {boolean}
*/
public clear: bool = true;
/**
* Canvas element used by engine.
* @type {HTMLCanvasElement}
*/
public canvas: HTMLCanvasElement;
/**
* Render context of stage's canvas.
* @type {CanvasRenderingContext2D}
*/
public context: CanvasRenderingContext2D;
/**
* Do not use pause screen when game is paused?
* (Default to false, aka always use PauseScreen)
* @type {boolean}
*/
public disablePauseScreen: bool = false;
public offset: Point;
/**
* Do not use boot screen when engine starts?
* (Default to false, aka always use BootScreen)
* @type {boolean}
*/
public disableBootScreen: bool = false;
/**
* Offset from this stage to the canvas element.
* @type {MicroPoint}
*/
public offset: MicroPoint;
/**
* This object manages scaling of the game, see(StageScaleMode).
* @type {StageScaleMode}
*/
public scale: StageScaleMode;
/**
* Which mode will the game be scaled.
* Available: StageScaleMode.EXACT_FIT, StageScaleMode.NO_SCALE, StageScaleMode.SHOW_ALL.
* @type {number}
*/
public scaleMode: number;
public minScaleX: number = null;
public maxScaleX: number = null;
public minScaleY: number = null;
public maxScaleY: number = null;
/**
* Update stage for rendering. This will handle scaling, clearing
* and PauseScreen/BootScreen updating and rendering.
*/
public update() {
this.scale.update();
@@ -82,18 +167,23 @@ module Phaser {
this.context.clearRect(0, 0, this.width, this.height);
}
}
if (this._game.isRunning == false && this.disableBootScreen == false)
{
this._bootScreen.update();
this._bootScreen.render();
}
public renderDebugInfo() {
this.context.fillStyle = 'rgb(255,255,255)';
this.context.fillText(Phaser.VERSION, 10, 20);
this.context.fillText('Game Size: ' + this.width + ' x ' + this.height, 10, 40);
this.context.fillText('x: ' + this.x + ' y: ' + this.y, 10, 60);
if (this._game.paused == true && this.disablePauseScreen == false)
{
this._pauseScreen.update();
this._pauseScreen.render();
}
}
//if (document['hidden'] === true || document['webkitHidden'] === true)
/**
* This method is called when the canvas elements visibility is changed.
*/
private visibilityChange(event) {
if (this.disablePauseScreen)
@@ -101,71 +191,43 @@ module Phaser {
return;
}
if (event.type == 'blur' && this._game.paused == false && this._game.isBooted == true)
if (event.type == 'blur' || document['hidden'] == true || document['webkitHidden'] == true)
{
this._game.paused = true;
this.drawPauseScreen();
if (this._game.paused == false)
{
this.pauseGame();
}
}
else if (event.type == 'focus')
else
{
this._game.paused = false;
if (this._game.paused == true)
{
this.resumeGame();
}
}
}
public drawInitScreen() {
this.context.fillStyle = 'rgb(40, 40, 40)';
this.context.fillRect(0, 0, this.width, this.height);
this.context.fillStyle = 'rgb(255,255,255)';
this.context.font = 'bold 18px Arial';
this.context.textBaseline = 'top';
this.context.fillText(Phaser.VERSION, 54, 32);
this.context.fillText('Game Size: ' + this.width + ' x ' + this.height, 32, 64);
this.context.fillText('www.photonstorm.com', 32, 96);
this.context.font = '16px Arial';
this.context.fillText('You are seeing this screen because you didn\'t specify any default', 32, 160);
this.context.fillText('functions in the Game constructor, or use Game.loadState()', 32, 184);
var image = new Image();
var that = this;
image.onload = function () {
that.context.drawImage(image, 32, 32);
};
image.src = this._logo;
}
private drawPauseScreen() {
public pauseGame() {
this._pauseScreen.onPaused();
this.saveCanvasValues();
this.context.fillStyle = 'rgba(0, 0, 0, 0.4)';
this.context.fillRect(0, 0, this.width, this.height);
// Draw a 'play' arrow
var arrowWidth = Math.round(this.width / 2);
var arrowHeight = Math.round(this.height / 2);
var sx = this.centerX - arrowWidth / 2;
var sy = this.centerY - arrowHeight / 2;
this.context.beginPath();
this.context.moveTo(sx, sy);
this.context.lineTo(sx, sy + arrowHeight);
this.context.lineTo(sx + arrowWidth, this.centerY);
this.context.fillStyle = 'rgba(255, 255, 255, 0.8)';
this.context.fill();
this.context.closePath();
this.restoreCanvasValues();
this._game.paused = true;
}
private getOffset(element): Point {
public resumeGame() {
this._pauseScreen.onResume();
this.restoreCanvasValues();
this._game.paused = false;
}
/**
* Get the DOM offset values of the given element
*/
private getOffset(element): MicroPoint {
var box = element.getBoundingClientRect();
@@ -174,14 +236,31 @@ module Phaser {
var scrollTop = window.pageYOffset || element.scrollTop || document.body.scrollTop;
var scrollLeft = window.pageXOffset || element.scrollLeft || document.body.scrollLeft;
return new Point(box.left + scrollLeft - clientLeft, box.top + scrollTop - clientTop);
return new MicroPoint(box.left + scrollLeft - clientLeft, box.top + scrollTop - clientTop);
}
/**
* Canvas strokeStyle.
* @type {string}
*/
public strokeStyle: string;
/**
* Canvas lineWidth.
* @type {number}
*/
public lineWidth: number;
/**
* Canvas fillStyle.
* @type {string}
*/
public fillStyle: string;
/**
* Save current canvas properties (strokeStyle, lineWidth and fillStyle) for later using.
*/
public saveCanvasValues() {
this.strokeStyle = this.context.strokeStyle;
@@ -190,6 +269,9 @@ module Phaser {
}
/**
* Restore current canvas values (strokeStyle, lineWidth and fillStyle) with saved values.
*/
public restoreCanvasValues() {
this.context.strokeStyle = this.strokeStyle;
@@ -238,8 +320,6 @@ module Phaser {
return Math.round(Math.random() * this.bounds.height);
}
private _logo: string = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAO1JREFUeNpi/P//PwM6YGRkxBQEAqBaRnQxFmwa10d6MAjrMqMofHv5L1we2SBGmAtAktg0ogOQQYHLd8ANYYFpPtTmzUAMAFmwnsEDrAdkCAvMZlIAsiFMMAEYsKvaSrQhIMCELkGsV2AAbIC8gCQYgwKIUABiNYBf9yoYH7n7n6CzN274g2IYEyFbsNmKLIaSkHpP7WSwUfbA0ASzFQRslBlxp0RcAF0TRhggA3zhAJIDpUKU5A9KyshpHDkjFZu5g2nJMFcwXVJSgqIGnBKx5bKenh4w/XzVbgbPtlIUcVgSxuoCUgHIIIAAAwArtXwJBABO6QAAAABJRU5ErkJggg==";
}
}
+111 -44
View File
@@ -10,10 +10,15 @@ module Phaser {
export class State {
/**
* State constructor
* Create a new <code>State</code>.
*/
constructor(game: Game) {
this.game = game;
this.add = game.add;
this.camera = game.camera;
this.cache = game.cache;
this.collision = game.collision;
@@ -29,73 +34,135 @@ module Phaser {
}
/**
* Reference to Game.
*/
public game: Game;
/**
* Currently used camera.
* @type {Camera}
*/
public camera: Camera;
/**
* Reference to the assets cache.
* @type {Cache}
*/
public cache: Cache;
/**
* Reference to the collision helper.
* @type {Collision}
*/
public collision: Collision;
/**
* Reference to the GameObject Factory.
* @type {GameObjectFactory}
*/
public add: GameObjectFactory;
/**
* Reference to the input manager
* @type {Input}
*/
public input: Input;
/**
* Reference to the assets loader.
* @type {Loader}
*/
public loader: Loader;
/**
* Reference to the math helper.
* @type {GameMath}
*/
public math: GameMath;
/**
* Reference to the motion helper.
* @type {Motion}
*/
public motion: Motion;
/**
* Reference to the sound manager.
* @type {SoundManager}
*/
public sound: SoundManager;
/**
* Reference to the stage.
* @type {Stage}
*/
public stage: Stage;
/**
* Reference to game clock.
* @type {Time}
*/
public time: Time;
/**
* Reference to the tween manager.
* @type {TweenManager}
*/
public tweens: TweenManager;
/**
* Reference to the world.
* @type {World}
*/
public world: World;
// Override these in your own States
// Overload these in your own States
/**
* Override this method to add some load operations.
* If you need to use the loader, you may need to use them here.
*/
public init() { }
/**
* This method is called after the game engine successfully switches states.
* Feel free to add any setup code here.(Do not load anything here, override init() instead)
*/
public create() { }
/**
* Put update logic here.
*/
public update() { }
/**
* Put render operations here.
*/
public render() { }
/**
* This method will be called when game paused.
*/
public paused() { }
// Handy Proxy methods
/**
* This method will be called when the state is destroyed
*/
public destroy() { }
public createCamera(x: number, y: number, width: number, height: number): Camera {
return this.game.world.createCamera(x, y, width, height);
}
public createGeomSprite(x: number, y: number): GeomSprite {
return this.world.createGeomSprite(x, y);
}
public createSprite(x: number, y: number, key?: string = ''): Sprite {
return this.game.world.createSprite(x, y, key);
}
public createDynamicTexture(width: number, height: number): DynamicTexture {
return this.game.world.createDynamicTexture(width, height);
}
public createGroup(MaxSize?: number = 0): Group {
return this.game.world.createGroup(MaxSize);
}
public createParticle(): Particle {
return this.game.world.createParticle();
}
public createEmitter(x?: number = 0, y?: number = 0, size?: number = 0): Emitter {
return this.game.world.createEmitter(x, y, size);
}
public createScrollZone(key: string, x?: number = 0, y?: number = 0, width?: number = 0, height?: number = 0): ScrollZone {
return this.game.world.createScrollZone(key, x, y, width, height);
}
public createTilemap(key: string, mapData: string, format: number, resizeWorld: bool = true, tileWidth?: number = 0, tileHeight?: number = 0): Tilemap {
return this.game.world.createTilemap(key, mapData, format, resizeWorld, tileWidth, tileHeight);
}
public createTween(obj): Tween {
return this.game.tweens.create(obj);
}
public collide(ObjectOrGroup1: Basic = null, ObjectOrGroup2: Basic = null, NotifyCallback = null): bool {
return this.collision.overlap(ObjectOrGroup1, ObjectOrGroup2, NotifyCallback, Collision.separate);
/**
* Checks for overlaps between two objects using the world QuadTree. Can be GameObject vs. GameObject, GameObject vs. Group or Group vs. Group.
* Note: Does not take the objects scrollFactor into account. All overlaps are check in world space.
* @param object1 The first GameObject or Group to check. If null the world.group is used.
* @param object2 The second GameObject or Group to check.
* @param notifyCallback A callback function that is called if the objects overlap. The two objects will be passed to this function in the same order in which you passed them to Collision.overlap.
* @param processCallback A callback function that lets you perform additional checks against the two objects if they overlap. If this is set then notifyCallback will only be called if processCallback returns true.
* @param context The context in which the callbacks will be called
* @returns {boolean} true if the objects overlap, otherwise false.
*/
public collide(objectOrGroup1: Basic = null, objectOrGroup2: Basic = null, notifyCallback = null, context? = this.game.callbackContext): bool {
return this.collision.overlap(objectOrGroup1, objectOrGroup2, notifyCallback, Collision.separate, context);
}
}
+25
View File
@@ -0,0 +1,25 @@
/// <reference path="Game.d.ts" />
module Phaser {
class Time {
constructor(game: Game);
private _game;
private _started;
public timeScale: number;
public elapsed: number;
public time: number;
public now: number;
public delta: number;
public totalElapsedSeconds : number;
public fps: number;
public fpsMin: number;
public fpsMax: number;
public msMin: number;
public msMax: number;
public frames: number;
private _timeLastSecond;
public update(): void;
public elapsedSince(since: number): number;
public elapsedSecondsSince(since: number): number;
public reset(): void;
}
}
+92 -39
View File
@@ -10,40 +10,64 @@ module Phaser {
export class Time {
/**
* Time constructor
* Create a new <code>Time</code>.
*
* @param game {Phaser.Game} Current game instance.
*/
constructor(game: Game) {
this._started = Date.now();
this._started = 0;
this._timeLastSecond = this._started;
this.time = this._started;
this._game = game;
}
/**
* Local private reference to game.
*/
private _game: Game;
/**
* Time when this object created.
* @param {number}
*/
private _started: number;
/**
* Time scale factor.
* Set it to 0.5 for slow motion, to 2.0 makes game twice faster.
* @type {number}
*/
public timeScale: number = 1.0;
/**
* Elapsed since last frame.
* @type {number}
*/
public elapsed: number = 0;
/**
*
* @property time
* @type Number
*/
* Game time counter.
* @property time
* @type {number}
*/
public time: number = 0;
/**
*
* @property now
* @type Number
*/
* Time of current frame.
* @property now
* @type {number}
*/
public now: number = 0;
/**
*
* @property delta
* @type Number
*/
* Elapsed time since last frame.
* @property delta
* @type {number}
*/
public delta: number = 0;
/**
@@ -57,23 +81,58 @@ module Phaser {
}
/**
* Frames per second.
* @type {number}
*/
public fps: number = 0;
/**
* Minimal fps.
* @type {number}
*/
public fpsMin: number = 1000;
/**
* Maximal fps.
* @type {number}
*/
public fpsMax: number = 0;
/**
* Mininal duration between 2 frames.
* @type {number}
*/
public msMin: number = 1000;
/**
* Maximal duration between 2 frames.
* @type {number}
*/
public msMax: number = 0;
/**
* How many frames in last second.
* @type {number}
*/
public frames: number = 0;
/**
* Time of last second.
* @type {number}
*/
private _timeLastSecond: number = 0;
/**
*
* @method update
*/
public update() {
* Update clock and calculate the fps.
* This is called automatically by Game._raf
* @method update
* @param {number} raf The current timestamp, either performance.now or Date.now
*/
public update(raf: number) {
// Can we use performance.now() ?
this.now = Date.now(); // mark
this.now = raf; // mark
//this.now = Date.now(); // mark
this.delta = this.now - this.time; // elapsedMS
this.msMin = Math.min(this.msMin, this.delta);
@@ -93,20 +152,14 @@ module Phaser {
this.time = this.now; // _total
//// Lock the delta at 0.1 to minimise fps tunneling
//if (this.delta > 0.1)
//{
// this.delta = 0.1;
//}
}
/**
*
* @method elapsedSince
* @param {Number} since
* @return {Number}
*/
* How long has passed since given time.
* @method elapsedSince
* @param {number} since The time you want to measure.
* @return {number} Duration between given time and now.
*/
public elapsedSince(since: number): number {
return this.now - since;
@@ -114,11 +167,11 @@ module Phaser {
}
/**
*
* @method elapsedSecondsSince
* @param {Number} since
* @return {Number}
*/
* How long has passed since give time (in seconds).
* @method elapsedSecondsSince
* @param {number} since The time you want to measure (in seconds).
* @return {number} Duration between given time and now (in seconds).
*/
public elapsedSecondsSince(since: number): number {
return (this.now - since) * 0.001;
@@ -126,9 +179,9 @@ module Phaser {
}
/**
*
* @method reset
*/
* Set the start time to now.
* @method reset
*/
public reset() {
this._started = this.now;
+15
View File
@@ -0,0 +1,15 @@
/// <reference path="Game.d.ts" />
/// <reference path="system/Tween.d.ts" />
module Phaser {
class TweenManager {
constructor(game: Game);
private _game;
private _tweens;
public getAll(): Tween[];
public removeAll(): void;
public create(object): Tween;
public add(tween: Tween): Tween;
public remove(tween: Tween): void;
public update(): bool;
}
}
+41 -1
View File
@@ -7,7 +7,7 @@
* The Game has a single instance of the TweenManager through which all Tween objects are created and updated.
* Tweens are hooked into the game clock and pause system, adjusting based on the game state.
* TweenManager is based heavily on tween.js by sole (http://soledadpenades.com).
* I converted it to TypeScript, swapped the callbacks for signals and patched a few issues with regard
* I converted it to TypeScript, swapped the callbacks for signals and patched a few issues with regard
* to properties and completion errors. Please see https://github.com/sole/tween.js for a full list of contributors.
*/
@@ -15,6 +15,10 @@ module Phaser {
export class TweenManager {
/**
* TweenManager constructor
* @param game {Game} A reference to the current Game.
*/
constructor(game: Phaser.Game) {
this._game = game;
@@ -22,27 +26,53 @@ module Phaser {
}
/**
* Local private reference to Game
*/
private _game: Phaser.Game;
/**
* Local private array which is the container of all tween objects.
*/
private _tweens: Phaser.Tween[];
/**
* Get all the tween objects in an array.
* @return {Phaser.Tween[]} Array with all tween objects.
*/
public getAll() {
return this._tweens;
}
/**
* Remove all tween objects.
*/
public removeAll() {
this._tweens.length = 0;
}
/**
* Create a tween object for a specific object.
*
* @param object {object} Object you wish the tween will affect.
* @return {Phaser.Tween} The newly created tween object.
*/
public create(object): Phaser.Tween {
return new Phaser.Tween(object, this._game);
}
/**
* Add an exist tween object to the manager.
*
* @param tween {Phaser.Tween} The tween object you want to add.
* @return {Phaser.Tween} The tween object you added to the manager.
*/
public add(tween: Phaser.Tween) {
tween.parent = this._game;
@@ -53,6 +83,11 @@ module Phaser {
}
/**
* Remove a tween from this manager.
*
* @param tween {Phaser.Tween} The tween object you want to remove.
*/
public remove(tween: Phaser.Tween) {
var i = this._tweens.indexOf(tween);
@@ -64,6 +99,11 @@ module Phaser {
}
/**
* Update all the tween objects you added to this manager.
*
* @return {boolean} Return false if there's no tween to update, otherwise return true.
*/
public update() {
if (this._tweens.length === 0)
+411
View File
@@ -0,0 +1,411 @@
/// <reference path="Game.ts" />
/// <reference path="geom/Vector2.ts" />
/// <reference path="verlet/Composite.ts" />
/// <reference path="verlet/Particle.ts" />
/// <reference path="verlet/DistanceConstraint.ts" />
/// <reference path="verlet/PinConstraint.ts" />
/// <reference path="verlet/AngleConstraint.ts" />
/**
* Phaser - Verlet
*
* Based on verlet-js by Sub Protocol released under MIT
*/
module Phaser.Verlet {
export class VerletManager {
/**
* Creates a new Vector2 object.
* @class Vector2
* @constructor
* @param {Number} x The x coordinate of vector2
* @param {Number} y The y coordinate of vector2
* @return {Vector2} This object
**/
constructor(game: Game, width: number, height: number) {
this._game = game;
this.width = width;
this.height = height;
this.gravity = new Vector2(0, 0.2);
this.friction = 0.99;
this.groundFriction = 0.8;
this.canvas = game.stage.canvas;
this.context = game.stage.context;
this._game.input.onDown.add(this.mouseDownHandler, this);
this._game.input.onUp.add(this.mouseUpHandler, this);
}
private _game: Game;
private _v = new Phaser.Vector2;
public composites = [];
public width: number;
public height: number;
public step: number = 16;
public gravity: Vector2;
public friction: number;
public groundFriction: number;
public selectionRadius: number = 20;
public draggedEntity = null;
public highlightColor = '#4f545c';
/**
* A reference to the canvas this renders to
* @type {HTMLCanvasElement}
*/
public canvas: HTMLCanvasElement;
/**
* A reference to the context this renders to
* @type {CanvasRenderingContext2D}
*/
public context: CanvasRenderingContext2D;
/**
* Computes time of intersection of a particle with a wall
*
* @param {Vec2} line walls root position
* @param {Vec2} p particle position
* @param {Vec2} dir walls direction
* @param {Vec2} v particles velocity
*/
public intersectionTime(wall, p, dir, v) {
if (dir.x != 0)
{
var denominator = v.y - dir.y * v.x / dir.x;
if (denominator == 0) return undefined; // Movement is parallel to wall
var numerator = wall.y + dir.y * (p.x - wall.x) / dir.x - p.y;
return numerator / denominator;
}
else
{
if (v.x == 0) return undefined; // parallel again
var denominator = v.x;
var numerator = wall.x - p.x;
return numerator / denominator;
}
}
public intersectionPoint(wall, p, dir, v) {
var t = this.intersectionTime(wall, p, dir, v);
return new Phaser.Vector2(p.x + v.x * t, p.y + v.y * t);
}
public bounds(particle: Phaser.Verlet.Particle) {
this._v.mutableSet(particle.pos);
this._v.mutableSub(particle.lastPos);
if (particle.pos.y > this.height - 1)
{
particle.pos.mutableSet(this.intersectionPoint(new Phaser.Vector2(0, this.height - 1), particle.lastPos, new Phaser.Vector2(1, 0), this._v));
}
if (particle.pos.x < 0)
{
particle.pos.mutableSet(this.intersectionPoint(new Phaser.Vector2(0, 0), particle.pos, new Phaser.Vector2(0, 1), this._v));
}
if (particle.pos.x > this.width - 1)
{
particle.pos.mutableSet(this.intersectionPoint(new Phaser.Vector2(this.width - 1, 0), particle.pos, new Phaser.Vector2(0, 1), this._v));
}
}
public createPoint(pos: Vector2) {
var composite = new Phaser.Verlet.Composite(this._game);
composite.particles.push(new Phaser.Verlet.Particle(pos));
this.composites.push(composite);
return composite;
}
public createLineSegments(vertices, stiffness) {
var composite = new Phaser.Verlet.Composite(this._game);
var i;
for (i in vertices)
{
composite.particles.push(new Phaser.Verlet.Particle(vertices[i]));
if (i > 0)
{
composite.constraints.push(new Phaser.Verlet.DistanceConstraint(composite.particles[i], composite.particles[i - 1], stiffness));
}
}
this.composites.push(composite);
return composite;
}
public createCloth(origin, width, height, segments, pinMod, stiffness) {
var composite = new Phaser.Verlet.Composite(this._game);
var xStride = width / segments;
var yStride = height / segments;
var x;
var y;
for (y = 0; y < segments; ++y)
{
for (x = 0; x < segments; ++x)
{
var px = origin.x + x * xStride - width / 2 + xStride / 2;
var py = origin.y + y * yStride - height / 2 + yStride / 2;
composite.particles.push(new Phaser.Verlet.Particle(new Vector2(px, py)));
if (x > 0)
{
composite.constraints.push(new Phaser.Verlet.DistanceConstraint(composite.particles[y * segments + x], composite.particles[y * segments + x - 1], stiffness));
}
if (y > 0)
{
composite.constraints.push(new Phaser.Verlet.DistanceConstraint(composite.particles[y * segments + x], composite.particles[(y - 1) * segments + x], stiffness));
}
}
}
for (x = 0; x < segments; ++x)
{
if (x % pinMod == 0)
{
composite.pin(x);
}
}
this.composites.push(composite);
return composite;
}
public createTire(origin, radius, segments, spokeStiffness, treadStiffness) {
var stride = (2 * Math.PI) / segments;
var i;
var composite = new Phaser.Verlet.Composite(this._game);
// particles
for (i = 0; i < segments; ++i)
{
var theta = i * stride;
composite.particles.push(new Particle(new Vector2(origin.x + Math.cos(theta) * radius, origin.y + Math.sin(theta) * radius)));
}
var center = new Particle(origin);
composite.particles.push(center);
// constraints
for (i = 0; i < segments; ++i)
{
composite.constraints.push(new DistanceConstraint(composite.particles[i], composite.particles[(i + 1) % segments], treadStiffness));
composite.constraints.push(new DistanceConstraint(composite.particles[i], center, spokeStiffness))
composite.constraints.push(new DistanceConstraint(composite.particles[i], composite.particles[(i + 5) % segments], treadStiffness));
}
this.composites.push(composite);
return composite;
}
public update() {
if (this.composites.length == 0)
{
return;
}
var i, j, c;
for (c in this.composites)
{
for (i in this.composites[c].particles)
{
var particles = this.composites[c].particles;
// calculate velocity
var velocity = particles[i].pos.sub(particles[i].lastPos).scale(this.friction);
// ground friction
if (particles[i].pos.y >= this.height - 1 && velocity.length2() > 0.000001)
{
var m = velocity.length();
velocity.x /= m;
velocity.y /= m;
velocity.mutableScale(m * this.groundFriction);
}
// save last good state
particles[i].lastPos.mutableSet(particles[i].pos);
// gravity
particles[i].pos.mutableAdd(this.gravity);
// inertia
particles[i].pos.mutableAdd(velocity);
}
}
// handle dragging of entities
if (this.draggedEntity)
{
this.draggedEntity.pos.mutableSet(this._game.input.position);
}
// relax
var stepCoef = 1 / this.step;
for (c in this.composites)
{
var constraints = this.composites[c].constraints;
for (i = 0; i < this.step; ++i)
{
for (j in constraints)
{
constraints[j].relax(stepCoef);
}
}
}
// bounds checking
for (c in this.composites)
{
var particles = this.composites[c].particles;
for (i in particles)
{
this.bounds(particles[i]);
}
}
}
private mouseDownHandler() {
var nearest = this.nearestEntity();
if (nearest)
{
this.draggedEntity = nearest;
}
}
private mouseUpHandler() {
this.draggedEntity = null;
}
public nearestEntity() {
var c, i;
var d2Nearest = 0;
var entity = null;
var constraintsNearest = null;
// find nearest point
for (c in this.composites)
{
var particles = this.composites[c].particles;
for (i in particles)
{
var d2 = particles[i].pos.distance2(this._game.input.position);
if (d2 <= this.selectionRadius * this.selectionRadius && (entity == null || d2 < d2Nearest))
{
entity = particles[i];
constraintsNearest = this.composites[c].constraints;
d2Nearest = d2;
}
}
}
// search for pinned constraints for this entity
for (i in constraintsNearest)
{
if (constraintsNearest[i] instanceof PinConstraint && constraintsNearest[i].a == entity)
{
entity = constraintsNearest[i];
}
}
return entity;
}
public hideNearestEntityCircle: bool = false;
public render() {
var i, c;
for (c in this.composites)
{
// draw constraints
if (this.composites[c].drawConstraints)
{
this.composites[c].drawConstraints(this.context, this.composites[c]);
}
else
{
var constraints = this.composites[c].constraints;
for (i in constraints)
{
constraints[i].render(this.context);
}
}
// draw particles
if (this.composites[c].drawParticles)
{
this.composites[c].drawParticles(this.context, this.composites[c]);
}
else
{
var particles = this.composites[c].particles;
for (i in particles)
{
particles[i].render(this.context);
}
}
}
// highlight nearest / dragged entity
var nearest = this.draggedEntity || this.nearestEntity();
if (nearest && this.hideNearestEntityCircle == false)
{
this.context.beginPath();
this.context.arc(nearest.pos.x, nearest.pos.y, 8, 0, 2 * Math.PI);
this.context.strokeStyle = this.highlightColor;
this.context.stroke();
this.context.closePath();
}
}
}
}
+32
View File
@@ -0,0 +1,32 @@
/// <reference path="Game.d.ts" />
module Phaser {
class World {
constructor(game: Game, width: number, height: number);
private _game;
public cameras: CameraManager;
public group: Group;
public bounds: Rectangle;
public worldDivisions: number;
public update(): void;
public render(): void;
public destroy(): void;
public setSize(width: number, height: number, updateCameraBounds?: bool): void;
public width : number;
public height : number;
public centerX : number;
public centerY : number;
public randomX : number;
public randomY : number;
public createCamera(x: number, y: number, width: number, height: number): Camera;
public removeCamera(id: number): bool;
public getAllCameras(): Camera[];
public createSprite(x: number, y: number, key?: string): Sprite;
public createGeomSprite(x: number, y: number): GeomSprite;
public createDynamicTexture(width: number, height: number): DynamicTexture;
public createGroup(MaxSize?: number): Group;
public createScrollZone(key: string, x?: number, y?: number, width?: number, height?: number): ScrollZone;
public createTilemap(key: string, mapData: string, format: number, resizeWorld?: bool, tileWidth?: number, tileHeight?: number): Tilemap;
public createParticle(): Particle;
public createEmitter(x?: number, y?: number, size?: number): Emitter;
}
}
+147 -13
View File
@@ -3,6 +3,8 @@
/**
* Phaser - World
*
* "This world is but a canvas to our imagination." - Henry David Thoreau
*
* A game has only one world. The world is an abstract place in which all game objects live. It is not bound
* by stage limits and can be any size or dimension. You look into the world via cameras and all game objects
* live within the world at world-based coordinates. By default a world is created the same size as your Stage.
@@ -12,13 +14,18 @@ module Phaser {
export class World {
/**
* World constructor
* Create a new <code>World</code> with specific width and height.
*
* @param width {number} Width of the world bound.
* @param height {number} Height of the world bound.
*/
constructor(game: Game, width: number, height: number) {
this._game = game;
this._cameras = new CameraManager(this._game, 0, 0, width, height);
this._game.camera = this._cameras.current;
this.cameras = new CameraManager(this._game, 0, 0, width, height);
this.group = new Group(this._game, 0);
@@ -28,41 +35,80 @@ module Phaser {
}
/**
* Local private reference to game.
*/
private _game: Game;
private _cameras: CameraManager;
/**
* Camera manager of this world.
* @type {CameraManager}
*/
public cameras: CameraManager;
/**
* Object container stores every object created with `create*` methods.
* @type {Group}
*/
public group: Group;
/**
* Bound of this world that objects can not escape from.
* @type {Rectangle}
*/
public bounds: Rectangle;
/**
* @type {number}
*/
public worldDivisions: number;
/**
* This is called automatically every frame, and is where main logic performs.
*/
public update() {
this.group.preUpdate();
this.group.update();
this.group.postUpdate();
this._cameras.update();
this.cameras.update();
}
/**
* Render every thing to the screen, automatically called after update().
*/
public render() {
// Unlike in flixel our render process is camera driven, not group driven
this._cameras.render();
this.cameras.render();
}
/**
* Clean up memory.
*/
public destroy() {
this.group.destroy();
this._cameras.destroy();
this.cameras.destroy();
}
// World methods
public setSize(width: number, height: number, updateCameraBounds: bool = true) {
/**
* Update size of this world with specific width and height.
* You can choose update camera bounds and verlet manager automatically or not.
*
* @param width {number} New width of the world.
* @param height {number} New height of the world.
* @param [updateCameraBounds] {boolean} update camera bounds automatically or not. Default to true.
* @param [updateVerletBounds] {boolean} update verlet bounds automatically or not. Default to true.
*/
public setSize(width: number, height: number, updateCameraBounds: bool = true, updateVerletBounds: bool = true) {
this.bounds.width = width;
this.bounds.height = height;
@@ -72,6 +118,12 @@ module Phaser {
this._game.camera.setBounds(0, 0, width, height);
}
if (updateVerletBounds == true)
{
this._game.verlet.width = width;
this._game.verlet.height = height;
}
}
public get width(): number {
@@ -108,48 +160,130 @@ module Phaser {
// Cameras
/**
* Create a new camera with specific position and size.
*
* @param x {number} X position of the new camera.
* @param y {number} Y position of the new camera.
* @param width {number} Width of the new camera.
* @param height {number} Height of the new camera.
* @returns {Camera} The newly created camera object.
*/
public createCamera(x: number, y: number, width: number, height: number): Camera {
return this._cameras.addCamera(x, y, width, height);
return this.cameras.addCamera(x, y, width, height);
}
/**
* Remove a new camera with its id.
*
* @param id {number} ID of the camera you want to remove.
* @returns {boolean} True if successfully removed the camera, otherwise return false.
*/
public removeCamera(id: number): bool {
return this._cameras.removeCamera(id);
return this.cameras.removeCamera(id);
}
/**
* Get all the cameras.
*
* @returns {array} An array contains all the cameras.
*/
public getAllCameras(): Camera[] {
return this._cameras.getAll();
return this.cameras.getAll();
}
// Game Objects
/**
* Create a new Sprite with specific position and sprite sheet key.
*
* @param x {number} X position of the new sprite.
* @param y {number} Y position of the new sprite.
* @param [key] {string} key for the sprite sheet you want it to use.
* @returns {Sprite} The newly created sprite object.
*/
public createSprite(x: number, y: number, key?: string = ''): Sprite {
return <Sprite> this.group.add(new Sprite(this._game, x, y, key));
}
/**
* Create a new GeomSprite with specific position.
*
* @param x {number} X position of the new geom sprite.
* @param y {number} Y position of the new geom sprite.
* @returns {GeomSprite} The newly created geom sprite object.
*/
public createGeomSprite(x: number, y: number): GeomSprite {
return <GeomSprite> this.group.add(new GeomSprite(this._game, x, y));
}
/**
* Create a new DynamicTexture with specific size.
*
* @param width {number} Width of the texture.
* @param height {number} Height of the texture.
* @returns {DynamicTexture} The newly created dynamic texture object.
*/
public createDynamicTexture(width: number, height: number): DynamicTexture {
return new DynamicTexture(this._game, width, height);
}
public createGroup(MaxSize?: number = 0): Group {
return <Group> this.group.add(new Group(this._game, MaxSize));
/**
* Create a new object container.
*
* @param [maxSize] {number} capacity of this group.
* @returns {Group} The newly created group.
*/
public createGroup(maxSize?: number = 0): Group {
return <Group> this.group.add(new Group(this._game, maxSize));
}
/**
* Create a new ScrollZone object with image key, position and size.
*
* @param key {number} Key to a image you wish this object to use.
* @param x {number} X position of this object.
* @param y {number} Y position of this object.
* @param width {number} Width of this object.
* @param height {number} Height of this object.
* @returns {ScrollZone} The newly created scroll zone object.
*/
public createScrollZone(key: string, x?: number = 0, y?: number = 0, width?: number = 0, height?: number = 0): ScrollZone {
return <ScrollZone> this.group.add(new ScrollZone(this._game, key, x, y, width, height));
}
/**
* Create a new Tilemap.
*
* @param key {string} Key for tileset image.
* @param mapData {string} Data of this tilemap.
* @param format {number} Format of map data. (Tilemap.FORMAT_CSV or Tilemap.FORMAT_TILED_JSON)
* @param [resizeWorld] {boolean} resize the world to make same as tilemap?
* @param [tileWidth] {number} width of each tile.
* @param [tileHeight] {number} height of each tile.
* @return {Tilemap} The newly created tilemap object.
*/
public createTilemap(key: string, mapData: string, format: number, resizeWorld: bool = true, tileWidth?: number = 0, tileHeight?: number = 0): Tilemap {
return <Tilemap> this.group.add(new Tilemap(this._game, key, mapData, format, resizeWorld, tileWidth, tileHeight));
}
/**
* Create a new Particle.
*
* @return {Particle} The newly created particle object.
*/
public createParticle(): Particle {
return new Particle(this._game);
}
/**
* Create a new Emitter.
*
* @param [x] {number} x position of the emitter.
* @param [y] {number} y position of the emitter.
* @param [size] {number} size of this emitter.
* @return {Emitter} The newly created emitter object.
*/
public createEmitter(x?: number = 0, y?: number = 0, size?: number = 0): Emitter {
return <Emitter> this.group.add(new Emitter(this._game, x, y, size));
}
+38
View File
@@ -0,0 +1,38 @@
/// <reference path="../Game.d.ts" />
/// <reference path="../Group.d.ts" />
module Phaser {
class Emitter extends Group {
constructor(game: Game, X?: number, Y?: number, Size?: number);
public x: number;
public y: number;
public width: number;
public height: number;
public minParticleSpeed: MicroPoint;
public maxParticleSpeed: MicroPoint;
public particleDrag: MicroPoint;
public minRotation: number;
public maxRotation: number;
public gravity: number;
public on: bool;
public frequency: number;
public lifespan: number;
public bounce: number;
public particleClass;
private _quantity;
private _explode;
private _timer;
private _counter;
private _point;
public destroy(): void;
public makeParticles(Graphics, Quantity?: number, BakedRotations?: number, Multiple?: bool, Collide?: number): Emitter;
public update(): void;
public kill(): void;
public start(Explode?: bool, Lifespan?: number, Frequency?: number, Quantity?: number): void;
public emitParticle(): void;
public setSize(Width: number, Height: number): void;
public setXSpeed(Min?: number, Max?: number): void;
public setYSpeed(Min?: number, Max?: number): void;
public setRotation(Min?: number, Max?: number): void;
public at(Object): void;
}
}
+75 -72
View File
@@ -16,24 +16,26 @@ module Phaser {
/**
* Creates a new <code>Emitter</code> object at a specific position.
* Does NOT automatically generate or attach particles!
*
* @param X The X position of the emitter.
* @param Y The Y position of the emitter.
* @param Size Optional, specifies a maximum capacity for this emitter.
*
* @param x {number} The X position of the emitter.
* @param y {number} The Y position of the emitter.
* @param [size] {number} Specifies a maximum capacity for this emitter.
*/
constructor(game: Game, X: number = 0, Y: number = 0, Size: number = 0) {
super(game, Size);
this.x = X;
this.y = Y;
constructor(game: Game, x: number = 0, y: number = 0, size: number = 0) {
super(game, size);
this.x = x;
this.y = y;
this.width = 0;
this.height = 0;
this.minParticleSpeed = new Point(-100, -100);
this.maxParticleSpeed = new Point(100, 100);
this.minParticleSpeed = new MicroPoint(-100, -100);
this.maxParticleSpeed = new MicroPoint(100, 100);
this.minRotation = -360;
this.maxRotation = 360;
this.gravity = 0;
this.particleClass = null;
this.particleDrag = new Point();
this.particleDrag = new MicroPoint();
this.frequency = 0.1;
this.lifespan = 3;
this.bounce = 0;
@@ -41,7 +43,8 @@ module Phaser {
this._counter = 0;
this._explode = true;
this.on = false;
this._point = new Point();
this._point = new MicroPoint();
}
/**
@@ -68,18 +71,18 @@ module Phaser {
* The minimum possible velocity of a particle.
* The default value is (-100,-100).
*/
public minParticleSpeed: Point;
public minParticleSpeed: MicroPoint;
/**
* The maximum possible velocity of a particle.
* The default value is (100,100).
*/
public maxParticleSpeed: Point;
public maxParticleSpeed: MicroPoint;
/**
* The X and Y drag component of particles launched from the emitter.
*/
public particleDrag: Point;
public particleDrag: MicroPoint;
/**
* The minimum possible angular velocity of a particle. The default value is -360.
@@ -149,7 +152,7 @@ module Phaser {
/**
* Internal point object, handy for reusing for memory mgmt purposes.
*/
private _point: Point;
private _point: MicroPoint;
/**
* Clean up memory.
@@ -165,24 +168,23 @@ module Phaser {
/**
* This function generates a new array of particle sprites to attach to the emitter.
*
* @param Graphics If you opted to not pre-configure an array of Sprite objects, you can simply pass in a particle image or sprite sheet.
* @param Quantity The number of particles to generate when using the "create from image" option.
* @param BakedRotations How many frames of baked rotation to use (boosts performance). Set to zero to not use baked rotations.
* @param Multiple Whether the image in the Graphics param is a single particle or a bunch of particles (if it's a bunch, they need to be square!).
* @param Collide Whether the particles should be flagged as not 'dead' (non-colliding particles are higher performance). 0 means no collisions, 0-1 controls scale of particle's bounding box.
*
* @return This Emitter instance (nice for chaining stuff together, if you're into that).
*
* @param graphics If you opted to not pre-configure an array of Sprite objects, you can simply pass in a particle image or sprite sheet.
* @param quantity {number} The number of particles to generate when using the "create from image" option.
* @param multiple {boolean} Whether the image in the Graphics param is a single particle or a bunch of particles (if it's a bunch, they need to be square!).
* @param collide {number} Whether the particles should be flagged as not 'dead' (non-colliding particles are higher performance). 0 means no collisions, 0-1 controls scale of particle's bounding box.
*
* @return This Emitter instance (nice for chaining stuff together, if you're into that).
*/
public makeParticles(Graphics, Quantity: number = 50, BakedRotations: number = 16, Multiple: bool = false, Collide: number = 0.8): Emitter {
public makeParticles(graphics, quantity: number = 50, multiple: bool = false, collide: number = 0): Emitter {
this.maxSize = Quantity;
this.maxSize = quantity;
var totalFrames: number = 1;
/*
if(Multiple)
{
{
var sprite:Sprite = new Sprite(this._game);
sprite.loadGraphic(Graphics,true);
totalFrames = sprite.frames;
@@ -194,7 +196,7 @@ module Phaser {
var particle: Particle;
var i: number = 0;
while (i < Quantity)
while (i < quantity)
{
if (this.particleClass == null)
{
@@ -205,7 +207,7 @@ module Phaser {
particle = new this.particleClass(this._game);
}
if (Multiple)
if (multiple)
{
/*
randomFrame = this._game.math.random()*totalFrames;
@@ -227,17 +229,18 @@ module Phaser {
particle.loadGraphic(Graphics);
*/
if (Graphics)
if (graphics)
{
particle.loadGraphic(Graphics);
particle.loadGraphic(graphics);
}
}
if (Collide > 0)
if (collide > 0)
{
particle.width *= Collide;
particle.height *= Collide;
particle.allowCollisions = Collision.ANY;
particle.width *= collide;
particle.height *= collide;
//particle.centerOffsets();
}
else
@@ -317,23 +320,23 @@ module Phaser {
/**
* Call this function to start emitting particles.
*
* @param Explode Whether the particles should all burst out at once.
* @param Lifespan How long each particle lives once emitted. 0 = forever.
* @param Frequency Ignored if Explode is set to true. Frequency is how often to emit a particle. 0 = never emit, 0.1 = 1 particle every 0.1 seconds, 5 = 1 particle every 5 seconds.
* @param Quantity How many particles to launch. 0 = "all of the particles".
*
* @param explode {boolean} Whether the particles should all burst out at once.
* @param lifespan {number} How long each particle lives once emitted. 0 = forever.
* @param frequency {number} Ignored if Explode is set to true. Frequency is how often to emit a particle. 0 = never emit, 0.1 = 1 particle every 0.1 seconds, 5 = 1 particle every 5 seconds.
* @param quantity {number} How many particles to launch. 0 = "all of the particles".
*/
public start(Explode: bool = true, Lifespan: number = 0, Frequency: number = 0.1, Quantity: number = 0) {
public start(explode: bool = true, lifespan: number = 0, frequency: number = 0.1, quantity: number = 0) {
this.revive();
this.visible = true;
this.on = true;
this._explode = Explode;
this.lifespan = Lifespan;
this.frequency = Frequency;
this._quantity += Quantity;
this._explode = explode;
this.lifespan = lifespan;
this.frequency = frequency;
this._quantity += quantity;
this._counter = 0;
this._timer = 0;
@@ -394,55 +397,55 @@ module Phaser {
/**
* A more compact way of setting the width and height of the emitter.
*
* @param Width The desired width of the emitter (particles are spawned randomly within these dimensions).
* @param Height The desired height of the emitter.
*
* @param width {number} The desired width of the emitter (particles are spawned randomly within these dimensions).
* @param height {number} The desired height of the emitter.
*/
public setSize(Width: number, Height: number) {
this.width = Width;
this.height = Height;
public setSize(width: number, height: number) {
this.width = width;
this.height = height;
}
/**
* A more compact way of setting the X velocity range of the emitter.
*
* @param Min The minimum value for this range.
* @param Max The maximum value for this range.
*
* @param Min {number} The minimum value for this range.
* @param Max {number} The maximum value for this range.
*/
public setXSpeed(Min: number = 0, Max: number = 0) {
this.minParticleSpeed.x = Min;
this.maxParticleSpeed.x = Max;
public setXSpeed(min: number = 0, max: number = 0) {
this.minParticleSpeed.x = min;
this.maxParticleSpeed.x = max;
}
/**
* A more compact way of setting the Y velocity range of the emitter.
*
* @param Min The minimum value for this range.
* @param Max The maximum value for this range.
*
* @param Min {number} The minimum value for this range.
* @param Max {number} The maximum value for this range.
*/
public setYSpeed(Min: number = 0, Max: number = 0) {
this.minParticleSpeed.y = Min;
this.maxParticleSpeed.y = Max;
public setYSpeed(min: number = 0, max: number = 0) {
this.minParticleSpeed.y = min;
this.maxParticleSpeed.y = max;
}
/**
* A more compact way of setting the angular velocity constraints of the emitter.
*
* @param Min The minimum value for this range.
* @param Max The maximum value for this range.
*
* @param Min {number} The minimum value for this range.
* @param Max {number} The maximum value for this range.
*/
public setRotation(Min: number = 0, Max: number = 0) {
this.minRotation = Min;
this.maxRotation = Max;
public setRotation(min: number = 0, max: number = 0) {
this.minRotation = min;
this.maxRotation = max;
}
/**
* Change the emitter's midpoint to match the midpoint of a <code>Object</code>.
*
* @param Object The <code>Object</code> that you want to sync up with.
*
* @param Object {object} The <code>Object</code> that you want to sync up with.
*/
public at(Object) {
Object.getMidpoint(this._point);
public at(object) {
object.getMidpoint(this._point);
this.x = this._point.x - (this.width >> 1);
this.y = this._point.y - (this.height >> 1);
}
+84
View File
@@ -0,0 +1,84 @@
/// <reference path="../Game.d.ts" />
/// <reference path="../Basic.d.ts" />
/// <reference path="../Signal.d.ts" />
module Phaser {
class GameObject extends Basic {
constructor(game: Game, x?: number, y?: number, width?: number, height?: number);
private _angle;
static ALIGN_TOP_LEFT: number;
static ALIGN_TOP_CENTER: number;
static ALIGN_TOP_RIGHT: number;
static ALIGN_CENTER_LEFT: number;
static ALIGN_CENTER: number;
static ALIGN_CENTER_RIGHT: number;
static ALIGN_BOTTOM_LEFT: number;
static ALIGN_BOTTOM_CENTER: number;
static ALIGN_BOTTOM_RIGHT: number;
static OUT_OF_BOUNDS_STOP: number;
static OUT_OF_BOUNDS_KILL: number;
public _point: MicroPoint;
public cameraBlacklist: number[];
public bounds: Rectangle;
public worldBounds: Quad;
public outOfBoundsAction: number;
public align: number;
public facing: number;
public alpha: number;
public scale: MicroPoint;
public origin: MicroPoint;
public z: number;
public rotationOffset: number;
public renderRotation: bool;
public immovable: bool;
public velocity: MicroPoint;
public mass: number;
public elasticity: number;
public acceleration: MicroPoint;
public drag: MicroPoint;
public maxVelocity: MicroPoint;
public angularVelocity: number;
public angularAcceleration: number;
public angularDrag: number;
public maxAngular: number;
public scrollFactor: MicroPoint;
public health: number;
public moves: bool;
public touching: number;
public wasTouching: number;
public allowCollisions: number;
public last: MicroPoint;
public inputEnabled: bool;
private _inputOver;
public onInputOver: Signal;
public onInputOut: Signal;
public onInputDown: Signal;
public onInputUp: Signal;
public preUpdate(): void;
public update(): void;
public postUpdate(): void;
private updateInput();
private updateMotion();
public overlaps(ObjectOrGroup, InScreenSpace?: bool, Camera?: Camera): bool;
public overlapsAt(X: number, Y: number, ObjectOrGroup, InScreenSpace?: bool, Camera?: Camera): bool;
public overlapsPoint(point: Point, InScreenSpace?: bool, Camera?: Camera): bool;
public onScreen(Camera?: Camera): bool;
public getScreenXY(point?: MicroPoint, Camera?: Camera): MicroPoint;
public solid : bool;
public getMidpoint(point?: MicroPoint): MicroPoint;
public reset(X: number, Y: number): void;
public isTouching(Direction: number): bool;
public justTouched(Direction: number): bool;
public hurt(Damage: number): void;
public setBounds(x: number, y: number, width: number, height: number): void;
public hideFromCamera(camera: Camera): void;
public showToCamera(camera: Camera): void;
public clearCameraList(): void;
public destroy(): void;
public x : number;
public y : number;
public rotation : number;
public angle : number;
public width : number;
public height : number;
}
}
+434 -160
View File
@@ -1,6 +1,7 @@
/// <reference path="../Game.ts" />
/// <reference path="../Basic.ts" />
/// <reference path="../Signal.ts" />
/// <reference path="../system/CollisionMask.ts" />
/**
* Phaser - GameObject
@@ -13,11 +14,24 @@ module Phaser {
export class GameObject extends Basic {
/**
* GameObject constructor
*
* Create a new <code>GameObject</code> object at specific position with specific width and height.
*
* @param [x] {number} The x position of the object.
* @param [y] {number} The y position of the object.
* @param [width] {number} The width of the object.
* @param [height] {number} The height of the object.
*/
constructor(game: Game, x?: number = 0, y?: number = 0, width?: number = 16, height?: number = 16) {
super(game);
this.bounds = new Rectangle(x, y, width, height);
this.canvas = game.stage.canvas;
this.context = game.stage.context;
this.frameBounds = new Rectangle(x, y, width, height);
this.exists = true;
this.active = true;
this.visible = true;
@@ -27,10 +41,9 @@ module Phaser {
this.scale = new MicroPoint(1, 1);
this.last = new MicroPoint(x, y);
this.origin = new MicroPoint(this.bounds.halfWidth, this.bounds.halfHeight);
this.align = GameObject.ALIGN_TOP_LEFT;
this.mass = 1.0;
this.elasticity = 0.0;
this.mass = 1;
this.elasticity = 0;
this.health = 1;
this.immovable = false;
this.moves = true;
@@ -52,68 +65,303 @@ module Phaser {
this.maxAngular = 10000;
this.cameraBlacklist = [];
this.scrollFactor = new MicroPoint(1.0, 1.0);
this.scrollFactor = new MicroPoint(1, 1);
this.collisionMask = new CollisionMask(game, this, x, y, width, height);
}
/**
* Angle of this object.
* @type {number}
*/
private _angle: number = 0;
/**
* Pivot position enum: at the top-left corner.
* @type {number}
*/
public static ALIGN_TOP_LEFT: number = 0;
/**
* Pivot position enum: at the top-center corner.
* @type {number}
*/
public static ALIGN_TOP_CENTER: number = 1;
/**
* Pivot position enum: at the top-right corner.
* @type {number}
*/
public static ALIGN_TOP_RIGHT: number = 2;
/**
* Pivot position enum: at the center-left corner.
* @type {number}
*/
public static ALIGN_CENTER_LEFT: number = 3;
/**
* Pivot position enum: at the center corner.
* @type {number}
*/
public static ALIGN_CENTER: number = 4;
/**
* Pivot position enum: at the center-right corner.
* @type {number}
*/
public static ALIGN_CENTER_RIGHT: number = 5;
/**
* Pivot position enum: at the bottom-left corner.
* @type {number}
*/
public static ALIGN_BOTTOM_LEFT: number = 6;
/**
* Pivot position enum: at the bottom-center corner.
* @type {number}
*/
public static ALIGN_BOTTOM_CENTER: number = 7;
/**
* Pivot position enum: at the bottom-right corner.
* @type {number}
*/
public static ALIGN_BOTTOM_RIGHT: number = 8;
/**
* Enum value for outOfBoundsAction. Stop the object when is out of world bounds.
* @type {number}
*/
public static OUT_OF_BOUNDS_STOP: number = 0;
/**
* Enum value for outOfBoundsAction. Kill the object when is out of world bounds.
* @type {number}
*/
public static OUT_OF_BOUNDS_KILL: number = 1;
/**
* A reference to the Canvas this GameObject will render to
* @type {HTMLCanvasElement}
*/
public canvas: HTMLCanvasElement;
/**
* A reference to the Canvas Context2D this GameObject will render to
* @type {CanvasRenderingContext2D}
*/
public context: CanvasRenderingContext2D;
/**
* Position of this object after scrolling.
* @type {MicroPoint}
*/
public _point: MicroPoint;
/**
* An Array of Cameras to which this GameObject won't render
* @type {Array}
*/
public cameraBlacklist: number[];
public bounds: Rectangle;
/**
* Rectangle container of this object.
* @type {Rectangle}
*/
public frameBounds: Rectangle;
/**
* This objects CollisionMask
* @type {CollisionMask}
*/
public collisionMask: CollisionMask;
/**
* A rectangular area which is object is allowed to exist within. If it travels outside of this area it will perform the outOfBoundsAction.
* @type {Quad}
*/
public worldBounds: Quad;
/**
* What action will be performed when object is out of the worldBounds.
* This will default to GameObject.OUT_OF_BOUNDS_STOP.
* @type {number}
*/
public outOfBoundsAction: number = 0;
/**
* At which point the graphic of this object will align to.
* Align of the object will default to GameObject.ALIGN_TOP_LEFT.
* @type {number}
*/
public align: number;
/**
* Orientation of the object.
* @type {number}
*/
public facing: number;
/**
* Set alpha to a number between 0 and 1 to change the opacity.
* @type {number}
*/
public alpha: number;
/**
* Scale factor of the object.
* @type {MicroPoint}
*/
public scale: MicroPoint;
/**
* Origin is the anchor point that the object will rotate by.
* The origin will default to its center.
* @type {MicroPoint}
*/
public origin: MicroPoint;
/**
* Z-order value of the object.
*/
public z: number = 0;
// This value is added to the angle of the GameObject.
// For example if you had a sprite drawn facing straight up then you could set
// rotationOffset to 90 and it would correspond correctly with Phasers rotation system
/**
* This value is added to the angle of the GameObject.
* For example if you had a sprite drawn facing straight up then you could set
* rotationOffset to 90 and it would correspond correctly with Phasers rotation system
* @type {number}
*/
public rotationOffset: number = 0;
/**
* Controls if the GameObject is rendered rotated or not.
* If renderRotation is false then the object can still rotate but it will never be rendered rotated.
* @type {boolean}
*/
public renderRotation: bool = true;
// Physics properties
/**
* Whether this object will be moved by impacts with other objects or not.
* @type {boolean}
*/
public immovable: bool;
// Velocity is given in pixels per second. Therefore a velocity of
// 100 will move at a rate of 100 pixels every 1000 ms (1sec). It's not balls-on
// accurate due to the way timers work, but it's pretty close. Expect tolerance
// of +- 10 px. Also that speed assumes no drag
/**
* Basic speed of this object.
*
* Velocity is given in pixels per second. Therefore a velocity of
* 100 will move at a rate of 100 pixels every 1000 ms (1sec). It's not balls-on
* accurate due to the way timers work, but it's pretty close. Expect tolerance
* of +- 10 px. Also that speed assumes no drag.
*
* @type {MicroPoint}
*/
public velocity: MicroPoint;
/**
* The virtual mass of the object.
* @type {number}
*/
public mass: number;
/**
* The bounciness of the object.
* @type {number}
*/
public elasticity: number;
/**
* How fast the speed of this object is changing.
* @type {number}
*/
public acceleration: MicroPoint;
/**
* This isn't drag exactly, more like deceleration that is only applied
* when acceleration is not affecting the sprite.
* @type {MicroPoint}
*/
public drag: MicroPoint;
/**
* It will cap the speed automatically if you use the acceleration
* to change its velocity.
* @type {MicroPoint}
*/
public maxVelocity: MicroPoint;
/**
* How fast this object is rotating.
* @type {number}
*/
public angularVelocity: number;
/**
* How fast angularVelocity of this object is changing.
* @type {number}
*/
public angularAcceleration: number;
/**
* Deacceleration of angularVelocity will be applied when it's rotating.
* @type {number}
*/
public angularDrag: number;
/**
* It will cap the rotate speed automatically if you use the angularAcceleration
* to change its angularVelocity.
* @type {number}
*/
public maxAngular: number;
/**
* A point that can store numbers from 0 to 1 (for X and Y independently)
* which governs how much this object is affected by the camera .
* @type {MicroPoint}
*/
public scrollFactor: MicroPoint;
/**
* Handy for storing health percentage or armor points or whatever.
* @type {number}
*/
public health: number;
/**
* Set this to false if you want to skip the automatic motion/movement stuff
* (see updateMotion()).
* @type {boolean}
*/
public moves: bool = true;
/**
* Bit field of flags (use with UP, DOWN, LEFT, RIGHT, etc) indicating surface contacts.
* @type {number}
*/
public touching: number;
/**
* Bit field of flags (use with UP, DOWN, LEFT, RIGHT, etc) indicating surface contacts from the previous game loop step.
* @type {number}
*/
public wasTouching: number;
/**
* Bit field of flags (use with UP, DOWN, LEFT, RIGHT, etc) indicating collision directions.
* @type {number}
*/
public allowCollisions: number;
/**
* Important variable for collision processing.
* @type {MicroPoint}
*/
public last: MicroPoint;
// Input
@@ -125,18 +373,27 @@ module Phaser {
public onInputDown: Phaser.Signal;
public onInputUp: Phaser.Signal;
/**
* Pre-update is called right before update() on each object in the game loop.
*/
public preUpdate() {
// flicker time
this.last.x = this.frameBounds.x;
this.last.y = this.frameBounds.y;
this.last.x = this.bounds.x;
this.last.y = this.bounds.y;
this.collisionMask.preUpdate();
}
/**
* Override this function to update your class's position and appearance.
*/
public update() {
}
/**
* Automatically called after update() by the game loop.
*/
public postUpdate() {
if (this.moves)
@@ -174,6 +431,8 @@ module Phaser {
}
}
}
this.collisionMask.update();
if (this.inputEnabled)
{
@@ -185,9 +444,15 @@ module Phaser {
}
/**
* Update input.
*/
private updateInput() {
}
/**
* Internal function for updating the position and speed of this object.
*/
private updateMotion() {
var delta: number;
@@ -202,13 +467,13 @@ module Phaser {
this.velocity.x += velocityDelta;
delta = this.velocity.x * this._game.time.elapsed;
this.velocity.x += velocityDelta;
this.bounds.x += delta;
this.frameBounds.x += delta;
velocityDelta = (this._game.motion.computeVelocity(this.velocity.y, this.acceleration.y, this.drag.y, this.maxVelocity.y) - this.velocity.y) / 2;
this.velocity.y += velocityDelta;
delta = this.velocity.y * this._game.time.elapsed;
this.velocity.y += velocityDelta;
this.bounds.y += delta;
this.frameBounds.y += delta;
}
@@ -216,24 +481,24 @@ module Phaser {
* Checks to see if some <code>GameObject</code> overlaps this <code>GameObject</code> or <code>Group</code>.
* If the group has a LOT of things in it, it might be faster to use <code>Collision.overlaps()</code>.
* WARNING: Currently tilemaps do NOT support screen space overlap checks!
*
* @param ObjectOrGroup The object or group being tested.
* @param InScreenSpace Whether to take scroll factors numbero account when checking for overlap. Default is false, or "only compare in world space."
* @param Camera Specify which game camera you want. If null getScreenXY() will just grab the first global camera.
*
* @return Whether or not the two objects overlap.
*
* @param objectOrGroup {object} The object or group being tested.
* @param inScreenSpace {boolean} Whether to take scroll factors numbero account when checking for overlap. Default is false, or "only compare in world space."
* @param camera {Camera} Specify which game camera you want. If null getScreenXY() will just grab the first global camera.
*
* @return {boolean} Whether or not the objects overlap this.
*/
public overlaps(ObjectOrGroup, InScreenSpace: bool = false, Camera: Camera = null): bool {
public overlaps(objectOrGroup, inScreenSpace: bool = false, camera: Camera = null): bool {
if (ObjectOrGroup.isGroup)
if (objectOrGroup.isGroup)
{
var results: bool = false;
var i: number = 0;
var members = <Group> ObjectOrGroup.members;
var members = <Group> objectOrGroup.members;
while (i < length)
{
if (this.overlaps(members[i++], InScreenSpace, Camera))
if (this.overlaps(members[i++], inScreenSpace, camera))
{
results = true;
}
@@ -243,61 +508,50 @@ module Phaser {
}
/*
if (typeof ObjectOrGroup === 'Tilemap')
if (!inScreenSpace)
{
//Since tilemap's have to be the caller, not the target, to do proper tile-based collisions,
// we redirect the call to the tilemap overlap here.
return ObjectOrGroup.overlaps(this, InScreenSpace, Camera);
}
*/
//var object: GameObject = ObjectOrGroup;
if (!InScreenSpace)
{
return (ObjectOrGroup.x + ObjectOrGroup.width > this.x) && (ObjectOrGroup.x < this.x + this.width) &&
(ObjectOrGroup.y + ObjectOrGroup.height > this.y) && (ObjectOrGroup.y < this.y + this.height);
return (objectOrGroup.x + objectOrGroup.width > this.x) && (objectOrGroup.x < this.x + this.width) &&
(objectOrGroup.y + objectOrGroup.height > this.y) && (objectOrGroup.y < this.y + this.height);
}
if (Camera == null)
if (camera == null)
{
Camera = this._game.camera;
camera = this._game.camera;
}
var objectScreenPos: Point = ObjectOrGroup.getScreenXY(null, Camera);
var objectScreenPos: Point = objectOrGroup.getScreenXY(null, camera);
this.getScreenXY(this._point, Camera);
this.getScreenXY(this._point, camera);
return (objectScreenPos.x + ObjectOrGroup.width > this._point.x) && (objectScreenPos.x < this._point.x + this.width) &&
(objectScreenPos.y + ObjectOrGroup.height > this._point.y) && (objectScreenPos.y < this._point.y + this.height);
return (objectScreenPos.x + objectOrGroup.width > this._point.x) && (objectScreenPos.x < this._point.x + this.width) &&
(objectScreenPos.y + objectOrGroup.height > this._point.y) && (objectScreenPos.y < this._point.y + this.height);
}
/**
* Checks to see if this <code>GameObject</code> were located at the given position, would it overlap the <code>GameObject</code> or <code>Group</code>?
* This is distinct from overlapsPoint(), which just checks that point, rather than taking the object's size numbero account.
* WARNING: Currently tilemaps do NOT support screen space overlap checks!
*
* @param X The X position you want to check. Pretends this object (the caller, not the parameter) is located here.
* @param Y The Y position you want to check. Pretends this object (the caller, not the parameter) is located here.
* @param ObjectOrGroup The object or group being tested.
* @param InScreenSpace Whether to take scroll factors numbero account when checking for overlap. Default is false, or "only compare in world space."
* @param Camera Specify which game camera you want. If null getScreenXY() will just grab the first global camera.
*
* @return Whether or not the two objects overlap.
*
* @param X {number} The X position you want to check. Pretends this object (the caller, not the parameter) is located here.
* @param Y {number} The Y position you want to check. Pretends this object (the caller, not the parameter) is located here.
* @param objectOrGroup {object} The object or group being tested.
* @param inScreenSpace {boolean} Whether to take scroll factors numbero account when checking for overlap. Default is false, or "only compare in world space."
* @param camera {Camera} Specify which game camera you want. If null getScreenXY() will just grab the first global camera.
*
* @return {boolean} Whether or not the two objects overlap.
*/
public overlapsAt(X: number, Y: number, ObjectOrGroup, InScreenSpace: bool = false, Camera: Camera = null): bool {
public overlapsAt(X: number, Y: number, objectOrGroup, inScreenSpace: bool = false, camera: Camera = null): bool {
if (ObjectOrGroup.isGroup)
if (objectOrGroup.isGroup)
{
var results: bool = false;
var basic;
var i: number = 0;
var members = ObjectOrGroup.members;
var members = objectOrGroup.members;
while (i < length)
{
if (this.overlapsAt(X, Y, members[i++], InScreenSpace, Camera))
if (this.overlapsAt(X, Y, members[i++], inScreenSpace, camera))
{
results = true;
}
@@ -306,67 +560,53 @@ module Phaser {
return results;
}
/*
if (typeof ObjectOrGroup === 'Tilemap')
if (!inScreenSpace)
{
//Since tilemap's have to be the caller, not the target, to do proper tile-based collisions,
// we redirect the call to the tilemap overlap here.
//However, since this is overlapsAt(), we also have to invent the appropriate position for the tilemap.
//So we calculate the offset between the player and the requested position, and subtract that from the tilemap.
var tilemap: Tilemap = ObjectOrGroup;
return tilemap.overlapsAt(tilemap.x - (X - this.x), tilemap.y - (Y - this.y), this, InScreenSpace, Camera);
}
*/
//var object: GameObject = ObjectOrGroup;
if (!InScreenSpace)
{
return (ObjectOrGroup.x + ObjectOrGroup.width > X) && (ObjectOrGroup.x < X + this.width) &&
(ObjectOrGroup.y + ObjectOrGroup.height > Y) && (ObjectOrGroup.y < Y + this.height);
return (objectOrGroup.x + objectOrGroup.width > X) && (objectOrGroup.x < X + this.width) &&
(objectOrGroup.y + objectOrGroup.height > Y) && (objectOrGroup.y < Y + this.height);
}
if (Camera == null)
if (camera == null)
{
Camera = this._game.camera;
camera = this._game.camera;
}
var objectScreenPos: Point = ObjectOrGroup.getScreenXY(null, Camera);
var objectScreenPos: Point = objectOrGroup.getScreenXY(null, Camera);
this._point.x = X - Camera.scroll.x * this.scrollFactor.x; //copied from getScreenXY()
this._point.y = Y - Camera.scroll.y * this.scrollFactor.y;
this._point.x = X - camera.scroll.x * this.scrollFactor.x; //copied from getScreenXY()
this._point.y = Y - camera.scroll.y * this.scrollFactor.y;
this._point.x += (this._point.x > 0) ? 0.0000001 : -0.0000001;
this._point.y += (this._point.y > 0) ? 0.0000001 : -0.0000001;
return (objectScreenPos.x + ObjectOrGroup.width > this._point.x) && (objectScreenPos.x < this._point.x + this.width) &&
(objectScreenPos.y + ObjectOrGroup.height > this._point.y) && (objectScreenPos.y < this._point.y + this.height);
return (objectScreenPos.x + objectOrGroup.width > this._point.x) && (objectScreenPos.x < this._point.x + this.width) &&
(objectScreenPos.y + objectOrGroup.height > this._point.y) && (objectScreenPos.y < this._point.y + this.height);
}
/**
* Checks to see if a point in 2D world space overlaps this <code>GameObject</code>.
*
* @param Point The point in world space you want to check.
* @param InScreenSpace Whether to take scroll factors numbero account when checking for overlap.
* @param Camera Specify which game camera you want. If null getScreenXY() will just grab the first global camera.
*
* @return Whether or not the point overlaps this object.
*
* @param point {Point} The point in world space you want to check.
* @param inScreenSpace {boolean} Whether to take scroll factors into account when checking for overlap.
* @param camera {Camera} Specify which game camera you want. If null getScreenXY() will just grab the first global camera.
*
* @return Whether or not the point overlaps this object.
*/
public overlapsPoint(point: Point, InScreenSpace: bool = false, Camera: Camera = null): bool {
public overlapsPoint(point: Point, inScreenSpace: bool = false, camera: Camera = null): bool {
if (!InScreenSpace)
if (!inScreenSpace)
{
return (point.x > this.x) && (point.x < this.x + this.width) && (point.y > this.y) && (point.y < this.y + this.height);
}
if (Camera == null)
if (camera == null)
{
Camera = this._game.camera;
camera = this._game.camera;
}
var X: number = point.x - Camera.scroll.x;
var Y: number = point.y - Camera.scroll.y;
var X: number = point.x - camera.scroll.x;
var Y: number = point.y - camera.scroll.y;
this.getScreenXY(this._point, Camera);
this.getScreenXY(this._point, camera);
return (X > this._point.x) && (X < this._point.x + this.width) && (Y > this._point.y) && (Y < this._point.y + this.height);
@@ -374,46 +614,46 @@ module Phaser {
/**
* Check and see if this object is currently on screen.
*
* @param Camera Specify which game camera you want. If null getScreenXY() will just grab the first global camera.
*
* @return Whether the object is on screen or not.
*
* @param camera {Camera} Specify which game camera you want. If null getScreenXY() will just grab the first global camera.
*
* @return {boolean} Whether the object is on screen or not.
*/
public onScreen(Camera: Camera = null): bool {
public onScreen(camera: Camera = null): bool {
if (Camera == null)
if (camera == null)
{
Camera = this._game.camera;
camera = this._game.camera;
}
this.getScreenXY(this._point, Camera);
this.getScreenXY(this._point, camera);
return (this._point.x + this.width > 0) && (this._point.x < Camera.width) && (this._point.y + this.height > 0) && (this._point.y < Camera.height);
return (this._point.x + this.width > 0) && (this._point.x < camera.width) && (this._point.y + this.height > 0) && (this._point.y < camera.height);
}
/**
* Call this to figure out the on-screen position of the object.
*
* @param Camera Specify which game camera you want. If null getScreenXY() will just grab the first global camera.
* @param Point Takes a <code>MicroPoint</code> object and assigns the post-scrolled X and Y values of this object to it.
*
* @return The <code>MicroPoint</code> you passed in, or a new <code>Point</code> if you didn't pass one, containing the screen X and Y position of this object.
*
* @param point {Point} Takes a <code>MicroPoint</code> object and assigns the post-scrolled X and Y values of this object to it.
* @param camera {Camera} Specify which game camera you want. If null getScreenXY() will just grab the first global camera.
*
* @return {MicroPoint} The <code>MicroPoint</code> you passed in, or a new <code>Point</code> if you didn't pass one, containing the screen X and Y position of this object.
*/
public getScreenXY(point: MicroPoint = null, Camera: Camera = null): MicroPoint {
public getScreenXY(point: MicroPoint = null, camera: Camera = null): MicroPoint {
if (point == null)
{
point = new MicroPoint();
}
if (Camera == null)
if (camera == null)
{
Camera = this._game.camera;
camera = this._game.camera;
}
point.x = this.x - Camera.scroll.x * this.scrollFactor.x;
point.y = this.y - Camera.scroll.y * this.scrollFactor.y;
point.x = this.x - camera.scroll.x * this.scrollFactor.x;
point.y = this.y - camera.scroll.y * this.scrollFactor.y;
point.x += (point.x > 0) ? 0.0000001 : -0.0000001;
point.y += (point.y > 0) ? 0.0000001 : -0.0000001;
@@ -430,12 +670,9 @@ module Phaser {
return (this.allowCollisions & Collision.ANY) > Collision.NONE;
}
/**
* @private
*/
public set solid(Solid: bool) {
public set solid(value: bool) {
if (Solid)
if (value)
{
this.allowCollisions = Collision.ANY;
}
@@ -448,10 +685,10 @@ module Phaser {
/**
* Retrieve the midpoint of this object in world coordinates.
*
* @Point Allows you to pass in an existing <code>Point</code> object if you're so inclined. Otherwise a new one is created.
*
* @return A <code>Point</code> object containing the midpoint of this object in world coordinates.
*
* @param point {Point} Allows you to pass in an existing <code>Point</code> object if you're so inclined. Otherwise a new one is created.
*
* @return {MicroPoint} A <code>Point</code> object containing the midpoint of this object in world coordinates.
*/
public getMidpoint(point: MicroPoint = null): MicroPoint {
@@ -460,7 +697,7 @@ module Phaser {
point = new MicroPoint();
}
point.copyFrom(this.bounds.center);
point.copyFrom(this.frameBounds.center);
return point;
@@ -469,19 +706,19 @@ module Phaser {
/**
* Handy for reviving game objects.
* Resets their existence flags and position.
*
* @param X The new X position of this object.
* @param Y The new Y position of this object.
*
* @param x {number} The new X position of this object.
* @param y {number} The new Y position of this object.
*/
public reset(X: number, Y: number) {
public reset(x: number, y: number) {
this.revive();
this.touching = Collision.NONE;
this.wasTouching = Collision.NONE;
this.x = X;
this.y = Y;
this.last.x = X;
this.last.y = Y;
this.x = x;
this.y = y;
this.last.x = x;
this.last.y = y;
this.velocity.x = 0;
this.velocity.y = 0;
@@ -489,37 +726,37 @@ module Phaser {
/**
* Handy for checking if this object is touching a particular surface.
* For slightly better performance you can just &amp; the value directly numbero <code>touching</code>.
* For slightly better performance you can just &amp; the value directly into <code>touching</code>.
* However, this method is good for readability and accessibility.
*
* @param Direction Any of the collision flags (e.g. LEFT, FLOOR, etc).
*
* @return Whether the object is touching an object in (any of) the specified direction(s) this frame.
*
* @param Direction {number} Any of the collision flags (e.g. LEFT, FLOOR, etc).
*
* @return {boolean} Whether the object is touching an object in (any of) the specified direction(s) this frame.
*/
public isTouching(Direction: number): bool {
return (this.touching & Direction) > Collision.NONE;
public isTouching(direction: number): bool {
return (this.touching & direction) > Collision.NONE;
}
/**
* Handy for checking if this object is just landed on a particular surface.
*
* @param Direction Any of the collision flags (e.g. LEFT, FLOOR, etc).
*
* @return Whether the object just landed on (any of) the specified surface(s) this frame.
* Handy function for checking if this object just landed on a particular surface.
*
* @param Direction {number} Any of the collision flags (e.g. LEFT, FLOOR, etc).
*
* @returns {boolean} Whether the object just landed on any specicied surfaces.
*/
public justTouched(Direction: number): bool {
return ((this.touching & Direction) > Collision.NONE) && ((this.wasTouching & Direction) <= Collision.NONE);
public justTouched(direction: number): bool {
return ((this.touching & direction) > Collision.NONE) && ((this.wasTouching & direction) <= Collision.NONE);
}
/**
* Reduces the "health" variable of this sprite by the amount specified in Damage.
* Calls kill() if health drops to or below zero.
*
* @param Damage How much health to take away (use a negative number to give a health bonus).
*
* @param Damage {number} How much health to take away (use a negative number to give a health bonus).
*/
public hurt(Damage: number) {
public hurt(damage: number) {
this.health = this.health - Damage;
this.health = this.health - damage;
if (this.health <= 0)
{
@@ -532,6 +769,11 @@ module Phaser {
* Set the world bounds that this GameObject can exist within. By default a GameObject can exist anywhere
* in the world. But by setting the bounds (which are given in world dimensions, not screen dimensions)
* it can be stopped from leaving the world, or a section of it.
*
* @param x {number} x position of the bound
* @param y {number} y position of the bound
* @param width {number} width of its bound
* @param height {number} height of its bound
*/
public setBounds(x: number, y: number, width: number, height: number) {
@@ -539,8 +781,22 @@ module Phaser {
}
/**
* Set the world bounds that this GameObject can exist within based on the size of the current game world.
*
* @param action {number} The action to take if the object hits the world bounds, either OUT_OF_BOUNDS_KILL or OUT_OF_BOUNDS_STOP
*/
public setBoundsFromWorld(action?: number = GameObject.OUT_OF_BOUNDS_STOP) {
this.setBounds(this._game.world.bounds.x, this._game.world.bounds.y, this._game.world.bounds.width, this._game.world.bounds.height);
this.outOfBoundsAction = action;
}
/**
* If you do not wish this object to be visible to a specific camera, pass the camera here.
*
* @param camera {Camera} The specific camera.
*/
public hideFromCamera(camera: Camera) {
@@ -551,6 +807,12 @@ module Phaser {
}
/**
* Make this object only visible to a specific camera.
*
* @param camera {Camera} The camera you wish it to be visible.
*/
public showToCamera(camera: Camera) {
if (this.cameraBlacklist.indexOf(camera.ID) !== -1)
@@ -560,30 +822,42 @@ module Phaser {
}
/**
* This clears the camera black list, making the GameObject visible to all cameras.
*/
public clearCameraList() {
this.cameraBlacklist.length = 0;
}
/**
* Clean up memory.
*/
public destroy() {
}
public setPosition(x: number, y: number) {
this.x = x;
this.y = y;
}
public get x(): number {
return this.bounds.x;
return this.frameBounds.x;
}
public set x(value: number) {
this.bounds.x = value;
this.frameBounds.x = value;
}
public get y(): number {
return this.bounds.y;
return this.frameBounds.y;
}
public set y(value: number) {
this.bounds.y = value;
this.frameBounds.y = value;
}
public get rotation(): number {
@@ -603,19 +877,19 @@ module Phaser {
}
public set width(value:number) {
this.bounds.width = value;
this.frameBounds.width = value;
}
public set height(value:number) {
this.bounds.height = value;
this.frameBounds.height = value;
}
public get width(): number {
return this.bounds.width;
return this.frameBounds.width;
}
public get height(): number {
return this.bounds.height;
return this.frameBounds.height;
}
}
+40
View File
@@ -0,0 +1,40 @@
/// <reference path="../Game.d.ts" />
module Phaser {
class GeomSprite extends GameObject {
constructor(game: Game, x?: number, y?: number);
private _dx;
private _dy;
private _dw;
private _dh;
public type: number;
static UNASSIGNED: number;
static CIRCLE: number;
static LINE: number;
static POINT: number;
static RECTANGLE: number;
public circle: Circle;
public line: Line;
public point: Point;
public rect: Rectangle;
public renderOutline: bool;
public renderFill: bool;
public lineWidth: number;
public lineColor: string;
public fillColor: string;
public loadCircle(circle: Circle): GeomSprite;
public loadLine(line: Line): GeomSprite;
public loadPoint(point: Point): GeomSprite;
public loadRectangle(rect: Rectangle): GeomSprite;
public createCircle(diameter: number): GeomSprite;
public createLine(x: number, y: number): GeomSprite;
public createPoint(): GeomSprite;
public createRectangle(width: number, height: number): GeomSprite;
public refresh(): void;
public update(): void;
public inCamera(camera: Rectangle): bool;
public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number): bool;
public renderPoint(offsetX, offsetY, point, size): void;
public renderDebugInfo(x: number, y: number, color?: string): void;
public collide(source: GeomSprite): bool;
}
}
+262 -77
View File
@@ -1,4 +1,5 @@
/// <reference path="../Game.ts" />
/// <reference path="../geom/Polygon.ts" />
/**
* Phaser - GeomSprite
@@ -12,6 +13,14 @@ module Phaser {
export class GeomSprite extends GameObject {
/**
* GeomSprite constructor
* Create a new <code>GeomSprite</code>.
*
* @param game {Phaser.Game} Current game instance.
* @param [x] {number} the initial x position of the sprite.
* @param [y] {number} the initial y position of the sprite.
*/
constructor(game: Game, x?: number = 0, y?: number = 0) {
super(game, x, y);
@@ -28,26 +37,112 @@ module Phaser {
private _dw: number = 0;
private _dh: number = 0;
/**
* Geom type of this sprite. (available: UNASSIGNED, CIRCLE, LINE, POINT, RECTANGLE)
* @type {number}
*/
public type: number = 0;
/**
* Not completely set yet. (the default type)
*/
public static UNASSIGNED: number = 0;
/**
* Circle.
* @type {number}
*/
public static CIRCLE: number = 1;
/**
* Line.
* @type {number}
*/
public static LINE: number = 2;
/**
* Point.
* @type {number}
*/
public static POINT: number = 3;
/**
* Rectangle.
* @type {number}
*/
public static RECTANGLE: number = 4;
/**
* Polygon.
* @type {number}
*/
public static POLYGON: number = 5;
/**
* Circle shape container. A Circle instance.
* @type {Circle}
*/
public circle: Circle;
/**
* Line shape container. A Line instance.
* @type {Line}
*/
public line: Line;
/**
* Point shape container. A Point instance.
* @type {Point}
*/
public point: Point;
/**
* Rectangle shape container. A Rectangle instance.
* @type {Rectangle}
*/
public rect: Rectangle;
/**
* Polygon shape container. A Polygon instance.
* @type {Polygon}
*/
public polygon: Polygon;
/**
* Render outline of this sprite or not. (default is true)
* @type {boolean}
*/
public renderOutline: bool = true;
/**
* Fill the shape or not. (default is true)
* @type {boolean}
*/
public renderFill: bool = true;
/**
* Width of outline. (default is 1)
* @type {number}
*/
public lineWidth: number = 1;
/**
* Width of outline. (default is 1)
* @type {number}
*/
public lineColor: string = 'rgb(0,255,0)';
/**
* The color of the filled area in rgb or rgba string format
* @type {string} Defaults to rgb(0,100,0) - a green color
*/
public fillColor: string = 'rgb(0,100,0)';
/**
* Just like Sprite.loadGraphic(), this will load a circle and set its shape to Circle.
* @param circle {Circle} Circle geometry define.
* @return {GeomSprite} GeomSprite instance itself.
*/
loadCircle(circle:Circle): GeomSprite {
this.refresh();
@@ -57,7 +152,11 @@ module Phaser {
}
/**
* Just like Sprite.loadGraphic(), this will load a line and set its shape to Line.
* @param line {Line} Line geometry define.
* @return {GeomSprite} GeomSprite instance itself.
*/
loadLine(line:Line): GeomSprite {
this.refresh();
@@ -67,6 +166,11 @@ module Phaser {
}
/**
* Just like Sprite.loadGraphic(), this will load a point and set its shape to Point.
* @param point {Point} Point geometry define.
* @return {GeomSprite} GeomSprite instance itself.
*/
loadPoint(point:Point): GeomSprite {
this.refresh();
@@ -76,6 +180,11 @@ module Phaser {
}
/**
* Just like Sprite.loadGraphic(), this will load a rect and set its shape to Rectangle.
* @param rect {Rectangle} Rectangle geometry define.
* @return {GeomSprite} GeomSprite instance itself.
*/
loadRectangle(rect:Rectangle): GeomSprite {
this.refresh();
@@ -85,47 +194,87 @@ module Phaser {
}
/**
* Create a circle shape with specific diameter.
* @param diameter {number} Diameter of the circle.
* @return {GeomSprite} GeomSprite instance itself.
*/
createCircle(diameter: number): GeomSprite {
this.refresh();
this.circle = new Circle(this.x, this.y, diameter);
this.type = GeomSprite.CIRCLE;
this.bounds.setTo(this.circle.x - this.circle.radius, this.circle.y - this.circle.radius, this.circle.diameter, this.circle.diameter);
this.frameBounds.setTo(this.circle.x - this.circle.radius, this.circle.y - this.circle.radius, this.circle.diameter, this.circle.diameter);
return this;
}
/**
* Create a line shape with specific end point.
* @param x {number} X position of the end point.
* @param y {number} Y position of the end point.
* @return {GeomSprite} GeomSprite instance itself.
*/
createLine(x: number, y: number): GeomSprite {
this.refresh();
this.line = new Line(this.x, this.y, x, y);
this.type = GeomSprite.LINE;
this.bounds.setTo(this.x, this.y, this.line.width, this.line.height);
this.frameBounds.setTo(this.x, this.y, this.line.width, this.line.height);
return this;
}
/**
* Create a point shape at spriter's position.
* @return {GeomSprite} GeomSprite instance itself.
*/
createPoint(): GeomSprite {
this.refresh();
this.point = new Point(this.x, this.y);
this.type = GeomSprite.POINT;
this.bounds.width = 1;
this.bounds.height = 1;
this.frameBounds.width = 1;
this.frameBounds.height = 1;
return this;
}
/**
* Create a rectangle shape of the given width and height size
* @param width {Number} Width of the rectangle
* @param height {Number} Height of the rectangle
* @return {GeomSprite} GeomSprite instance.
*/
createRectangle(width: number, height: number): GeomSprite {
this.refresh();
this.rect = new Rectangle(this.x, this.y, width, height);
this.type = GeomSprite.RECTANGLE;
this.bounds.copyFrom(this.rect);
this.frameBounds.copyFrom(this.rect);
return this;
}
/**
* Create a polygon object
* @param width {Number} Width of the rectangle
* @param height {Number} Height of the rectangle
* @return {GeomSprite} GeomSprite instance.
*/
createPolygon(points?: Vector2[] = []): GeomSprite {
this.refresh();
this.polygon = new Polygon(new Vector2(this.x, this.y), points);
this.type = GeomSprite.POLYGON;
//this.frameBounds.copyFrom(this.rect);
return this;
}
/**
* Destroy all geom shapes of this sprite.
*/
refresh() {
this.circle = null;
@@ -135,6 +284,9 @@ module Phaser {
}
/**
* Update bounds.
*/
update() {
// Update bounds and position?
@@ -146,14 +298,14 @@ module Phaser {
{
this.circle.x = this.x;
this.circle.y = this.y;
this.bounds.width = this.circle.diameter;
this.bounds.height = this.circle.diameter;
this.frameBounds.width = this.circle.diameter;
this.frameBounds.height = this.circle.diameter;
}
else if (this.type == GeomSprite.LINE)
{
this.line.x1 = this.x;
this.line.y1 = this.y;
this.bounds.setTo(this.x, this.y, this.line.width, this.line.height);
this.frameBounds.setTo(this.x, this.y, this.line.width, this.line.height);
}
else if (this.type == GeomSprite.POINT)
{
@@ -164,29 +316,41 @@ module Phaser {
{
this.rect.x = this.x;
this.rect.y = this.y;
this.bounds.copyFrom(this.rect);
this.frameBounds.copyFrom(this.rect);
}
}
/**
* Check whether this object is visible in a specific camera rectangle.
* @param camera {Rectangle} The rectangle you want to check.
* @return {boolean} Return true if bounds of this sprite intersects the given rectangle, otherwise return false.
*/
public inCamera(camera: Rectangle): bool {
if (this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0)
{
this._dx = this.bounds.x - (camera.x * this.scrollFactor.x);
this._dy = this.bounds.y - (camera.y * this.scrollFactor.x);
this._dw = this.bounds.width * this.scale.x;
this._dh = this.bounds.height * this.scale.y;
this._dx = this.frameBounds.x - (camera.x * this.scrollFactor.x);
this._dy = this.frameBounds.y - (camera.y * this.scrollFactor.x);
this._dw = this.frameBounds.width * this.scale.x;
this._dh = this.frameBounds.height * this.scale.y;
return (camera.right > this._dx) && (camera.x < this._dx + this._dw) && (camera.bottom > this._dy) && (camera.y < this._dy + this._dh);
}
else
{
return camera.intersects(this.bounds);
return camera.intersects(this.frameBounds);
}
}
/**
* Render this sprite to specific camera. Called by game loop after update().
* @param camera {Camera} Camera this sprite will be rendered to.
* @cameraOffsetX {number} X offset to the camera.
* @cameraOffsetY {number} Y offset to the camera.
* @return {boolean} Return false if not rendered, otherwise return true.
*/
public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number): bool {
// Render checks
@@ -198,21 +362,14 @@ module Phaser {
// Alpha
if (this.alpha !== 1)
{
var globalAlpha = this._game.stage.context.globalAlpha;
this._game.stage.context.globalAlpha = this.alpha;
var globalAlpha = this.context.globalAlpha;
this.context.globalAlpha = this.alpha;
}
this._dx = cameraOffsetX + (this.bounds.x - camera.worldView.x);
this._dy = cameraOffsetY + (this.bounds.y - camera.worldView.y);
this._dw = this.bounds.width * this.scale.x;
this._dh = this.bounds.height * this.scale.y;
// Circles are drawn center based
if (this.type == GeomSprite.CIRCLE)
{
this._dx += this.circle.radius;
this._dy += this.circle.radius;
}
this._dx = cameraOffsetX + (this.frameBounds.x - camera.worldView.x);
this._dy = cameraOffsetY + (this.frameBounds.y - camera.worldView.y);
this._dw = this.frameBounds.width * this.scale.x;
this._dh = this.frameBounds.height * this.scale.y;
// Apply camera difference
if (this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0)
@@ -225,9 +382,9 @@ module Phaser {
/*
if (this.angle !== 0)
{
this._game.stage.context.save();
this._game.stage.context.translate(this._dx + (this._dw / 2) - this.origin.x, this._dy + (this._dh / 2) - this.origin.y);
this._game.stage.context.rotate(this.angle * (Math.PI / 180));
this.context.save();
this.context.translate(this._dx + (this._dw / 2) - this.origin.x, this._dy + (this._dh / 2) - this.origin.y);
this.context.rotate(this.angle * (Math.PI / 180));
this._dx = -(this._dw / 2);
this._dy = -(this._dh / 2);
}
@@ -241,12 +398,12 @@ module Phaser {
this._game.stage.saveCanvasValues();
// Debug
//this._game.stage.context.fillStyle = 'rgba(255,0,0,0.5)';
//this._game.stage.context.fillRect(this.bounds.x, this.bounds.y, this.bounds.width, this.bounds.height);
//this.context.fillStyle = 'rgba(255,0,0,0.5)';
//this.context.fillRect(this.frameBounds.x, this.frameBounds.y, this.frameBounds.width, this.frameBounds.height);
this._game.stage.context.lineWidth = this.lineWidth;
this._game.stage.context.strokeStyle = this.lineColor;
this._game.stage.context.fillStyle = this.fillColor;
this.context.lineWidth = this.lineWidth;
this.context.strokeStyle = this.lineColor;
this.context.fillStyle = this.fillColor;
if (this._game.stage.fillStyle !== this.fillColor)
{
@@ -255,61 +412,74 @@ module Phaser {
// Primitive Renderer
if (this.type == GeomSprite.CIRCLE)
{
this._game.stage.context.beginPath();
this._game.stage.context.arc(this._dx, this._dy, this.circle.radius, 0, Math.PI * 2);
this._game.stage.context.stroke();
this.context.beginPath();
this.context.arc(this._dx, this._dy, this.circle.radius, 0, Math.PI * 2);
if (this.renderOutline)
{
this.context.stroke();
}
if (this.renderFill)
{
this._game.stage.context.fill();
this.context.fill();
}
this._game.stage.context.closePath();
this.context.closePath();
}
else if (this.type == GeomSprite.LINE)
{
this._game.stage.context.beginPath();
this._game.stage.context.moveTo(this._dx, this._dy);
this._game.stage.context.lineTo(this.line.x2, this.line.y2);
this._game.stage.context.stroke();
this._game.stage.context.closePath();
this.context.beginPath();
this.context.moveTo(this._dx, this._dy);
this.context.lineTo(this.line.x2, this.line.y2);
this.context.stroke();
this.context.closePath();
}
else if (this.type == GeomSprite.POINT)
{
this._game.stage.context.fillRect(this._dx, this._dy, 2, 2);
this.context.fillRect(this._dx, this._dy, 2, 2);
}
else if (this.type == GeomSprite.RECTANGLE)
{
// We can use the faster fillRect if we don't need the outline
if (this.renderOutline == false)
{
this._game.stage.context.fillRect(this._dx, this._dy, this.rect.width, this.rect.height);
this.context.fillRect(this._dx, this._dy, this.rect.width, this.rect.height);
}
else
{
this._game.stage.context.beginPath();
this._game.stage.context.rect(this._dx, this._dy, this.rect.width, this.rect.height);
this._game.stage.context.stroke();
this.context.beginPath();
this.context.rect(this._dx, this._dy, this.rect.width, this.rect.height);
this.context.stroke();
if (this.renderFill)
{
this._game.stage.context.fill();
this.context.fill();
}
this._game.stage.context.closePath();
this.context.closePath();
}
// And now the edge points
this._game.stage.context.fillStyle = 'rgb(255,255,255)';
this.renderPoint(this._dx, this._dy, this.rect.topLeft, 2);
this.renderPoint(this._dx, this._dy, this.rect.topCenter, 2);
this.renderPoint(this._dx, this._dy, this.rect.topRight, 2);
this.renderPoint(this._dx, this._dy, this.rect.leftCenter, 2);
this.renderPoint(this._dx, this._dy, this.rect.center, 2);
this.renderPoint(this._dx, this._dy, this.rect.rightCenter, 2);
this.renderPoint(this._dx, this._dy, this.rect.bottomLeft, 2);
this.renderPoint(this._dx, this._dy, this.rect.bottomCenter, 2);
this.renderPoint(this._dx, this._dy, this.rect.bottomRight, 2);
this.context.fillStyle = 'rgb(255,255,255)';
//this.renderPoint(this.rect.topLeft, this._dx, this._dy, 2);
//this.renderPoint(this.rect.topCenter, this._dx, this._dy, 2);
//this.renderPoint(this.rect.topRight, this._dx, this._dy, 2);
//this.renderPoint(this.rect.leftCenter, this._dx, this._dy, 2);
//this.renderPoint(this.rect.center, this._dx, this._dy, 2);
//this.renderPoint(this.rect.rightCenter, this._dx, this._dy, 2);
//this.renderPoint(this.rect.bottomLeft, this._dx, this._dy, 2);
//this.renderPoint(this.rect.bottomCenter, this._dx, this._dy, 2);
//this.renderPoint(this.rect.bottomRight, this._dx, this._dy, 2);
this.renderPoint(this.rect.topLeft, 0, 0, 2);
this.renderPoint(this.rect.topCenter, 0, 0, 2);
this.renderPoint(this.rect.topRight, 0, 0, 2);
this.renderPoint(this.rect.leftCenter, 0, 0, 2);
this.renderPoint(this.rect.center, 0, 0, 2);
this.renderPoint(this.rect.rightCenter, 0, 0, 2);
this.renderPoint(this.rect.bottomLeft, 0, 0, 2);
this.renderPoint(this.rect.bottomCenter, 0, 0, 2);
this.renderPoint(this.rect.bottomRight, 0, 0, 2);
}
@@ -317,39 +487,54 @@ module Phaser {
if (this.rotation !== 0)
{
this._game.stage.context.translate(0, 0);
this._game.stage.context.restore();
this.context.translate(0, 0);
this.context.restore();
}
if (globalAlpha > -1)
{
this._game.stage.context.globalAlpha = globalAlpha;
this.context.globalAlpha = globalAlpha;
}
return true;
}
public renderPoint(offsetX, offsetY, point, size) {
/**
* Render a point of geometry.
* @param point {Point} Position of the point.
* @param offsetX {number} X offset to its position.
* @param offsetY {number} Y offset to its position.
* @param [size] {number} point size.
*/
public renderPoint(point, offsetX?: number = 0, offsetY?: number = 0, size?: number = 1) {
offsetX = 0;
offsetY = 0;
this._game.stage.context.fillRect(offsetX + point.x, offsetY + point.y, 1, 1);
this.context.fillRect(offsetX + point.x, offsetY + point.y, size, size);
}
/**
* Render debug infos. (this method does not work now)
* @param x {number} X position of the debug info to be rendered.
* @param y {number} Y position of the debug info to be rendered.
* @param [color] {number} color of the debug info to be rendered. (format is css color string)
*/
public renderDebugInfo(x: number, y: number, color?: string = 'rgb(255,255,255)') {
//this._game.stage.context.fillStyle = color;
//this._game.stage.context.fillText('Sprite: ' + this.name + ' (' + this.bounds.width + ' x ' + this.bounds.height + ')', x, y);
//this._game.stage.context.fillText('x: ' + this.bounds.x.toFixed(1) + ' y: ' + this.bounds.y.toFixed(1) + ' rotation: ' + this.angle.toFixed(1), x, y + 14);
//this._game.stage.context.fillText('dx: ' + this._dx.toFixed(1) + ' dy: ' + this._dy.toFixed(1) + ' dw: ' + this._dw.toFixed(1) + ' dh: ' + this._dh.toFixed(1), x, y + 28);
//this._game.stage.context.fillText('sx: ' + this._sx.toFixed(1) + ' sy: ' + this._sy.toFixed(1) + ' sw: ' + this._sw.toFixed(1) + ' sh: ' + this._sh.toFixed(1), x, y + 42);
//this.context.fillStyle = color;
//this.context.fillText('Sprite: ' + this.name + ' (' + this.frameBounds.width + ' x ' + this.frameBounds.height + ')', x, y);
//this.context.fillText('x: ' + this.frameBounds.x.toFixed(1) + ' y: ' + this.frameBounds.y.toFixed(1) + ' rotation: ' + this.angle.toFixed(1), x, y + 14);
//this.context.fillText('dx: ' + this._dx.toFixed(1) + ' dy: ' + this._dy.toFixed(1) + ' dw: ' + this._dw.toFixed(1) + ' dh: ' + this._dh.toFixed(1), x, y + 28);
//this.context.fillText('sx: ' + this._sx.toFixed(1) + ' sy: ' + this._sy.toFixed(1) + ' sw: ' + this._sw.toFixed(1) + ' sh: ' + this._sh.toFixed(1), x, y + 42);
}
// Gives a basic boolean response to a geometric collision.
// If you need the details of the collision use the Collision functions instead and inspect the IntersectResult object.
/**
* Gives a basic boolean response to a geometric collision.
* If you need the details of the collision use the Collision functions instead and inspect the IntersectResult object.
* @param source {GeomSprite} Sprite you want to check.
* @return {boolean} Whether they overlaps or not.
*/
public collide(source: GeomSprite): bool {
// Circle vs. Circle
+11
View File
@@ -0,0 +1,11 @@
/// <reference path="../Game.d.ts" />
/// <reference path="Sprite.d.ts" />
module Phaser {
class Particle extends Sprite {
constructor(game: Game);
public lifespan: number;
public friction: number;
public update(): void;
public onEmit(): void;
}
}
+2
View File
@@ -22,6 +22,7 @@ module Phaser {
this.lifespan = 0;
this.friction = 500;
}
/**
@@ -43,6 +44,7 @@ module Phaser {
* be dead yet, and then has some special bounce behavior if there is some gravity on it.
*/
public update() {
//lifespan behavior
if (this.lifespan <= 0)
{
+22
View File
@@ -0,0 +1,22 @@
/// <reference path="../Game.d.ts" />
/// <reference path="../geom/Quad.d.ts" />
module Phaser {
class ScrollRegion {
constructor(x: number, y: number, width: number, height: number, speedX: number, speedY: number);
private _A;
private _B;
private _C;
private _D;
private _bounds;
private _scroll;
private _anchorWidth;
private _anchorHeight;
private _inverseWidth;
private _inverseHeight;
public visible: bool;
public scrollSpeed: MicroPoint;
public update(delta: number): void;
public render(context: CanvasRenderingContext2D, texture, dx: number, dy: number, dw: number, dh: number): void;
private crop(context, texture, srcX, srcY, srcW, srcH, destX, destY, destW, destH, offsetX, offsetY);
}
}
+49 -1
View File
@@ -10,8 +10,19 @@
module Phaser {
export class ScrollRegion{
export class ScrollRegion {
/**
* ScrollRegion constructor
* Create a new <code>ScrollRegion</code>.
*
* @param x {number} X position in world coordinate.
* @param y {number} Y position in world coordinate.
* @param width {number} Width of this object.
* @param height {number} Height of this object.
* @param speedX {number} X-axis scrolling speed.
* @param speedY {number} Y-axis scrolling speed.
*/
constructor(x: number, y: number, width: number, height: number, speedX:number, speedY:number) {
// Our seamless scrolling quads
@@ -38,9 +49,22 @@ module Phaser {
private _inverseWidth: number = 0;
private _inverseHeight: number = 0;
/**
* Will this region be rendered? (default to true)
* @type {boolean}
*/
public visible: bool = true;
/**
* Region scrolling speed.
* @type {MicroPoint}
*/
public scrollSpeed: MicroPoint;
/**
* Update region scrolling with tick time.
* @param delta {number} Elapsed time since last update.
*/
public update(delta: number) {
this._scroll.x += this.scrollSpeed.x;
@@ -102,6 +126,15 @@ module Phaser {
}
/**
* Render this region to specific context.
* @param context {CanvasRenderingContext2D} Canvas context this region will be rendered to.
* @param texture {object} The texture to be rendered.
* @param dx {number} X position in world coordinate.
* @param dy {number} Y position in world coordinate.
* @param width {number} Width of this region to be rendered.
* @param height {number} Height of this region to be rendered.
*/
public render(context:CanvasRenderingContext2D, texture, dx: number, dy: number, dw: number, dh: number) {
if (this.visible == false)
@@ -126,6 +159,21 @@ module Phaser {
}
/**
* Crop part of the texture and render it to the given context.
* @param context {CanvasRenderingContext2D} Canvas context the texture will be rendered to.
* @param texture {object} Texture to be rendered.
* @param srcX {number} Target region top-left x coordinate in the texture.
* @param srcX {number} Target region top-left y coordinate in the texture.
* @param srcW {number} Target region width in the texture.
* @param srcH {number} Target region height in the texture.
* @param destX {number} Render region top-left x coordinate in the context.
* @param destX {number} Render region top-left y coordinate in the context.
* @param destW {number} Target region width in the context.
* @param destH {number} Target region height in the context.
* @param offsetX {number} X offset to the context.
* @param offsetY {number} Y offset to the context.
*/
private crop(context, texture, srcX, srcY, srcW, srcH, destX, destY, destW, destH, offsetX, offsetY) {
offsetX += destX;
+23
View File
@@ -0,0 +1,23 @@
/// <reference path="../Game.d.ts" />
/// <reference path="../geom/Quad.d.ts" />
/// <reference path="ScrollRegion.d.ts" />
module Phaser {
class ScrollZone extends GameObject {
constructor(game: Game, key: string, x?: number, y?: number, width?: number, height?: number);
private _texture;
private _dynamicTexture;
private _dx;
private _dy;
private _dw;
private _dh;
public currentRegion: ScrollRegion;
public regions: ScrollRegion[];
public flipped: bool;
public addRegion(x: number, y: number, width: number, height: number, speedX?: number, speedY?: number): ScrollRegion;
public setSpeed(x: number, y: number): ScrollZone;
public update(): void;
public inCamera(camera: Rectangle): bool;
public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number): bool;
private createRepeatingTexture(regionWidth, regionHeight);
}
}
+105 -20
View File
@@ -15,6 +15,17 @@ module Phaser {
export class ScrollZone extends GameObject {
/**
* ScrollZone constructor
* Create a new <code>ScrollZone</code>.
*
* @param game {Phaser.Game} Current game instance.
* @param key {string} Asset key for image texture of this object.
* @param x {number} X position in world coordinate.
* @param y {number} Y position in world coordinate.
* @param [width] {number} width of this object.
* @param [height] {number} height of this object.
*/
constructor(game: Game, key:string, x: number = 0, y: number = 0, width?: number = 0, height?: number = 0) {
super(game, x, y, width, height);
@@ -49,19 +60,69 @@ module Phaser {
}
/**
* Texture of this object.
*/
private _texture;
/**
* If this zone is larger than texture image, this will be filled with a pattern of texture.
* @type {DynamicTexture}
*/
private _dynamicTexture: DynamicTexture = null;
// local rendering related temp vars to help avoid gc spikes
/**
* Local rendering related temp vars to help avoid gc spikes.
* @type {number}
*/
private _dx: number = 0;
/**
* Local rendering related temp vars to help avoid gc spikes.
* @type {number}
*/
private _dy: number = 0;
/**
* Local rendering related temp vars to help avoid gc spikes.
* @type {number}
*/
private _dw: number = 0;
/**
* Local rendering related temp vars to help avoid gc spikes.
* @type {number}
*/
private _dh: number = 0;
/**
* Current region this zone is scrolling.
* @type {ScrollRegion}
*/
public currentRegion: ScrollRegion;
/**
* Array contains all added regions.
* @type {ScrollRegion[]}
*/
public regions: ScrollRegion[];
/**
* Flip this zone vertically? (default to false)
* @type {boolean}
*/
public flipped: bool = false;
/**
* Add a new region to this zone.
* @param x {number} X position of the new region.
* @param y {number} Y position of the new region.
* @param width {number} Width of the new region.
* @param height {number} Height of the new region.
* @param [speedX] {number} x-axis scrolling speed.
* @param [speedY] {number} y-axis scrolling speed.
* @return {ScrollRegion} The newly added region.
*/
public addRegion(x: number, y: number, width: number, height: number, speedX?:number = 0, speedY?:number = 0):ScrollRegion {
if (x > this.width || y > this.height || x < 0 || y < 0 || (x + width) > this.width || (y + height) > this.height)
@@ -78,6 +139,11 @@ module Phaser {
}
/**
* Set scrolling speed of current region.
* @param x {number} X speed of current region.
* @param y {number} Y speed of current region.
*/
public setSpeed(x: number, y: number) {
if (this.currentRegion)
@@ -89,6 +155,9 @@ module Phaser {
}
/**
* Update regions.
*/
public update() {
for (var i = 0; i < this.regions.length; i++)
@@ -98,24 +167,36 @@ module Phaser {
}
/**
* Check whether this zone is visible in a specific camera rectangle.
* @param camera {Rectangle} The rectangle you want to check.
* @return {boolean} Return true if bound of this zone intersects the given rectangle, otherwise return false.
*/
public inCamera(camera: Rectangle): bool {
if (this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0)
{
this._dx = this.bounds.x - (camera.x * this.scrollFactor.x);
this._dy = this.bounds.y - (camera.y * this.scrollFactor.x);
this._dw = this.bounds.width * this.scale.x;
this._dh = this.bounds.height * this.scale.y;
this._dx = this.frameBounds.x - (camera.x * this.scrollFactor.x);
this._dy = this.frameBounds.y - (camera.y * this.scrollFactor.x);
this._dw = this.frameBounds.width * this.scale.x;
this._dh = this.frameBounds.height * this.scale.y;
return (camera.right > this._dx) && (camera.x < this._dx + this._dw) && (camera.bottom > this._dy) && (camera.y < this._dy + this._dh);
}
else
{
return camera.intersects(this.bounds, this.bounds.length);
return camera.intersects(this.frameBounds, this.frameBounds.length);
}
}
/**
* Render this zone object to a specific camera.
* @param camera {Camera} The camera this object will be render to.
* @param cameraOffsetX {number} X offset of camera.
* @param cameraOffsetY {number} Y offset of camera.
* @return Return false if not rendered, otherwise return true.
*/
public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number) {
// Render checks
@@ -127,14 +208,14 @@ module Phaser {
// Alpha
if (this.alpha !== 1)
{
var globalAlpha = this._game.stage.context.globalAlpha;
this._game.stage.context.globalAlpha = this.alpha;
var globalAlpha = this.context.globalAlpha;
this.context.globalAlpha = this.alpha;
}
this._dx = cameraOffsetX + (this.bounds.topLeft.x - camera.worldView.x);
this._dy = cameraOffsetY + (this.bounds.topLeft.y - camera.worldView.y);
this._dw = this.bounds.width * this.scale.x;
this._dh = this.bounds.height * this.scale.y;
this._dx = cameraOffsetX + (this.frameBounds.topLeft.x - camera.worldView.x);
this._dy = cameraOffsetY + (this.frameBounds.topLeft.y - camera.worldView.y);
this._dw = this.frameBounds.width * this.scale.x;
this._dh = this.frameBounds.height * this.scale.y;
// Apply camera difference
if (this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0)
@@ -146,12 +227,12 @@ module Phaser {
// Rotation - needs to work from origin point really, but for now from center
if (this.angle !== 0 || this.flipped == true)
{
this._game.stage.context.save();
this._game.stage.context.translate(this._dx + (this._dw / 2), this._dy + (this._dh / 2));
this.context.save();
this.context.translate(this._dx + (this._dw / 2), this._dy + (this._dh / 2));
if (this.angle !== 0)
{
this._game.stage.context.rotate(this.angle * (Math.PI / 180));
this.context.rotate(this.angle * (Math.PI / 180));
}
this._dx = -(this._dw / 2);
@@ -159,7 +240,7 @@ module Phaser {
if (this.flipped == true)
{
this._game.stage.context.scale(-1, 1);
this.context.scale(-1, 1);
}
}
@@ -172,23 +253,27 @@ module Phaser {
{
if (this._dynamicTexture)
{
this.regions[i].render(this._game.stage.context, this._dynamicTexture.canvas, this._dx, this._dy, this._dw, this._dh);
this.regions[i].render(this.context, this._dynamicTexture.canvas, this._dx, this._dy, this._dw, this._dh);
}
else
{
this.regions[i].render(this._game.stage.context, this._texture, this._dx, this._dy, this._dw, this._dh);
this.regions[i].render(this.context, this._texture, this._dx, this._dy, this._dw, this._dh);
}
}
if (globalAlpha > -1)
{
this._game.stage.context.globalAlpha = globalAlpha;
this.context.globalAlpha = globalAlpha;
}
return true;
}
/**
* Create repeating texture with _texture, and store it into the _dynamicTexture.
* Used to create texture when texture image is small than size of the zone.
*/
private createRepeatingTexture(regionWidth: number, regionHeight: number) {
// Work out how many we'll need of the source image to make it tile properly
+34
View File
@@ -0,0 +1,34 @@
/// <reference path="../Game.d.ts" />
/// <reference path="../AnimationManager.d.ts" />
/// <reference path="GameObject.d.ts" />
/// <reference path="../system/Camera.d.ts" />
module Phaser {
class Sprite extends GameObject {
constructor(game: Game, x?: number, y?: number, key?: string);
private _texture;
private _dynamicTexture;
private _sx;
private _sy;
private _sw;
private _sh;
private _dx;
private _dy;
private _dw;
private _dh;
public animations: AnimationManager;
public renderDebug: bool;
public renderDebugColor: string;
public renderDebugPointColor: string;
public flipped: bool;
public loadGraphic(key: string): Sprite;
public loadDynamicTexture(texture: DynamicTexture): Sprite;
public makeGraphic(width: number, height: number, color?: number): Sprite;
public inCamera(camera: Rectangle): bool;
public postUpdate(): void;
public frame : number;
public frameName : string;
public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number): bool;
private renderBounds(camera, cameraOffsetX, cameraOffsetY);
public renderDebugInfo(x: number, y: number, color?: string): void;
}
}
+189 -82
View File
@@ -14,6 +14,15 @@ module Phaser {
export class Sprite extends GameObject {
/**
* Sprite constructor
* Create a new <code>Sprite</code>.
*
* @param game {Phaser.Game} Current game instance.
* @param [x] {number} the initial x position of the sprite.
* @param [y] {number} the initial y position of the sprite.
* @param [key] {string} Key of the graphic you want to load for this sprite.
*/
constructor(game: Game, x?: number = 0, y?: number = 0, key?: string = null) {
super(game, x, y);
@@ -24,17 +33,26 @@ module Phaser {
if (key !== null)
{
this.cacheKey = key;
this.loadGraphic(key);
}
else
{
this.bounds.width = 16;
this.bounds.height = 16;
this.frameBounds.width = 16;
this.frameBounds.height = 16;
}
}
/**
* Texture of this sprite to be rendered.
*/
private _texture;
/**
* Texture of this sprite is DynamicTexture? (default to false)
* @type {boolean}
*/
private _dynamicTexture: bool = false;
// local rendering related temp vars to help avoid gc spikes
@@ -47,27 +65,76 @@ module Phaser {
private _dw: number = 0;
private _dh: number = 0;
/**
* This manages animations of the sprite. You can modify animations though it. (see AnimationManager)
* @type AnimationManager
*/
public animations: AnimationManager;
/**
* The cache key that was used for this texture (if any)
*/
public cacheKey: string;
/**
* Render bound of this sprite for debugging? (default to false)
* @type {boolean}
*/
public renderDebug: bool = false;
/**
* Color of the Sprite when no image is present. Format is a css color string.
* @type {string}
*/
public fillColor: string = 'rgb(255,255,255)';
/**
* Color of bound when render debug. (see renderDebug) Format is a css color string.
* @type {string}
*/
public renderDebugColor: string = 'rgba(0,255,0,0.5)';
/**
* Color of points when render debug. (see renderDebug) Format is a css color string.
* @type {string}
*/
public renderDebugPointColor: string = 'rgba(255,255,255,1)';
/**
* Flip the graphic horizontally? (defaults to false)
* @type {boolean}
*/
public flipped: bool = false;
public loadGraphic(key: string): Sprite {
/**
* Load graphic for this sprite. (graphic can be SpriteSheet or Texture)
* @param key {string} Key of the graphic you want to load for this sprite.
* @param clearAnimations {boolean} If this Sprite has a set of animation data already loaded you can choose to keep or clear it with this boolean
* @return {Sprite} Sprite instance itself.
*/
public loadGraphic(key: string, clearAnimations: bool = true): Sprite {
if (clearAnimations && this.animations.frameData !== null)
{
this.animations.destroy();
}
if (this._game.cache.getImage(key) !== null)
{
if (this._game.cache.isSpriteSheet(key) == false)
{
this._texture = this._game.cache.getImage(key);
this.bounds.width = this._texture.width;
this.bounds.height = this._texture.height;
this.frameBounds.width = this._texture.width;
this.frameBounds.height = this._texture.height;
this.collisionMask.width = this._texture.width;
this.collisionMask.height = this._texture.height;
}
else
{
this._texture = this._game.cache.getImage(key);
this.animations.loadFrameData(this._game.cache.getFrameData(key));
this.collisionMask.width = this.animations.currentFrame.width;
this.collisionMask.height = this.animations.currentFrame.height;
}
this._dynamicTexture = false;
@@ -77,12 +144,17 @@ module Phaser {
}
/**
* Load a DynamicTexture as its texture.
* @param texture {DynamicTexture} The texture object to be used by this sprite.
* @return {Sprite} Sprite instance itself.
*/
public loadDynamicTexture(texture: DynamicTexture): Sprite {
this._texture = texture;
this.bounds.width = this._texture.width;
this.bounds.height = this._texture.height;
this.frameBounds.width = this._texture.width;
this.frameBounds.height = this._texture.height;
this._dynamicTexture = true;
@@ -90,35 +162,49 @@ module Phaser {
}
public makeGraphic(width: number, height: number, color: number = 0xffffffff): Sprite {
/**
* This function creates a flat colored square image dynamically.
* @param width {number} The width of the sprite you want to generate.
* @param height {number} The height of the sprite you want to generate.
* @param [color] {number} specifies the color of the generated block. (format is 0xAARRGGBB)
* @return {Sprite} Sprite instance itself.
*/
public makeGraphic(width: number, height: number, color: string = 'rgb(255,255,255)'): Sprite {
this._texture = null;
this.width = width;
this.height = height;
this.fillColor = color;
this._dynamicTexture = false;
return this;
}
public inCamera(camera: Rectangle): bool {
if (this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0)
{
this._dx = this.bounds.x - (camera.x * this.scrollFactor.x);
this._dy = this.bounds.y - (camera.y * this.scrollFactor.x);
this._dw = this.bounds.width * this.scale.x;
this._dh = this.bounds.height * this.scale.y;
/**
* Check whether this object is visible in a specific camera rectangle.
* @param camera {Rectangle} The rectangle you want to check.
* @return {boolean} Return true if bounds of this sprite intersects the given rectangle, otherwise return false.
*/
public inCamera(camera: Rectangle, cameraOffsetX: number, cameraOffsetY: number): bool {
return (camera.right > this._dx) && (camera.x < this._dx + this._dw) && (camera.bottom > this._dy) && (camera.y < this._dy + this._dh);
}
else
// Object fixed in place regardless of the camera scrolling? Then it's always visible
if (this.scrollFactor.x == 0 && this.scrollFactor.y == 0)
{
return camera.intersects(this.bounds, this.bounds.length);
return true;
}
this._dx = (this.frameBounds.x - camera.x);
this._dy = (this.frameBounds.y - camera.y);
this._dw = this.frameBounds.width * this.scale.x;
this._dh = this.frameBounds.height * this.scale.y;
return (camera.right > this._dx) && (camera.x < this._dx + this._dw) && (camera.bottom > this._dy) && (camera.y < this._dy + this._dh);
}
/**
* Automatically called after update() by the game loop, this function just updates animations.
*/
public postUpdate() {
this.animations.update();
@@ -143,10 +229,17 @@ module Phaser {
return this.animations.frameName;
}
/**
* Render this sprite to specific camera. Called by game loop after update().
* @param camera {Camera} Camera this sprite will be rendered to.
* @cameraOffsetX {number} X offset to the camera.
* @cameraOffsetY {number} Y offset to the camera.
* @return {boolean} Return false if not rendered, otherwise return true.
*/
public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number): bool {
// Render checks
if (this.visible == false || this.scale.x == 0 || this.scale.y == 0 || this.alpha < 0.1 || this.cameraBlacklist.indexOf(camera.ID) !== -1 || this.inCamera(camera.worldView) == false)
if (this.visible == false || this.scale.x == 0 || this.scale.y == 0 || this.alpha < 0.1 || this.cameraBlacklist.indexOf(camera.ID) !== -1 || this.inCamera(camera.worldView, cameraOffsetX, cameraOffsetY) == false)
{
return false;
}
@@ -154,54 +247,55 @@ module Phaser {
// Alpha
if (this.alpha !== 1)
{
var globalAlpha = this._game.stage.context.globalAlpha;
this._game.stage.context.globalAlpha = this.alpha;
var globalAlpha = this.context.globalAlpha;
this.context.globalAlpha = this.alpha;
}
this._sx = 0;
this._sy = 0;
this._sw = this.bounds.width;
this._sh = this.bounds.height;
this._dx = cameraOffsetX + (this.bounds.topLeft.x - camera.worldView.x);
this._dy = cameraOffsetY + (this.bounds.topLeft.y - camera.worldView.y);
this._dw = this.bounds.width * this.scale.x;
this._dh = this.bounds.height * this.scale.y;
this._sw = this.frameBounds.width;
this._sh = this.frameBounds.height;
this._dx = (cameraOffsetX * this.scrollFactor.x) + this.frameBounds.topLeft.x - (camera.worldView.x * this.scrollFactor.x);
this._dy = (cameraOffsetY * this.scrollFactor.y) + this.frameBounds.topLeft.y - (camera.worldView.y * this.scrollFactor.y);
this._dw = this.frameBounds.width * this.scale.x;
this._dh = this.frameBounds.height * this.scale.y;
if (this.align == GameObject.ALIGN_TOP_CENTER)
{
this._dx -= this.bounds.halfWidth * this.scale.x;
this._dx -= this.frameBounds.halfWidth * this.scale.x;
}
else if (this.align == GameObject.ALIGN_TOP_RIGHT)
{
this._dx -= this.bounds.width * this.scale.x;
this._dx -= this.frameBounds.width * this.scale.x;
}
else if (this.align == GameObject.ALIGN_CENTER_LEFT)
{
this._dy -= this.bounds.halfHeight * this.scale.y;
this._dy -= this.frameBounds.halfHeight * this.scale.y;
}
else if (this.align == GameObject.ALIGN_CENTER)
{
this._dx -= this.bounds.halfWidth * this.scale.x;
this._dy -= this.bounds.halfHeight * this.scale.y;
this._dx -= this.frameBounds.halfWidth * this.scale.x;
this._dy -= this.frameBounds.halfHeight * this.scale.y;
}
else if (this.align == GameObject.ALIGN_CENTER_RIGHT)
{
this._dx -= this.bounds.width * this.scale.x;
this._dy -= this.bounds.halfHeight * this.scale.y;
this._dx -= this.frameBounds.width * this.scale.x;
this._dy -= this.frameBounds.halfHeight * this.scale.y;
}
else if (this.align == GameObject.ALIGN_BOTTOM_LEFT)
{
this._dy -= this.bounds.height * this.scale.y;
this._dy -= this.frameBounds.height * this.scale.y;
}
else if (this.align == GameObject.ALIGN_BOTTOM_CENTER)
{
this._dx -= this.bounds.halfWidth * this.scale.x;
this._dy -= this.bounds.height * this.scale.y;
this._dx -= this.frameBounds.halfWidth * this.scale.x;
this._dy -= this.frameBounds.height * this.scale.y;
}
else if (this.align == GameObject.ALIGN_BOTTOM_RIGHT)
{
this._dx -= this.bounds.width * this.scale.x;
this._dy -= this.bounds.height * this.scale.y;
this._dx -= this.frameBounds.width * this.scale.x;
this._dy -= this.frameBounds.height * this.scale.y;
}
if (this._dynamicTexture == false && this.animations.currentFrame !== null)
@@ -217,21 +311,21 @@ module Phaser {
}
// Apply camera difference
if (this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0)
if (this.scrollFactor.x !== 1 || this.scrollFactor.y !== 1)
{
this._dx -= (camera.worldView.x * this.scrollFactor.x);
this._dy -= (camera.worldView.y * this.scrollFactor.y);
//this._dx -= (camera.worldView.x * this.scrollFactor.x);
//this._dy -= (camera.worldView.y * this.scrollFactor.y);
}
// Rotation - needs to work from origin point really, but for now from center
if (this.angle !== 0 || this.rotationOffset !== 0 || this.flipped == true)
{
this._game.stage.context.save();
this._game.stage.context.translate(this._dx + (this._dw / 2), this._dy + (this._dh / 2));
this.context.save();
this.context.translate(this._dx + (this._dw / 2), this._dy + (this._dh / 2));
if (this.angle !== 0 || this.rotationOffset !== 0)
if (this.renderRotation == true && (this.angle !== 0 || this.rotationOffset !== 0))
{
this._game.stage.context.rotate((this.rotationOffset + this.angle) * (Math.PI / 180));
this.context.rotate((this.rotationOffset + this.angle) * (Math.PI / 180));
}
this._dx = -(this._dw / 2);
@@ -239,7 +333,7 @@ module Phaser {
if (this.flipped == true)
{
this._game.stage.context.scale(-1, 1);
this.context.scale(-1, 1);
}
}
@@ -256,7 +350,7 @@ module Phaser {
{
if (this._dynamicTexture)
{
this._game.stage.context.drawImage(
this.context.drawImage(
this._texture.canvas, // Source Image
this._sx, // Source X (location within the source image)
this._sy, // Source Y
@@ -270,7 +364,7 @@ module Phaser {
}
else
{
this._game.stage.context.drawImage(
this.context.drawImage(
this._texture, // Source Image
this._sx, // Source X (location within the source image)
this._sy, // Source Y
@@ -285,64 +379,77 @@ module Phaser {
}
else
{
this._game.stage.context.fillStyle = 'rgb(255,255,255)';
this._game.stage.context.fillRect(this._dx, this._dy, this._dw, this._dh);
this.context.fillStyle = this.fillColor;
this.context.fillRect(this._dx, this._dy, this._dw, this._dh);
}
if (this.flipped === true || this.rotation !== 0 || this.rotationOffset !== 0)
{
//this._game.stage.context.translate(0, 0);
this._game.stage.context.restore();
//this.context.translate(0, 0);
this.context.restore();
}
if (this.renderDebug)
{
this.renderBounds(camera, cameraOffsetX, cameraOffsetY);
//this.collisionMask.render(camera, cameraOffsetX, cameraOffsetY);
}
if (globalAlpha > -1)
{
this._game.stage.context.globalAlpha = globalAlpha;
this.context.globalAlpha = globalAlpha;
}
return true;
}
// Renders the bounding box around this Sprite and the contact points. Useful for visually debugging.
/**
* Renders the bounding box around this Sprite and the contact points. Useful for visually debugging.
* @param camera {Camera} Camera the bound will be rendered to.
* @param cameraOffsetX {number} X offset of bound to the camera.
* @param cameraOffsetY {number} Y offset of bound to the camera.
*/
private renderBounds(camera:Camera, cameraOffsetX:number, cameraOffsetY:number) {
this._dx = cameraOffsetX + (this.bounds.topLeft.x - camera.worldView.x);
this._dy = cameraOffsetY + (this.bounds.topLeft.y - camera.worldView.y);
this._dx = cameraOffsetX + (this.frameBounds.topLeft.x - camera.worldView.x);
this._dy = cameraOffsetY + (this.frameBounds.topLeft.y - camera.worldView.y);
this._game.stage.context.fillStyle = this.renderDebugColor;
this._game.stage.context.fillRect(this._dx, this._dy, this._dw, this._dh);
this._game.stage.context.fillStyle = this.renderDebugPointColor;
var hw = this.bounds.halfWidth * this.scale.x;
var hh = this.bounds.halfHeight * this.scale.y;
var sw = (this.bounds.width * this.scale.x) - 1;
var sh = (this.bounds.height * this.scale.y) - 1;
this.context.fillStyle = this.renderDebugColor;
this.context.fillRect(this._dx, this._dy, this.frameBounds.width, this.frameBounds.height);
this._game.stage.context.fillRect(this._dx, this._dy, 1, 1); // top left
this._game.stage.context.fillRect(this._dx + hw, this._dy, 1, 1); // top center
this._game.stage.context.fillRect(this._dx + sw, this._dy, 1, 1); // top right
this._game.stage.context.fillRect(this._dx, this._dy + hh, 1, 1); // left center
this._game.stage.context.fillRect(this._dx + hw, this._dy + hh, 1, 1); // center
this._game.stage.context.fillRect(this._dx + sw, this._dy + hh, 1, 1); // right center
this._game.stage.context.fillRect(this._dx, this._dy + sh, 1, 1); // bottom left
this._game.stage.context.fillRect(this._dx + hw, this._dy + sh, 1, 1); // bottom center
this._game.stage.context.fillRect(this._dx + sw, this._dy + sh, 1, 1); // bottom right
//this.context.fillStyle = this.renderDebugPointColor;
//var hw = this.frameBounds.halfWidth * this.scale.x;
//var hh = this.frameBounds.halfHeight * this.scale.y;
//var sw = (this.frameBounds.width * this.scale.x) - 1;
//var sh = (this.frameBounds.height * this.scale.y) - 1;
//this.context.fillRect(this._dx, this._dy, 1, 1); // top left
//this.context.fillRect(this._dx + hw, this._dy, 1, 1); // top center
//this.context.fillRect(this._dx + sw, this._dy, 1, 1); // top right
//this.context.fillRect(this._dx, this._dy + hh, 1, 1); // left center
//this.context.fillRect(this._dx + hw, this._dy + hh, 1, 1); // center
//this.context.fillRect(this._dx + sw, this._dy + hh, 1, 1); // right center
//this.context.fillRect(this._dx, this._dy + sh, 1, 1); // bottom left
//this.context.fillRect(this._dx + hw, this._dy + sh, 1, 1); // bottom center
//this.context.fillRect(this._dx + sw, this._dy + sh, 1, 1); // bottom right
}
/**
* Render debug infos. (including name, bounds info, position and some other properties)
* @param x {number} X position of the debug info to be rendered.
* @param y {number} Y position of the debug info to be rendered.
* @param [color] {number} color of the debug info to be rendered. (format is css color string)
*/
public renderDebugInfo(x: number, y: number, color?: string = 'rgb(255,255,255)') {
this._game.stage.context.fillStyle = color;
this._game.stage.context.fillText('Sprite: ' + this.name + ' (' + this.bounds.width + ' x ' + this.bounds.height + ')', x, y);
this._game.stage.context.fillText('x: ' + this.bounds.x.toFixed(1) + ' y: ' + this.bounds.y.toFixed(1) + ' rotation: ' + this.angle.toFixed(1), x, y + 14);
this._game.stage.context.fillText('dx: ' + this._dx.toFixed(1) + ' dy: ' + this._dy.toFixed(1) + ' dw: ' + this._dw.toFixed(1) + ' dh: ' + this._dh.toFixed(1), x, y + 28);
this._game.stage.context.fillText('sx: ' + this._sx.toFixed(1) + ' sy: ' + this._sy.toFixed(1) + ' sw: ' + this._sw.toFixed(1) + ' sh: ' + this._sh.toFixed(1), x, y + 42);
this.context.fillStyle = color;
this.context.fillText('Sprite: ' + this.name + ' (' + this.frameBounds.width + ' x ' + this.frameBounds.height + ')', x, y);
this.context.fillText('x: ' + this.frameBounds.x.toFixed(1) + ' y: ' + this.frameBounds.y.toFixed(1) + ' rotation: ' + this.angle.toFixed(1), x, y + 14);
this.context.fillText('dx: ' + this._dx.toFixed(1) + ' dy: ' + this._dy.toFixed(1) + ' dw: ' + this._dw.toFixed(1) + ' dh: ' + this._dh.toFixed(1), x, y + 28);
this.context.fillText('sx: ' + this._sx.toFixed(1) + ' sy: ' + this._sy.toFixed(1) + ' sw: ' + this._sw.toFixed(1) + ' sh: ' + this._sh.toFixed(1), x, y + 42);
}
+31
View File
@@ -0,0 +1,31 @@
/// <reference path="../Game.d.ts" />
/// <reference path="GameObject.d.ts" />
/// <reference path="../system/TilemapLayer.d.ts" />
/// <reference path="../system/Tile.d.ts" />
module Phaser {
class Tilemap extends GameObject {
constructor(game: Game, key: string, mapData: string, format: number, resizeWorld?: bool, tileWidth?: number, tileHeight?: number);
static FORMAT_CSV: number;
static FORMAT_TILED_JSON: number;
public tiles: Tile[];
public layers: TilemapLayer[];
public currentLayer: TilemapLayer;
public collisionLayer: TilemapLayer;
public mapFormat: number;
public update(): void;
public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number): void;
private parseCSV(data, key, tileWidth, tileHeight);
private parseTiledJSON(data, key);
private generateTiles(qty);
public widthInPixels : number;
public heightInPixels : number;
public setCollisionRange(start: number, end: number, collision?: number, resetCollisions?: bool): void;
public setCollisionByIndex(values: number[], collision?: number, resetCollisions?: bool): void;
public getTile(x: number, y: number, layer?: number): Tile;
public getTileFromWorldXY(x: number, y: number, layer?: number): Tile;
public getTileFromInputXY(layer?: number): Tile;
public getTileOverlaps(object: GameObject): bool;
public collide(objectOrGroup?, callback?): bool;
public collideGameObject(object: GameObject): bool;
}
}
+289 -13
View File
@@ -1,6 +1,7 @@
/// <reference path="../Game.ts" />
/// <reference path="GameObject.ts" />
/// <reference path="../system/TilemapLayer.ts" />
/// <reference path="../system/Tile.ts" />
/**
* Phaser - Tilemap
@@ -13,13 +14,26 @@ module Phaser {
export class Tilemap extends GameObject {
/**
* Tilemap constructor
* Create a new <code>Tilemap</code>.
*
* @param game {Phaser.Game} Current game instance.
* @param key {string} Asset key for this map.
* @param mapData {string} Data of this map. (a big 2d array, normally in csv)
* @param format {number} Format of this map data, available: Tilemap.FORMAT_CSV or Tilemap.FORMAT_TILED_JSON.
* @param resizeWorld {boolean} Resize the world bound automatically based on this tilemap?
* @param tileWidth {number} Width of tiles in this map.
* @param tileHeight {number} Height of tiles in this map.
*/
constructor(game: Game, key: string, mapData: string, format: number, resizeWorld: bool = true, tileWidth?: number = 0, tileHeight?: number = 0) {
super(game);
this.isGroup = false;
this._layers = [];
this.tiles = [];
this.layers = [];
this.mapFormat = format;
@@ -41,33 +55,89 @@ module Phaser {
}
private _layers : TilemapLayer[];
private _tempCollisionData;
/**
* Tilemap data format enum: CSV.
* @type {number}
*/
public static FORMAT_CSV: number = 0;
/**
* Tilemap data format enum: Tiled JSON.
* @type {number}
*/
public static FORMAT_TILED_JSON: number = 1;
/**
* Array contains tile objects of this map.
* @type {Tile[]}
*/
public tiles : Tile[];
/**
* Array contains tilemap layer objects of this map.
* @type {TilemapLayer[]}
*/
public layers : TilemapLayer[];
/**
* Current tilemap layer.
* @type {TilemapLayer}
*/
public currentLayer: TilemapLayer;
/**
* The tilemap layer for collision.
* @type {TilemapLayer}
*/
public collisionLayer: TilemapLayer;
/**
* Tilemap collision callback.
* @type {function}
*/
public collisionCallback = null;
/**
* Context for the collision callback called with.
*/
public collisionCallbackContext;
/**
* Format of this tilemap data. Available values: Tilemap.FORMAT_CSV or Tilemap.FORMAT_TILED_JSON.
* @type {number}
*/
public mapFormat: number;
/**
* Inherited update method.
*/
public update() {
}
/**
* Render this tilemap to a specific camera with specific offset.
* @param camera {Camera} The camera this tilemap will be rendered to.
* @param cameraOffsetX {number} X offset of the camera.
* @param cameraOffsetY {number} Y offset of the camera.
*/
public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number) {
if (this.cameraBlacklist.indexOf(camera.ID) == -1)
{
// Loop through the layers
for (var i = 0; i < this._layers.length; i++)
for (var i = 0; i < this.layers.length; i++)
{
this._layers[i].render(camera, cameraOffsetX, cameraOffsetY);
this.layers[i].render(camera, cameraOffsetX, cameraOffsetY);
}
}
}
/**
* Parset csv map data and generate tiles.
* @param data {string} CSV map data.
* @param key {string} Asset key for tileset image.
* @param tileWidth {number} Width of its tile.
* @param tileHeight {number} Height of its tile.
*/
private parseCSV(data: string, key: string, tileWidth: number, tileHeight: number) {
var layer: TilemapLayer = new TilemapLayer(this._game, key, Tilemap.FORMAT_CSV, 'TileLayerCSV' + this._layers.length.toString(), tileWidth, tileHeight);
var layer: TilemapLayer = new TilemapLayer(this._game, this, key, Tilemap.FORMAT_CSV, 'TileLayerCSV' + this.layers.length.toString(), tileWidth, tileHeight);
// Trim any rogue whitespace from the data
data = data.trim();
@@ -85,13 +155,22 @@ module Phaser {
}
layer.updateBounds();
var tileQuantity = layer.parseTileOffsets();
this.currentLayer = layer;
this.collisionLayer = layer;
this._layers.push(layer);
this.layers.push(layer);
this.generateTiles(tileQuantity);
}
/**
* Parset JSON map data and generate tiles.
* @param data {string} JSON map data.
* @param key {string} Asset key for tileset image.
*/
private parseTiledJSON(data: string, key: string) {
// Trim any rogue whitespace from the data
@@ -101,10 +180,12 @@ module Phaser {
for (var i = 0; i < json.layers.length; i++)
{
var layer: TilemapLayer = new TilemapLayer(this._game, key, Tilemap.FORMAT_TILED_JSON, json.layers[i].name, json.tilewidth, json.tileheight);
var layer: TilemapLayer = new TilemapLayer(this._game, this, key, Tilemap.FORMAT_TILED_JSON, json.layers[i].name, json.tilewidth, json.tileheight);
layer.alpha = json.layers[i].opacity;
layer.visible = json.layers[i].visible;
layer.tileMargin = json.tilesets[0].margin;
layer.tileSpacing = json.tilesets[0].spacing;
var c = 0;
var row;
@@ -129,12 +210,30 @@ module Phaser {
layer.updateBounds();
var tileQuantity = layer.parseTileOffsets();
this.currentLayer = layer;
this.collisionLayer = layer;
this._layers.push(layer);
this.layers.push(layer);
}
this.generateTiles(tileQuantity);
}
/**
* Create tiles of given quantity.
* @param qty {number} Quentity of tiles to be generated.
*/
private generateTiles(qty:number) {
for (var i = 0; i < qty; i++)
{
this.tiles.push(new Tile(this._game, this, i, this.currentLayer.tileWidth, this.currentLayer.tileHeight));
}
}
public get widthInPixels(): number {
@@ -145,15 +244,192 @@ module Phaser {
return this.currentLayer.heightInPixels;
}
// Tile Collision
/**
* Set callback to be called when this tilemap collides.
* @param context {object} Callback will be called with this context.
* @param callback {function} Callback function.
*/
public setCollisionCallback(context, callback) {
this.collisionCallbackContext = context;
this.collisionCallback = callback;
}
/**
* Set collision configs of tiles in a range index.
* @param start {number} First index of tiles.
* @param end {number} Last index of tiles.
* @param collision {number} Bit field of flags. (see Tile.allowCollision)
* @param resetCollisions {boolean} Reset collision flags before set.
* @param separateX {boolean} Enable seprate at x-axis.
* @param separateY {boolean} Enable seprate at y-axis.
*/
public setCollisionRange(start: number, end: number, collision?:number = Collision.ANY, resetCollisions?: bool = false, separateX?: bool = true, separateY?: bool = true) {
for (var i = start; i < end; i++)
{
this.tiles[i].setCollision(collision, resetCollisions, separateX, separateY);
}
}
/**
* Set collision configs of tiles with given index.
* @param values {number[]} Index array which contains all tile indexes. The tiles with those indexes will be setup with rest parameters.
* @param collision {number} Bit field of flags. (see Tile.allowCollision)
* @param resetCollisions {boolean} Reset collision flags before set.
* @param separateX {boolean} Enable seprate at x-axis.
* @param separateY {boolean} Enable seprate at y-axis.
*/
public setCollisionByIndex(values:number[], collision?:number = Collision.ANY, resetCollisions?: bool = false, separateX?: bool = true, separateY?: bool = true) {
for (var i = 0; i < values.length; i++)
{
this.tiles[values[i]].setCollision(collision, resetCollisions, separateX, separateY);
}
}
// Tile Management
/**
* Get the tile by its index.
* @param value {number} Index of the tile you want to get.
* @return {Tile} The tile with given index.
*/
public getTileByIndex(value: number):Tile {
if (this.tiles[value])
{
return this.tiles[value];
}
return null;
}
/**
* Get the tile located at specific position and layer.
* @param x {number} X position of this tile located.
* @param y {number} Y position of this tile located.
* @param [layer] {number} layer of this tile located.
* @return {Tile} The tile with specific properties.
*/
public getTile(x: number, y: number, layer?: number = 0):Tile {
return this.tiles[this.layers[layer].getTileIndex(x, y)];
}
/**
* Get the tile located at specific position (in world coordinate) and layer. (thus you give a position of a point which is within the tile)
* @param x {number} X position of the point in target tile.
* @param x {number} Y position of the point in target tile.
* @param [layer] {number} layer of this tile located.
* @return {Tile} The tile with specific properties.
*/
public getTileFromWorldXY(x: number, y: number, layer?: number = 0):Tile {
return this.tiles[this.layers[layer].getTileFromWorldXY(x, y)];
}
public getTileFromInputXY(layer?: number = 0):Tile {
return this.tiles[this.layers[layer].getTileFromWorldXY(this._game.input.getWorldX(), this._game.input.getWorldY())];
}
/**
* Get tiles overlaps the given object.
* @param object {GameObject} Tiles you want to get that overlaps this.
* @return {array} Array with tiles informations. (Each contains x, y and the tile.)
*/
public getTileOverlaps(object: GameObject) {
return this.currentLayer.getTileOverlaps(object);
}
// COLLIDE
/**
* Check whether this tilemap collides with the given game object or group of objects.
* @param objectOrGroup {function} Target object of group you want to check.
* @param callback {function} This is called if objectOrGroup collides the tilemap.
* @param context {object} Callback will be called with this context.
* @return {boolean} Return true if this collides with given object, otherwise return false.
*/
public collide(objectOrGroup = null, callback = null, context = null) {
if (callback !== null && context !== null)
{
this.collisionCallback = callback;
this.collisionCallbackContext = context;
}
if (objectOrGroup == null)
{
objectOrGroup = this._game.world.group;
}
// Group?
if (objectOrGroup.isGroup == false)
{
this.collideGameObject(objectOrGroup);
}
else
{
objectOrGroup.forEachAlive(this, this.collideGameObject, true);
}
}
/**
* Check whether this tilemap collides with the given game object.
* @param object {GameObject} Target object you want to check.
* @return {boolean} Return true if this collides with given object, otherwise return false.
*/
public collideGameObject(object: GameObject): bool {
if (object !== this && object.immovable == false && object.exists == true && object.allowCollisions != Collision.NONE)
{
this._tempCollisionData = this.collisionLayer.getTileOverlaps(object);
if (this.collisionCallback !== null && this._tempCollisionData.length > 0)
{
this.collisionCallback.call(this.collisionCallbackContext, object, this._tempCollisionData);
}
return true;
}
else
{
return false;
}
}
/**
* Set a tile to a specific layer.
* @param x {number} X position of this tile.
* @param y {number} Y position of this tile.
* @param index {number} The index of this tile type in the core map data.
* @param [layer] {number} which layer you want to set the tile to.
*/
public putTile(x: number, y: number, index: number, layer?: number = 0) {
this.layers[layer].putTile(x, y, index);
}
// Set current layer
// Set layer order?
// Get tile from x/y
// Get block of tiles
// Swap tiles around
// Delete tiles of certain type
// Erase tiles
}
}
+34
View File
@@ -0,0 +1,34 @@
/// <reference path="../Game.d.ts" />
module Phaser {
class Circle {
constructor(x?: number, y?: number, diameter?: number);
private _diameter;
private _radius;
public x: number;
public y: number;
public diameter : number;
public radius : number;
public circumference(): number;
public bottom : number;
public left : number;
public right : number;
public top : number;
public area : number;
public isEmpty : bool;
public intersectCircleLine(line: Line): bool;
public clone(output?: Circle): Circle;
public contains(x: number, y: number): bool;
public containsPoint(point: Point): bool;
public containsCircle(circle: Circle): bool;
public copyFrom(source: Circle): Circle;
public copyTo(target: Circle): Circle;
public distanceTo(target: any, round?: bool): number;
public equals(toCompare: Circle): bool;
public intersects(toIntersect: Circle): bool;
public circumferencePoint(angle: number, asDegrees?: bool, output?: Point): Point;
public offset(dx: number, dy: number): Circle;
public offsetPoint(point: Point): Circle;
public setTo(x: number, y: number, diameter: number): Circle;
public toString(): string;
}
}
+22 -12
View File
@@ -14,42 +14,52 @@ module Phaser {
* Creates a new Circle object with the center coordinate specified by the x and y parameters and the diameter specified by the diameter parameter. If you call this function without parameters, a circle with x, y, diameter and radius properties set to 0 is created.
* @class Circle
* @constructor
* @param {Number} x The x coordinate of the center of the circle.
* @param {Number} y The y coordinate of the center of the circle.
* @param {Number} [x] The x coordinate of the center of the circle.
* @param {Number} [y] The y coordinate of the center of the circle.
* @param {Number} [diameter] The diameter of the circle.
* @return {Circle} This circle object
**/
constructor(x: number = 0, y: number = 0, diameter: number = 0) {
this._pos = new Vector2;
this.setTo(x, y, diameter);
}
private _diameter: number = 0;
private _radius: number = 0;
private _pos: Vector2;
/**
/**
* The x coordinate of the center of the circle
* @property x
* @type Number
**/
public x: number = 0;
/**
/**
* The y coordinate of the center of the circle
* @property y
* @type Number
**/
public y: number = 0;
/**
* The position of this Circle object represented by a Vector2
* @property pos
* @type Vector2
**/
public get pos(): Vector2 {
return this._pos.setTo(this.x, this.y);
}
/**
* The diameter of the circle. The largest distance between any two points on the circle. The same as the radius * 2.
* @method diameter
* @return {Number}
**/
get diameter(): number {
return this._diameter;
}
/**
@@ -262,7 +272,7 @@ module Phaser {
**/
get isEmpty(): bool {
if (this._diameter < 1)
if (this._diameter <= 0)
{
return true;
}
@@ -287,7 +297,7 @@ module Phaser {
/**
* Returns a new Circle object with the same values for the x, y, width, and height properties as the original Circle object.
* @method clone
* @param {Circle} output Optional Circle object. If given the values will be set into the object, otherwise a brand new Circle object will be created and returned.
* @param {Circle} [optional] output Optional Circle object. If given the values will be set into the object, otherwise a brand new Circle object will be created and returned.
* @return {Phaser.Circle}
**/
public clone(output?: Circle = new Circle): Circle {
@@ -364,7 +374,7 @@ module Phaser {
* Returns the distance from the center of this Circle object to the given object (can be Circle, Point or anything with x/y values)
* @method distanceFrom
* @param {Circle/Point} target - The destination Point object.
* @param {Boolean} round - Round the distance to the nearest integer (default false)
* @param {Boolean} [optional] round - Round the distance to the nearest integer (default false)
* @return {Number} The distance between this Point object and the destination Point object.
**/
public distanceTo(target: any, round?: bool = false): number {
@@ -418,9 +428,9 @@ module Phaser {
/**
* Returns a Point object containing the coordinates of a point on the circumference of this Circle based on the given angle.
* @method circumferencePoint
* @param {Number} The angle in radians (unless asDegrees is true) to return the point from.
* @param {Boolean} Is the given angle in radians (false) or degrees (true)?
* @param {Phaser.Point} An optional Point object to put the result in to. If none specified a new Point object will be created.
* @param {Number} angle The angle in radians (unless asDegrees is true) to return the point from.
* @param {Boolean} asDegrees Is the given angle in radians (false) or degrees (true)?
* @param {Phaser.Point} [optional] output An optional Point object to put the result in to. If none specified a new Point object will be created.
* @return {Phaser.Point} The Point object holding the result.
**/
public circumferencePoint(angle: number, asDegrees: bool = false, output?: Point = new Point): Point {
+15
View File
@@ -0,0 +1,15 @@
/// <reference path="../Game.d.ts" />
module Phaser {
class IntersectResult {
public result: bool;
public x: number;
public y: number;
public x1: number;
public y1: number;
public x2: number;
public y2: number;
public width: number;
public height: number;
public setTo(x1: number, y1: number, x2?: number, y2?: number, width?: number, height?: number): void;
}
}
+9 -9
View File
@@ -13,55 +13,55 @@ module Phaser {
/**
* Did they intersect or not?
* @property result
* @type Boolean
* @type {Boolean}
*/
result: bool = false;
/**
* @property x
* @type Number
* @type {Number}
*/
x: number;
/**
* @property y
* @type Number
* @type {Number}
*/
y: number;
/**
* @property x1
* @type Number
* @type {Number}
*/
x1: number;
/**
* @property y1
* @type Number
* @type {Number}
*/
y1: number;
/**
* @property x2
* @type Number
* @type {Number}
*/
x2: number;
/**
* @property y2
* @type Number
* @type {Number}
*/
y2: number;
/**
* @property width
* @type Number
* @type {Number}
*/
width: number;
/**
* @property height
* @type Number
* @type {Number}
*/
height: number;
+27
View File
@@ -0,0 +1,27 @@
/// <reference path="../Game.d.ts" />
module Phaser {
class Line {
constructor(x1?: number, y1?: number, x2?: number, y2?: number);
public x1: number;
public y1: number;
public x2: number;
public y2: number;
public clone(output?: Line): Line;
public copyFrom(source: Line): Line;
public copyTo(target: Line): Line;
public setTo(x1?: number, y1?: number, x2?: number, y2?: number): Line;
public width : number;
public height : number;
public length : number;
public getY(x: number): number;
public angle : number;
public slope : number;
public perpSlope : number;
public yIntercept : number;
public isPointOnLine(x: number, y: number): bool;
public isPointOnLineSegment(x: number, y: number): bool;
public intersectLineLine(line): any;
public perp(x: number, y: number, output?: Line): Line;
public toString(): string;
}
}
+25 -25
View File
@@ -11,7 +11,7 @@ module Phaser {
export class Line {
/**
*
*
* @constructor
* @param {Number} x1
* @param {Number} y1
@@ -26,35 +26,35 @@ module Phaser {
}
/**
*
*
* @property x1
* @type Number
* @type {Number}
*/
public x1: number = 0;
/**
*
*
* @property y1
* @type Number
* @type {Number}
*/
public y1: number = 0;
/**
*
*
* @property x2
* @type Number
* @type {Number}
*/
public x2: number = 0;
/**
*
*
* @property y2
* @type Number
* @type {Number}
*/
public y2: number = 0;
/**
*
*
* @method clone
* @param {Phaser.Line} [output]
* @return {Phaser.Line}
@@ -66,7 +66,7 @@ module Phaser {
}
/**
*
*
* @method copyFrom
* @param {Phaser.Line} source
* @return {Phaser.Line}
@@ -78,7 +78,7 @@ module Phaser {
}
/**
*
*
* @method copyTo
* @param {Phaser.Line} target
* @return {Phaser.Line}
@@ -90,7 +90,7 @@ module Phaser {
}
/**
*
*
* @method setTo
* @param {Number} x1
* @param {Number} y1
@@ -122,7 +122,7 @@ module Phaser {
}
/**
*
*
* @method length
* @return {Number}
*/
@@ -133,7 +133,7 @@ module Phaser {
}
/**
*
*
* @method getY
* @param {Number} x
* @return {Number}
@@ -145,7 +145,7 @@ module Phaser {
}
/**
*
*
* @method angle
* @return {Number}
*/
@@ -156,7 +156,7 @@ module Phaser {
}
/**
*
*
* @method slope
* @return {Number}
*/
@@ -167,7 +167,7 @@ module Phaser {
}
/**
*
*
* @method perpSlope
* @return {Number}
*/
@@ -178,7 +178,7 @@ module Phaser {
}
/**
*
*
* @method yIntercept
* @return {Number}
*/
@@ -189,7 +189,7 @@ module Phaser {
}
/**
*
*
* @method isPointOnLine
* @param {Number} x
* @param {Number} y
@@ -209,7 +209,7 @@ module Phaser {
}
/**
*
*
* @method isPointOnLineSegment
* @param {Number} x
* @param {Number} y
@@ -234,7 +234,7 @@ module Phaser {
}
/**
*
*
* @method intersectLineLine
* @param {Any} line
* @return {Any}
@@ -244,7 +244,7 @@ module Phaser {
}
/**
*
*
* @method perp
* @param {Number} x
* @param {Number} y
@@ -285,12 +285,12 @@ module Phaser {
{
var perp = this.perp()
return Phaser.intersectLineCircle(this,circle);
}
*/
/**
*
*
* @method toString
* @return {String}
*/
+16
View File
@@ -0,0 +1,16 @@
/// <reference path="../Game.d.ts" />
module Phaser {
class MicroPoint {
constructor(x?: number, y?: number, parent?: any);
private _x;
private _y;
public parent: any;
public x : number;
public y : number;
public copyFrom(source: any): MicroPoint;
public copyTo(target: any): MicroPoint;
public setTo(x: number, y: number, callParent?: bool): MicroPoint;
public equals(toCompare): bool;
public toString(): string;
}
}
+8 -8
View File
@@ -33,10 +33,10 @@ module Phaser {
public parent: any;
/**
/**
* The x coordinate of the top-left corner of the rectangle
* @property x
* @type Number
* @type {Number}
**/
public get x(): number {
@@ -44,10 +44,10 @@ module Phaser {
}
/**
/**
* The y coordinate of the top-left corner of the rectangle
* @property y
* @type Number
* @type {Number}
**/
public get y(): number {
@@ -55,10 +55,10 @@ module Phaser {
}
/**
/**
* The x coordinate of the top-left corner of the rectangle
* @property x
* @type Number
* @type {Number}
**/
public set x(value: number) {
@@ -71,10 +71,10 @@ module Phaser {
}
/**
/**
* The y coordinate of the top-left corner of the rectangle
* @property y
* @type Number
* @type {Number}
**/
public set y(value:number) {
+28
View File
@@ -0,0 +1,28 @@
/// <reference path="../Game.d.ts" />
module Phaser {
class Point {
constructor(x?: number, y?: number);
public x: number;
public y: number;
public add(toAdd: Point, output?: Point): Point;
public addTo(x?: number, y?: number): Point;
public subtractFrom(x?: number, y?: number): Point;
public invert(): Point;
public clamp(min: number, max: number): Point;
public clampX(min: number, max: number): Point;
public clampY(min: number, max: number): Point;
public clone(output?: Point): Point;
public copyFrom(source: Point): Point;
public copyTo(target: Point): Point;
public distanceTo(target: Point, round?: bool): number;
static distanceBetween(pointA: Point, pointB: Point, round?: bool): number;
public distanceCompare(target: Point, distance: number): bool;
public equals(toCompare: Point): bool;
public interpolate(pointA, pointB, f): void;
public offset(dx: number, dy: number): Point;
public polar(length, angle): void;
public setTo(x: number, y: number): Point;
public subtract(point: Point, output?: Point): Point;
public toString(): string;
}
}
+30 -4
View File
@@ -23,17 +23,17 @@ module Phaser {
}
/**
/**
* The horizontal position of this point (default 0)
* @property x
* @type Number
* @type {Number}
**/
public x: number;
/**
/**
* The vertical position of this point (default 0)
* @property y
* @type Number
* @type {Number}
**/
public y: number;
@@ -296,6 +296,32 @@ module Phaser {
}
/**
* Rotates the point around the x/y coordinates given to the desired angle
* @param x {number} The x coordinate of the anchor point
* @param y {number} The y coordinate of the anchor point
* @param {Number} angle The angle in radians (unless asDegrees is true) to return the point from.
* @param {Boolean} asDegrees Is the given angle in radians (false) or degrees (true)?
* @param {Number} distance An optional distance constraint between the point and the anchor
* @return The modified point object
*/
public rotate(cx: number, cy: number, angle: number, asDegrees: bool = false, distance?:number = null) {
if (asDegrees)
{
angle = angle * GameMath.DEG_TO_RAD;
}
// Get distance from origin (cx/cy) to this point
if (distance === null)
{
distance = Math.sqrt(((cx - this.x) * (cx - this.x)) + ((cy - this.y) * (cy - this.y)));
}
return this.setTo(cx + distance * Math.cos(angle), cy + distance * Math.sin(angle));
}
/**
* Sets the x and y values of this Point object to the given coordinates.
* @method setTo
+60
View File
@@ -0,0 +1,60 @@
/// <reference path="../Game.ts" />
/**
* Phaser - Polygon
*
*/
module Phaser {
export class Polygon {
/**
* A *convex* clockwise polygon
* @class Polygon
* @constructor
* @param {Vector2} pos A vector representing the origin of the polygon (all other points are relative to this one)
* @param {Array.<Vector2>} points An Array of vectors representing the points in the polygon, in clockwise order.
**/
constructor(pos?: Vector2 = new Vector2, points?: Vector2[] = [], parent?:any = null) {
this.pos = pos;
this.points = points;
this.parent = parent;
this.recalc();
}
public parent: any;
public pos: Vector2;
public points: Vector2[];
public edges: Vector2[];
public normals: Vector2[];
/**
* Recalculate the edges and normals of the polygon. This
* MUST be called if the points array is modified at all and
* the edges or normals are to be accessed.
*/
public recalc() {
var points = this.points;
var len = points.length;
this.edges = [];
this.normals = [];
for (var i = 0; i < len; i++)
{
var p1 = points[i];
var p2 = i < len - 1 ? points[i + 1] : points[0];
var e = new Vector2().copyFrom(p2).sub(p1);
var n = new Vector2().copyFrom(e).perp().normalize();
this.edges.push(e);
this.normals.push(n);
}
}
}
}
+19
View File
@@ -0,0 +1,19 @@
/// <reference path="../Game.d.ts" />
module Phaser {
class Quad {
constructor(x?: number, y?: number, width?: number, height?: number);
public x: number;
public y: number;
public width: number;
public height: number;
public setTo(x: number, y: number, width: number, height: number): Quad;
public left : number;
public right : number;
public top : number;
public bottom : number;
public halfWidth : number;
public halfHeight : number;
public intersects(q, t?: number): bool;
public toString(): string;
}
}
+87 -5
View File
@@ -1,4 +1,5 @@
/// <reference path="../Game.ts" />
/// <reference path="Polygon.ts" />
/**
* Phaser - Quad
@@ -19,7 +20,7 @@ module Phaser {
* @param {Number} y The y coordinate of the top-left corner of the quad.
* @param {Number} width The width of the quad.
* @param {Number} height The height of the quad.
* @return {Quad } This object
* @return {Quad} This object
**/
constructor(x: number = 0, y: number = 0, width: number = 0, height: number = 0) {
@@ -68,17 +69,98 @@ module Phaser {
return this.y + this.height;
}
public get halfWidth(): number {
return this.width / 2;
}
public get halfHeight(): number {
return this.height / 2;
}
/**
* Determines whether the object specified intersects (overlaps) with this Quad object.
* This method checks the x, y, width, and height properties of the specified Quad object to see if it intersects with this Quad object.
* @method intersects
* @param {Quad} q The Quad to compare against to see if it intersects with this Quad.
* @param {Number} t A tolerance value to allow for an intersection test with padding, default to 0
* @param {Object} quad The object to check for intersection with this Quad. Must have left/right/top/bottom properties (Rectangle, Quad).
* @param {Number} tolerance A tolerance value to allow for an intersection test with padding, default to 0
* @return {Boolean} A value of true if the specified object intersects with this Quad; otherwise false.
**/
public intersects(q: Quad, t?: number = 0): bool {
public intersects(quad, tolerance?: number = 0): bool {
return !(q.left > this.right + t || q.right < this.left - t || q.top > this.bottom + t || q.bottom < this.top - t);
return !(quad.left > this.right + tolerance || quad.right < this.left - tolerance || quad.top > this.bottom + tolerance || quad.bottom < this.top - tolerance);
}
/**
* Determines whether the object specified intersects (overlaps) with the given values.
* @method intersectsProps
* @param {Number} left
* @param {Number} right
* @param {Number} top
* @param {Number} bottomt
* @param {Number} tolerance A tolerance value to allow for an intersection test with padding, default to 0
* @return {Boolean} A value of true if the specified object intersects with this Quad; otherwise false.
**/
public intersectsRaw(left: number, right: number, top: number, bottom: number, tolerance?: number = 0): bool {
return !(left > this.right + tolerance || right < this.left - tolerance || top > this.bottom + tolerance || bottom < this.top - tolerance);
}
/**
* Determines whether the specified coordinates are contained within the region defined by this Quad object.
* @method contains
* @param {Number} x The x coordinate of the point to test.
* @param {Number} y The y coordinate of the point to test.
* @return {Boolean} A value of true if the Rectangle object contains the specified point; otherwise false.
**/
public contains(x: number, y: number): bool {
if (x >= this.x && x <= this.right && y >= this.y && y <= this.bottom)
{
return true;
}
return false;
}
/**
* Copies the x/y/width/height values from the source object into this Quad
* @method copyFrom
* @param {Any} source The source object to copy from. Can be a Quad, Rectangle or any object with exposed x/y/width/height properties
* @return {Quad} This object
**/
public copyFrom(source): Quad {
return this.setTo(source.x, source.y, source.width, source.height);
}
/**
* Copies the x/y/width/height values from this Quad into the given target object
* @method copyTo
* @param {Any} target The object to copy this quads values in to. Can be a Quad, Rectangle or any object with exposed x/y/width/height properties
* @return {Any} The target object
**/
public copyTo(target): any {
return target.copyFrom(this);
}
/**
* Creates and returns a Polygon that is the same as this Quad.
* @method toPolygon
* @return {Polygon} A new Polygon that represents this quad.
**/
public toPolygon(): Polygon {
return new Polygon(new Vector2(this.x, this.y), [
new Vector2(), new Vector2(this.width, 0),
new Vector2(this.width, this.height), new Vector2(0, this.height)
]);
}
+57
View File
@@ -0,0 +1,57 @@
/// <reference path="../Game.d.ts" />
/// <reference path="MicroPoint.d.ts" />
module Phaser {
class Rectangle {
constructor(x?: number, y?: number, width?: number, height?: number);
private _tempX;
private _tempY;
private _tempWidth;
private _tempHeight;
public x : number;
public y : number;
public topLeft: MicroPoint;
public topCenter: MicroPoint;
public topRight: MicroPoint;
public leftCenter: MicroPoint;
public center: MicroPoint;
public rightCenter: MicroPoint;
public bottomLeft: MicroPoint;
public bottomCenter: MicroPoint;
public bottomRight: MicroPoint;
private _width;
private _height;
private _halfWidth;
private _halfHeight;
public length: number;
public updateBounds(): void;
public width : number;
public height : number;
public halfWidth : number;
public halfHeight : number;
public bottom : number;
public left : number;
public right : number;
public size(output?: Point): Point;
public volume : number;
public perimeter : number;
public top : number;
public clone(output?: Rectangle): Rectangle;
public contains(x: number, y: number): bool;
public containsPoint(point: any): bool;
public containsRect(rect: Rectangle): bool;
public copyFrom(source: Rectangle): Rectangle;
public copyTo(target: Rectangle): Rectangle;
public equals(toCompare: Rectangle): bool;
public inflate(dx: number, dy: number): Rectangle;
public inflatePoint(point: Point): Rectangle;
public intersection(toIntersect: Rectangle, output?: Rectangle): Rectangle;
public intersects(r2: Rectangle, t?: number): bool;
public isEmpty : bool;
public offset(dx: number, dy: number): Rectangle;
public offsetPoint(point: Point): Rectangle;
public setEmpty(): Rectangle;
public setTo(x: number, y: number, width: number, height: number): Rectangle;
public union(toUnion: Rectangle, output?: Rectangle): Rectangle;
public toString(): string;
}
}
+60 -60
View File
@@ -57,10 +57,10 @@ module Phaser {
private _tempWidth: number = null;
private _tempHeight: number = null;
/**
/**
* The x coordinate of the top-left corner of the rectangle
* @property x
* @type Number
* @type {Number}
**/
public get x(): number {
@@ -68,10 +68,10 @@ module Phaser {
}
/**
/**
* The y coordinate of the top-left corner of the rectangle
* @property y
* @type Number
* @type {Number}
**/
public get y(): number {
@@ -79,10 +79,10 @@ module Phaser {
}
/**
/**
* The x coordinate of the top-left corner of the rectangle
* @property x
* @type Number
* @type {Number}
**/
public set x(value: number) {
@@ -90,10 +90,10 @@ module Phaser {
}
/**
/**
* The y coordinate of the top-left corner of the rectangle
* @property y
* @type Number
* @type {Number}
**/
public set y(value:number) {
@@ -101,105 +101,105 @@ module Phaser {
}
/**
/**
* The x and y coordinate of the top-left corner of the rectangle (same as x/y)
* @property topLeft
* @type MicroPoint
* @type {MicroPoint}
**/
public topLeft: MicroPoint;
/**
/**
* The x and y coordinate of the top-center of the rectangle
* @property topCenter
* @type MicroPoint
* @type {MicroPoint}
**/
public topCenter: MicroPoint;
/**
/**
* The x and y coordinate of the top-right corner of the rectangle
* @property topRight
* @type MicroPoint
* @type {MicroPoint}
**/
public topRight: MicroPoint;
/**
/**
* The x and y coordinate of the left-center of the rectangle
* @property leftCenter
* @type MicroPoint
* @type {MicroPoint}
**/
public leftCenter: MicroPoint;
/**
/**
* The x and y coordinate of the center of the rectangle
* @property center
* @type MicroPoint
* @type {MicroPoint}
**/
public center: MicroPoint;
/**
/**
* The x and y coordinate of the right-center of the rectangle
* @property rightCenter
* @type MicroPoint
* @type {MicroPoint}
**/
public rightCenter: MicroPoint;
/**
/**
* The x and y coordinate of the bottom-left corner of the rectangle
* @property bottomLeft
* @type MicroPoint
* @type {MicroPoint}
**/
public bottomLeft: MicroPoint;
/**
/**
* The x and y coordinate of the bottom-center of the rectangle
* @property bottomCenter
* @type MicroPoint
* @type {MicroPoint}
**/
public bottomCenter: MicroPoint;
/**
/**
* The x and y coordinate of the bottom-right corner of the rectangle
* @property bottomRight
* @type MicroPoint
* @type {MicroPoint}
**/
public bottomRight: MicroPoint;
/**
/**
* The width of the rectangle
* @property width
* @type Number
* @type {Number}
**/
private _width: number = 0;
/**
/**
* The height of the rectangle
* @property height
* @type Number
* @type {Number}
**/
private _height: number = 0;
/**
/**
* Half of the width of the rectangle
* @property halfWidth
* @type Number
* @type {Number}
**/
private _halfWidth: number = 0;
/**
/**
* Half of the height of the rectangle
* @property halfHeight
* @type Number
* @type {Number}
**/
private _halfHeight: number = 0;
/**
/**
* The size of the longest side (width or height)
* @property length
* @type Number
* @type {Number}
**/
public length: number = 0;
/**
/**
* Updates all of the MicroPoints based on the values of width and height.
* You should not normally call this directly.
**/
@@ -264,10 +264,10 @@ module Phaser {
}
/**
/**
* The width of the rectangle
* @property width
* @type Number
* @type {Number}
**/
public set width(value: number) {
@@ -277,10 +277,10 @@ module Phaser {
}
/**
/**
* The height of the rectangle
* @property height
* @type Number
* @type {Number}
**/
public set height(value: number) {
@@ -290,10 +290,10 @@ module Phaser {
}
/**
/**
* The width of the rectangle
* @property width
* @type Number
* @type {Number}
**/
public get width(): number {
@@ -301,10 +301,10 @@ module Phaser {
}
/**
/**
* The height of the rectangle
* @property height
* @type Number
* @type {Number}
**/
public get height(): number {
@@ -312,10 +312,10 @@ module Phaser {
}
/**
/**
* Half of the width of the rectangle
* @property halfWidth
* @type Number
* @type {Number}
**/
public get halfWidth(): number {
@@ -323,10 +323,10 @@ module Phaser {
}
/**
/**
* Half of the height of the rectangle
* @property halfHeight
* @type Number
* @type {Number}
**/
public get halfHeight(): number {
@@ -350,7 +350,7 @@ module Phaser {
* The sum of the y and height properties.
* Changing the bottom property of a Rectangle object has no effect on the x, y and width properties, but does change the height property.
* @method bottom
* @param {Number} value
* @param {Number} value
**/
public set bottom(value: number) {
@@ -372,7 +372,7 @@ module Phaser {
* Changing the left property of a Rectangle object has no effect on the y and height properties.
* However it does affect the width property, whereas changing the x value does not affect the width property.
* @method left
* @ return {number}
* @ return {Number}
**/
public get left(): number {
@@ -385,7 +385,7 @@ module Phaser {
* Changing the left property of a Rectangle object has no effect on the y and height properties.
* However it does affect the width property, whereas changing the x value does not affect the width property.
* @method left
* @param {Number} value
* @param {Number} value
**/
public set left(value: number) {
@@ -411,7 +411,7 @@ module Phaser {
* Changing the right property of a Rectangle object has no effect on the x, y and height properties.
* However it does affect the width property.
* @method right
* @return {Number}
* @return {Number}
**/
public get right(): number {
@@ -424,7 +424,7 @@ module Phaser {
* Changing the right property of a Rectangle object has no effect on the x, y and height properties.
* However it does affect the width property.
* @method right
* @param {Number} value
* @param {Number} value
**/
public set right(value: number) {
@@ -456,7 +456,7 @@ module Phaser {
/**
* The volume of the Rectangle object in pixels, derived from width * height
* @method volume
* @return {Number}
* @return {Number}
**/
public get volume(): number {
@@ -467,7 +467,7 @@ module Phaser {
/**
* The perimeter size of the Rectangle object in pixels. This is the sum of all 4 sides.
* @method perimeter
* @return {Number}
* @return {Number}
**/
public get perimeter(): number {
@@ -480,7 +480,7 @@ module Phaser {
* Changing the top property of a Rectangle object has no effect on the x and width properties.
* However it does affect the height property, whereas changing the y value does not affect the height property.
* @method top
* @return {Number}
* @return {Number}
**/
public get top(): number {
@@ -626,7 +626,7 @@ module Phaser {
/**
* Increases the size of the Rectangle object by the specified amounts.
* The center point of the Rectangle object stays the same, and its size increases to the left and right by the dx value,
* The center point of the Rectangle object stays the same, and its size increases to the left and right by the dx value,
* and to the top and the bottom by the dy value.
* @method inflate
* @param {Number} dx The amount to be added to the left side of this Rectangle.
@@ -661,7 +661,7 @@ module Phaser {
/**
* If the Rectangle object specified in the toIntersect parameter intersects with this Rectangle object,
* returns the area of intersection as a Rectangle object. If the rectangles do not intersect, this method
* returns the area of intersection as a Rectangle object. If the rectangles do not intersect, this method
* returns an empty Rectangle object with its properties set to 0.
* @method intersection
* @param {Rectangle} toIntersect The Rectangle object to compare against to see if it intersects with this Rectangle object.
@@ -797,7 +797,7 @@ module Phaser {
/**
* Returns a string representation of this object.
* @method toString
* @return {string} a string representation of the instance.
* @return {String} a string representation of the instance.
**/
public toString(): string {
+87
View File
@@ -0,0 +1,87 @@
/// <reference path="../Game.ts" />
/// <reference path="Polygon.ts" />
/**
* Phaser - Response
*
*/
module Phaser {
export class Response {
/**
* An object representing the result of an intersection. Contain information about:
* - The two objects participating in the intersection
* - The vector representing the minimum change necessary to extract the first object
* from the second one.
* - Whether the first object is entirely inside the second, or vice versa.
*
* @constructor
*/
constructor() {
this.a = null;
this.b = null;
this.overlapN = new Vector2;
this.overlapV = new Vector2;
this.clear();
}
/**
* The first object in the collision
*/
public a;
/**
* The second object in the collision
*/
public b;
/**
* The shortest colliding axis (unit-vector)
*/
public overlapN: Vector2;
/**
* The overlap vector (i.e. overlapN.scale(overlap, overlap)).
* If this vector is subtracted from the position of `a`, `a` and `b` will no longer be colliding.
*/
public overlapV: Vector2;
/**
* Whether the first object is completely inside the second.
*/
public aInB: bool;
/**
* Whether the second object is completely inside the first.
*/
public bInA: bool;
/**
* Magnitude of the overlap on the shortest colliding axis
*/
public overlap: number;
/**
* Set some values of the response back to their defaults. Call this between tests if
* you are going to reuse a single Response object for multiple intersection tests (recommented)
*
* @return {Response} This for chaining
*/
public clear() {
this.aInB = true;
this.bInA = true;
this.overlap = Number.MAX_VALUE;
return this;
}
}
}
+457
View File
@@ -0,0 +1,457 @@
/// <reference path="../Game.ts" />
/**
* Phaser - Vector2
*
* A two dimensional vector.
* Contains methods and ideas from verlet-js by Sub Protocol, SAT.js by Jim Riecken and N by Metanet Software. Brandon Jones, Colin MacKenzie IV
*/
module Phaser {
export class Vector2 {
/**
* Creates a new Vector2 object.
* @class Vector2
* @constructor
* @param {Number} x The x position of the vector
* @param {Number} y The y position of the vector
* @return {Vector2} This object
**/
constructor(x: number = 0, y: number = 0) {
//var GLMAT_ARRAY_TYPE = (typeof Float32Array !== 'undefined') ? Float32Array : Array;
this.x = x;
this.y = y;
}
public x: number;
public y: number;
public setTo(x: number, y: number): Vector2 {
this.x = x;
this.y = y;
return this;
}
/**
* Add this vector to the given one and return the result.
*
* @param {Vector2} v The other Vector.
* @param {Vector2} The output Vector.
* @return {Vector2} The new Vector
*/
public add(v: Vector2, output?:Vector2 = new Vector2): Vector2 {
return output.setTo(this.x + v.x, this.y + v.y);
}
/**
* Subtract this vector to the given one and return the result.
*
* @param {Vector2} v The other Vector.
* @param {Vector2} The output Vector.
* @return {Vector2} The new Vector
*/
public sub(v: Vector2, output?:Vector2 = new Vector2): Vector2 {
return output.setTo(this.x - v.x, this.y - v.y);
}
/**
* Multiply this vector with the given one and return the result.
*
* @param {Vector2} v The other Vector.
* @param {Vector2} The output Vector.
* @return {Vector2} The new Vector
*/
public mul(v: Vector2, output?:Vector2 = new Vector2): Vector2 {
return output.setTo(this.x * v.x, this.y * v.y);
}
/**
* Divide this vector by the given one and return the result.
*
* @param {Vector2} v The other Vector.
* @param {Vector2} The output Vector.
* @return {Vector2} The new Vector
*/
public div(v: Vector2, output?:Vector2 = new Vector2): Vector2 {
return output.setTo(this.x / v.x, this.y / v.y);
}
/**
* Scale this vector by the given values and return the result.
*
* @param {number} x The scaling factor in the x direction.
* @param {?number=} y The scaling factor in the y direction. If this
* is not specified, the x scaling factor will be used.
* @return {Vector} The new Vector
*/
public scale(x: number, y?:number = null, output?:Vector2 = new Vector2): Vector2 {
if (y === null)
{
y = x;
}
return output.setTo(this.x * x, this.y * y);
}
/**
* Rotate this vector by 90 degrees
*
* @return {Vector} This for chaining.
*/
public perp(output?: Vector2 = this): Vector2 {
var x = this.x;
return output.setTo(this.y, -x);
}
// Same as copyFrom, used by VerletManager
public mutableSet(v: Vector2): Vector2 {
this.x = v.x;
this.y = v.y;
return this;
}
/**
* Add another vector to this one.
*
* @param {Vector} other The other Vector.
* @return {Vector} This for chaining.
*/
public mutableAdd(v: Vector2): Vector2 {
this.x += v.x;
this.y += v.y;
return this;
}
/**
* Subtract another vector from this one.
*
* @param {Vector} other The other Vector.
* @return {Vector} This for chaining.
*/
public mutableSub(v: Vector2): Vector2 {
this.x -= v.x;
this.y -= v.y;
return this;
}
/**
* Multiply another vector with this one.
*
* @param {Vector} other The other Vector.
* @return {Vector} This for chaining.
*/
public mutableMul(v: Vector2): Vector2 {
this.x *= v.x;
this.y *= v.y;
return this;
}
/**
* Divide this vector by another one.
*
* @param {Vector} other The other Vector.
* @return {Vector} This for chaining.
*/
public mutableDiv(v: Vector2): Vector2 {
this.x /= v.x;
this.y /= v.y;
return this;
}
/**
* Scale this vector.
*
* @param {number} x The scaling factor in the x direction.
* @param {?number=} y The scaling factor in the y direction. If this
* is not specified, the x scaling factor will be used.
* @return {Vector} This for chaining.
*/
public mutableScale(x: number, y?:number): Vector2 {
this.x *= x;
this.y *= y || x;
return this;
}
/**
* Multiply this vector by the given scalar.
*
* @param {number} scalar
* @return {Vector2} This for chaining.
*/
public mutableMultiplyByScalar(scalar: number): Vector2 {
this.x *= scalar;
this.y *= scalar;
return this;
}
/**
* Divide this vector by the given scalar.
*
* @param {number} scalar
* @return {Vector2} This for chaining.
*/
public mutableDivideByScalar(scalar: number): Vector2 {
this.x /= scalar;
this.y /= scalar;
return this;
}
/**
* Reverse this vector.
*
* @return {Vector} This for chaining.
*/
public reverse(): Vector2 {
this.x = -this.x;
this.y = -this.y;
return this;
}
public edge(v: Vector2, output?: Vector2 = new Vector2): Vector2 {
return this.sub(v, output);
}
public equals(v: Vector2): bool {
return this.x == v.x && this.y == v.y;
}
public epsilonEquals(v: Vector2, epsilon:number): bool {
return Math.abs(this.x - v.x) <= epsilon && Math.abs(this.y - v.y) <= epsilon;
}
/**
* Get the length of this vector.
*
* @return {number} The length of this vector.
*/
public length(): number {
return Math.sqrt((this.x * this.x) + (this.y * this.y));
}
/**
* Get the length^2 of this vector.
*
* @return {number} The length^2 of this vector.
*/
public length2(): number {
return (this.x * this.x) + (this.y * this.y);
}
/**
* Get the distance between this vector and the given vector.
*
* @return {Vector2} v The vector to check
*/
public distance(v: Vector2): number {
return Math.sqrt(this.distance2(v));
}
/**
* Get the distance^2 between this vector and the given vector.
*
* @return {Vector2} v The vector to check
*/
public distance2(v: Vector2): number {
return ((v.x - this.x) * (v.x - this.x)) + ((v.y - this.y) * (v.y - this.y));
}
/**
* Project this vector on to another vector.
*
* @param {Vector} other The vector to project onto.
* @return {Vector} This for chaining.
*/
public project(other: Vector2): Vector2 {
var amt = this.dot(other) / other.length2();
if (amt != 0)
{
this.x = amt * other.x;
this.y = amt * other.y;
}
return this;
}
/**
* Project this vector onto a vector of unit length.
*
* @param {Vector} other The unit vector to project onto.
* @return {Vector} This for chaining.
*/
public projectN(other: Vector2): Vector2 {
var amt = this.dot(other);
if (amt != 0)
{
this.x = amt * other.x;
this.y = amt * other.y;
}
return this;
}
/**
* Reflect this vector on an arbitrary axis.
*
* @param {Vector} axis The vector representing the axis.
* @return {Vector} This for chaining.
*/
public reflect(axis): Vector2 {
var x = this.x;
var y = this.y;
this.project(axis).scale(2);
this.x -= x;
this.y -= y;
return this;
}
/**
* Reflect this vector on an arbitrary axis (represented by a unit vector)
*
* @param {Vector} axis The unit vector representing the axis.
* @return {Vector} This for chaining.
*/
public reflectN(axis): Vector2 {
var x = this.x;
var y = this.y;
this.projectN(axis).scale(2);
this.x -= x;
this.y -= y;
return this;
}
public getProjectionMagnitude(v: Vector2): number {
var den = v.dot(v);
if (den == 0)
{
return 0;
}
else
{
return Math.abs(this.dot(v) / den);
}
}
public direction(output?: Vector2 = new Vector2): Vector2 {
output.copyFrom(this);
return this.normalize(output);
}
public normalRightHand(output?: Vector2 = this): Vector2 {
return output.setTo(this.y * -1, this.x);
}
/**
* Normalize (make unit length) this vector.
*
* @return {Vector} This for chaining.
*/
public normalize(output?: Vector2 = this): Vector2 {
var m = this.length();
if (m != 0)
{
output.setTo(this.x / m, this.y / m);
}
return output;
}
public getMagnitude(): number {
return Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2));
}
/**
* Get the dot product of this vector against another.
*
* @param {Vector} other The vector to dot this one against.
* @return {number} The dot product.
*/
public dot(v: Vector2): number {
return ((this.x * v.x) + (this.y * v.y));
}
/**
* Get the cross product of this vector against another.
*
* @param {Vector} other The vector to cross this one against.
* @return {number} The cross product.
*/
public cross(v: Vector2): number {
return ((this.x * v.y) - (this.y * v.x));
}
/**
* Get the angle between this vector and the given vector.
*
* @return {Vector2} v The vector to check
*/
public angle(v: Vector2): number {
return Math.atan2(this.x * v.y - this.y * v.x, this.x * v.x + this.y * v.y);
}
public angle2(vLeft: Vector2, vRight: Vector2): number {
return vLeft.sub(this).angle(vRight.sub(this));
}
/**
* Rotate this vector around the origin to the given angle (theta) and return the result in a new Vector
*
* @return {Vector2} v The vector to check
*/
public rotate(origin, theta, output?: Vector2 = new Vector2): Vector2 {
var x = this.x - origin.x;
var y = this.y - origin.y;
return output.setTo(x * Math.cos(theta) - y * Math.sin(theta) + origin.x, x * Math.sin(theta) + y * Math.cos(theta) + origin.y);
}
public clone(output?: Vector2 = new Vector2): Vector2 {
return output.setTo(this.x, this.y);
}
public copyFrom(v: Vector2): Vector2 {
this.x = v.x;
this.y = v.y;
return this;
}
public copyTo(v: Vector2): Vector2 {
return v.setTo(this.x, this.y);
}
/**
* Returns a string representation of this object.
* @method toString
* @return {string} a string representation of the object.
**/
public toString(): string {
return "[{Vector2 (x=" + this.x + " y=" + this.y + ")}]";
}
}
}
+3 -3
View File
@@ -1,13 +1,13 @@
/**
* Phaser
*
* v0.9.3 - April 22nd 2013
* v0.9.6 - May 21st 2013
*
* A small and feature-packed 2D canvas game framework born from the firey pits of Flixel and Kiwi.
*
* Richard Davey (@photonstorm)
*
* Many thanks to Adam Saltsman (@ADAMATOMIC) for the original Flixel AS3 code on which Phaser is based.
* Many thanks to Adam Saltsman (@ADAMATOMIC) for releasing Flixel on which Phaser took a lot of inspiration.
*
* "If you want your children to be intelligent, read them fairy tales."
* "If you want them to be more intelligent, read them more fairy tales."
@@ -15,5 +15,5 @@
*/
var Phaser;
(function (Phaser) {
Phaser.VERSION = 'Phaser version 0.9.3';
Phaser.VERSION = 'Phaser version 0.9.6';
})(Phaser || (Phaser = {}));
+80
View File
@@ -0,0 +1,80 @@
/// <reference path="../gameobjects/Sprite.d.ts" />
/// <reference path="../Game.d.ts" />
module Phaser {
class Camera {
constructor(game: Game, id: number, x: number, y: number, width: number, height: number);
private _game;
private _clip;
private _stageX;
private _stageY;
private _rotation;
private _target;
private _sx;
private _sy;
private _fxFlashColor;
private _fxFlashComplete;
private _fxFlashDuration;
private _fxFlashAlpha;
private _fxFadeColor;
private _fxFadeComplete;
private _fxFadeDuration;
private _fxFadeAlpha;
private _fxShakeIntensity;
private _fxShakeDuration;
private _fxShakeComplete;
private _fxShakeOffset;
private _fxShakeDirection;
private _fxShakePrevX;
private _fxShakePrevY;
static STYLE_LOCKON: number;
static STYLE_PLATFORMER: number;
static STYLE_TOPDOWN: number;
static STYLE_TOPDOWN_TIGHT: number;
static SHAKE_BOTH_AXES: number;
static SHAKE_HORIZONTAL_ONLY: number;
static SHAKE_VERTICAL_ONLY: number;
public ID: number;
public worldView: Rectangle;
public totalSpritesRendered: number;
public scale: MicroPoint;
public scroll: MicroPoint;
public bounds: Rectangle;
public deadzone: Rectangle;
public showBorder: bool;
public borderColor: string;
public opaque: bool;
private _bgColor;
private _bgTexture;
private _bgTextureRepeat;
public showShadow: bool;
public shadowColor: string;
public shadowBlur: number;
public shadowOffset: MicroPoint;
public visible: bool;
public alpha: number;
public inputX: number;
public inputY: number;
public fx: FXManager;
public flash(color?: number, duration?: number, onComplete?, force?: bool): void;
public fade(color?: number, duration?: number, onComplete?, force?: bool): void;
public shake(intensity?: number, duration?: number, onComplete?, force?: bool, direction?: number): void;
public stopFX(): void;
public follow(target: Sprite, style?: number): void;
public focusOnXY(x: number, y: number): void;
public focusOn(point): void;
public setBounds(x?: number, y?: number, width?: number, height?: number): void;
public update(): void;
public render(): void;
public backgroundColor : string;
public setTexture(key: string, repeat?: string): void;
public setPosition(x: number, y: number): void;
public setSize(width: number, height: number): void;
public renderDebugInfo(x: number, y: number, color?: string): void;
public x : number;
public y : number;
public width : number;
public height : number;
public rotation : number;
private checkClip();
}
}
+243 -265
View File
@@ -14,14 +14,16 @@ module Phaser {
export class Camera {
/**
* Instantiates a new camera at the specified location, with the specified size and zoom level.
*
* @param X X location of the camera's display in pixels. Uses native, 1:1 resolution, ignores zoom.
* @param Y Y location of the camera's display in pixels. Uses native, 1:1 resolution, ignores zoom.
* @param Width The width of the camera display in pixels.
* @param Height The height of the camera display in pixels.
* @param Zoom The initial zoom level of the camera. A zoom level of 2 will make all pixels display at 2x resolution.
*/
*Sprite constructor
* Instantiates a new camera at the specified location, with the specified size and zoom level.
*
* @param game {Phaser.Game} Current game instance.
* @param id {number} Unique identity.
* @param x {number} X location of the camera's display in pixels. Uses native, 1:1 resolution, ignores zoom.
* @param y {number} Y location of the camera's display in pixels. Uses native, 1:1 resolution, ignores zoom.
* @param width {number} The width of the camera display in pixels.
* @param height {number} The height of the camera display in pixels.
*/
constructor(game: Game, id: number, x: number, y: number, width: number, height: number) {
this._game = game;
@@ -29,6 +31,7 @@ module Phaser {
this.ID = id;
this._stageX = x;
this._stageY = y;
this.fx = new FXManager(this._game, this);
// The view into the world canvas we wish to render
this.worldView = new Rectangle(0, 0, width, height);
@@ -37,6 +40,9 @@ module Phaser {
}
/**
* Local private reference to Game.
*/
private _game: Game;
private _clip: bool = false;
@@ -47,180 +53,184 @@ module Phaser {
private _sx: number = 0;
private _sy: number = 0;
private _fxFlashColor: string;
private _fxFlashComplete = null;
private _fxFlashDuration: number = 0;
private _fxFlashAlpha: number = 0;
private _fxFadeColor: string;
private _fxFadeComplete = null;
private _fxFadeDuration: number = 0;
private _fxFadeAlpha: number = 0;
private _fxShakeIntensity: number = 0;
private _fxShakeDuration: number = 0;
private _fxShakeComplete = null;
private _fxShakeOffset: Point = new Point(0, 0);
private _fxShakeDirection: number = 0;
private _fxShakePrevX: number = 0;
private _fxShakePrevY: number = 0;
/**
* Camera "follow" style preset: camera has no deadzone, just tracks the focus object directly.
* @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}
*/
public static STYLE_TOPDOWN_TIGHT: number = 3;
public static SHAKE_BOTH_AXES: number = 0;
public static SHAKE_HORIZONTAL_ONLY: number = 1;
public static SHAKE_VERTICAL_ONLY: number = 2;
/**
* 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;
public scale: Point = new Point(1, 1);
public scroll: Point = new Point(0, 0);
/**
* 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}
*/
public deadzone: Rectangle = null;
// 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
public opaque: bool = true;
/**
* 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 = 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}
*/
private _bgTextureRepeat: string = 'repeat';
// Camera Shadow
/**
* Render camera shadow or not. (default is false)
* @type {boolean}
*/
public showShadow: bool = false;
public shadowColor: string = 'rgb(0,0,0)';
public shadowBlur: number = 10;
public shadowOffset: Point = new Point(4, 4);
/**
* 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}
*/
public shadowOffset: MicroPoint = new MicroPoint(4, 4);
/**
* Whether this camera visible or not. (default is true)
* @type {boolean}
*/
public visible: bool = true;
/**
* Alpha of the camera. (everything rendered to this camera will be affected)
* @type {number}
*/
public alpha: number = 1;
// The x/y position of the current input event in world coordinates
/**
* The x position of the current input event in world coordinates.
* @type {number}
*/
public inputX: number = 0;
/**
* The y position of the current input event in world coordinates.
* @type {number}
*/
public inputY: number = 0;
/**
* The camera is filled with this color and returns to normal at the given duration.
*
* @param Color The color you want to use in 0xRRGGBB format, i.e. 0xffffff for white.
* @param Duration How long it takes for the flash to fade.
* @param OnComplete An optional function you want to run when the flash finishes. Set to null for no callback.
* @param Force Force an already running flash effect to reset.
*/
public flash(color: number = 0xffffff, duration: number = 1, onComplete = null, force: bool = false) {
if (force === false && this._fxFlashAlpha > 0)
{
// You can't flash again unless you force it
return;
}
if (duration <= 0)
{
duration = 1;
}
var red = color >> 16 & 0xFF;
var green = color >> 8 & 0xFF;
var blue = color & 0xFF;
this._fxFlashColor = 'rgba(' + red + ',' + green + ',' + blue + ',';
this._fxFlashDuration = duration;
this._fxFlashAlpha = 1;
this._fxFlashComplete = onComplete;
}
/**
* The camera is gradually filled with this color.
*
* @param Color The color you want to use in 0xRRGGBB format, i.e. 0xffffff for white.
* @param Duration How long it takes for the flash to fade.
* @param OnComplete An optional function you want to run when the flash finishes. Set to null for no callback.
* @param Force Force an already running flash effect to reset.
*/
public fade(color: number = 0x000000, duration: number = 1, onComplete = null, force: bool = false) {
if (force === false && this._fxFadeAlpha > 0)
{
// You can't fade again unless you force it
return;
}
if (duration <= 0)
{
duration = 1;
}
var red = color >> 16 & 0xFF;
var green = color >> 8 & 0xFF;
var blue = color & 0xFF;
this._fxFadeColor = 'rgba(' + red + ',' + green + ',' + blue + ',';
this._fxFadeDuration = duration;
this._fxFadeAlpha = 0.01;
this._fxFadeComplete = onComplete;
}
/**
* A simple screen-shake effect.
*
* @param Intensity Percentage of screen size representing the maximum distance that the screen can move while shaking.
* @param Duration The length in seconds that the shaking effect should last.
* @param OnComplete A function you want to run when the shake effect finishes.
* @param Force Force the effect to reset (default = true, unlike flash() and fade()!).
* @param Direction Whether to shake on both axes, just up and down, or just side to side (use class constants SHAKE_BOTH_AXES, SHAKE_VERTICAL_ONLY, or SHAKE_HORIZONTAL_ONLY).
*/
public shake(intensity: number = 0.05, duration: number = 0.5, onComplete = null, force: bool = true, direction: number = Camera.SHAKE_BOTH_AXES) {
if (!force && ((this._fxShakeOffset.x != 0) || (this._fxShakeOffset.y != 0)))
{
return;
}
// If a shake is not already running we need to store the offsets here
if (this._fxShakeOffset.x == 0 && this._fxShakeOffset.y == 0)
{
this._fxShakePrevX = this._stageX;
this._fxShakePrevY = this._stageY;
}
this._fxShakeIntensity = intensity;
this._fxShakeDuration = duration;
this._fxShakeComplete = onComplete;
this._fxShakeDirection = direction;
this._fxShakeOffset.setTo(0, 0);
}
/**
* Just turns off all the camera effects instantly.
* Effects manager.
* @type {FXManager}
*/
public stopFX() {
this._fxFlashAlpha = 0;
this._fxFadeAlpha = 0;
if (this._fxShakeDuration !== 0)
{
this._fxShakeDuration = 0;
this._fxShakeOffset.setTo(0, 0);
this._stageX = this._fxShakePrevX;
this._stageY = this._fxShakePrevY;
}
}
public fx: FXManager;
/**
* Tells this camera object what sprite to track.
* @param target {Sprite} The object you want the camera to track. Set to null to not follow anything.
* @param [style] {number} Leverage one of the existing "deadzone" presets. If you use a custom deadzone, ignore this parameter and manually specify the deadzone after calling follow().
*/
public follow(target: Sprite, style?: number = Camera.STYLE_LOCKON) {
this._target = target;
var helper: number;
switch (style)
@@ -246,6 +256,11 @@ module Phaser {
}
/**
* Move the camera focus to this location instantly.
* @param x {number} X position.
* @param y {number} Y position.
*/
public focusOnXY(x: number, y: number) {
x += (x > 0) ? 0.0000001 : -0.0000001;
@@ -256,7 +271,11 @@ module Phaser {
}
public focusOn(point: Point) {
/**
* Move the camera focus to this location instantly.
* @param point {any} Point you want to focus.
*/
public focusOn(point) {
point.x += (point.x > 0) ? 0.0000001 : -0.0000001;
point.y += (point.y > 0) ? 0.0000001 : -0.0000001;
@@ -268,35 +287,38 @@ module Phaser {
/**
* Specify the boundaries of the world or where the camera is allowed to move.
*
* @param X The smallest X value of your world (usually 0).
* @param Y The smallest Y value of your world (usually 0).
* @param Width The largest X value of your world (usually the world width).
* @param Height The largest Y value of your world (usually the world height).
* @param UpdateWorld Whether the global quad-tree's dimensions should be updated to match (default: false).
*
* @param x {number} The smallest X value of your world (usually 0).
* @param y {number} The smallest Y value of your world (usually 0).
* @param width {number} The largest X value of your world (usually the world width).
* @param height {number} The largest Y value of your world (usually the world height).
*/
public setBounds(X: number = 0, Y: number = 0, Width: number = 0, Height: number = 0, UpdateWorld: bool = false) {
public setBounds(x: number = 0, y: number = 0, width: number = 0, height: number = 0) {
if (this.bounds == null)
{
this.bounds = new Rectangle();
}
this.bounds.setTo(X, Y, Width, Height);
this.bounds.setTo(x, y, width, height);
//if(UpdateWorld)
// G.worldBounds.copyFrom(bounds);
this.scroll.setTo(0, 0);
this.update();
}
/**
* Update focusing and scrolling.
*/
public update() {
this.fx.preUpdate();
if (this._target !== null)
{
if (this.deadzone == null)
{
this.focusOnXY(this._target.x + this._target.origin.x, this._target.y + this._target.origin.y);
this.focusOnXY(this._target.x, this._target.y);
}
else
{
@@ -335,7 +357,7 @@ module Phaser {
}
// Make sure we didn't go outside the camera's bounds
// Make sure we didn't go outside the cameras bounds
if (this.bounds !== null)
{
if (this.scroll.x < this.bounds.left)
@@ -345,7 +367,7 @@ module Phaser {
if (this.scroll.x > this.bounds.right - this.width)
{
this.scroll.x = this.bounds.right - this.width;
this.scroll.x = (this.bounds.right - this.width) + 1;
}
if (this.scroll.y < this.bounds.top)
@@ -355,7 +377,7 @@ module Phaser {
if (this.scroll.y > this.bounds.bottom - this.height)
{
this.scroll.y = this.bounds.bottom - this.height;
this.scroll.y = (this.bounds.bottom - this.height) + 1;
}
}
@@ -366,77 +388,13 @@ module Phaser {
this.inputX = this.worldView.x + this._game.input.x;
this.inputY = this.worldView.y + this._game.input.y;
// Update the Flash effect
if (this._fxFlashAlpha > 0)
{
this._fxFlashAlpha -= this._game.time.elapsed / this._fxFlashDuration;
this._fxFlashAlpha = this._game.math.roundTo(this._fxFlashAlpha, -2);
if (this._fxFlashAlpha <= 0)
{
this._fxFlashAlpha = 0;
if (this._fxFlashComplete !== null)
{
this._fxFlashComplete();
}
}
}
// Update the Fade effect
if (this._fxFadeAlpha > 0)
{
this._fxFadeAlpha += this._game.time.elapsed / this._fxFadeDuration;
this._fxFadeAlpha = this._game.math.roundTo(this._fxFadeAlpha, -2);
if (this._fxFadeAlpha >= 1)
{
this._fxFadeAlpha = 1;
if (this._fxFadeComplete !== null)
{
this._fxFadeComplete();
}
}
}
// Update the "shake" special effect
if (this._fxShakeDuration > 0)
{
this._fxShakeDuration -= this._game.time.elapsed;
this._fxShakeDuration = this._game.math.roundTo(this._fxShakeDuration, -2);
if (this._fxShakeDuration <= 0)
{
this._fxShakeDuration = 0;
this._fxShakeOffset.setTo(0, 0);
this._stageX = this._fxShakePrevX;
this._stageY = this._fxShakePrevY;
if (this._fxShakeComplete != null)
{
this._fxShakeComplete();
}
}
else
{
if ((this._fxShakeDirection == Camera.SHAKE_BOTH_AXES) || (this._fxShakeDirection == Camera.SHAKE_HORIZONTAL_ONLY))
{
//this._fxShakeOffset.x = ((this._game.math.random() * this._fxShakeIntensity * this.worldView.width * 2 - this._fxShakeIntensity * this.worldView.width) * this._zoom;
this._fxShakeOffset.x = (this._game.math.random() * this._fxShakeIntensity * this.worldView.width * 2 - this._fxShakeIntensity * this.worldView.width);
}
if ((this._fxShakeDirection == Camera.SHAKE_BOTH_AXES) || (this._fxShakeDirection == Camera.SHAKE_VERTICAL_ONLY))
{
//this._fxShakeOffset.y = (this._game.math.random() * this._fxShakeIntensity * this.worldView.height * 2 - this._fxShakeIntensity * this.worldView.height) * this._zoom;
this._fxShakeOffset.y = (this._game.math.random() * this._fxShakeIntensity * this.worldView.height * 2 - this._fxShakeIntensity * this.worldView.height);
}
}
}
this.fx.postUpdate();
}
/**
* Draw background, shadow, effects, and objects if this is visible.
*/
public render() {
if (this.visible === false || this.alpha < 0.1)
@@ -444,22 +402,15 @@ module Phaser {
return;
}
if ((this._fxShakeOffset.x != 0) || (this._fxShakeOffset.y != 0))
if (this._rotation !== 0 || this._clip || this.scale.x !== 1 || this.scale.y !== 1)
{
//this._stageX = this._fxShakePrevX + (this.worldView.halfWidth * this._zoom) + this._fxShakeOffset.x;
//this._stageY = this._fxShakePrevY + (this.worldView.halfHeight * this._zoom) + this._fxShakeOffset.y;
this._stageX = this._fxShakePrevX + (this.worldView.halfWidth) + this._fxShakeOffset.x;
this._stageY = this._fxShakePrevY + (this.worldView.halfHeight) + this._fxShakeOffset.y;
//console.log('shake', this._fxShakeDuration, this._fxShakeIntensity, this._fxShakeOffset.x, this._fxShakeOffset.y);
this._game.stage.context.save();
}
//if (this._rotation !== 0 || this._clip || this.scale.x !== 1 || this.scale.y !== 1)
//{
// 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();
//}
// It may be safe/quicker to just save the context every frame regardless
this._game.stage.context.save();
this.fx.preRender(this, this._stageX, this._stageY, this.worldView.width, this.worldView.height);
if (this.alpha !== 1)
{
@@ -470,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;
@@ -496,6 +447,10 @@ 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)
@@ -513,15 +468,17 @@ module Phaser {
}
// Shadow off
if (this.showShadow)
if (this.showShadow == true)
{
this._game.stage.context.shadowBlur = 0;
this._game.stage.context.shadowOffsetX = 0;
this._game.stage.context.shadowOffsetY = 0;
}
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)
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);
@@ -531,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;
@@ -539,34 +496,23 @@ module Phaser {
this._game.stage.context.stroke();
}
// "Flash" FX
if (this._fxFlashAlpha > 0)
{
this._game.stage.context.fillStyle = this._fxFlashColor + this._fxFlashAlpha + ')';
this._game.stage.context.fillRect(this._sx, this._sy, this.worldView.width, this.worldView.height);
}
// "Fade" FX
if (this._fxFadeAlpha > 0)
{
this._game.stage.context.fillStyle = this._fxFadeColor + this._fxFadeAlpha + ')';
this._game.stage.context.fillRect(this._sx, this._sy, this.worldView.width, this.worldView.height);
}
// Scale off
if (this.scale.x !== 1 || this.scale.y !== 1)
{
this._game.stage.context.scale(1, 1);
}
if (this._rotation !== 0 || this._clip)
this.fx.postRender(this, this._sx, this._sy, this.worldView.width, this.worldView.height);
if (this._rotation !== 0 || (this._clip && this.disableClipping == false))
{
this._game.stage.context.translate(0, 0);
//this._game.stage.context.restore();
}
// maybe just do this every frame regardless?
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)
{
@@ -585,6 +531,11 @@ module Phaser {
return this._bgColor;
}
/**
* Set camera background texture.
* @param key {string} Asset key of the texture.
* @param [repeat] {string} what kind of repeat will this texture used for background.
*/
public setTexture(key: string, repeat?: string = 'repeat') {
this._bgTexture = this._game.stage.context.createPattern(this._game.cache.getImage(key), repeat);
@@ -592,6 +543,11 @@ module Phaser {
}
/**
* Set position of this camera.
* @param x {number} X position.
* @param y {number} Y position.
*/
public setPosition(x: number, y: number) {
this._stageX = x;
@@ -601,15 +557,25 @@ module Phaser {
}
/**
* Give this camera a new size.
* @param width {number} Width of new size.
* @param height {number} Height of new size.
*/
public setSize(width: number, height: number) {
this.worldView.width = width;
this.worldView.height = height;
this.checkClip();
}
/**
* Render debug infos. (including id, position, rotation, scrolling factor, bounds and some other properties)
* @param x {number} X position of the debug info to be rendered.
* @param y {number} Y position of the debug info to be rendered.
* @param [color] {number} color of the debug info to be rendered. (format is css color string)
*/
public renderDebugInfo(x: number, y: number, color?: string = 'rgb(255,255,255)') {
this._game.stage.context.fillStyle = color;
@@ -647,6 +613,12 @@ module Phaser {
}
public set width(value: number) {
if (value > this._game.stage.width)
{
value = this._game.stage.width;
}
this.worldView.width = value;
this.checkClip();
}
@@ -656,6 +628,12 @@ module Phaser {
}
public set height(value: number) {
if (value > this._game.stage.height)
{
value = this._game.stage.height;
}
this.worldView.height = value;
this.checkClip();
}
+501
View File
@@ -0,0 +1,501 @@
/// <reference path="../Game.ts" />
/**
* Phaser - CollisionMask
*/
module Phaser {
export class CollisionMask {
/**
* CollisionMask constructor. Creates a new <code>CollisionMask</code> for the given GameObject.
*
* @param game {Phaser.Game} Current game instance.
* @param parent {Phaser.GameObject} The GameObject this CollisionMask belongs to.
* @param x {number} The initial x position of the CollisionMask.
* @param y {number} The initial y position of the CollisionMask.
* @param width {number} The width of the CollisionMask.
* @param height {number} The height of the CollisionMask.
*/
constructor(game: Game, parent: GameObject, x: number, y: number, width: number, height: number) {
this._game = game;
this._parent = parent;
// By default the CollisionMask is a quad
this.type = CollisionMask.QUAD;
this.quad = new Phaser.Quad(this._parent.x, this._parent.y, this._parent.width, this._parent.height);
this.offset = new MicroPoint(0, 0);
this.last = new MicroPoint(0, 0);
this._ref = this.quad;
return this;
}
private _game;
private _parent;
// An internal reference to the active collision shape
private _ref;
/**
* Geom type of this sprite. (available: QUAD, POINT, CIRCLE, LINE, RECTANGLE, POLYGON)
* @type {number}
*/
public type: number = 0;
/**
* Quad (a smaller version of Rectangle).
* @type {number}
*/
public static QUAD: number = 0;
/**
* Point.
* @type {number}
*/
public static POINT: number = 1;
/**
* Circle.
* @type {number}
*/
public static CIRCLE: number = 2;
/**
* Line.
* @type {number}
*/
public static LINE: number = 3;
/**
* Rectangle.
* @type {number}
*/
public static RECTANGLE: number = 4;
/**
* Polygon.
* @type {number}
*/
public static POLYGON: number = 5;
/**
* Rectangle shape container. A Rectangle instance.
* @type {Rectangle}
*/
public quad: Quad;
/**
* Point shape container. A Point instance.
* @type {Point}
*/
public point: Point;
/**
* Circle shape container. A Circle instance.
* @type {Circle}
*/
public circle: Circle;
/**
* Line shape container. A Line instance.
* @type {Line}
*/
public line: Line;
/**
* Rectangle shape container. A Rectangle instance.
* @type {Rectangle}
*/
public rect: Rectangle;
/**
* A value from the top-left of the GameObject frame that this collisionMask is offset to.
* If the CollisionMask is a Quad/Rectangle the offset relates to the top-left of that Quad.
* If the CollisionMask is a Circle the offset relates to the center of the circle.
* @type {MicroPoint}
*/
public offset: MicroPoint;
/**
* The previous x/y coordinates of the CollisionMask, used for hull calculations
* @type {MicroPoint}
*/
public last: MicroPoint;
/**
* Create a circle shape with specific diameter.
* @param diameter {number} Diameter of the circle.
* @return {CollisionMask} This
*/
createCircle(diameter: number): CollisionMask {
this.type = CollisionMask.CIRCLE;
this.circle = new Circle(this.last.x, this.last.y, diameter);
this._ref = this.circle;
return this;
}
/**
* Pre-update is called right before update() on each object in the game loop.
*/
public preUpdate() {
this.last.x = this.x;
this.last.y = this.y;
}
public update() {
this._ref.x = this._parent.x + this.offset.x;
this._ref.y = this._parent.y + this.offset.y;
}
/**
* Renders the bounding box around this Sprite and the contact points. Useful for visually debugging.
* @param camera {Camera} Camera the bound will be rendered to.
* @param cameraOffsetX {number} X offset of bound to the camera.
* @param cameraOffsetY {number} Y offset of bound to the camera.
*/
public render(camera:Camera, cameraOffsetX:number, cameraOffsetY:number) {
var _dx = cameraOffsetX + (this.x - camera.worldView.x);
var _dy = cameraOffsetY + (this.y - camera.worldView.y);
this._parent.context.fillStyle = this._parent.renderDebugColor;
if (this.type == CollisionMask.QUAD)
{
this._parent.context.fillRect(_dx, _dy, this.width, this.height);
}
else if (this.type == CollisionMask.CIRCLE)
{
this._parent.context.beginPath();
this._parent.context.arc(_dx, _dy, this.circle.radius, 0, Math.PI * 2);
this._parent.context.fill();
this._parent.context.closePath();
}
}
/**
* Destroy all objects and references belonging to this CollisionMask
*/
public destroy() {
this._game = null;
this._parent = null;
this._ref = null;
this.quad = null;
this.point = null;
this.circle = null;
this.rect = null;
this.line = null;
this.offset = null;
}
public intersectsRaw(left: number, right: number, top: number, bottom: number): bool {
//if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height))
return true;
}
public intersectsVector(vector: Phaser.Vector2): bool {
if (this.type == CollisionMask.QUAD)
{
return this.quad.contains(vector.x, vector.y);
}
}
/**
* Gives a basic boolean response to a geometric collision.
* If you need the details of the collision use the Collision functions instead and inspect the IntersectResult object.
* @param source {GeomSprite} Sprite you want to check.
* @return {boolean} Whether they overlaps or not.
*/
public intersects(source: CollisionMask): bool {
// Quad vs. Quad
if (this.type == CollisionMask.QUAD && source.type == CollisionMask.QUAD)
{
return this.quad.intersects(source.quad);
}
// Circle vs. Circle
if (this.type == CollisionMask.CIRCLE && source.type == CollisionMask.CIRCLE)
{
return Collision.circleToCircle(this.circle, source.circle).result;
}
// Circle vs. Rect
if (this.type == CollisionMask.CIRCLE && source.type == CollisionMask.RECTANGLE)
{
return Collision.circleToRectangle(this.circle, source.rect).result;
}
// Circle vs. Point
if (this.type == CollisionMask.CIRCLE && source.type == CollisionMask.POINT)
{
return Collision.circleContainsPoint(this.circle, source.point).result;
}
// Circle vs. Line
if (this.type == CollisionMask.CIRCLE && source.type == CollisionMask.LINE)
{
return Collision.lineToCircle(source.line, this.circle).result;
}
// Rect vs. Rect
if (this.type == CollisionMask.RECTANGLE && source.type == CollisionMask.RECTANGLE)
{
return Collision.rectangleToRectangle(this.rect, source.rect).result;
}
// Rect vs. Circle
if (this.type == CollisionMask.RECTANGLE && source.type == CollisionMask.CIRCLE)
{
return Collision.circleToRectangle(source.circle, this.rect).result;
}
// Rect vs. Point
if (this.type == CollisionMask.RECTANGLE && source.type == CollisionMask.POINT)
{
return Collision.pointToRectangle(source.point, this.rect).result;
}
// Rect vs. Line
if (this.type == CollisionMask.RECTANGLE && source.type == CollisionMask.LINE)
{
return Collision.lineToRectangle(source.line, this.rect).result;
}
// Point vs. Point
if (this.type == CollisionMask.POINT && source.type == CollisionMask.POINT)
{
return this.point.equals(source.point);
}
// Point vs. Circle
if (this.type == CollisionMask.POINT && source.type == CollisionMask.CIRCLE)
{
return Collision.circleContainsPoint(source.circle, this.point).result;
}
// Point vs. Rect
if (this.type == CollisionMask.POINT && source.type == CollisionMask.RECTANGLE)
{
return Collision.pointToRectangle(this.point, source.rect).result;
}
// Point vs. Line
if (this.type == CollisionMask.POINT && source.type == CollisionMask.LINE)
{
return source.line.isPointOnLine(this.point.x, this.point.y);
}
// Line vs. Line
if (this.type == CollisionMask.LINE && source.type == CollisionMask.LINE)
{
return Collision.lineSegmentToLineSegment(this.line, source.line).result;
}
// Line vs. Circle
if (this.type == CollisionMask.LINE && source.type == CollisionMask.CIRCLE)
{
return Collision.lineToCircle(this.line, source.circle).result;
}
// Line vs. Rect
if (this.type == CollisionMask.LINE && source.type == CollisionMask.RECTANGLE)
{
return Collision.lineSegmentToRectangle(this.line, source.rect).result;
}
// Line vs. Point
if (this.type == CollisionMask.LINE && source.type == CollisionMask.POINT)
{
return this.line.isPointOnLine(source.point.x, source.point.y);
}
return false;
}
public checkHullIntersection(mask: CollisionMask): bool {
if ((this.hullX + this.hullWidth > mask.hullX) && (this.hullX < mask.hullX + mask.width) && (this.hullY + this.hullHeight > mask.hullY) && (this.hullY < mask.hullY + mask.hullHeight))
{
return true;
}
else
{
return false;
}
}
public get hullWidth(): number {
if (this.deltaX > 0)
{
return this.width + this.deltaX;
}
else
{
return this.width - this.deltaX;
}
}
public get hullHeight(): number {
if (this.deltaY > 0)
{
return this.height + this.deltaY;
}
else
{
return this.height - this.deltaY;
}
}
public get hullX(): number {
if (this.x < this.last.x)
{
return this.x;
}
else
{
return this.last.x;
}
}
public get hullY(): number {
if (this.y < this.last.y)
{
return this.y;
}
else
{
return this.last.y;
}
}
public get deltaXAbs(): number {
return (this.deltaX > 0 ? this.deltaX : -this.deltaX);
}
public get deltaYAbs(): number {
return (this.deltaY > 0 ? this.deltaY : -this.deltaY);
}
public get deltaX(): number {
return this.x - this.last.x;
}
public get deltaY(): number {
return this.y - this.last.y;
}
public get x(): number {
return this._ref.x;
//return this.quad.x;
}
public set x(value: number) {
this._ref.x = value;
//this.quad.x = value;
}
public get y(): number {
return this._ref.y;
//return this.quad.y;
}
public set y(value: number) {
this._ref.y = value;
//this.quad.y = value;
}
//public get rotation(): number {
// return this._angle;
//}
//public set rotation(value: number) {
// this._angle = this._game.math.wrap(value, 360, 0);
//}
//public get angle(): number {
// return this._angle;
//}
//public set angle(value: number) {
// this._angle = this._game.math.wrap(value, 360, 0);
//}
public set width(value:number) {
//this.quad.width = value;
this._ref.width = value;
}
public set height(value:number) {
//this.quad.height = value;
this._ref.height = value;
}
public get width(): number {
//return this.quad.width;
return this._ref.width;
}
public get height(): number {
//return this.quad.height;
return this._ref.height;
}
public get left(): number {
return this.x;
}
public get right(): number {
return this.x + this.width;
}
public get top(): number {
return this.y;
}
public get bottom(): number {
return this.y + this.height;
}
public get halfWidth(): number {
return this.width / 2;
}
public get halfHeight(): number {
return this.height / 2;
}
}
}
+49
View File
@@ -0,0 +1,49 @@
/// <reference path="../Game.d.ts" />
module Phaser {
class Device {
constructor();
public desktop: bool;
public iOS: bool;
public android: bool;
public chromeOS: bool;
public linux: bool;
public macOS: bool;
public windows: bool;
public canvas: bool;
public file: bool;
public fileSystem: bool;
public localStorage: bool;
public webGL: bool;
public worker: bool;
public touch: bool;
public css3D: bool;
public arora: bool;
public chrome: bool;
public epiphany: bool;
public firefox: bool;
public ie: bool;
public ieVersion: number;
public mobileSafari: bool;
public midori: bool;
public opera: bool;
public safari: bool;
public webApp: bool;
public audioData: bool;
public webaudio: bool;
public ogg: bool;
public mp3: bool;
public wav: bool;
public m4a: bool;
public iPhone: bool;
public iPhone4: bool;
public iPad: bool;
public pixelRatio: number;
private _checkOS();
private _checkFeatures();
private _checkBrowser();
private _checkAudio();
private _checkDevice();
private _checkCSS3D();
public getAll(): string;
}
}
+163 -169
View File
@@ -12,10 +12,8 @@ module Phaser {
export class Device {
/**
*
* @constructor
* @return {Device} This Object
*/
* Device constructor
*/
constructor() {
this._checkAudio();
@@ -29,260 +27,235 @@ module Phaser {
// Operating System
/**
* Is running desktop?
* @type {boolean}
*/
public desktop: bool = false;
/**
*
* @property iOS
* @type Boolean
*/
* Is running on iOS?
* @type {boolean}
*/
public iOS: bool = false;
/**
*
* @property android
* @type Boolean
*/
/**
* Is running on android?
* @type {boolean}
*/
public android: bool = false;
/**
*
* @property chromeOS
* @type Boolean
*/
* Is running on chromeOS?
* @type {boolean}
*/
public chromeOS: bool = false;
/**
*
* @property linux
* @type Boolean
*/
* Is running on linux?
* @type {boolean}
*/
public linux: bool = false;
/**
*
* @property maxOS
* @type Boolean
*/
* Is running on maxOS?
* @type {boolean}
*/
public macOS: bool = false;
/**
*
* @property windows
* @type Boolean
*/
* Is running on windows?
* @type {boolean}
*/
public windows: bool = false;
// Features
/**
*
* @property canvas
* @type Boolean
*/
* Is canvas available?
* @type {boolean}
*/
public canvas: bool = false;
/**
*
* @property file
* @type Boolean
*/
* Is file available?
* @type {boolean}
*/
public file: bool = false;
/**
*
* @property fileSystem
* @type Boolean
*/
* Is fileSystem available?
* @type {boolean}
*/
public fileSystem: bool = false;
/**
*
* @property localStorage
* @type Boolean
*/
* Is localStorage available?
* @type {boolean}
*/
public localStorage: bool = false;
/**
*
* @property webGL
* @type Boolean
*/
* Is webGL available?
* @type {boolean}
*/
public webGL: bool = false;
/**
*
* @property worker
* @type Boolean
*/
* Is worker available?
* @type {boolean}
*/
public worker: bool = false;
/**
*
* @property touch
* @type Boolean
*/
* Is touch available?
* @type {boolean}
*/
public touch: bool = false;
/**
*
* @property css3D
* @type Boolean
*/
* Is mspointer available?
* @type {boolean}
*/
public mspointer: bool = false;
/**
* Is css3D available?
* @type {boolean}
*/
public css3D: bool = false;
// Browser
/**
*
* @property arora
* @type Boolean
*/
* Is running in arora?
* @type {boolean}
*/
public arora: bool = false;
/**
*
* @property chrome
* @type Boolean
*/
* Is running in chrome?
* @type {boolean}
*/
public chrome: bool = false;
/**
*
* @property epiphany
* @type Boolean
*/
* Is running in epiphany?
* @type {boolean}
*/
public epiphany: bool = false;
/**
*
* @property firefox
* @type Boolean
*/
* Is running in firefox?
* @type {boolean}
*/
public firefox: bool = false;
/**
*
* @property ie
* @type Boolean
*/
* Is running in ie?
* @type {boolean}
*/
public ie: bool = false;
/**
*
* @property ieVersion
* @type Number
*/
* Version of ie?
* @type Number
*/
public ieVersion: number = 0;
/**
*
* @property mobileSafari
* @type Boolean
*/
* Is running in mobileSafari?
* @type {boolean}
*/
public mobileSafari: bool = false;
/**
*
* @property midori
* @type Boolean
*/
* Is running in midori?
* @type {boolean}
*/
public midori: bool = false;
/**
*
* @property opera
* @type Boolean
*/
* Is running in opera?
* @type {boolean}
*/
public opera: bool = false;
/**
*
* @property safari
* @type Boolean
*/
* Is running in safari?
* @type {boolean}
*/
public safari: bool = false;
public webApp: bool = false;
// Audio
/**
*
* @property audioData
* @type Boolean
*/
* Is audioData available?
* @type {boolean}
*/
public audioData: bool = false;
/**
*
* @property webaudio
* @type Boolean
*/
* Is webaudio available?
* @type {boolean}
*/
public webaudio: bool = false;
/**
*
* @property ogg
* @type Boolean
*/
* Is ogg available?
* @type {boolean}
*/
public ogg: bool = false;
/**
*
* @property mp3
* @type Boolean
*/
* Is mp3 available?
* @type {boolean}
*/
public mp3: bool = false;
/**
*
* @property wav
* @type Boolean
*/
* Is wav available?
* @type {boolean}
*/
public wav: bool = false;
/**
*
* @property m4a
* @type Boolean
*/
* Is m4a available?
* @type {boolean}
*/
public m4a: bool = false;
// Device
/**
*
* @property iPhone
* @type Boolean
*/
* Is running on iPhone?
* @type {boolean}
*/
public iPhone: bool = false;
/**
*
* @property iPhone4
* @type Boolean
*/
* Is running on iPhone4?
* @type {boolean}
*/
public iPhone4: bool = false;
/**
*
* @property iPad
* @type Boolean
*/
* Is running on iPad?
* @type {boolean}
*/
public iPad: bool = false;
/**
*
* @property pixelRatio
* @type Number
*/
* PixelRatio of the host device?
* @type Number
*/
public pixelRatio: number = 0;
/**
*
* @method _checkOS
* @private
*/
* Check which OS is game running on.
* @private
*/
private _checkOS() {
var ua = navigator.userAgent;
@@ -320,10 +293,9 @@ module Phaser {
}
/**
*
* @method _checkFeatures
* @private
*/
* Check HTML5 features of the host environment.
* @private
*/
private _checkFeatures() {
this.canvas = !!window['CanvasRenderingContext2D'];
@@ -347,13 +319,17 @@ module Phaser {
this.touch = true;
}
if (window.navigator.msPointerEnabled)
{
this.mspointer = true;
}
}
/**
*
* @method _checkBrowser
* @private
*/
* Check what browser is game running in.
* @private
*/
private _checkBrowser() {
var ua = navigator.userAgent;
@@ -405,10 +381,9 @@ module Phaser {
}
/**
*
* @method _checkAudio
* @private
*/
* Check audio support.
* @private
*/
private _checkAudio() {
this.audioData = !!(window['Audio']);
@@ -449,10 +424,9 @@ module Phaser {
}
/**
*
* @method _checkDevice
* @private
*/
* Check PixelRatio of devices.
* @private
*/
private _checkDevice() {
this.pixelRatio = window['devicePixelRatio'] || 1;
@@ -463,10 +437,9 @@ module Phaser {
}
/**
*
* @method _checkCSS3D
* @private
*/
* Check whether the host environment support 3D CSS.
* @private
*/
private _checkCSS3D() {
var el = document.createElement('p');
@@ -497,11 +470,31 @@ module Phaser {
}
public isConsoleOpen(): bool {
if (window.console && window.console['firebug'])
{
return true;
}
if (window.console)
{
console.profile();
console.profileEnd();
if (console.clear) console.clear();
return console['profiles'].length > 0;
}
return false;
}
/**
*
* @method getAll
* @return {String}
*/
* Get all informations of host device.
* @return {string} Informations in a string.
*/
public getAll(): string {
var output: string = '';
@@ -541,6 +534,7 @@ module Phaser {
output = output.concat('WebGL: ' + this.webGL + '\n');
output = output.concat('Worker: ' + this.worker + '\n');
output = output.concat('Touch: ' + this.touch + '\n');
output = output.concat('MSPointer: ' + this.mspointer + '\n');
output = output.concat('CSS 3D: ' + this.css3D + '\n');
output = output.concat('\n');
+9
View File
@@ -0,0 +1,9 @@
/// <reference path="../Game.d.ts" />
module Phaser {
class LinkedList {
constructor();
public object: Basic;
public next: LinkedList;
public destroy(): void;
}
}
+53
View File
@@ -0,0 +1,53 @@
/// <reference path="../Game.d.ts" />
/// <reference path="LinkedList.d.ts" />
module Phaser {
class QuadTree extends Rectangle {
constructor(X: number, Y: number, Width: number, Height: number, Parent?: QuadTree);
static A_LIST: number;
static B_LIST: number;
static divisions: number;
private _canSubdivide;
private _headA;
private _tailA;
private _headB;
private _tailB;
private static _min;
private _northWestTree;
private _northEastTree;
private _southEastTree;
private _southWestTree;
private _leftEdge;
private _rightEdge;
private _topEdge;
private _bottomEdge;
private _halfWidth;
private _halfHeight;
private _midpointX;
private _midpointY;
private static _object;
private static _objectLeftEdge;
private static _objectTopEdge;
private static _objectRightEdge;
private static _objectBottomEdge;
private static _list;
private static _useBothLists;
private static _processingCallback;
private static _notifyCallback;
private static _iterator;
private static _objectHullX;
private static _objectHullY;
private static _objectHullWidth;
private static _objectHullHeight;
private static _checkObjectHullX;
private static _checkObjectHullY;
private static _checkObjectHullWidth;
private static _checkObjectHullHeight;
public destroy(): void;
public load(ObjectOrGroup1: Basic, ObjectOrGroup2?: Basic, NotifyCallback?, ProcessCallback?): void;
public add(ObjectOrGroup: Basic, List: number): void;
private addObject();
private addToList();
public execute(): bool;
private overlapNode();
}
}
+65 -186
View File
@@ -15,33 +15,29 @@ module Phaser {
/**
* Instantiate a new Quad Tree node.
*
* @param X The X-coordinate of the point in space.
* @param Y The Y-coordinate of the point in space.
* @param Width Desired width of this node.
* @param Height Desired height of this node.
* @param Parent The parent branch or node. Pass null to create a root.
*
* @param {Number} x The X-coordinate of the point in space.
* @param {Number} y The Y-coordinate of the point in space.
* @param {Number} width Desired width of this node.
* @param {Number} height Desired height of this node.
* @param {Number} parent The parent branch or node. Pass null to create a root.
*/
constructor(X: number, Y: number, Width: number, Height: number, Parent: QuadTree = null) {
constructor(x: number, y: number, width: number, height: number, parent: QuadTree = null) {
super(X, Y, Width, Height);
//console.log('-------- QuadTree',X,Y,Width,Height);
super(x, y, width, height);
this._headA = this._tailA = new LinkedList();
this._headB = this._tailB = new LinkedList();
//Copy the parent's children (if there are any)
if (Parent != null)
if (parent != null)
{
//console.log('Parent not null');
var iterator: LinkedList;
var ot: LinkedList;
if (Parent._headA.object != null)
if (parent._headA.object != null)
{
iterator = Parent._headA;
//console.log('iterator set to parent headA');
iterator = parent._headA;
while (iterator != null)
{
@@ -57,10 +53,9 @@ module Phaser {
}
}
if (Parent._headB.object != null)
if (parent._headB.object != null)
{
iterator = Parent._headB;
//console.log('iterator set to parent headB');
iterator = parent._headB;
while (iterator != null)
{
@@ -83,8 +78,6 @@ module Phaser {
this._canSubdivide = (this.width > QuadTree._min) || (this.height > QuadTree._min);
//console.log('canSubdivided', this._canSubdivide);
//Set up comparison/sort helpers
this._northWestTree = null;
this._northEastTree = null;
@@ -215,26 +208,6 @@ module Phaser {
*/
private static _object;
/**
* Internal, used to reduce recursive method parameters during object placement and tree formation.
*/
private static _objectLeftEdge: number;
/**
* Internal, used to reduce recursive method parameters during object placement and tree formation.
*/
private static _objectTopEdge: number;
/**
* Internal, used to reduce recursive method parameters during object placement and tree formation.
*/
private static _objectRightEdge: number;
/**
* Internal, used to reduce recursive method parameters during object placement and tree formation.
*/
private static _objectBottomEdge: number;
/**
* Internal, used during tree processing and overlap checks.
*/
@@ -255,51 +228,16 @@ module Phaser {
*/
private static _notifyCallback;
/**
* Internal, used during tree processing and overlap checks.
*/
private static _callbackContext;
/**
* Internal, used during tree processing and overlap checks.
*/
private static _iterator: LinkedList;
/**
* Internal, helpers for comparing actual object-to-object overlap - see <code>overlapNode()</code>.
*/
private static _objectHullX: number;
/**
* Internal, helpers for comparing actual object-to-object overlap - see <code>overlapNode()</code>.
*/
private static _objectHullY: number;
/**
* Internal, helpers for comparing actual object-to-object overlap - see <code>overlapNode()</code>.
*/
private static _objectHullWidth: number;
/**
* Internal, helpers for comparing actual object-to-object overlap - see <code>overlapNode()</code>.
*/
private static _objectHullHeight: number;
/**
* Internal, helpers for comparing actual object-to-object overlap - see <code>overlapNode()</code>.
*/
private static _checkObjectHullX: number;
/**
* Internal, helpers for comparing actual object-to-object overlap - see <code>overlapNode()</code>.
*/
private static _checkObjectHullY: number;
/**
* Internal, helpers for comparing actual object-to-object overlap - see <code>overlapNode()</code>.
*/
private static _checkObjectHullWidth: number;
/**
* Internal, helpers for comparing actual object-to-object overlap - see <code>overlapNode()</code>.
*/
private static _checkObjectHullHeight: number;
/**
* Clean up memory.
*/
@@ -348,21 +286,20 @@ module Phaser {
/**
* Load objects and/or groups into the quad tree, and register notify and processing callbacks.
*
* @param ObjectOrGroup1 Any object that is or extends GameObject or Group.
* @param ObjectOrGroup2 Any object that is or extends GameObject or Group. If null, the first parameter will be checked against itself.
* @param NotifyCallback A function with the form <code>myFunction(Object1:GameObject,Object2:GameObject)</code> that is called whenever two objects are found to overlap in world space, and either no ProcessCallback is specified, or the ProcessCallback returns true.
* @param ProcessCallback A function with the form <code>myFunction(Object1:GameObject,Object2:GameObject):bool</code> that is called whenever two objects are found to overlap in world space. The NotifyCallback is only called if this function returns true. See GameObject.separate().
*
* @param {Basic} objectOrGroup1 Any object that is or extends GameObject or Group.
* @param {Basic} objectOrGroup2 Any object that is or extends GameObject or Group. If null, the first parameter will be checked against itself.
* @param {Function} notifyCallback A function with the form <code>myFunction(Object1:GameObject,Object2:GameObject)</code> that is called whenever two objects are found to overlap in world space, and either no processCallback is specified, or the processCallback returns true.
* @param {Function} processCallback A function with the form <code>myFunction(Object1:GameObject,Object2:GameObject):bool</code> that is called whenever two objects are found to overlap in world space. The notifyCallback is only called if this function returns true. See GameObject.separate().
* @param context The context in which the callbacks will be called
*/
public load(ObjectOrGroup1: Basic, ObjectOrGroup2: Basic = null, NotifyCallback = null, ProcessCallback = null) {
public load(objectOrGroup1: Basic, objectOrGroup2: Basic = null, notifyCallback = null, processCallback = null, context = null) {
//console.log('quadtree load', QuadTree.divisions, ObjectOrGroup1, ObjectOrGroup2);
this.add(objectOrGroup1, QuadTree.A_LIST);
this.add(ObjectOrGroup1, QuadTree.A_LIST);
if (ObjectOrGroup2 != null)
if (objectOrGroup2 != null)
{
this.add(ObjectOrGroup2, QuadTree.B_LIST);
this.add(objectOrGroup2, QuadTree.B_LIST);
QuadTree._useBothLists = true;
}
else
@@ -370,11 +307,9 @@ module Phaser {
QuadTree._useBothLists = false;
}
QuadTree._notifyCallback = NotifyCallback;
QuadTree._processingCallback = ProcessCallback;
//console.log('use both', QuadTree._useBothLists);
//console.log('------------ end of load');
QuadTree._notifyCallback = notifyCallback;
QuadTree._processingCallback = processCallback;
QuadTree._callbackContext = context;
}
@@ -382,20 +317,20 @@ module Phaser {
* Call this function to add an object to the root of the tree.
* This function will recursively add all group members, but
* not the groups themselves.
*
* @param ObjectOrGroup GameObjects are just added, Groups are recursed and their applicable members added accordingly.
* @param List A <code>uint</code> flag indicating the list to which you want to add the objects. Options are <code>QuadTree.A_LIST</code> and <code>QuadTree.B_LIST</code>.
*
* @param {Basic} objectOrGroup GameObjects are just added, Groups are recursed and their applicable members added accordingly.
* @param {Number} list A <code>uint</code> flag indicating the list to which you want to add the objects. Options are <code>QuadTree.A_LIST</code> and <code>QuadTree.B_LIST</code>.
*/
public add(ObjectOrGroup: Basic, List: number) {
public add(objectOrGroup: Basic, list: number) {
QuadTree._list = List;
QuadTree._list = list;
if (ObjectOrGroup.isGroup == true)
if (objectOrGroup.isGroup == true)
{
var i: number = 0;
var basic: Basic;
var members = <Group> ObjectOrGroup['members'];
var l: number = ObjectOrGroup['length'];
var members = <Group> objectOrGroup['members'];
var l: number = objectOrGroup['length'];
while (i < l)
{
@@ -405,7 +340,7 @@ module Phaser {
{
if (basic.isGroup)
{
this.add(basic, List);
this.add(basic, list);
}
else
{
@@ -413,10 +348,6 @@ module Phaser {
if (QuadTree._object.exists && QuadTree._object.allowCollisions)
{
QuadTree._objectLeftEdge = QuadTree._object.x;
QuadTree._objectTopEdge = QuadTree._object.y;
QuadTree._objectRightEdge = QuadTree._object.x + QuadTree._object.width;
QuadTree._objectBottomEdge = QuadTree._object.y + QuadTree._object.height;
this.addObject();
}
}
@@ -425,17 +356,10 @@ module Phaser {
}
else
{
QuadTree._object = ObjectOrGroup;
//console.log('add - not group:', ObjectOrGroup.name);
QuadTree._object = objectOrGroup;
if (QuadTree._object.exists && QuadTree._object.allowCollisions)
{
QuadTree._objectLeftEdge = QuadTree._object.x;
QuadTree._objectTopEdge = QuadTree._object.y;
QuadTree._objectRightEdge = QuadTree._object.x + QuadTree._object.width;
QuadTree._objectBottomEdge = QuadTree._object.y + QuadTree._object.height;
//console.log('object properties', QuadTree._objectLeftEdge, QuadTree._objectTopEdge, QuadTree._objectRightEdge, QuadTree._objectBottomEdge);
this.addObject();
}
}
@@ -447,23 +371,18 @@ module Phaser {
*/
private addObject() {
//console.log('addObject');
//If this quad (not its children) lies entirely inside this object, add it here
if (!this._canSubdivide || ((this._leftEdge >= QuadTree._objectLeftEdge) && (this._rightEdge <= QuadTree._objectRightEdge) && (this._topEdge >= QuadTree._objectTopEdge) && (this._bottomEdge <= QuadTree._objectBottomEdge)))
if (!this._canSubdivide || ((this._leftEdge >= QuadTree._object.collisionMask.x) && (this._rightEdge <= QuadTree._object.collisionMask.right) && (this._topEdge >= QuadTree._object.collisionMask.y) && (this._bottomEdge <= QuadTree._object.collisionMask.bottom)))
{
//console.log('add To List');
this.addToList();
return;
}
//See if the selected object fits completely inside any of the quadrants
if ((QuadTree._objectLeftEdge > this._leftEdge) && (QuadTree._objectRightEdge < this._midpointX))
if ((QuadTree._object.collisionMask.x > this._leftEdge) && (QuadTree._object.collisionMask.right < this._midpointX))
{
if ((QuadTree._objectTopEdge > this._topEdge) && (QuadTree._objectBottomEdge < this._midpointY))
if ((QuadTree._object.collisionMask.y > this._topEdge) && (QuadTree._object.collisionMask.bottom < this._midpointY))
{
//console.log('Adding NW tree');
if (this._northWestTree == null)
{
this._northWestTree = new QuadTree(this._leftEdge, this._topEdge, this._halfWidth, this._halfHeight, this);
@@ -473,10 +392,8 @@ module Phaser {
return;
}
if ((QuadTree._objectTopEdge > this._midpointY) && (QuadTree._objectBottomEdge < this._bottomEdge))
if ((QuadTree._object.collisionMask.y > this._midpointY) && (QuadTree._object.collisionMask.bottom < this._bottomEdge))
{
//console.log('Adding SW tree');
if (this._southWestTree == null)
{
this._southWestTree = new QuadTree(this._leftEdge, this._midpointY, this._halfWidth, this._halfHeight, this);
@@ -487,12 +404,10 @@ module Phaser {
}
}
if ((QuadTree._objectLeftEdge > this._midpointX) && (QuadTree._objectRightEdge < this._rightEdge))
if ((QuadTree._object.collisionMask.x > this._midpointX) && (QuadTree._object.collisionMask.right < this._rightEdge))
{
if ((QuadTree._objectTopEdge > this._topEdge) && (QuadTree._objectBottomEdge < this._midpointY))
if ((QuadTree._object.collisionMask.y > this._topEdge) && (QuadTree._object.collisionMask.bottom < this._midpointY))
{
//console.log('Adding NE tree');
if (this._northEastTree == null)
{
this._northEastTree = new QuadTree(this._midpointX, this._topEdge, this._halfWidth, this._halfHeight, this);
@@ -502,10 +417,8 @@ module Phaser {
return;
}
if ((QuadTree._objectTopEdge > this._midpointY) && (QuadTree._objectBottomEdge < this._bottomEdge))
if ((QuadTree._object.collisionMask.y > this._midpointY) && (QuadTree._object.collisionMask.bottom < this._bottomEdge))
{
//console.log('Adding SE tree');
if (this._southEastTree == null)
{
this._southEastTree = new QuadTree(this._midpointX, this._midpointY, this._halfWidth, this._halfHeight, this);
@@ -517,47 +430,43 @@ module Phaser {
}
//If it wasn't completely contained we have to check out the partial overlaps
if ((QuadTree._objectRightEdge > this._leftEdge) && (QuadTree._objectLeftEdge < this._midpointX) && (QuadTree._objectBottomEdge > this._topEdge) && (QuadTree._objectTopEdge < this._midpointY))
if ((QuadTree._object.collisionMask.right > this._leftEdge) && (QuadTree._object.collisionMask.x < this._midpointX) && (QuadTree._object.collisionMask.bottom > this._topEdge) && (QuadTree._object.collisionMask.y < this._midpointY))
{
if (this._northWestTree == null)
{
this._northWestTree = new QuadTree(this._leftEdge, this._topEdge, this._halfWidth, this._halfHeight, this);
}
//console.log('added to north west partial tree');
this._northWestTree.addObject();
}
if ((QuadTree._objectRightEdge > this._midpointX) && (QuadTree._objectLeftEdge < this._rightEdge) && (QuadTree._objectBottomEdge > this._topEdge) && (QuadTree._objectTopEdge < this._midpointY))
if ((QuadTree._object.collisionMask.right > this._midpointX) && (QuadTree._object.collisionMask.x < this._rightEdge) && (QuadTree._object.collisionMask.bottom > this._topEdge) && (QuadTree._object.collisionMask.y < this._midpointY))
{
if (this._northEastTree == null)
{
this._northEastTree = new QuadTree(this._midpointX, this._topEdge, this._halfWidth, this._halfHeight, this);
}
//console.log('added to north east partial tree');
this._northEastTree.addObject();
}
if ((QuadTree._objectRightEdge > this._midpointX) && (QuadTree._objectLeftEdge < this._rightEdge) && (QuadTree._objectBottomEdge > this._midpointY) && (QuadTree._objectTopEdge < this._bottomEdge))
if ((QuadTree._object.collisionMask.right > this._midpointX) && (QuadTree._object.collisionMask.x < this._rightEdge) && (QuadTree._object.collisionMask.bottom > this._midpointY) && (QuadTree._object.collisionMask.y < this._bottomEdge))
{
if (this._southEastTree == null)
{
this._southEastTree = new QuadTree(this._midpointX, this._midpointY, this._halfWidth, this._halfHeight, this);
}
//console.log('added to south east partial tree');
this._southEastTree.addObject();
}
if ((QuadTree._objectRightEdge > this._leftEdge) && (QuadTree._objectLeftEdge < this._midpointX) && (QuadTree._objectBottomEdge > this._midpointY) && (QuadTree._objectTopEdge < this._bottomEdge))
if ((QuadTree._object.collisionMask.right > this._leftEdge) && (QuadTree._object.collisionMask.x < this._midpointX) && (QuadTree._object.collisionMask.bottom > this._midpointY) && (QuadTree._object.collisionMask.y < this._bottomEdge))
{
if (this._southWestTree == null)
{
this._southWestTree = new QuadTree(this._leftEdge, this._midpointY, this._halfWidth, this._halfHeight, this);
}
//console.log('added to south west partial tree');
this._southWestTree.addObject();
}
@@ -568,13 +477,10 @@ module Phaser {
*/
private addToList() {
//console.log('Adding to List');
var ot: LinkedList;
if (QuadTree._list == QuadTree.A_LIST)
{
//console.log('A LIST');
if (this._tailA.object != null)
{
ot = this._tailA;
@@ -586,7 +492,6 @@ module Phaser {
}
else
{
//console.log('B LIST');
if (this._tailB.object != null)
{
ot = this._tailB;
@@ -628,20 +533,15 @@ module Phaser {
* <code>QuadTree</code>'s other main function. Call this after adding objects
* using <code>QuadTree.load()</code> to compare the objects that you loaded.
*
* @return Whether or not any overlaps were found.
* @return {Boolean} Whether or not any overlaps were found.
*/
public execute(): bool {
//console.log('quadtree execute');
var overlapProcessed: bool = false;
var iterator: LinkedList;
if (this._headA.object != null)
{
//console.log('---------------------------------------------------');
//console.log('headA iterator');
iterator = this._headA;
while (iterator != null)
@@ -659,7 +559,6 @@ module Phaser {
if (QuadTree._object.exists && (QuadTree._object.allowCollisions > 0) && (QuadTree._iterator != null) && (QuadTree._iterator.object != null) && QuadTree._iterator.object.exists && this.overlapNode())
{
//console.log('headA iterator overlapped true');
overlapProcessed = true;
}
@@ -671,25 +570,21 @@ module Phaser {
//Advance through the tree by calling overlap on each child
if ((this._northWestTree != null) && this._northWestTree.execute())
{
//console.log('NW quadtree execute');
overlapProcessed = true;
}
if ((this._northEastTree != null) && this._northEastTree.execute())
{
//console.log('NE quadtree execute');
overlapProcessed = true;
}
if ((this._southEastTree != null) && this._southEastTree.execute())
{
//console.log('SE quadtree execute');
overlapProcessed = true;
}
if ((this._southWestTree != null) && this._southWestTree.execute())
{
//console.log('SW quadtree execute');
overlapProcessed = true;
}
@@ -698,14 +593,12 @@ module Phaser {
}
/**
* An private for comparing an object against the contents of a node.
*
* @return Whether or not any overlaps were found.
* A private for comparing an object against the contents of a node.
*
* @return {Boolean} Whether or not any overlaps were found.
*/
private overlapNode(): bool {
//console.log('overlapNode');
//Walk the list and check for overlaps
var overlapProcessed: bool = false;
var checkObject;
@@ -714,7 +607,6 @@ module Phaser {
{
if (!QuadTree._object.exists || (QuadTree._object.allowCollisions <= 0))
{
//console.log('break 1');
break;
}
@@ -722,32 +614,12 @@ module Phaser {
if ((QuadTree._object === checkObject) || !checkObject.exists || (checkObject.allowCollisions <= 0))
{
//console.log('break 2');
QuadTree._iterator = QuadTree._iterator.next;
continue;
}
//calculate bulk hull for QuadTree._object
QuadTree._objectHullX = (QuadTree._object.x < QuadTree._object.last.x) ? QuadTree._object.x : QuadTree._object.last.x;
QuadTree._objectHullY = (QuadTree._object.y < QuadTree._object.last.y) ? QuadTree._object.y : QuadTree._object.last.y;
QuadTree._objectHullWidth = QuadTree._object.x - QuadTree._object.last.x;
QuadTree._objectHullWidth = QuadTree._object.width + ((QuadTree._objectHullWidth > 0) ? QuadTree._objectHullWidth : -QuadTree._objectHullWidth);
QuadTree._objectHullHeight = QuadTree._object.y - QuadTree._object.last.y;
QuadTree._objectHullHeight = QuadTree._object.height + ((QuadTree._objectHullHeight > 0) ? QuadTree._objectHullHeight : -QuadTree._objectHullHeight);
//calculate bulk hull for checkObject
QuadTree._checkObjectHullX = (checkObject.x < checkObject.last.x) ? checkObject.x : checkObject.last.x;
QuadTree._checkObjectHullY = (checkObject.y < checkObject.last.y) ? checkObject.y : checkObject.last.y;
QuadTree._checkObjectHullWidth = checkObject.x - checkObject.last.x;
QuadTree._checkObjectHullWidth = checkObject.width + ((QuadTree._checkObjectHullWidth > 0) ? QuadTree._checkObjectHullWidth : -QuadTree._checkObjectHullWidth);
QuadTree._checkObjectHullHeight = checkObject.y - checkObject.last.y;
QuadTree._checkObjectHullHeight = checkObject.height + ((QuadTree._checkObjectHullHeight > 0) ? QuadTree._checkObjectHullHeight : -QuadTree._checkObjectHullHeight);
//check for intersection of the two hulls
if ((QuadTree._objectHullX + QuadTree._objectHullWidth > QuadTree._checkObjectHullX) && (QuadTree._objectHullX < QuadTree._checkObjectHullX + QuadTree._checkObjectHullWidth) && (QuadTree._objectHullY + QuadTree._objectHullHeight > QuadTree._checkObjectHullY) && (QuadTree._objectHullY < QuadTree._checkObjectHullY + QuadTree._checkObjectHullHeight))
if (QuadTree._object.collisionMask.checkHullIntersection(checkObject.collisionMask))
{
//console.log('intersection!');
//Execute callback functions if they exist
if ((QuadTree._processingCallback == null) || QuadTree._processingCallback(QuadTree._object, checkObject))
{
@@ -756,7 +628,14 @@ module Phaser {
if (overlapProcessed && (QuadTree._notifyCallback != null))
{
QuadTree._notifyCallback(QuadTree._object, checkObject);
if (QuadTree._callbackContext !== null)
{
QuadTree._notifyCallback.call(QuadTree._callbackContext, QuadTree._object, checkObject);
}
else
{
QuadTree._notifyCallback(QuadTree._object, checkObject);
}
}
}
+26
View File
@@ -0,0 +1,26 @@
/// <reference path="../Game.d.ts" />
module Phaser {
class RandomDataGenerator {
constructor(seeds?: string[]);
private s0;
private s1;
private s2;
private c;
private uint32();
private fract32();
private rnd();
private hash(data);
public sow(seeds?: string[]): void;
public integer : number;
public frac : number;
public real : number;
public integerInRange(min: number, max: number): number;
public realInRange(min: number, max: number): number;
public normal : number;
public uuid : string;
public pick(array);
public weightedPick(array);
public timestamp(min?: number, max?: number): number;
public angle : number;
}
}
+20
View File
@@ -0,0 +1,20 @@
/// <reference path="../Game.d.ts" />
module Phaser {
class RequestAnimationFrame {
constructor(callback, callbackContext);
private _callback;
private _callbackContext;
public setCallback(callback): void;
private _timeOutID;
private _isSetTimeOut;
public isUsingSetTimeOut(): bool;
public isUsingRAF(): bool;
public lastTime: number;
public currentTime: number;
public isRunning: bool;
public start(callback?): void;
public stop(): void;
public RAFUpdate(): void;
public SetTimeoutUpdate(): void;
}
}
+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;
}
}

Some files were not shown because too many files have changed in this diff Show More