40 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
584 changed files with 69295 additions and 24899 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: 204 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

+82 -36
View File
@@ -3,6 +3,42 @@ module.exports = function (grunt) {
grunt.loadNpmTasks('grunt-contrib-watch'); grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-copy'); 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({ grunt.initConfig({
pkg: grunt.file.readJSON('package.json'), pkg: grunt.file.readJSON('package.json'),
typescript: { typescript: {
@@ -10,49 +46,59 @@ module.exports = function (grunt) {
src: ['Phaser/**/*.ts'], src: ['Phaser/**/*.ts'],
dest: 'build/phaser.js', dest: 'build/phaser.js',
options: { 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: { copy: {
main: { main: {
files: [{ files: [{
src: 'build/phaser.js', src: 'build/phaser.js',
dest: 'Tests/phaser.js' dest: 'Tests/phaser.js'
}] }]
}, },
amd: { fx: {
files: [{ files: [{
src: 'build/phaser.js', src: 'build/phaser-fx.js',
dest: 'build/phaser.amd.js' dest: 'Tests/phaser-fx.js'
}], }]
options: { },
processContent: function(content) { mainAmd: {
var replacement = [ files: [{
'(function (root, factory) {', src: 'build/phaser.js',
' if (typeof exports === \'object\') {', dest: 'build/phaser.amd.js'
' module.exports = factory();', }],
' } else if (typeof define === \'function\' && define.amd) {', options: {
' define(factory);', processContent: wrapPhaserInUmd
' } else {', }
' root.Phaser = factory();', },
' }', fxAmd: {
'}(this, function () {', files: [{
content, src: 'build/phaser-fx.js',
'return Phaser;', dest: 'build/phaser-fx.amd.js'
'}));' }],
]; options: {
return replacement.join('\n'); processContent: wrapAddonInUmd
} }
} }
} },
}, watch: {
watch: {
files: '**/*.ts', files: '**/*.ts',
tasks: ['typescript', 'copy'] 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 { export class AnimationManager {
/**
* AnimationManager constructor
* Create a new <code>AnimationManager</code>.
*
* @param parent {Sprite} Owner sprite of this manager.
*/
constructor(game: Game, parent: Sprite) { constructor(game: Game, parent: Sprite) {
this._game = game; this._game = game;
@@ -24,16 +30,47 @@ module Phaser {
} }
/**
* Local private reference to game.
*/
private _game: Game; private _game: Game;
/**
* Local private reference to its owner sprite.
*/
private _parent: Sprite; private _parent: Sprite;
/**
* Animation key-value container.
*/
private _anims: {}; private _anims: {};
/**
* Index of current frame.
* @type {number}
*/
private _frameIndex: number; private _frameIndex: number;
/**
* Data contains animation frames.
* @type {FrameData}
*/
private _frameData: FrameData = null; private _frameData: FrameData = null;
/**
* Keeps track of the current animation being played.
*/
public currentAnim: Animation; public currentAnim: Animation;
/**
* Keeps track of the current frame of animation.
*/
public currentFrame: Frame = null; public currentFrame: Frame = null;
/**
* Load animation frame data.
* @param frameData Data to be loaded.
*/
public loadFrameData(frameData: FrameData) { public loadFrameData(frameData: FrameData) {
this._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) if (this._frameData == null)
{ {
@@ -72,8 +118,16 @@ module Phaser {
this.currentAnim = this._anims[name]; this.currentAnim = this._anims[name];
this.currentFrame = this.currentAnim.currentFrame; 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 { private validateFrames(frames: any[], useNumericIndex: bool): bool {
for (var i = 0; i < frames.length; i++) 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) { public play(name: string, frameRate?: number = null, loop?: bool) {
if (this._anims[name]) 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) { public stop(name: string) {
if (this._anims[name]) if (this._anims[name])
@@ -128,13 +192,16 @@ module Phaser {
} }
/**
* Update animation and parent sprite's bounds.
*/
public update() { public update() {
if (this.currentAnim && this.currentAnim.update() == true) if (this.currentAnim && this.currentAnim.update() == true)
{ {
this.currentFrame = this.currentAnim.currentFrame; this.currentFrame = this.currentAnim.currentFrame;
this._parent.bounds.width = this.currentFrame.width; this._parent.frameBounds.width = this.currentFrame.width;
this._parent.bounds.height = this.currentFrame.height; this._parent.frameBounds.height = this.currentFrame.height;
} }
} }
@@ -144,7 +211,15 @@ module Phaser {
} }
public get frameTotal(): number { public get frameTotal(): number {
return this._frameData.total;
if (this._frameData)
{
return this._frameData.total;
}
else
{
return -1;
}
} }
public get frame(): number { public get frame(): number {
@@ -157,8 +232,8 @@ module Phaser {
{ {
this.currentFrame = this._frameData.getFrame(value); this.currentFrame = this._frameData.getFrame(value);
this._parent.bounds.width = this.currentFrame.width; this._parent.frameBounds.width = this.currentFrame.width;
this._parent.bounds.height = this.currentFrame.height; this._parent.frameBounds.height = this.currentFrame.height;
this._frameIndex = value; this._frameIndex = value;
} }
@@ -174,13 +249,26 @@ module Phaser {
{ {
this.currentFrame = this._frameData.getFrameByName(value); this.currentFrame = this._frameData.getFrameByName(value);
this._parent.bounds.width = this.currentFrame.width; this._parent.frameBounds.width = this.currentFrame.width;
this._parent.bounds.height = this.currentFrame.height; this._parent.frameBounds.height = this.currentFrame.height;
this._frameIndex = this.currentFrame.index; 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.visible = true;
this.alive = true; this.alive = true;
this.isGroup = false; this.isGroup = false;
this.ignoreGlobalUpdate = false;
this.ignoreGlobalRender = false;
this.ignoreDrawDebug = false; this.ignoreDrawDebug = false;
} }
@@ -70,6 +72,16 @@ module Phaser {
*/ */
public alive: bool; 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 * Setting this to true will prevent the object from appearing
* when the visual debug mode in the debugger overlay is toggled on. * 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. * Override this to update your class's position and appearance.
* This is where most of your game rules and behavioral code will go. * 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 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 { export class Cache {
/**
* Cache constructor
*/
constructor(game: Game) { constructor(game: Game) {
this._game = game; this._game = game;
@@ -22,19 +25,53 @@ module Phaser {
} }
/**
* Local private reference to game.
*/
private _game: Game; private _game: Game;
/**
* Canvas key-value container.
* @type {object}
*/
private _canvases; private _canvases;
/**
* Image key-value container.
* @type {object}
*/
private _images; private _images;
/**
* Sound key-value container.
* @type {object}
*/
private _sounds; private _sounds;
/**
* Text key-value container.
* @type {object}
*/
private _text; 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) { public addCanvas(key: string, canvas: HTMLCanvasElement, context: CanvasRenderingContext2D) {
this._canvases[key] = { canvas: canvas, context: context }; 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) { 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 }; 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] = { 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) { public addImage(key: string, url: string, data) {
this._images[key] = { url: url, data: data, spriteSheet: false }; 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) { public addSound(key: string, url: string, data) {
this._sounds[key] = { url: url, data: data, decoded: false }; 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) { public decodedSound(key: string, data) {
this._sounds[key].data = 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) { public addText(key: string, url: string, data) {
this._text[key] = { url: url, data: 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) { public getCanvas(key: string) {
if (this._canvases[key]) 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) { public getImage(key: string) {
if (this._images[key]) 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 { public getFrameData(key: string): FrameData {
if (this._images[key] && this._images[key].spriteSheet == true) 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) { public getSound(key: string) {
if (this._sounds[key]) 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 { public isSoundDecoded(key: string): bool {
if (this._sounds[key]) 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 { public isSpriteSheet(key: string): bool {
if (this._images[key]) 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) { public getText(key: string) {
if (this._text[key]) if (this._text[key])
@@ -147,6 +258,9 @@ module Phaser {
} }
/**
* Clean up cache memory.
*/
public destroy() { public destroy() {
for (var item in this._canvases) 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 * Your game only has one CameraManager instance and it's responsible for looking after, creating and destroying
* all of the cameras in the world. * 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 { module Phaser {
export class CameraManager { 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) { constructor(game: Game, x: number, y: number, width: number, height: number) {
this._game = game; this._game = game;
@@ -25,24 +31,58 @@ module Phaser {
} }
/**
* Local private reference to Game.
*/
private _game: Game; private _game: Game;
/**
* Local container for storing cameras.
*/
private _cameras: Camera[]; private _cameras: Camera[];
/**
* Local helper stores index of next created camera.
*/
private _cameraInstance: number = 0; private _cameraInstance: number = 0;
/**
* Currently used camera.
*/
public current: Camera; public current: Camera;
/**
* Get all the cameras.
*
* @returns {Camera[]} An array contains all the cameras.
*/
public getAll(): Camera[] { public getAll(): Camera[] {
return this._cameras; return this._cameras;
} }
/**
* Update cameras.
*/
public update() { public update() {
this._cameras.forEach((camera) => camera.update()); this._cameras.forEach((camera) => camera.update());
} }
/**
* Render cameras.
*/
public render() { public render() {
this._cameras.forEach((camera) => camera.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 { public addCamera(x: number, y: number, width: number, height: number): Camera {
var newCam: Camera = new Camera(this._game, this._cameraInstance, x, y, width, height); 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 { public removeCamera(id: number): bool {
for (var c = 0; c < this._cameras.length; c++) for (var c = 0; c < this._cameras.length; c++)
@@ -76,6 +122,9 @@ module Phaser {
} }
/**
* Clean up memory.
*/
public destroy() { public destroy() {
this._cameras.length = 0; 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;
}
}
+715 -61
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);
}
}
+121 -20
View File
@@ -13,6 +13,14 @@ module Phaser {
export class DynamicTexture { 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) { constructor(game: Game, width: number, height: number) {
this._game = game; this._game = game;
@@ -26,6 +34,9 @@ module Phaser {
} }
/**
* Local private reference to game.
*/
private _game: Game; private _game: Game;
private _sx: number = 0; private _sx: number = 0;
@@ -39,10 +50,30 @@ module Phaser {
// Input / Output nodes? // Input / Output nodes?
/**
* Bound of this texture with width and height info.
* @type {Rectangle}
*/
public bounds: Rectangle; public bounds: Rectangle;
/**
* This class is actually a wrapper of canvas.
* @type {HTMLCanvasElement}
*/
public canvas: HTMLCanvasElement; public canvas: HTMLCanvasElement;
/**
* Canvas context of this object.
* @type {CanvasRenderingContext2D}
*/
public context: 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 { public getPixel(x: number, y: number): number {
//r = imageData.data[0]; //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) { public getPixel32(x: number, y: number) {
var imageData = this.context.getImageData(x, y, 1, 1); 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) { public getPixels(rect: Rectangle) {
return this.context.getImageData(rect.x, rect.y, rect.width, rect.height); 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.fillStyle = color;
this.context.fillRect(x, y, 1, 1); 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) { public setPixel32(x: number, y: number, color: number) {
this.context.fillStyle = color; 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) { public setPixels(rect: Rectangle, input) {
this.context.putImageData(input, rect.x, rect.y); 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) { public fillRect(rect: Rectangle, color: number) {
this.context.fillStyle = color; 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) { public pasteImage(key: string, frame?: number = -1, destX?: number = 0, destY?: number = 0, destWidth?: number = null, destHeight?: number = null) {
var texture = null; var texture = null;
@@ -138,21 +204,27 @@ module Phaser {
if (texture != null) if (texture != null)
{ {
this.context.drawImage( this.context.drawImage(
texture, // Source Image texture, // Source Image
this._sx, // Source X (location within the source image) this._sx, // Source X (location within the source image)
this._sy, // Source Y this._sy, // Source Y
this._sw, // Source Width this._sw, // Source Width
this._sh, // Source Height this._sh, // Source Height
this._dx, // Destination X (where on the canvas it'll be drawn) this._dx, // Destination X (where on the canvas it'll be drawn)
this._dy, // Destination Y this._dy, // Destination Y
this._dw, // Destination Width (always same as Source Width unless scaled) this._dw, // Destination Width (always same as Source Width unless scaled)
this._dh // Destination Height (always same as Source Height 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 // 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) { 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 // 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() { public clear() {
this.context.clearRect(0, 0, this.bounds.width, this.bounds.height); 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 { public get width(): number {
return this.bounds.width; return this.bounds.width;
} }
@@ -184,12 +285,12 @@ module Phaser {
/** /**
* Given an alpha and 3 color values this will return an integer representation of it * 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 alpha {number} The Alpha value (between 0 and 255)
* @param red The Red channel value (between 0 and 255) * @param red {number} The Red channel value (between 0 and 255)
* @param green The Green channel value (between 0 and 255) * @param green {number} The Green channel value (between 0 and 255)
* @param blue The Blue 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) * @return A native color value integer (format: 0xAARRGGBB)
*/ */
private getColor32(alpha: number, red: number, green: number, blue: number): number { private getColor32(alpha: number, red: number, green: number, blue: number): number {
@@ -200,11 +301,11 @@ module Phaser {
/** /**
* Given 3 color values this will return an integer representation of it * Given 3 color values this will return an integer representation of it
* *
* @param red The Red channel value (between 0 and 255) * @param red {number} The Red channel value (between 0 and 255)
* @param green The Green channel value (between 0 and 255) * @param green {number} The Green channel value (between 0 and 255)
* @param blue The Blue 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) * @return A native color value integer (format: 0xRRGGBB)
*/ */
private getColor(red: number, green: number, blue: number): number { 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;
}
}
+303 -82
View File
@@ -4,7 +4,9 @@
/// <reference path="CameraManager.ts" /> /// <reference path="CameraManager.ts" />
/// <reference path="Collision.ts" /> /// <reference path="Collision.ts" />
/// <reference path="DynamicTexture.ts" /> /// <reference path="DynamicTexture.ts" />
/// <reference path="FXManager.ts" />
/// <reference path="GameMath.ts" /> /// <reference path="GameMath.ts" />
/// <reference path="GameObjectFactory.ts" />
/// <reference path="Group.ts" /> /// <reference path="Group.ts" />
/// <reference path="Loader.ts" /> /// <reference path="Loader.ts" />
/// <reference path="Motion.ts" /> /// <reference path="Motion.ts" />
@@ -14,13 +16,16 @@
/// <reference path="Stage.ts" /> /// <reference path="Stage.ts" />
/// <reference path="Time.ts" /> /// <reference path="Time.ts" />
/// <reference path="TweenManager.ts" /> /// <reference path="TweenManager.ts" />
/// <reference path="VerletManager.ts" />
/// <reference path="World.ts" /> /// <reference path="World.ts" />
/// <reference path="geom/Vector2.ts" />
/// <reference path="system/Device.ts" /> /// <reference path="system/Device.ts" />
/// <reference path="system/RandomDataGenerator.ts" /> /// <reference path="system/RandomDataGenerator.ts" />
/// <reference path="system/RequestAnimationFrame.ts" /> /// <reference path="system/RequestAnimationFrame.ts" />
/// <reference path="system/input/Input.ts" /> /// <reference path="system/input/Input.ts" />
/// <reference path="system/input/Keyboard.ts" /> /// <reference path="system/input/Keyboard.ts" />
/// <reference path="system/input/Mouse.ts" /> /// <reference path="system/input/Mouse.ts" />
/// <reference path="system/input/MSPointer.ts" />
/// <reference path="system/input/Touch.ts" /> /// <reference path="system/input/Touch.ts" />
/// <reference path="gameobjects/Emitter.ts" /> /// <reference path="gameobjects/Emitter.ts" />
/// <reference path="gameobjects/GameObject.ts" /> /// <reference path="gameobjects/GameObject.ts" />
@@ -44,13 +49,29 @@ module Phaser {
export class Game { 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.callbackContext = callbackContext;
this.onInitCallback = initCallback; this.onInitCallback = initCallback;
this.onCreateCallback = createCallback; this.onCreateCallback = createCallback;
this.onUpdateCallback = updateCallback; this.onUpdateCallback = updateCallback;
this.onRenderCallback = renderCallback; this.onRenderCallback = renderCallback;
this.onDestroyCallback = destroyCallback;
if (document.readyState === 'complete' || document.readyState === 'interactive') if (document.readyState === 'complete' || document.readyState === 'interactive')
{ {
@@ -64,38 +85,202 @@ module Phaser {
} }
private _raf: RequestAnimationFrame; /**
* Game loop trigger wrapper.
*/
public _raf: RequestAnimationFrame;
/**
* Max allowable accumulation.
* @type {number}
*/
private _maxAccumulation: number = 32; private _maxAccumulation: number = 32;
/**
* Total number of milliseconds elapsed since last update loop.
* @type {number}
*/
private _accumulator: number = 0; private _accumulator: number = 0;
/**
* Milliseconds of time per step of the game loop.
* @type {number}
*/
private _step: number = 0; private _step: number = 0;
/**
* Whether loader complete loading or not.
* @type {boolean}
*/
private _loadComplete: bool = false; private _loadComplete: bool = false;
/**
* Game is paused?
* @type {boolean}
*/
private _paused: bool = false; private _paused: bool = false;
/**
* The state to be switched to in the next frame.
* @type {State}
*/
private _pendingState = null; private _pendingState = null;
// Event callbacks /**
* The current State object (defaults to null)
* @type {State}
*/
public state = null;
/**
* Context for calling the callbacks.
*/
public callbackContext; public callbackContext;
/**
* This will be called when init states. (loading assets...)
* @type {function}
*/
public onInitCallback = null; public onInitCallback = null;
/**
* This will be called when create states. (setup states...)
* @type {function}
*/
public onCreateCallback = null; public onCreateCallback = null;
/**
* This will be called when update states.
* @type {function}
*/
public onUpdateCallback = null; public onUpdateCallback = null;
/**
* This will be called when render states.
* @type {function}
*/
public onRenderCallback = null; public onRenderCallback = null;
/**
* This will be called when states paused.
* @type {function}
*/
public onPausedCallback = null; public onPausedCallback = null;
/**
* 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; public cache: Cache;
/**
* Reference to the collision helper.
* @type {Collision}
*/
public collision: Collision; public collision: Collision;
/**
* Reference to the input manager
* @type {Input}
*/
public input: Input; public input: Input;
/**
* Reference to the assets loader.
* @type {Loader}
*/
public loader: Loader; public loader: Loader;
/**
* Reference to the math helper.
* @type {GameMath}
*/
public math: GameMath; public math: GameMath;
/**
* Reference to the motion helper.
* @type {Motion}
*/
public motion: Motion; public motion: Motion;
/**
* Reference to the sound manager.
* @type {SoundManager}
*/
public sound: SoundManager; public sound: SoundManager;
/**
* Reference to the stage.
* @type {Stage}
*/
public stage: Stage; public stage: Stage;
/**
* Reference to game clock.
* @type {Time}
*/
public time: Time; public time: Time;
/**
* Reference to the tween manager.
* @type {TweenManager}
*/
public tweens: 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; public world: World;
/**
* Instance of repeatable random data generator helper.
* @type {RandomDataGenerator}
*/
public rnd: RandomDataGenerator; public rnd: RandomDataGenerator;
/**
* Contains device information and capabilities.
* @type {Device}
*/
public device: Device; public device: Device;
/**
* Whether the game engine is booted, aka available.
* @type {boolean}
*/
public isBooted: bool = false; 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) { private boot(parent: string, width: number, height: number) {
if (this.isBooted == true) if (this.isBooted == true)
@@ -114,6 +299,7 @@ module Phaser {
this.math = new GameMath(this); this.math = new GameMath(this);
this.stage = new Stage(this, parent, width, height); this.stage = new Stage(this, parent, width, height);
this.world = new World(this, width, height); this.world = new World(this, width, height);
this.add = new GameObjectFactory(this);
this.sound = new SoundManager(this); this.sound = new SoundManager(this);
this.cache = new Cache(this); this.cache = new Cache(this);
this.collision = new Collision(this); this.collision = new Collision(this);
@@ -122,21 +308,23 @@ module Phaser {
this.tweens = new TweenManager(this); this.tweens = new TweenManager(this);
this.input = new Input(this); this.input = new Input(this);
this.rnd = new RandomDataGenerator([(Date.now() * Math.random()).toString()]); this.rnd = new RandomDataGenerator([(Date.now() * Math.random()).toString()]);
this.verlet = new Phaser.Verlet.VerletManager(this, width, height);
this.framerate = 60; this.framerate = 60;
this.isBooted = true;
this.input.start();
// Display the default game screen? // Display the default game screen?
if (this.onInitCallback == null && this.onCreateCallback == null && this.onUpdateCallback == null && this.onRenderCallback == null && this._pendingState == null) if (this.onInitCallback == null && this.onCreateCallback == null && this.onUpdateCallback == null && this.onRenderCallback == null && this._pendingState == null)
{ {
this.isBooted = false; this._raf = new RequestAnimationFrame(this, this.bootLoop);
this.stage.drawInitScreen();
} }
else else
{ {
this.isBooted = true; this.isRunning = true;
this._loadComplete = false; this._loadComplete = false;
this._raf = new RequestAnimationFrame(this.loop, this); this._raf = new RequestAnimationFrame(this, this.loop);
if (this._pendingState) if (this._pendingState)
{ {
@@ -153,32 +341,52 @@ module Phaser {
} }
/**
* Called when the loader has finished after init was run.
*/
private loadComplete() { private loadComplete() {
// Called when the loader has finished after init was run
this._loadComplete = true; this._loadComplete = true;
} }
private loop() { /**
* Game loop method will be called when it's booting.
*/
private bootLoop() {
this.time.update();
this.tweens.update(); this.tweens.update();
if (this._paused == true)
{
if (this.onPausedCallback !== null)
{
this.onPausedCallback.call(this.callbackContext);
}
return;
}
this.input.update(); this.input.update();
this.stage.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; this._accumulator += this.time.delta;
if (this._accumulator > this._maxAccumulation) if (this._accumulator > this._maxAccumulation)
@@ -207,6 +415,9 @@ module Phaser {
} }
/**
* Start current state.
*/
private startState() { private startState() {
if (this.onInitCallback !== null) if (this.onInitCallback !== null)
@@ -239,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.onInitCallback = initCallback;
this.onCreateCallback = createCallback; this.onCreateCallback = createCallback;
this.onUpdateCallback = updateCallback; this.onUpdateCallback = updateCallback;
this.onRenderCallback = renderCallback; 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) { public switchState(state, clearWorld: bool = true, clearCache: bool = false) {
if (this.isBooted == false) if (this.isBooted == false)
@@ -256,47 +482,61 @@ module Phaser {
return; return;
} }
// Destroy current state?
if (this.onDestroyCallback !== null)
{
this.onDestroyCallback.call(this.callbackContext);
}
this.input.reset(true);
// Prototype? // Prototype?
if (typeof state === 'function') if (typeof state === 'function')
{ {
state = new state(this); this.state = new state(this);
} }
// Ok, have we got the right functions? // 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.onInitCallback = null;
this.onCreateCallback = null; this.onCreateCallback = null;
this.onUpdateCallback = null; this.onUpdateCallback = null;
this.onRenderCallback = null; this.onRenderCallback = null;
this.onPausedCallback = null; this.onPausedCallback = null;
this.onDestroyCallback = null;
// Bingo, let's set them up // 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) if (clearWorld)
@@ -320,7 +560,9 @@ module Phaser {
} }
// Nuke the whole game from orbit /**
* Nuke the whole game from orbit
*/
public destroy() { public destroy() {
this.callbackContext = null; this.callbackContext = null;
@@ -329,6 +571,7 @@ module Phaser {
this.onUpdateCallback = null; this.onUpdateCallback = null;
this.onRenderCallback = null; this.onRenderCallback = null;
this.onPausedCallback = null; this.onPausedCallback = null;
this.onDestroyCallback = null;
this.cache = null; this.cache = null;
this.input = null; this.input = null;
this.loader = null; this.loader = null;
@@ -349,12 +592,22 @@ module Phaser {
if (value == true && this._paused == false) if (value == true && this._paused == false)
{ {
this._paused = true; this._paused = true;
this._raf.callback = this.pausedLoop;
} }
else if (value == false && this._paused == true) else if (value == false && this._paused == true)
{ {
this._paused = false; this._paused = false;
this.time.time = Date.now(); //this.time.time = window.performance.now ? (performance.now() + performance.timing.navigationStart) : Date.now();
this.input.reset(); this.input.reset();
if (this.isRunning == false)
{
this._raf.callback = this.bootLoop;
}
else
{
this._raf.callback = this.loop;
}
} }
} }
@@ -374,50 +627,18 @@ module Phaser {
} }
// Handy Proxy methods /**
* Checks for overlaps between two objects using the world QuadTree. Can be GameObject vs. GameObject, GameObject vs. Group or Group vs. Group.
public createCamera(x: number, y: number, width: number, height: number): Camera { * Note: Does not take the objects scrollFactor into account. All overlaps are check in world space.
return this.world.createCamera(x, y, width, height); * @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.
public createGeomSprite(x: number, y: number): GeomSprite { * @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.
return this.world.createGeomSprite(x, y); * @param context The context in which the callbacks will be called
} * @returns {boolean} true if the objects overlap, otherwise false.
*/
public createSprite(x: number, y: number, key?: string = ''): Sprite { public collide(objectOrGroup1: Basic = null, objectOrGroup2: Basic = null, notifyCallback = null, context? = this.callbackContext): bool {
return this.world.createSprite(x, y, key); return this.collision.overlap(objectOrGroup1, objectOrGroup2, notifyCallback, Collision.separate, context);
}
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 { public get camera(): Camera {
+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;
}
}
+76 -14
View File
@@ -166,7 +166,7 @@ module Phaser {
* *
* @param input - the value to snap * @param input - the value to snap
* @param gap - the interval gap of the grid * @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 { public snapTo(input: number, gap: number, start: number = 0): number {
if (gap == 0) return input; if (gap == 0) return input;
@@ -183,7 +183,7 @@ module Phaser {
* *
* @param input - the value to snap * @param input - the value to snap
* @param gap - the interval gap of the grid * @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 { public snapToFloor(input: number, gap: number, start: number = 0): number {
if (gap == 0) return input; if (gap == 0) return input;
@@ -200,7 +200,7 @@ module Phaser {
* *
* @param input - the value to snap * @param input - the value to snap
* @param gap - the interval gap of the grid * @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 { public snapToCeil(input: number, gap: number, start: number = 0): number {
if (gap == 0) return input; if (gap == 0) return input;
@@ -855,29 +855,27 @@ module Phaser {
/** /**
* Fetch a random entry from the given array. * Fetch a random entry from the given array.
* Will return null if random selection is missing, or array has no entries. * 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 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 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 length Optional restriction on the number of values you want to randomly select from.
* *
* @return The random object that was selected. * @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) if (l > 0)
{ {
return Objects[StartIndex + Math.floor(Math.random() * l)]; return objects[startIndex + Math.floor(Math.random() * l)];
} }
} }
@@ -1005,6 +1003,70 @@ module Phaser {
return ax * bx + ay * by; 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;
}
}
+164 -61
View File
@@ -5,7 +5,6 @@
* Phaser - Group * Phaser - Group
* *
* This class is used for organising, updating and sorting game objects. * This class is used for organising, updating and sorting game objects.
*
*/ */
module Phaser { module Phaser {
@@ -22,9 +21,31 @@ module Phaser {
this._maxSize = MaxSize; this._maxSize = MaxSize;
this._marker = 0; this._marker = 0;
this._sortIndex = null; 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. * Use with <code>sort()</code> to sort in ascending order.
*/ */
@@ -48,25 +69,62 @@ module Phaser {
public length: number; public length: number;
/** /**
* Internal tracker for the maximum capacity of the group. * You can set a globalCompositeOperation that will be applied before the render method is called on this Groups children.
* Default is 0, or no max capacity. * 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, * 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. * 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 basic: Basic;
var i: number = 0; var i: number = 0;
@@ -108,10 +171,10 @@ module Phaser {
{ {
basic = this.members[i++]; basic = this.members[i++];
if ((basic != null) && basic.exists && basic.active) if ((basic != null) && basic.exists && basic.active && basic.ignoreGlobalUpdate == false)
{ {
basic.preUpdate(); basic.preUpdate();
basic.update(); basic.update(forceUpdate);
basic.postUpdate(); basic.postUpdate();
} }
} }
@@ -120,7 +183,29 @@ module Phaser {
/** /**
* Automatically goes through and calls render on everything you added. * 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 basic: Basic;
var i: number = 0; var i: number = 0;
@@ -129,11 +214,21 @@ module Phaser {
{ {
basic = this.members[i++]; 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. * 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, * 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. * 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, * <p>WARNING: If the group has a maxSize that has already been met,
* the object will NOT be added to the group!</p> * the object will NOT be added to the group!</p>
* *
* @param Object The object you want to add to the group. * @param {Basic} Object The object you want to add to the group.
* * @return {Basic} The same <code>Basic</code> object that was passed in.
* @return 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. //Don't bother adding an object twice.
if (this.members.indexOf(Object) >= 0) if (this.members.indexOf(Object) >= 0)
@@ -269,9 +363,9 @@ module Phaser {
* and no object class was provided, it will return null * and no object class was provided, it will return null
* instead of a valid object!</p> * 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! * @param {class} 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;). * @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) { public recycle(ObjectClass = null) {
@@ -321,21 +415,21 @@ module Phaser {
/** /**
* Removes an object from the group. * Removes an object from the group.
* *
* @param Object The <code>Basic</code> you want to remove. * @param {Basic} object The <code>Basic</code> you want to remove.
* @param Splice Whether the object should be cut from the array entirely or not. * @param {boolean} splice Whether the object should be cut from the array entirely or not.
* *
* @return The removed object. * @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)) if ((index < 0) || (index >= this.members.length))
{ {
return null; return null;
} }
if (Splice) if (splice)
{ {
this.members.splice(index, 1); this.members.splice(index, 1);
this.length--; this.length--;
@@ -345,30 +439,30 @@ module Phaser {
this.members[index] = null; this.members[index] = null;
} }
return Object; return object;
} }
/** /**
* Replaces an existing <code>Basic</code> with a new one. * Replaces an existing <code>Basic</code> with a new one.
* *
* @param OldObject The object you want to replace. * @param {Basic} oldObject The object you want to replace.
* @param NewObject The new object you want to use instead. * @param {Basic} newObject The new object you want to use instead.
* *
* @return The new object. * @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)) if ((index < 0) || (index >= this.members.length))
{ {
return null; return null;
} }
this.members[index] = NewObject; this.members[index] = newObject;
return NewObject; return newObject;
} }
@@ -379,13 +473,13 @@ module Phaser {
* <code>State.update()</code> override. To sort all existing objects after * <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>. * 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 {string} 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 {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._sortIndex = index;
this._sortOrder = Order; this._sortOrder = order;
this.members.sort(this.sortHandler); this.members.sort(this.sortHandler);
} }
@@ -393,9 +487,9 @@ module Phaser {
/** /**
* Go through and set the specified variable to the specified value on all members of the group. * 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 {string} 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 {Object} 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 {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) { public setAll(VariableName: string, Value: Object, Recurse: bool = true) {
@@ -424,8 +518,8 @@ module Phaser {
* Go through and call the specified function on all members of the group. * Go through and call the specified function on all members of the group.
* Currently only works on functions that have no required parameters. * 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 {string} 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 {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) { public callAll(FunctionName: string, Recurse: bool = true) {
@@ -450,6 +544,10 @@ module Phaser {
} }
} }
/**
* @param {function} callback
* @param {boolean} recursive
*/
public forEach(callback, recursive: bool = false) { public forEach(callback, recursive: bool = false) {
var basic; var basic;
@@ -474,6 +572,11 @@ module Phaser {
} }
/**
* @param {any} context
* @param {function} callback
* @param {boolean} recursive
*/
public forEachAlive(context, callback, recursive: bool = false) { public forEachAlive(context, callback, recursive: bool = false) {
var basic; var basic;
@@ -502,9 +605,9 @@ module Phaser {
* Call this function to retrieve the first object with exists == false in the group. * 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. * 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. * @param {any} [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. * @return {any} A <code>Basic</code> currently flagged as not existing.
*/ */
public getFirstAvailable(ObjectClass = null) { public getFirstAvailable(ObjectClass = null) {
@@ -529,7 +632,7 @@ module Phaser {
* Call this function to retrieve the first index set to 'null'. * Call this function to retrieve the first index set to 'null'.
* Returns -1 if no index stores a null object. * 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 { public getFirstNull(): number {
@@ -557,7 +660,7 @@ module Phaser {
* Call this function to retrieve the first object with exists == true in the group. * 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. * 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 { public getFirstExtant(): Basic {
@@ -582,7 +685,7 @@ module Phaser {
* Call this function to retrieve the first object with dead == false in the group. * 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. * 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 { public getFirstAlive(): Basic {
@@ -607,7 +710,7 @@ module Phaser {
* Call this function to retrieve the first object with dead == true in the group. * 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. * 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 { public getFirstDead(): Basic {
@@ -631,7 +734,7 @@ module Phaser {
/** /**
* Call this function to find out how many members of the group are not dead. * 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 { public countLiving(): number {
@@ -664,7 +767,7 @@ module Phaser {
/** /**
* Call this function to find out how many members of the group are dead. * 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 { public countDead(): number {
@@ -697,10 +800,10 @@ module Phaser {
/** /**
* Returns a member at random from the group. * 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 {number} 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 {number} Length Optional restriction on the number of values you want to randomly select from.
* *
* @return A <code>Basic</code> from the members list. * @return {Basic} A <code>Basic</code> from the members list.
*/ */
public getRandom(StartIndex: number = 0, Length: number = 0): Basic { public getRandom(StartIndex: number = 0, Length: number = 0): Basic {
@@ -744,10 +847,10 @@ module Phaser {
/** /**
* Helper function for the sort process. * Helper function for the sort process.
* *
* @param Obj1 The first object being sorted. * @param {Basic} Obj1 The first object being sorted.
* @param Obj2 The second object being sorted. * @param {Basic} Obj2 The second object being sorted.
* *
* @return An integer value: -1 (Obj1 before Obj2), 0 (same), or 1 (Obj1 after Obj2). * @return {number} An integer value: -1 (Obj1 before Obj2), 0 (same), or 1 (Obj1 after Obj2).
*/ */
public sortHandler(Obj1: Basic, Obj2: Basic): number { 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);
}
}
+236 -33
View File
@@ -11,6 +11,12 @@ module Phaser {
export class Loader { 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) { constructor(game: Game, callback) {
this._game = game; this._game = game;
@@ -22,19 +28,70 @@ module Phaser {
} }
/**
* Local private reference to game.
*/
private _game: Game; private _game: Game;
/**
* Array stors assets keys. So you can get that asset by its unique key.
*/
private _keys: string[]; private _keys: string[];
/**
* Contains all the assets file infos.
*/
private _fileList; private _fileList;
/**
* Game initialial assets loading callback.
*/
private _gameCreateComplete; private _gameCreateComplete;
private _onComplete; private _onComplete;
private _onFileLoad; private _onFileLoad;
/**
* Indicates assets loading progress. (from 0 to 100)
* @type {number}
*/
private _progressChunk: number; private _progressChunk: number;
private _xhr: XMLHttpRequest; private _xhr: XMLHttpRequest;
/**
* Length of assets queue.
* @type {number}
*/
private _queueSize: number; private _queueSize: number;
/**
* True if game is completely loaded.
* @type {boolean}
*/
public hasLoaded: bool; public hasLoaded: bool;
/**
* Loading progress (from 0 to 1)
* @type {number}
*/
public progress: 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() { public reset() {
this._queueSize = 0; 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) { public addImageFile(key: string, url: string) {
if (this.checkKeyExists(key) === false) 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) { public addSpriteSheet(key: string, url: string, frameWidth: number, frameHeight: number, frameMax?: number = -1) {
if (this.checkKeyExists(key) === false) 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 (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._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); this._keys.push(key);
} }
else else
{ {
// A json string or object has been given if (format == Loader.TEXTURE_ATLAS_JSON_ARRAY)
if (typeof jsonData === 'string')
{ {
var data = JSON.parse(jsonData); // A json string or object has been given
// Malformed? if (typeof atlasData === 'string')
if (data['frames'])
{ {
this._queueSize++; atlasData = JSON.parse(atlasData);
this._fileList[key] = { type: 'textureatlas', key: key, url: url, data: null, jsonURL: null, jsonData: data['frames'], error: false, loaded: false };
this._keys.push(key);
} }
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? // An xml string or object has been given
if (jsonData['frames']) if (typeof atlasData === 'string')
{ {
this._queueSize++; var xml;
this._fileList[key] = { type: 'textureatlas', key: key, url: url, data: null, jsonURL: null, jsonData: jsonData['frames'], error: false, loaded: false };
this._keys.push(key); 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) { public addAudioFile(key: string, url: string) {
if (this.checkKeyExists(key) === false) 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) { public addTextFile(key: string, url: string) {
if (this.checkKeyExists(key) === false) 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) { public removeFile(key: string) {
delete this._fileList[key]; delete this._fileList[key];
} }
/**
* Remove all file loading requests.
*/
public removeAll() { public removeAll() {
this._fileList = {}; 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) { public load(onFileLoadCallback = null, onCompleteCallback = null) {
this.progress = 0; this.progress = 0;
@@ -176,6 +306,9 @@ module Phaser {
} }
/**
* Load files. Private method ONLY used by loader.
*/
private loadFile() { private loadFile() {
var file = this._fileList[this._keys.pop()]; var file = this._fileList[this._keys.pop()];
@@ -191,6 +324,7 @@ module Phaser {
file.data.name = file.key; file.data.name = file.key;
file.data.onload = () => this.fileComplete(file.key); file.data.onload = () => this.fileComplete(file.key);
file.data.onerror = () => this.fileError(file.key); file.data.onerror = () => this.fileError(file.key);
file.data.crossOrigin = this.crossOrigin;
file.data.src = file.url; file.data.src = file.url;
break; 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) { private fileError(key: string) {
this._fileList[key].loaded = true; 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) { private fileComplete(key: string) {
this._fileList[key].loaded = true; this._fileList[key].loaded = true;
@@ -240,18 +382,27 @@ module Phaser {
break; break;
case 'textureatlas': 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 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; loadNext = false;
this._xhr.open("GET", file.jsonURL, true); this._xhr.open("GET", file.atlasURL, true);
this._xhr.responseType = "text"; 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(); this._xhr.send();
} }
break; 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) { private jsonLoadComplete(key: string) {
var data = JSON.parse(this._xhr.response); var data = JSON.parse(this._xhr.response);
var file = this._fileList[key];
// Malformed? this._game.cache.addTextureAtlas(file.key, file.url, file.data, data['frames'], file.format);
if (data['frames'])
{
var file = this._fileList[key];
this._game.cache.addTextureAtlas(file.key, file.url, file.data, data['frames']);
}
this.nextFile(key, true); 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]; var file = this._fileList[key];
file.error = true; file.error = true;
this.nextFile(key, 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) { private nextFile(previousKey: string, success: bool) {
this.progress = Math.round(this.progress + this._progressChunk); 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) 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 { private checkKeyExists(key: string): bool {
if (this._fileList[key]) 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;
}
}
+55 -55
View File
@@ -22,12 +22,12 @@ module Phaser {
/** /**
* A tween-like function that takes a starting velocity and some other factors and returns an altered velocity. * 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 {number} Velocity Any component of velocity (e.g. 20).
* @param Acceleration Rate at which the velocity is changing. * @param {number} 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 {number} 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. * @param {number} Max An absolute value cap for the velocity.
* *
* @return The altered Velocity value. * @return {number} The altered Velocity value.
*/ */
public computeVelocity(Velocity: number, Acceleration: number = 0, Drag: number = 0, Max: number = 10000): number { public computeVelocity(Velocity: number, Acceleration: number = 0, Drag: number = 0, Max: number = 10000): number {
@@ -72,10 +72,10 @@ module Phaser {
/** /**
* Given the angle and speed calculate the velocity and return it as a Point * 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 {number} 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 * @param {number} 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 * @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 { public velocityFromAngle(angle: number, speed: number): Point {
@@ -98,10 +98,10 @@ module Phaser {
* If you need the object to accelerate, see accelerateTowardsObject() instead * 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) * 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 {GameObject} source The Sprite on which the velocity will be set
* @param dest The Sprite where the source object will move to * @param {GameObject} 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 {number} 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 {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) public moveTowardsObject(source:GameObject, dest:GameObject, speed:number= 60, maxTime:number = 0)
{ {
@@ -125,11 +125,11 @@ module Phaser {
* You must give a maximum speed value, beyond which the Sprite won't go any faster.<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. * If you don't need acceleration look at moveTowardsObject() instead.
* *
* @param source The Sprite on which the acceleration will be set * @param {GameObject} source The Sprite on which the acceleration will be set
* @param dest The Sprite where the source object will move towards * @param {GameObject} dest The Sprite where the source object will move towards
* @param speed The speed it will accelerate in pixels per second * @param {number} 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 {number} 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 {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) public accelerateTowardsObject(source:GameObject, dest:GameObject, speed:number, xSpeedMax:number, ySpeedMax:number)
{ {
@@ -152,9 +152,9 @@ module Phaser {
* Timings are approximate due to the way Flash timers work, and irrespective of SWF frame rate. Allow for a variance of +- 50ms.<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> * The source object doesn't stop moving automatically should it ever reach the destination coordinates.<br>
* *
* @param source The Sprite to move * @param {GameObject} source The Sprite to move
* @param speed The speed it will move, in pixels per second (default is 60 pixels/sec) * @param {number} 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 {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) public moveTowardsMouse(source:GameObject, speed:number = 60, maxTime:number = 0)
{ {
@@ -178,10 +178,10 @@ module Phaser {
* You must give a maximum speed value, beyond which the Sprite won't go any faster.<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. * If you don't need acceleration look at moveTowardsMouse() instead.
* *
* @param source The Sprite on which the acceleration will be set * @param {GameObject} source The Sprite on which the acceleration will be set
* @param speed The speed it will accelerate in pixels per second * @param {number} 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 {number} 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 {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) public accelerateTowardsMouse(source:GameObject, speed:number, xSpeedMax:number, ySpeedMax:number)
{ {
@@ -203,10 +203,10 @@ module Phaser {
* Timings are approximate due to the way Flash timers work, and irrespective of SWF frame rate. Allow for a variance of +- 50ms.<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> * The source object doesn't stop moving automatically should it ever reach the destination coordinates.<br>
* *
* @param source The Sprite to move * @param {GameObject} source The Sprite to move
* @param target The Point coordinates to move the source Sprite towards * @param {Point} 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 {number} 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 {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) public moveTowardsPoint(source:GameObject, target:Point, speed:number = 60, maxTime:number = 0)
{ {
@@ -229,11 +229,11 @@ module Phaser {
* You must give a maximum speed value, beyond which the Sprite won't go any faster.<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. * If you don't need acceleration look at moveTowardsPoint() instead.
* *
* @param source The Sprite on which the acceleration will be set * @param {GameObject} source The Sprite on which the acceleration will be set
* @param target The Point coordinates to move the source Sprite towards * @param {Point} target The Point coordinates to move the source Sprite towards
* @param speed The speed it will accelerate in pixels per second * @param {number} 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 {number} 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 {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) public accelerateTowardsPoint(source:GameObject, target:Point, speed:number, xSpeedMax:number, ySpeedMax:number)
{ {
@@ -252,9 +252,9 @@ module Phaser {
/** /**
* Find the distance (in pixels, rounded) between two Sprites, taking their origin into account * Find the distance (in pixels, rounded) between two Sprites, taking their origin into account
* *
* @param a The first Sprite * @param {GameObject} a The first Sprite
* @param b The second Sprite * @param {GameObject} b The second Sprite
* @return int Distance (in pixels) * @return {number} int Distance (in pixels)
*/ */
public distanceBetween(a:GameObject, b:GameObject):number public distanceBetween(a:GameObject, b:GameObject):number
{ {
@@ -268,9 +268,9 @@ module Phaser {
/** /**
* Find the distance (in pixels, rounded) from an Sprite to the given Point, taking the source origin into account * Find the distance (in pixels, rounded) from an Sprite to the given Point, taking the source origin into account
* *
* @param a The Sprite * @param {GameObject} a The Sprite
* @param target The Point * @param {Point} target The Point
* @return int Distance (in pixels) * @return {number} Distance (in pixels)
*/ */
public distanceToPoint(a:GameObject, target:Point):number public distanceToPoint(a:GameObject, target:Point):number
{ {
@@ -283,8 +283,8 @@ module Phaser {
/** /**
* Find the distance (in pixels, rounded) from the object x/y and the mouse x/y * Find the distance (in pixels, rounded) from the object x/y and the mouse x/y
* *
* @param a The Sprite to test against * @param {GameObject} a Sprite to test against
* @return int The distance between the given sprite and the mouse coordinates * @return {number} The distance between the given sprite and the mouse coordinates
*/ */
public distanceToMouse(a:GameObject):number public distanceToMouse(a:GameObject):number
{ {
@@ -298,11 +298,11 @@ module Phaser {
* Find the angle (in radians) between an Sprite and an Point. The source sprite takes its x/y and origin into account. * 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) * 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 {GameObject} a The Sprite to test from
* @param target The Point to angle the Sprite towards * @param {Point} target The Point to angle the Sprite towards
* @param asDegrees If you need the value in degrees instead of radians, set to true * @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) * @return {number} The angle (in radians unless asDegrees is true)
*/ */
public angleBetweenPoint(a:GameObject, target:Point, asDegrees:bool = false):number public angleBetweenPoint(a:GameObject, target:Point, asDegrees:bool = false):number
{ {
@@ -323,11 +323,11 @@ module Phaser {
* Find the angle (in radians) between the two Sprite, taking their x/y and origin into account. * 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) * 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 {GameObject} a The Sprite to test from
* @param b The Sprite to test to * @param {GameObject} b The Sprite to test to
* @param asDegrees If you need the value in degrees instead of radians, set to true * @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) * @return {number} The angle (in radians unless asDegrees is true)
*/ */
public angleBetween(a:GameObject, b:GameObject, asDegrees:bool = false):number public angleBetween(a:GameObject, b:GameObject, asDegrees:bool = false):number
{ {
@@ -347,10 +347,10 @@ module Phaser {
/** /**
* Given the GameObject and speed calculate the velocity and return it as an Point based on the direction the sprite is facing * 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 {GameObject} parent The Sprite to get the facing value from
* @param speed The speed it will move, in pixels per second sq * @param {number} 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 * @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 public velocityFromFacing(parent:GameObject, speed:number):Point
{ {
@@ -381,10 +381,10 @@ module Phaser {
* Find the angle (in radians) between an Sprite and the mouse, taking their x/y and origin into account. * 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) * 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 {GameObject} a The Object to test from
* @param asDegrees If you need the value in degrees instead of radians, set to true * @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) * @return {number} The angle (in radians unless asDegrees is true)
*/ */
public angleBetweenMouse(a:GameObject, asDegrees:bool = false):number public angleBetweenMouse(a:GameObject, asDegrees:bool = false):number
{ {
+70 -4
View File
@@ -47,12 +47,14 @@
<TypeScriptIncludeComments>true</TypeScriptIncludeComments> <TypeScriptIncludeComments>true</TypeScriptIncludeComments>
<TypeScriptSourceMap>false</TypeScriptSourceMap> <TypeScriptSourceMap>false</TypeScriptSourceMap>
<TypeScriptOutFile>../build/phaser.js</TypeScriptOutFile> <TypeScriptOutFile>../build/phaser.js</TypeScriptOutFile>
<TypeScriptGeneratesDeclarations>true</TypeScriptGeneratesDeclarations>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'"> <PropertyGroup Condition="'$(Configuration)' == 'Release'">
<TypeScriptTarget>ES5</TypeScriptTarget> <TypeScriptTarget>ES5</TypeScriptTarget>
<TypeScriptIncludeComments>false</TypeScriptIncludeComments> <TypeScriptIncludeComments>false</TypeScriptIncludeComments>
<TypeScriptSourceMap>false</TypeScriptSourceMap> <TypeScriptSourceMap>false</TypeScriptSourceMap>
<TypeScriptOutFile>../build/phaser.js</TypeScriptOutFile> <TypeScriptOutFile>../build/phaser.js</TypeScriptOutFile>
<TypeScriptGeneratesDeclarations>true</TypeScriptGeneratesDeclarations>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Folder Include="plugins\" /> <Folder Include="plugins\" />
@@ -67,12 +69,20 @@
<Content Include="DynamicTexture.js"> <Content Include="DynamicTexture.js">
<DependentUpon>DynamicTexture.ts</DependentUpon> <DependentUpon>DynamicTexture.ts</DependentUpon>
</Content> </Content>
<TypeScriptCompile Include="FXManager.ts" />
<Content Include="FXManager.js">
<DependentUpon>FXManager.ts</DependentUpon>
</Content>
<Content Include="Game.js"> <Content Include="Game.js">
<DependentUpon>Game.ts</DependentUpon> <DependentUpon>Game.ts</DependentUpon>
</Content> </Content>
<Content Include="GameMath.js"> <Content Include="GameMath.js">
<DependentUpon>GameMath.ts</DependentUpon> <DependentUpon>GameMath.ts</DependentUpon>
</Content> </Content>
<TypeScriptCompile Include="GameObjectFactory.ts" />
<Content Include="GameObjectFactory.js">
<DependentUpon>GameObjectFactory.ts</DependentUpon>
</Content>
<Content Include="gameobjects\Emitter.js"> <Content Include="gameobjects\Emitter.js">
<DependentUpon>Emitter.ts</DependentUpon> <DependentUpon>Emitter.ts</DependentUpon>
</Content> </Content>
@@ -99,9 +109,33 @@
<Content Include="gameobjects\Tilemap.js"> <Content Include="gameobjects\Tilemap.js">
<DependentUpon>Tilemap.ts</DependentUpon> <DependentUpon>Tilemap.ts</DependentUpon>
</Content> </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"> <Content Include="geom\Circle.js">
<DependentUpon>Circle.ts</DependentUpon> <DependentUpon>Circle.ts</DependentUpon>
</Content> </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"> <Content Include="geom\IntersectResult.js">
<DependentUpon>IntersectResult.ts</DependentUpon> <DependentUpon>IntersectResult.ts</DependentUpon>
</Content> </Content>
@@ -112,6 +146,14 @@
<Content Include="geom\MicroPoint.js"> <Content Include="geom\MicroPoint.js">
<DependentUpon>MicroPoint.ts</DependentUpon> <DependentUpon>MicroPoint.ts</DependentUpon>
</Content> </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"> <Content Include="geom\Point.js">
<DependentUpon>Point.ts</DependentUpon> <DependentUpon>Point.ts</DependentUpon>
</Content> </Content>
@@ -122,9 +164,37 @@
<Content Include="geom\Rectangle.js"> <Content Include="geom\Rectangle.js">
<DependentUpon>Rectangle.ts</DependentUpon> <DependentUpon>Rectangle.ts</DependentUpon>
</Content> </Content>
<TypeScriptCompile Include="geom\Vector2.ts" />
<Content Include="geom\Vector2.js">
<DependentUpon>Vector2.ts</DependentUpon>
</Content>
<Content Include="SoundManager.js"> <Content Include="SoundManager.js">
<DependentUpon>SoundManager.ts</DependentUpon> <DependentUpon>SoundManager.ts</DependentUpon>
</Content> </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"> <Content Include="system\Sound.js">
<DependentUpon>Sound.ts</DependentUpon> <DependentUpon>Sound.ts</DependentUpon>
</Content> </Content>
@@ -215,9 +285,6 @@
<Content Include="system\easing\Sinusoidal.js"> <Content Include="system\easing\Sinusoidal.js">
<DependentUpon>Sinusoidal.ts</DependentUpon> <DependentUpon>Sinusoidal.ts</DependentUpon>
</Content> </Content>
<Content Include="system\input\Finger.js">
<DependentUpon>Finger.ts</DependentUpon>
</Content>
<Content Include="system\input\Input.js"> <Content Include="system\input\Input.js">
<DependentUpon>Input.ts</DependentUpon> <DependentUpon>Input.ts</DependentUpon>
</Content> </Content>
@@ -234,7 +301,6 @@
<TypeScriptCompile Include="system\input\Mouse.ts" /> <TypeScriptCompile Include="system\input\Mouse.ts" />
<TypeScriptCompile Include="system\input\Keyboard.ts" /> <TypeScriptCompile Include="system\input\Keyboard.ts" />
<TypeScriptCompile Include="system\input\Input.ts" /> <TypeScriptCompile Include="system\input\Input.ts" />
<TypeScriptCompile Include="system\input\Finger.ts" />
<TypeScriptCompile Include="system\easing\Sinusoidal.ts" /> <TypeScriptCompile Include="system\easing\Sinusoidal.ts" />
<TypeScriptCompile Include="system\easing\Quintic.ts" /> <TypeScriptCompile Include="system\easing\Quintic.ts" />
<TypeScriptCompile Include="system\easing\Quartic.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 * Phaser
* *
* v0.9.4 - April 28th 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. * A small and feature-packed 2D canvas game framework born from the firey pits of Flixel and Kiwi.
* *
* Richard Davey (@photonstorm) * 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 your children to be intelligent, read them fairy tales."
* "If you want them to be more intelligent, read them more fairy tales." * "If you want them to be more intelligent, read them more fairy tales."
@@ -16,6 +16,6 @@
module Phaser { module Phaser {
export var VERSION: string = 'Phaser version 0.9.4'; 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) 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); this._bindings.splice(i, 1);
} }
@@ -224,14 +224,17 @@ module Phaser {
*/ */
public removeAll() { public removeAll() {
var n: number = this._bindings.length; if (this._bindings)
while (n--)
{ {
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 { export class SoundManager {
/**
* SoundManager constructor
* Create a new <code>SoundManager</code>.
*/
constructor(game: Game) { constructor(game: Game) {
this._game = game; this._game = game;
@@ -36,18 +40,39 @@ module Phaser {
} }
/**
* Local private reference to game.
*/
private _game: Game; private _game: Game;
/**
* Reference to AudioContext instance.
*/
private _context = null; private _context = null;
/**
* Gain node created from audio context.
*/
private _gainNode; private _gainNode;
/**
* Volume of sounds.
* @type {number}
*/
private _volume: number; private _volume: number;
/**
* Mute sounds.
*/
public mute() { public mute() {
this._gainNode.gain.value = 0; this._gainNode.gain.value = 0;
} }
/**
* Enable sounds.
*/
public unmute() { public unmute() {
this._gainNode.gain.value = this._volume; this._gainNode.gain.value = this._volume;
@@ -65,6 +90,12 @@ module Phaser {
return this._volume; 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) { public decode(key: string, callback = null, sound?: Sound = null) {
var soundData = this._game.cache.getSound(key); 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 { public play(key: string, volume?: number = 1, loop?: bool = false): Sound {
if (this._context === null) if (this._context === null)
@@ -111,7 +149,7 @@ module Phaser {
var tempSound: Sound = new Sound(this._context, this._gainNode, null, volume, loop); 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 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; 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;
}
}
+155 -77
View File
@@ -1,6 +1,8 @@
/// <reference path="Phaser.ts" /> /// <reference path="Phaser.ts" />
/// <reference path="Game.ts" /> /// <reference path="Game.ts" />
/// <reference path="system/StageScaleMode.ts" /> /// <reference path="system/StageScaleMode.ts" />
/// <reference path="system/screens/BootScreen.ts" />
/// <reference path="system/screens/PauseScreen.ts" />
/** /**
* Phaser - Stage * Phaser - Stage
@@ -13,6 +15,15 @@ module Phaser {
export class Stage { 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) { constructor(game: Game, parent: string, width: number, height: number) {
this._game = game; this._game = game;
@@ -33,16 +44,22 @@ module Phaser {
// Consume default actions on the canvas // Consume default actions on the canvas
this.canvas.style.msTouchAction = 'none'; this.canvas.style.msTouchAction = 'none';
this.canvas.style['ms-touch-action'] = 'none';
this.canvas.style['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.context = this.canvas.getContext('2d');
this.offset = this.getOffset(this.canvas); 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.aspectRatio = width / height;
this.scaleMode = StageScaleMode.NO_SCALE; this.scaleMode = StageScaleMode.NO_SCALE;
this.scale = new StageScaleMode(this._game); this.scale = new StageScaleMode(this._game);
this._bootScreen = new BootScreen(this._game);
this._pauseScreen = new PauseScreen(this._game, width, height);
document.addEventListener('visibilitychange', (event) => this.visibilityChange(event), false); document.addEventListener('visibilitychange', (event) => this.visibilityChange(event), false);
document.addEventListener('webkitvisibilitychange', (event) => this.visibilityChange(event), false); document.addEventListener('webkitvisibilitychange', (event) => this.visibilityChange(event), false);
window.onblur = (event) => this.visibilityChange(event); window.onblur = (event) => this.visibilityChange(event);
@@ -50,28 +67,96 @@ module Phaser {
} }
/**
* Local private reference to game.
*/
private _game: 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; public aspectRatio: number;
/**
* Clear the whole stage every frame? (Default to true)
* @type {boolean}
*/
public clear: bool = true; public clear: bool = true;
/**
* Canvas element used by engine.
* @type {HTMLCanvasElement}
*/
public canvas: HTMLCanvasElement; public canvas: HTMLCanvasElement;
/**
* Render context of stage's canvas.
* @type {CanvasRenderingContext2D}
*/
public context: 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 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; 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 scaleMode: number;
public minScaleX: number = null; /**
public maxScaleX: number = null; * Update stage for rendering. This will handle scaling, clearing
public minScaleY: number = null; * and PauseScreen/BootScreen updating and rendering.
public maxScaleY: number = null; */
public update() { public update() {
this.scale.update(); this.scale.update();
@@ -82,92 +167,67 @@ module Phaser {
this.context.clearRect(0, 0, this.width, this.height); 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() { if (this._game.paused == true && this.disablePauseScreen == false)
{
this.context.fillStyle = 'rgb(255,255,255)'; this._pauseScreen.update();
this.context.fillText(Phaser.VERSION, 10, 20); this._pauseScreen.render();
this.context.fillText('Game Size: ' + this.width + ' x ' + this.height, 10, 40); }
this.context.fillText('x: ' + this.x + ' y: ' + this.y, 10, 60);
} }
//if (document['hidden'] === true || document['webkitHidden'] === true) /**
* This method is called when the canvas elements visibility is changed.
*/
private visibilityChange(event) { private visibilityChange(event) {
//console.log(event);
if (this.disablePauseScreen) if (this.disablePauseScreen)
{ {
return; 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; if (this._game.paused == false)
this.drawPauseScreen(); {
this.pauseGame();
}
} }
else if (event.type == 'focus') else
{ {
this._game.paused = false; if (this._game.paused == true)
{
this.resumeGame();
}
} }
} }
public drawInitScreen() { public pauseGame() {
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() {
this._pauseScreen.onPaused();
this.saveCanvasValues(); this.saveCanvasValues();
this._game.paused = true;
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();
} }
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(); var box = element.getBoundingClientRect();
@@ -176,14 +236,31 @@ module Phaser {
var scrollTop = window.pageYOffset || element.scrollTop || document.body.scrollTop; var scrollTop = window.pageYOffset || element.scrollTop || document.body.scrollTop;
var scrollLeft = window.pageXOffset || element.scrollLeft || document.body.scrollLeft; 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; public strokeStyle: string;
/**
* Canvas lineWidth.
* @type {number}
*/
public lineWidth: number; public lineWidth: number;
/**
* Canvas fillStyle.
* @type {string}
*/
public fillStyle: string; public fillStyle: string;
/**
* Save current canvas properties (strokeStyle, lineWidth and fillStyle) for later using.
*/
public saveCanvasValues() { public saveCanvasValues() {
this.strokeStyle = this.context.strokeStyle; this.strokeStyle = this.context.strokeStyle;
@@ -192,6 +269,9 @@ module Phaser {
} }
/**
* Restore current canvas values (strokeStyle, lineWidth and fillStyle) with saved values.
*/
public restoreCanvasValues() { public restoreCanvasValues() {
this.context.strokeStyle = this.strokeStyle; this.context.strokeStyle = this.strokeStyle;
@@ -240,8 +320,6 @@ module Phaser {
return Math.round(Math.random() * this.bounds.height); 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 { export class State {
/**
* State constructor
* Create a new <code>State</code>.
*/
constructor(game: Game) { constructor(game: Game) {
this.game = game; this.game = game;
this.add = game.add;
this.camera = game.camera; this.camera = game.camera;
this.cache = game.cache; this.cache = game.cache;
this.collision = game.collision; this.collision = game.collision;
@@ -29,73 +34,135 @@ module Phaser {
} }
/**
* Reference to Game.
*/
public game: Game; public game: Game;
/**
* Currently used camera.
* @type {Camera}
*/
public camera: Camera; public camera: Camera;
/**
* Reference to the assets cache.
* @type {Cache}
*/
public cache: Cache; public cache: Cache;
/**
* Reference to the collision helper.
* @type {Collision}
*/
public collision: Collision; public collision: Collision;
/**
* Reference to the GameObject Factory.
* @type {GameObjectFactory}
*/
public add: GameObjectFactory;
/**
* Reference to the input manager
* @type {Input}
*/
public input: Input; public input: Input;
/**
* Reference to the assets loader.
* @type {Loader}
*/
public loader: Loader; public loader: Loader;
/**
* Reference to the math helper.
* @type {GameMath}
*/
public math: GameMath; public math: GameMath;
/**
* Reference to the motion helper.
* @type {Motion}
*/
public motion: Motion; public motion: Motion;
/**
* Reference to the sound manager.
* @type {SoundManager}
*/
public sound: SoundManager; public sound: SoundManager;
/**
* Reference to the stage.
* @type {Stage}
*/
public stage: Stage; public stage: Stage;
/**
* Reference to game clock.
* @type {Time}
*/
public time: Time; public time: Time;
/**
* Reference to the tween manager.
* @type {TweenManager}
*/
public tweens: TweenManager; public tweens: TweenManager;
/**
* Reference to the world.
* @type {World}
*/
public world: 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() { } 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() { } public create() { }
/**
* Put update logic here.
*/
public update() { } public update() { }
/**
* Put render operations here.
*/
public render() { } public render() { }
/**
* This method will be called when game paused.
*/
public 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); * 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.
public createGeomSprite(x: number, y: number): GeomSprite { * @param object2 The second GameObject or Group to check.
return this.world.createGeomSprite(x, y); * @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
public createSprite(x: number, y: number, key?: string = ''): Sprite { * @returns {boolean} true if the objects overlap, otherwise false.
return this.game.world.createSprite(x, y, key); */
} 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);
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);
} }
} }
+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 { export class Time {
/**
* Time constructor
* Create a new <code>Time</code>.
*
* @param game {Phaser.Game} Current game instance.
*/
constructor(game: Game) { constructor(game: Game) {
this._started = Date.now(); this._started = 0;
this._timeLastSecond = this._started; this._timeLastSecond = this._started;
this.time = this._started; this.time = this._started;
this._game = game;
} }
/**
* Local private reference to game.
*/
private _game: Game; private _game: Game;
/**
* Time when this object created.
* @param {number}
*/
private _started: 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; public timeScale: number = 1.0;
/**
* Elapsed since last frame.
* @type {number}
*/
public elapsed: number = 0; public elapsed: number = 0;
/** /**
* * Game time counter.
* @property time * @property time
* @type Number * @type {number}
*/ */
public time: number = 0; public time: number = 0;
/** /**
* * Time of current frame.
* @property now * @property now
* @type Number * @type {number}
*/ */
public now: number = 0; public now: number = 0;
/** /**
* * Elapsed time since last frame.
* @property delta * @property delta
* @type Number * @type {number}
*/ */
public delta: number = 0; public delta: number = 0;
/** /**
@@ -57,23 +81,58 @@ module Phaser {
} }
/**
* Frames per second.
* @type {number}
*/
public fps: number = 0; public fps: number = 0;
/**
* Minimal fps.
* @type {number}
*/
public fpsMin: number = 1000; public fpsMin: number = 1000;
/**
* Maximal fps.
* @type {number}
*/
public fpsMax: number = 0; public fpsMax: number = 0;
/**
* Mininal duration between 2 frames.
* @type {number}
*/
public msMin: number = 1000; public msMin: number = 1000;
/**
* Maximal duration between 2 frames.
* @type {number}
*/
public msMax: number = 0; public msMax: number = 0;
/**
* How many frames in last second.
* @type {number}
*/
public frames: number = 0; public frames: number = 0;
/**
* Time of last second.
* @type {number}
*/
private _timeLastSecond: number = 0; private _timeLastSecond: number = 0;
/** /**
* * Update clock and calculate the fps.
* @method update * This is called automatically by Game._raf
*/ * @method update
public update() { * @param {number} raf The current timestamp, either performance.now or Date.now
*/
public update(raf: number) {
// Can we use performance.now() ? this.now = raf; // mark
this.now = Date.now(); // mark //this.now = Date.now(); // mark
this.delta = this.now - this.time; // elapsedMS this.delta = this.now - this.time; // elapsedMS
this.msMin = Math.min(this.msMin, this.delta); this.msMin = Math.min(this.msMin, this.delta);
@@ -93,20 +152,14 @@ module Phaser {
this.time = this.now; // _total this.time = this.now; // _total
//// Lock the delta at 0.1 to minimise fps tunneling
//if (this.delta > 0.1)
//{
// this.delta = 0.1;
//}
} }
/** /**
* * How long has passed since given time.
* @method elapsedSince * @method elapsedSince
* @param {Number} since * @param {number} since The time you want to measure.
* @return {Number} * @return {number} Duration between given time and now.
*/ */
public elapsedSince(since: number): number { public elapsedSince(since: number): number {
return this.now - since; return this.now - since;
@@ -114,11 +167,11 @@ module Phaser {
} }
/** /**
* * How long has passed since give time (in seconds).
* @method elapsedSecondsSince * @method elapsedSecondsSince
* @param {Number} since * @param {number} since The time you want to measure (in seconds).
* @return {Number} * @return {number} Duration between given time and now (in seconds).
*/ */
public elapsedSecondsSince(since: number): number { public elapsedSecondsSince(since: number): number {
return (this.now - since) * 0.001; return (this.now - since) * 0.001;
@@ -126,9 +179,9 @@ module Phaser {
} }
/** /**
* * Set the start time to now.
* @method reset * @method reset
*/ */
public reset() { public reset() {
this._started = this.now; 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;
}
}
+40
View File
@@ -15,6 +15,10 @@ module Phaser {
export class TweenManager { export class TweenManager {
/**
* TweenManager constructor
* @param game {Game} A reference to the current Game.
*/
constructor(game: Phaser.Game) { constructor(game: Phaser.Game) {
this._game = game; this._game = game;
@@ -22,27 +26,53 @@ module Phaser {
} }
/**
* Local private reference to Game
*/
private _game: Phaser.Game; private _game: Phaser.Game;
/**
* Local private array which is the container of all tween objects.
*/
private _tweens: Phaser.Tween[]; private _tweens: Phaser.Tween[];
/**
* Get all the tween objects in an array.
* @return {Phaser.Tween[]} Array with all tween objects.
*/
public getAll() { public getAll() {
return this._tweens; return this._tweens;
} }
/**
* Remove all tween objects.
*/
public removeAll() { public removeAll() {
this._tweens.length = 0; 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 { public create(object): Phaser.Tween {
return new Phaser.Tween(object, this._game); 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) { public add(tween: Phaser.Tween) {
tween.parent = this._game; 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) { public remove(tween: Phaser.Tween) {
var i = this._tweens.indexOf(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() { public update() {
if (this._tweens.length === 0) 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;
}
}
+139 -5
View File
@@ -3,6 +3,8 @@
/** /**
* Phaser - World * 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 * 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 * 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. * live within the world at world-based coordinates. By default a world is created the same size as your Stage.
@@ -12,14 +14,19 @@ module Phaser {
export class World { 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) { constructor(game: Game, width: number, height: number) {
this._game = game; this._game = game;
this.cameras = new CameraManager(this._game, 0, 0, width, height); this.cameras = new CameraManager(this._game, 0, 0, width, height);
this._game.camera = this.cameras.current;
this.group = new Group(this._game, 0); this.group = new Group(this._game, 0);
this.bounds = new Rectangle(0, 0, width, height); this.bounds = new Rectangle(0, 0, width, height);
@@ -28,13 +35,37 @@ module Phaser {
} }
/**
* Local private reference to game.
*/
private _game: Game; private _game: Game;
/**
* Camera manager of this world.
* @type {CameraManager}
*/
public cameras: CameraManager; public cameras: CameraManager;
/**
* Object container stores every object created with `create*` methods.
* @type {Group}
*/
public group: Group; public group: Group;
/**
* Bound of this world that objects can not escape from.
* @type {Rectangle}
*/
public bounds: Rectangle; public bounds: Rectangle;
/**
* @type {number}
*/
public worldDivisions: number; public worldDivisions: number;
/**
* This is called automatically every frame, and is where main logic performs.
*/
public update() { public update() {
this.group.preUpdate(); this.group.preUpdate();
@@ -45,6 +76,9 @@ module Phaser {
} }
/**
* Render every thing to the screen, automatically called after update().
*/
public render() { public render() {
// Unlike in flixel our render process is camera driven, not group driven // Unlike in flixel our render process is camera driven, not group driven
@@ -52,6 +86,9 @@ module Phaser {
} }
/**
* Clean up memory.
*/
public destroy() { public destroy() {
this.group.destroy(); this.group.destroy();
@@ -62,7 +99,16 @@ module Phaser {
// World methods // 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.width = width;
this.bounds.height = height; this.bounds.height = height;
@@ -72,6 +118,12 @@ module Phaser {
this._game.camera.setBounds(0, 0, width, height); 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 { public get width(): number {
@@ -108,48 +160,130 @@ module Phaser {
// Cameras // 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 { 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 { 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[] { public getAllCameras(): Camera[] {
return this.cameras.getAll(); return this.cameras.getAll();
} }
// Game Objects // 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 { public createSprite(x: number, y: number, key?: string = ''): Sprite {
return <Sprite> this.group.add(new Sprite(this._game, x, y, key)); 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 { public createGeomSprite(x: number, y: number): GeomSprite {
return <GeomSprite> this.group.add(new GeomSprite(this._game, x, y)); 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 { public createDynamicTexture(width: number, height: number): DynamicTexture {
return new DynamicTexture(this._game, width, height); 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 { 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)); 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 { 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)); 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 { public createParticle(): Particle {
return new Particle(this._game); 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 { public createEmitter(x?: number = 0, y?: number = 0, size?: number = 0): Emitter {
return <Emitter> this.group.add(new Emitter(this._game, x, y, size)); 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;
}
}
+56 -54
View File
@@ -17,14 +17,16 @@ module Phaser {
* Creates a new <code>Emitter</code> object at a specific position. * Creates a new <code>Emitter</code> object at a specific position.
* Does NOT automatically generate or attach particles! * Does NOT automatically generate or attach particles!
* *
* @param X The X position of the emitter. * @param x {number} The X position of the emitter.
* @param Y The Y position of the emitter. * @param y {number} The Y position of the emitter.
* @param Size Optional, specifies a maximum capacity for this emitter. * @param [size] {number} Specifies a maximum capacity for this emitter.
*/ */
constructor(game: Game, X: number = 0, Y: number = 0, Size: number = 0) { constructor(game: Game, x: number = 0, y: number = 0, size: number = 0) {
super(game, Size);
this.x = X; super(game, size);
this.y = Y;
this.x = x;
this.y = y;
this.width = 0; this.width = 0;
this.height = 0; this.height = 0;
this.minParticleSpeed = new MicroPoint(-100, -100); this.minParticleSpeed = new MicroPoint(-100, -100);
@@ -42,6 +44,7 @@ module Phaser {
this._explode = true; this._explode = true;
this.on = false; this.on = false;
this._point = new MicroPoint(); this._point = new MicroPoint();
} }
/** /**
@@ -166,17 +169,16 @@ module Phaser {
/** /**
* This function generates a new array of particle sprites to attach to the emitter. * 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 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 quantity {number} 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 {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 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 {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.
* @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). * @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): Emitter { public makeParticles(graphics, quantity: number = 50, multiple: bool = false, collide: number = 0): Emitter {
this.maxSize = Quantity; this.maxSize = quantity;
var totalFrames: number = 1; var totalFrames: number = 1;
@@ -194,7 +196,7 @@ module Phaser {
var particle: Particle; var particle: Particle;
var i: number = 0; var i: number = 0;
while (i < Quantity) while (i < quantity)
{ {
if (this.particleClass == null) if (this.particleClass == null)
{ {
@@ -205,7 +207,7 @@ module Phaser {
particle = new this.particleClass(this._game); particle = new this.particleClass(this._game);
} }
if (Multiple) if (multiple)
{ {
/* /*
randomFrame = this._game.math.random()*totalFrames; randomFrame = this._game.math.random()*totalFrames;
@@ -227,18 +229,18 @@ module Phaser {
particle.loadGraphic(Graphics); particle.loadGraphic(Graphics);
*/ */
if (Graphics) if (graphics)
{ {
particle.loadGraphic(Graphics); particle.loadGraphic(graphics);
} }
} }
if (Collide > 0) if (collide > 0)
{ {
particle.allowCollisions = Collision.ANY; particle.allowCollisions = Collision.ANY;
particle.width *= Collide; particle.width *= collide;
particle.height *= Collide; particle.height *= collide;
//particle.centerOffsets(); //particle.centerOffsets();
} }
else else
@@ -319,22 +321,22 @@ module Phaser {
/** /**
* Call this function to start emitting particles. * Call this function to start emitting particles.
* *
* @param Explode Whether the particles should all burst out at once. * @param explode {boolean} Whether the particles should all burst out at once.
* @param Lifespan How long each particle lives once emitted. 0 = forever. * @param lifespan {number} 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 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 How many particles to launch. 0 = "all of the particles". * @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.revive();
this.visible = true; this.visible = true;
this.on = true; this.on = true;
this._explode = Explode; this._explode = explode;
this.lifespan = Lifespan; this.lifespan = lifespan;
this.frequency = Frequency; this.frequency = frequency;
this._quantity += Quantity; this._quantity += quantity;
this._counter = 0; this._counter = 0;
this._timer = 0; this._timer = 0;
@@ -396,54 +398,54 @@ module Phaser {
/** /**
* A more compact way of setting the width and height of the emitter. * 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 width {number} The desired width of the emitter (particles are spawned randomly within these dimensions).
* @param Height The desired height of the emitter. * @param height {number} The desired height of the emitter.
*/ */
public setSize(Width: number, Height: number) { public setSize(width: number, height: number) {
this.width = Width; this.width = width;
this.height = Height; this.height = height;
} }
/** /**
* A more compact way of setting the X velocity range of the emitter. * A more compact way of setting the X velocity range of the emitter.
* *
* @param Min The minimum value for this range. * @param Min {number} The minimum value for this range.
* @param Max The maximum value for this range. * @param Max {number} The maximum value for this range.
*/ */
public setXSpeed(Min: number = 0, Max: number = 0) { public setXSpeed(min: number = 0, max: number = 0) {
this.minParticleSpeed.x = Min; this.minParticleSpeed.x = min;
this.maxParticleSpeed.x = Max; this.maxParticleSpeed.x = max;
} }
/** /**
* A more compact way of setting the Y velocity range of the emitter. * A more compact way of setting the Y velocity range of the emitter.
* *
* @param Min The minimum value for this range. * @param Min {number} The minimum value for this range.
* @param Max The maximum value for this range. * @param Max {number} The maximum value for this range.
*/ */
public setYSpeed(Min: number = 0, Max: number = 0) { public setYSpeed(min: number = 0, max: number = 0) {
this.minParticleSpeed.y = Min; this.minParticleSpeed.y = min;
this.maxParticleSpeed.y = Max; this.maxParticleSpeed.y = max;
} }
/** /**
* A more compact way of setting the angular velocity constraints of the emitter. * A more compact way of setting the angular velocity constraints of the emitter.
* *
* @param Min The minimum value for this range. * @param Min {number} The minimum value for this range.
* @param Max The maximum value for this range. * @param Max {number} The maximum value for this range.
*/ */
public setRotation(Min: number = 0, Max: number = 0) { public setRotation(min: number = 0, max: number = 0) {
this.minRotation = Min; this.minRotation = min;
this.maxRotation = Max; this.maxRotation = max;
} }
/** /**
* Change the emitter's midpoint to match the midpoint of a <code>Object</code>. * 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) { public at(object) {
Object.getMidpoint(this._point); object.getMidpoint(this._point);
this.x = this._point.x - (this.width >> 1); this.x = this._point.x - (this.width >> 1);
this.y = this._point.y - (this.height >> 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;
}
}
+411 -114
View File
@@ -1,6 +1,7 @@
/// <reference path="../Game.ts" /> /// <reference path="../Game.ts" />
/// <reference path="../Basic.ts" /> /// <reference path="../Basic.ts" />
/// <reference path="../Signal.ts" /> /// <reference path="../Signal.ts" />
/// <reference path="../system/CollisionMask.ts" />
/** /**
* Phaser - GameObject * Phaser - GameObject
@@ -13,11 +14,24 @@ module Phaser {
export class GameObject extends Basic { 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) { constructor(game: Game, x?: number = 0, y?: number = 0, width?: number = 16, height?: number = 16) {
super(game); 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.exists = true;
this.active = true; this.active = true;
this.visible = true; this.visible = true;
@@ -27,7 +41,6 @@ module Phaser {
this.scale = new MicroPoint(1, 1); this.scale = new MicroPoint(1, 1);
this.last = new MicroPoint(x, y); this.last = new MicroPoint(x, y);
this.origin = new MicroPoint(this.bounds.halfWidth, this.bounds.halfHeight);
this.align = GameObject.ALIGN_TOP_LEFT; this.align = GameObject.ALIGN_TOP_LEFT;
this.mass = 1; this.mass = 1;
this.elasticity = 0; this.elasticity = 0;
@@ -53,69 +66,302 @@ module Phaser {
this.cameraBlacklist = []; this.cameraBlacklist = [];
this.scrollFactor = new MicroPoint(1, 1); 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; private _angle: number = 0;
/**
* Pivot position enum: at the top-left corner.
* @type {number}
*/
public static ALIGN_TOP_LEFT: number = 0; public static ALIGN_TOP_LEFT: number = 0;
/**
* Pivot position enum: at the top-center corner.
* @type {number}
*/
public static ALIGN_TOP_CENTER: number = 1; public static ALIGN_TOP_CENTER: number = 1;
/**
* Pivot position enum: at the top-right corner.
* @type {number}
*/
public static ALIGN_TOP_RIGHT: number = 2; public static ALIGN_TOP_RIGHT: number = 2;
/**
* Pivot position enum: at the center-left corner.
* @type {number}
*/
public static ALIGN_CENTER_LEFT: number = 3; public static ALIGN_CENTER_LEFT: number = 3;
/**
* Pivot position enum: at the center corner.
* @type {number}
*/
public static ALIGN_CENTER: number = 4; public static ALIGN_CENTER: number = 4;
/**
* Pivot position enum: at the center-right corner.
* @type {number}
*/
public static ALIGN_CENTER_RIGHT: number = 5; public static ALIGN_CENTER_RIGHT: number = 5;
/**
* Pivot position enum: at the bottom-left corner.
* @type {number}
*/
public static ALIGN_BOTTOM_LEFT: number = 6; public static ALIGN_BOTTOM_LEFT: number = 6;
/**
* Pivot position enum: at the bottom-center corner.
* @type {number}
*/
public static ALIGN_BOTTOM_CENTER: number = 7; public static ALIGN_BOTTOM_CENTER: number = 7;
/**
* Pivot position enum: at the bottom-right corner.
* @type {number}
*/
public static ALIGN_BOTTOM_RIGHT: number = 8; 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; 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; 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; public _point: MicroPoint;
/**
* An Array of Cameras to which this GameObject won't render
* @type {Array}
*/
public cameraBlacklist: number[]; 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; 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; 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; public align: number;
/**
* Orientation of the object.
* @type {number}
*/
public facing: number; public facing: number;
/**
* Set alpha to a number between 0 and 1 to change the opacity.
* @type {number}
*/
public alpha: number; public alpha: number;
/**
* Scale factor of the object.
* @type {MicroPoint}
*/
public scale: 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; public origin: MicroPoint;
/**
* Z-order value of the object.
*/
public z: number = 0; 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 * This value is added to the angle of the GameObject.
// rotationOffset to 90 and it would correspond correctly with Phasers rotation system * 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; 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; public renderRotation: bool = true;
// Physics properties // Physics properties
/**
* Whether this object will be moved by impacts with other objects or not.
* @type {boolean}
*/
public immovable: bool; 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 * Basic speed of this object.
// accurate due to the way timers work, but it's pretty close. Expect tolerance *
// of +- 10 px. Also that speed assumes no drag * 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; public velocity: MicroPoint;
/**
* The virtual mass of the object.
* @type {number}
*/
public mass: number; public mass: number;
/**
* The bounciness of the object.
* @type {number}
*/
public elasticity: number; public elasticity: number;
/**
* How fast the speed of this object is changing.
* @type {number}
*/
public acceleration: MicroPoint; 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; public drag: MicroPoint;
/**
* It will cap the speed automatically if you use the acceleration
* to change its velocity.
* @type {MicroPoint}
*/
public maxVelocity: MicroPoint; public maxVelocity: MicroPoint;
/**
* How fast this object is rotating.
* @type {number}
*/
public angularVelocity: number; public angularVelocity: number;
/**
* How fast angularVelocity of this object is changing.
* @type {number}
*/
public angularAcceleration: number; public angularAcceleration: number;
/**
* Deacceleration of angularVelocity will be applied when it's rotating.
* @type {number}
*/
public angularDrag: 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; 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; public scrollFactor: MicroPoint;
/**
* Handy for storing health percentage or armor points or whatever.
* @type {number}
*/
public health: 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; public moves: bool = true;
/**
* Bit field of flags (use with UP, DOWN, LEFT, RIGHT, etc) indicating surface contacts.
* @type {number}
*/
public touching: 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; public wasTouching: number;
/**
* Bit field of flags (use with UP, DOWN, LEFT, RIGHT, etc) indicating collision directions.
* @type {number}
*/
public allowCollisions: number; public allowCollisions: number;
/**
* Important variable for collision processing.
* @type {MicroPoint}
*/
public last: MicroPoint; public last: MicroPoint;
// Input // Input
@@ -127,18 +373,27 @@ module Phaser {
public onInputDown: Phaser.Signal; public onInputDown: Phaser.Signal;
public onInputUp: Phaser.Signal; public onInputUp: Phaser.Signal;
/**
* Pre-update is called right before update() on each object in the game loop.
*/
public preUpdate() { public preUpdate() {
// flicker time this.last.x = this.frameBounds.x;
this.last.y = this.frameBounds.y;
this.last.x = this.bounds.x; this.collisionMask.preUpdate();
this.last.y = this.bounds.y;
} }
/**
* Override this function to update your class's position and appearance.
*/
public update() { public update() {
} }
/**
* Automatically called after update() by the game loop.
*/
public postUpdate() { public postUpdate() {
if (this.moves) if (this.moves)
@@ -177,6 +432,8 @@ module Phaser {
} }
} }
this.collisionMask.update();
if (this.inputEnabled) if (this.inputEnabled)
{ {
this.updateInput(); this.updateInput();
@@ -187,9 +444,15 @@ module Phaser {
} }
/**
* Update input.
*/
private updateInput() { private updateInput() {
} }
/**
* Internal function for updating the position and speed of this object.
*/
private updateMotion() { private updateMotion() {
var delta: number; var delta: number;
@@ -204,13 +467,13 @@ module Phaser {
this.velocity.x += velocityDelta; this.velocity.x += velocityDelta;
delta = this.velocity.x * this._game.time.elapsed; delta = this.velocity.x * this._game.time.elapsed;
this.velocity.x += velocityDelta; 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; 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; this.velocity.y += velocityDelta;
delta = this.velocity.y * this._game.time.elapsed; delta = this.velocity.y * this._game.time.elapsed;
this.velocity.y += velocityDelta; this.velocity.y += velocityDelta;
this.bounds.y += delta; this.frameBounds.y += delta;
} }
@@ -219,23 +482,23 @@ module Phaser {
* If the group has a LOT of things in it, it might be faster to use <code>Collision.overlaps()</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! * WARNING: Currently tilemaps do NOT support screen space overlap checks!
* *
* @param ObjectOrGroup The object or group being tested. * @param objectOrGroup {object} 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 inScreenSpace {boolean} 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. * @param camera {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. * @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 results: bool = false;
var i: number = 0; var i: number = 0;
var members = <Group> ObjectOrGroup.members; var members = <Group> objectOrGroup.members;
while (i < length) while (i < length)
{ {
if (this.overlaps(members[i++], InScreenSpace, Camera)) if (this.overlaps(members[i++], inScreenSpace, camera))
{ {
results = true; results = true;
} }
@@ -245,23 +508,23 @@ module Phaser {
} }
if (!InScreenSpace) if (!inScreenSpace)
{ {
return (ObjectOrGroup.x + ObjectOrGroup.width > this.x) && (ObjectOrGroup.x < this.x + this.width) && 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); (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) && 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); (objectScreenPos.y + objectOrGroup.height > this._point.y) && (objectScreenPos.y < this._point.y + this.height);
} }
/** /**
@@ -269,26 +532,26 @@ module Phaser {
* This is distinct from overlapsPoint(), which just checks that point, rather than taking the object's size numbero account. * 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! * 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 X {number} 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 Y {number} 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 objectOrGroup {object} 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 inScreenSpace {boolean} 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. * @param camera {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. * @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 results: bool = false;
var basic; var basic;
var i: number = 0; var i: number = 0;
var members = ObjectOrGroup.members; var members = objectOrGroup.members;
while (i < length) while (i < length)
{ {
if (this.overlapsAt(X, Y, members[i++], InScreenSpace, Camera)) if (this.overlapsAt(X, Y, members[i++], inScreenSpace, camera))
{ {
results = true; results = true;
} }
@@ -297,53 +560,53 @@ module Phaser {
return results; return results;
} }
if (!InScreenSpace) if (!inScreenSpace)
{ {
return (ObjectOrGroup.x + ObjectOrGroup.width > X) && (ObjectOrGroup.x < X + this.width) && return (objectOrGroup.x + objectOrGroup.width > X) && (objectOrGroup.x < X + this.width) &&
(ObjectOrGroup.y + ObjectOrGroup.height > Y) && (ObjectOrGroup.y < Y + this.height); (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.x = X - camera.scroll.x * this.scrollFactor.x; //copied from getScreenXY()
this._point.y = Y - Camera.scroll.y * this.scrollFactor.y; this._point.y = Y - camera.scroll.y * this.scrollFactor.y;
this._point.x += (this._point.x > 0) ? 0.0000001 : -0.0000001; this._point.x += (this._point.x > 0) ? 0.0000001 : -0.0000001;
this._point.y += (this._point.y > 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) && 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); (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>. * 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 point {Point} The point in world space you want to check.
* @param InScreenSpace Whether to take scroll factors numbero account when checking for overlap. * @param inScreenSpace {boolean} Whether to take scroll factors into account when checking for overlap.
* @param Camera Specify which game camera you want. If null getScreenXY() will just grab the first global camera. * @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. * @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); 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 X: number = point.x - camera.scroll.x;
var Y: number = point.y - Camera.scroll.y; 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); return (X > this._point.x) && (X < this._point.x + this.width) && (Y > this._point.y) && (Y < this._point.y + this.height);
@@ -352,45 +615,45 @@ module Phaser {
/** /**
* Check and see if this object is currently on screen. * 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. * @param camera {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. * @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. * 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 {Point} Takes a <code>MicroPoint</code> object and assigns the post-scrolled X and Y values of this object to it.
* @param 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 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. * @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) if (point == null)
{ {
point = new MicroPoint(); 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.x = this.x - camera.scroll.x * this.scrollFactor.x;
point.y = this.y - Camera.scroll.y * this.scrollFactor.y; point.y = this.y - camera.scroll.y * this.scrollFactor.y;
point.x += (point.x > 0) ? 0.0000001 : -0.0000001; point.x += (point.x > 0) ? 0.0000001 : -0.0000001;
point.y += (point.y > 0) ? 0.0000001 : -0.0000001; point.y += (point.y > 0) ? 0.0000001 : -0.0000001;
@@ -407,12 +670,9 @@ module Phaser {
return (this.allowCollisions & Collision.ANY) > Collision.NONE; return (this.allowCollisions & Collision.ANY) > Collision.NONE;
} }
/** public set solid(value: bool) {
* @private
*/
public set solid(Solid: bool) {
if (Solid) if (value)
{ {
this.allowCollisions = Collision.ANY; this.allowCollisions = Collision.ANY;
} }
@@ -426,9 +686,9 @@ module Phaser {
/** /**
* Retrieve the midpoint of this object in world coordinates. * 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. * @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 A <code>Point</code> object containing the midpoint of this object in world coordinates. * @return {MicroPoint} A <code>Point</code> object containing the midpoint of this object in world coordinates.
*/ */
public getMidpoint(point: MicroPoint = null): MicroPoint { public getMidpoint(point: MicroPoint = null): MicroPoint {
@@ -437,7 +697,7 @@ module Phaser {
point = new MicroPoint(); point = new MicroPoint();
} }
point.copyFrom(this.bounds.center); point.copyFrom(this.frameBounds.center);
return point; return point;
@@ -447,18 +707,18 @@ module Phaser {
* Handy for reviving game objects. * Handy for reviving game objects.
* Resets their existence flags and position. * Resets their existence flags and position.
* *
* @param X The new X position of this object. * @param x {number} The new X position of this object.
* @param Y The new Y 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.revive();
this.touching = Collision.NONE; this.touching = Collision.NONE;
this.wasTouching = Collision.NONE; this.wasTouching = Collision.NONE;
this.x = X; this.x = x;
this.y = Y; this.y = y;
this.last.x = X; this.last.x = x;
this.last.y = Y; this.last.y = y;
this.velocity.x = 0; this.velocity.x = 0;
this.velocity.y = 0; this.velocity.y = 0;
@@ -466,37 +726,37 @@ module Phaser {
/** /**
* Handy for checking if this object is touching a particular surface. * 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. * However, this method is good for readability and accessibility.
* *
* @param Direction Any of the collision flags (e.g. LEFT, FLOOR, etc). * @param Direction {number} 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. * @return {boolean} Whether the object is touching an object in (any of) the specified direction(s) this frame.
*/ */
public isTouching(Direction: number): bool { public isTouching(direction: number): bool {
return (this.touching & Direction) > Collision.NONE; return (this.touching & direction) > Collision.NONE;
} }
/** /**
* Handy for checking if this object is just landed on a particular surface. * Handy function for checking if this object just landed on a particular surface.
* *
* @param Direction Any of the collision flags (e.g. LEFT, FLOOR, etc). * @param Direction {number} 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. * @returns {boolean} Whether the object just landed on any specicied surfaces.
*/ */
public justTouched(Direction: number): bool { public justTouched(direction: number): bool {
return ((this.touching & Direction) > Collision.NONE) && ((this.wasTouching & Direction) <= Collision.NONE); return ((this.touching & direction) > Collision.NONE) && ((this.wasTouching & direction) <= Collision.NONE);
} }
/** /**
* Reduces the "health" variable of this sprite by the amount specified in Damage. * Reduces the "health" variable of this sprite by the amount specified in Damage.
* Calls kill() if health drops to or below zero. * 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) if (this.health <= 0)
{ {
@@ -509,6 +769,11 @@ module Phaser {
* Set the world bounds that this GameObject can exist within. By default a GameObject can exist anywhere * 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) * 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. * 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) { public setBounds(x: number, y: number, width: number, height: number) {
@@ -516,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. * 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) { public hideFromCamera(camera: Camera) {
@@ -528,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) { public showToCamera(camera: Camera) {
if (this.cameraBlacklist.indexOf(camera.ID) !== -1) if (this.cameraBlacklist.indexOf(camera.ID) !== -1)
@@ -537,30 +822,42 @@ module Phaser {
} }
/**
* This clears the camera black list, making the GameObject visible to all cameras.
*/
public clearCameraList() { public clearCameraList() {
this.cameraBlacklist.length = 0; this.cameraBlacklist.length = 0;
} }
/**
* Clean up memory.
*/
public destroy() { public destroy() {
}
public setPosition(x: number, y: number) {
this.x = x;
this.y = y;
} }
public get x(): number { public get x(): number {
return this.bounds.x; return this.frameBounds.x;
} }
public set x(value: number) { public set x(value: number) {
this.bounds.x = value; this.frameBounds.x = value;
} }
public get y(): number { public get y(): number {
return this.bounds.y; return this.frameBounds.y;
} }
public set y(value: number) { public set y(value: number) {
this.bounds.y = value; this.frameBounds.y = value;
} }
public get rotation(): number { public get rotation(): number {
@@ -580,19 +877,19 @@ module Phaser {
} }
public set width(value:number) { public set width(value:number) {
this.bounds.width = value; this.frameBounds.width = value;
} }
public set height(value:number) { public set height(value:number) {
this.bounds.height = value; this.frameBounds.height = value;
} }
public get width(): number { public get width(): number {
return this.bounds.width; return this.frameBounds.width;
} }
public get height(): number { 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="../Game.ts" />
/// <reference path="../geom/Polygon.ts" />
/** /**
* Phaser - GeomSprite * Phaser - GeomSprite
@@ -12,6 +13,14 @@ module Phaser {
export class GeomSprite extends GameObject { 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) { constructor(game: Game, x?: number = 0, y?: number = 0) {
super(game, x, y); super(game, x, y);
@@ -28,26 +37,112 @@ module Phaser {
private _dw: number = 0; private _dw: number = 0;
private _dh: number = 0; private _dh: number = 0;
/**
* Geom type of this sprite. (available: UNASSIGNED, CIRCLE, LINE, POINT, RECTANGLE)
* @type {number}
*/
public type: number = 0; public type: number = 0;
/**
* Not completely set yet. (the default type)
*/
public static UNASSIGNED: number = 0; public static UNASSIGNED: number = 0;
/**
* Circle.
* @type {number}
*/
public static CIRCLE: number = 1; public static CIRCLE: number = 1;
/**
* Line.
* @type {number}
*/
public static LINE: number = 2; public static LINE: number = 2;
/**
* Point.
* @type {number}
*/
public static POINT: number = 3; public static POINT: number = 3;
/**
* Rectangle.
* @type {number}
*/
public static RECTANGLE: number = 4; public static RECTANGLE: number = 4;
/**
* Polygon.
* @type {number}
*/
public static POLYGON: number = 5;
/**
* Circle shape container. A Circle instance.
* @type {Circle}
*/
public circle: Circle; public circle: Circle;
/**
* Line shape container. A Line instance.
* @type {Line}
*/
public line: Line; public line: Line;
/**
* Point shape container. A Point instance.
* @type {Point}
*/
public point: Point; public point: Point;
/**
* Rectangle shape container. A Rectangle instance.
* @type {Rectangle}
*/
public rect: 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; public renderOutline: bool = true;
/**
* Fill the shape or not. (default is true)
* @type {boolean}
*/
public renderFill: bool = true; public renderFill: bool = true;
/**
* Width of outline. (default is 1)
* @type {number}
*/
public lineWidth: number = 1; public lineWidth: number = 1;
/**
* Width of outline. (default is 1)
* @type {number}
*/
public lineColor: string = 'rgb(0,255,0)'; 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)'; 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 { loadCircle(circle:Circle): GeomSprite {
this.refresh(); 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 { loadLine(line:Line): GeomSprite {
this.refresh(); 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 { loadPoint(point:Point): GeomSprite {
this.refresh(); 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 { loadRectangle(rect:Rectangle): GeomSprite {
this.refresh(); 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 { createCircle(diameter: number): GeomSprite {
this.refresh(); this.refresh();
this.circle = new Circle(this.x, this.y, diameter); this.circle = new Circle(this.x, this.y, diameter);
this.type = GeomSprite.CIRCLE; 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; 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 { createLine(x: number, y: number): GeomSprite {
this.refresh(); this.refresh();
this.line = new Line(this.x, this.y, x, y); this.line = new Line(this.x, this.y, x, y);
this.type = GeomSprite.LINE; 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; return this;
} }
/**
* Create a point shape at spriter's position.
* @return {GeomSprite} GeomSprite instance itself.
*/
createPoint(): GeomSprite { createPoint(): GeomSprite {
this.refresh(); this.refresh();
this.point = new Point(this.x, this.y); this.point = new Point(this.x, this.y);
this.type = GeomSprite.POINT; this.type = GeomSprite.POINT;
this.bounds.width = 1; this.frameBounds.width = 1;
this.bounds.height = 1; this.frameBounds.height = 1;
return this; 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 { createRectangle(width: number, height: number): GeomSprite {
this.refresh(); this.refresh();
this.rect = new Rectangle(this.x, this.y, width, height); this.rect = new Rectangle(this.x, this.y, width, height);
this.type = GeomSprite.RECTANGLE; this.type = GeomSprite.RECTANGLE;
this.bounds.copyFrom(this.rect); this.frameBounds.copyFrom(this.rect);
return this; 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() { refresh() {
this.circle = null; this.circle = null;
@@ -135,6 +284,9 @@ module Phaser {
} }
/**
* Update bounds.
*/
update() { update() {
// Update bounds and position? // Update bounds and position?
@@ -146,14 +298,14 @@ module Phaser {
{ {
this.circle.x = this.x; this.circle.x = this.x;
this.circle.y = this.y; this.circle.y = this.y;
this.bounds.width = this.circle.diameter; this.frameBounds.width = this.circle.diameter;
this.bounds.height = this.circle.diameter; this.frameBounds.height = this.circle.diameter;
} }
else if (this.type == GeomSprite.LINE) else if (this.type == GeomSprite.LINE)
{ {
this.line.x1 = this.x; this.line.x1 = this.x;
this.line.y1 = this.y; 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) else if (this.type == GeomSprite.POINT)
{ {
@@ -164,29 +316,41 @@ module Phaser {
{ {
this.rect.x = this.x; this.rect.x = this.x;
this.rect.y = this.y; 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 { public inCamera(camera: Rectangle): bool {
if (this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0) if (this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0)
{ {
this._dx = this.bounds.x - (camera.x * this.scrollFactor.x); this._dx = this.frameBounds.x - (camera.x * this.scrollFactor.x);
this._dy = this.bounds.y - (camera.y * this.scrollFactor.x); this._dy = this.frameBounds.y - (camera.y * this.scrollFactor.x);
this._dw = this.bounds.width * this.scale.x; this._dw = this.frameBounds.width * this.scale.x;
this._dh = this.bounds.height * this.scale.y; 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); return (camera.right > this._dx) && (camera.x < this._dx + this._dw) && (camera.bottom > this._dy) && (camera.y < this._dy + this._dh);
} }
else 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 { public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number): bool {
// Render checks // Render checks
@@ -198,21 +362,14 @@ module Phaser {
// Alpha // Alpha
if (this.alpha !== 1) if (this.alpha !== 1)
{ {
var globalAlpha = this._game.stage.context.globalAlpha; var globalAlpha = this.context.globalAlpha;
this._game.stage.context.globalAlpha = this.alpha; this.context.globalAlpha = this.alpha;
} }
this._dx = cameraOffsetX + (this.bounds.x - camera.worldView.x); this._dx = cameraOffsetX + (this.frameBounds.x - camera.worldView.x);
this._dy = cameraOffsetY + (this.bounds.y - camera.worldView.y); this._dy = cameraOffsetY + (this.frameBounds.y - camera.worldView.y);
this._dw = this.bounds.width * this.scale.x; this._dw = this.frameBounds.width * this.scale.x;
this._dh = this.bounds.height * this.scale.y; this._dh = this.frameBounds.height * this.scale.y;
// Circles are drawn center based
if (this.type == GeomSprite.CIRCLE)
{
this._dx += this.circle.radius;
this._dy += this.circle.radius;
}
// Apply camera difference // Apply camera difference
if (this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0) if (this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0)
@@ -225,9 +382,9 @@ module Phaser {
/* /*
if (this.angle !== 0) if (this.angle !== 0)
{ {
this._game.stage.context.save(); this.context.save();
this._game.stage.context.translate(this._dx + (this._dw / 2) - this.origin.x, this._dy + (this._dh / 2) - this.origin.y); this.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.rotate(this.angle * (Math.PI / 180));
this._dx = -(this._dw / 2); this._dx = -(this._dw / 2);
this._dy = -(this._dh / 2); this._dy = -(this._dh / 2);
} }
@@ -241,12 +398,12 @@ module Phaser {
this._game.stage.saveCanvasValues(); this._game.stage.saveCanvasValues();
// Debug // Debug
//this._game.stage.context.fillStyle = 'rgba(255,0,0,0.5)'; //this.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.fillRect(this.frameBounds.x, this.frameBounds.y, this.frameBounds.width, this.frameBounds.height);
this._game.stage.context.lineWidth = this.lineWidth; this.context.lineWidth = this.lineWidth;
this._game.stage.context.strokeStyle = this.lineColor; this.context.strokeStyle = this.lineColor;
this._game.stage.context.fillStyle = this.fillColor; this.context.fillStyle = this.fillColor;
if (this._game.stage.fillStyle !== this.fillColor) if (this._game.stage.fillStyle !== this.fillColor)
{ {
@@ -255,61 +412,74 @@ module Phaser {
// Primitive Renderer // Primitive Renderer
if (this.type == GeomSprite.CIRCLE) if (this.type == GeomSprite.CIRCLE)
{ {
this._game.stage.context.beginPath(); this.context.beginPath();
this._game.stage.context.arc(this._dx, this._dy, this.circle.radius, 0, Math.PI * 2); this.context.arc(this._dx, this._dy, this.circle.radius, 0, Math.PI * 2);
this._game.stage.context.stroke();
if (this.renderOutline)
{
this.context.stroke();
}
if (this.renderFill) 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) else if (this.type == GeomSprite.LINE)
{ {
this._game.stage.context.beginPath(); this.context.beginPath();
this._game.stage.context.moveTo(this._dx, this._dy); this.context.moveTo(this._dx, this._dy);
this._game.stage.context.lineTo(this.line.x2, this.line.y2); this.context.lineTo(this.line.x2, this.line.y2);
this._game.stage.context.stroke(); this.context.stroke();
this._game.stage.context.closePath(); this.context.closePath();
} }
else if (this.type == GeomSprite.POINT) 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) else if (this.type == GeomSprite.RECTANGLE)
{ {
// We can use the faster fillRect if we don't need the outline // We can use the faster fillRect if we don't need the outline
if (this.renderOutline == false) 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 else
{ {
this._game.stage.context.beginPath(); this.context.beginPath();
this._game.stage.context.rect(this._dx, this._dy, this.rect.width, this.rect.height); this.context.rect(this._dx, this._dy, this.rect.width, this.rect.height);
this._game.stage.context.stroke(); this.context.stroke();
if (this.renderFill) if (this.renderFill)
{ {
this._game.stage.context.fill(); this.context.fill();
} }
this._game.stage.context.closePath(); this.context.closePath();
} }
// And now the edge points // And now the edge points
this._game.stage.context.fillStyle = 'rgb(255,255,255)'; this.context.fillStyle = 'rgb(255,255,255)';
this.renderPoint(this._dx, this._dy, this.rect.topLeft, 2); //this.renderPoint(this.rect.topLeft, this._dx, this._dy, 2);
this.renderPoint(this._dx, this._dy, this.rect.topCenter, 2); //this.renderPoint(this.rect.topCenter, this._dx, this._dy, 2);
this.renderPoint(this._dx, this._dy, this.rect.topRight, 2); //this.renderPoint(this.rect.topRight, this._dx, this._dy, 2);
this.renderPoint(this._dx, this._dy, this.rect.leftCenter, 2); //this.renderPoint(this.rect.leftCenter, this._dx, this._dy, 2);
this.renderPoint(this._dx, this._dy, this.rect.center, 2); //this.renderPoint(this.rect.center, this._dx, this._dy, 2);
this.renderPoint(this._dx, this._dy, this.rect.rightCenter, 2); //this.renderPoint(this.rect.rightCenter, this._dx, this._dy, 2);
this.renderPoint(this._dx, this._dy, this.rect.bottomLeft, 2); //this.renderPoint(this.rect.bottomLeft, this._dx, this._dy, 2);
this.renderPoint(this._dx, this._dy, this.rect.bottomCenter, 2); //this.renderPoint(this.rect.bottomCenter, this._dx, this._dy, 2);
this.renderPoint(this._dx, this._dy, this.rect.bottomRight, 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) if (this.rotation !== 0)
{ {
this._game.stage.context.translate(0, 0); this.context.translate(0, 0);
this._game.stage.context.restore(); this.context.restore();
} }
if (globalAlpha > -1) if (globalAlpha > -1)
{ {
this._game.stage.context.globalAlpha = globalAlpha; this.context.globalAlpha = globalAlpha;
} }
return true; 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; this.context.fillRect(offsetX + point.x, offsetY + point.y, size, size);
offsetY = 0;
this._game.stage.context.fillRect(offsetX + point.x, offsetY + point.y, 1, 1);
} }
/**
* 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)') { public renderDebugInfo(x: number, y: number, color?: string = 'rgb(255,255,255)') {
//this._game.stage.context.fillStyle = color; //this.context.fillStyle = color;
//this._game.stage.context.fillText('Sprite: ' + this.name + ' (' + this.bounds.width + ' x ' + this.bounds.height + ')', x, y); //this.context.fillText('Sprite: ' + this.name + ' (' + this.frameBounds.width + ' x ' + this.frameBounds.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.context.fillText('x: ' + this.frameBounds.x.toFixed(1) + ' y: ' + this.frameBounds.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.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.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 { public collide(source: GeomSprite): bool {
// Circle vs. Circle // 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;
}
}
+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 { 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) { constructor(x: number, y: number, width: number, height: number, speedX:number, speedY:number) {
// Our seamless scrolling quads // Our seamless scrolling quads
@@ -38,9 +49,22 @@ module Phaser {
private _inverseWidth: number = 0; private _inverseWidth: number = 0;
private _inverseHeight: number = 0; private _inverseHeight: number = 0;
/**
* Will this region be rendered? (default to true)
* @type {boolean}
*/
public visible: bool = true; public visible: bool = true;
/**
* Region scrolling speed.
* @type {MicroPoint}
*/
public scrollSpeed: MicroPoint; public scrollSpeed: MicroPoint;
/**
* Update region scrolling with tick time.
* @param delta {number} Elapsed time since last update.
*/
public update(delta: number) { public update(delta: number) {
this._scroll.x += this.scrollSpeed.x; 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) { public render(context:CanvasRenderingContext2D, texture, dx: number, dy: number, dw: number, dh: number) {
if (this.visible == false) 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) { private crop(context, texture, srcX, srcY, srcW, srcH, destX, destY, destW, destH, offsetX, offsetY) {
offsetX += destX; 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);
}
}
+104 -19
View File
@@ -15,6 +15,17 @@ module Phaser {
export class ScrollZone extends GameObject { 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) { constructor(game: Game, key:string, x: number = 0, y: number = 0, width?: number = 0, height?: number = 0) {
super(game, x, y, width, height); super(game, x, y, width, height);
@@ -49,19 +60,69 @@ module Phaser {
} }
/**
* Texture of this object.
*/
private _texture; 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; 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; private _dx: number = 0;
/**
* Local rendering related temp vars to help avoid gc spikes.
* @type {number}
*/
private _dy: number = 0; private _dy: number = 0;
/**
* Local rendering related temp vars to help avoid gc spikes.
* @type {number}
*/
private _dw: number = 0; private _dw: number = 0;
/**
* Local rendering related temp vars to help avoid gc spikes.
* @type {number}
*/
private _dh: number = 0; private _dh: number = 0;
/**
* Current region this zone is scrolling.
* @type {ScrollRegion}
*/
public currentRegion: ScrollRegion; public currentRegion: ScrollRegion;
/**
* Array contains all added regions.
* @type {ScrollRegion[]}
*/
public regions: ScrollRegion[]; public regions: ScrollRegion[];
/**
* Flip this zone vertically? (default to false)
* @type {boolean}
*/
public flipped: bool = false; 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 { 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) 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) { public setSpeed(x: number, y: number) {
if (this.currentRegion) if (this.currentRegion)
@@ -89,6 +155,9 @@ module Phaser {
} }
/**
* Update regions.
*/
public update() { public update() {
for (var i = 0; i < this.regions.length; i++) 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 { public inCamera(camera: Rectangle): bool {
if (this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0) if (this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0)
{ {
this._dx = this.bounds.x - (camera.x * this.scrollFactor.x); this._dx = this.frameBounds.x - (camera.x * this.scrollFactor.x);
this._dy = this.bounds.y - (camera.y * this.scrollFactor.x); this._dy = this.frameBounds.y - (camera.y * this.scrollFactor.x);
this._dw = this.bounds.width * this.scale.x; this._dw = this.frameBounds.width * this.scale.x;
this._dh = this.bounds.height * this.scale.y; 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); return (camera.right > this._dx) && (camera.x < this._dx + this._dw) && (camera.bottom > this._dy) && (camera.y < this._dy + this._dh);
} }
else 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) { public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number) {
// Render checks // Render checks
@@ -127,14 +208,14 @@ module Phaser {
// Alpha // Alpha
if (this.alpha !== 1) if (this.alpha !== 1)
{ {
var globalAlpha = this._game.stage.context.globalAlpha; var globalAlpha = this.context.globalAlpha;
this._game.stage.context.globalAlpha = this.alpha; this.context.globalAlpha = this.alpha;
} }
this._dx = cameraOffsetX + (this.bounds.topLeft.x - camera.worldView.x); this._dx = cameraOffsetX + (this.frameBounds.topLeft.x - camera.worldView.x);
this._dy = cameraOffsetY + (this.bounds.topLeft.y - camera.worldView.y); this._dy = cameraOffsetY + (this.frameBounds.topLeft.y - camera.worldView.y);
this._dw = this.bounds.width * this.scale.x; this._dw = this.frameBounds.width * this.scale.x;
this._dh = this.bounds.height * this.scale.y; this._dh = this.frameBounds.height * this.scale.y;
// Apply camera difference // Apply camera difference
if (this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0) 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 // Rotation - needs to work from origin point really, but for now from center
if (this.angle !== 0 || this.flipped == true) if (this.angle !== 0 || this.flipped == true)
{ {
this._game.stage.context.save(); this.context.save();
this._game.stage.context.translate(this._dx + (this._dw / 2), this._dy + (this._dh / 2)); this.context.translate(this._dx + (this._dw / 2), this._dy + (this._dh / 2));
if (this.angle !== 0) 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); this._dx = -(this._dw / 2);
@@ -159,7 +240,7 @@ module Phaser {
if (this.flipped == true) 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) 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 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) if (globalAlpha > -1)
{ {
this._game.stage.context.globalAlpha = globalAlpha; this.context.globalAlpha = globalAlpha;
} }
return true; 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) { private createRepeatingTexture(regionWidth: number, regionHeight: number) {
// Work out how many we'll need of the source image to make it tile properly // 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;
}
}
+187 -80
View File
@@ -14,6 +14,15 @@ module Phaser {
export class Sprite extends GameObject { 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) { constructor(game: Game, x?: number = 0, y?: number = 0, key?: string = null) {
super(game, x, y); super(game, x, y);
@@ -24,17 +33,26 @@ module Phaser {
if (key !== null) if (key !== null)
{ {
this.cacheKey = key;
this.loadGraphic(key); this.loadGraphic(key);
} }
else else
{ {
this.bounds.width = 16; this.frameBounds.width = 16;
this.bounds.height = 16; this.frameBounds.height = 16;
} }
} }
/**
* Texture of this sprite to be rendered.
*/
private _texture; private _texture;
/**
* Texture of this sprite is DynamicTexture? (default to false)
* @type {boolean}
*/
private _dynamicTexture: bool = false; private _dynamicTexture: bool = false;
// local rendering related temp vars to help avoid gc spikes // local rendering related temp vars to help avoid gc spikes
@@ -47,27 +65,76 @@ module Phaser {
private _dw: number = 0; private _dw: number = 0;
private _dh: 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; 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; 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)'; 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)'; public renderDebugPointColor: string = 'rgba(255,255,255,1)';
/**
* Flip the graphic horizontally? (defaults to false)
* @type {boolean}
*/
public flipped: bool = false; 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.getImage(key) !== null)
{ {
if (this._game.cache.isSpriteSheet(key) == false) if (this._game.cache.isSpriteSheet(key) == false)
{ {
this._texture = this._game.cache.getImage(key); this._texture = this._game.cache.getImage(key);
this.bounds.width = this._texture.width; this.frameBounds.width = this._texture.width;
this.bounds.height = this._texture.height; this.frameBounds.height = this._texture.height;
this.collisionMask.width = this._texture.width;
this.collisionMask.height = this._texture.height;
} }
else else
{ {
this._texture = this._game.cache.getImage(key); this._texture = this._game.cache.getImage(key);
this.animations.loadFrameData(this._game.cache.getFrameData(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; 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 { public loadDynamicTexture(texture: DynamicTexture): Sprite {
this._texture = texture; this._texture = texture;
this.bounds.width = this._texture.width; this.frameBounds.width = this._texture.width;
this.bounds.height = this._texture.height; this.frameBounds.height = this._texture.height;
this._dynamicTexture = true; 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._texture = null;
this.width = width; this.width = width;
this.height = height; this.height = height;
this.fillColor = color;
this._dynamicTexture = false; this._dynamicTexture = false;
return this; return this;
} }
public inCamera(camera: Rectangle): bool { /**
* 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 {
if (this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0) // Object fixed in place regardless of the camera scrolling? Then it's always visible
if (this.scrollFactor.x == 0 && this.scrollFactor.y == 0)
{ {
this._dx = this.bounds.x - (camera.x * this.scrollFactor.x); return true;
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;
return (camera.right > this._dx) && (camera.x < this._dx + this._dw) && (camera.bottom > this._dy) && (camera.y < this._dy + this._dh); this._dx = (this.frameBounds.x - camera.x);
} this._dy = (this.frameBounds.y - camera.y);
else this._dw = this.frameBounds.width * this.scale.x;
{ this._dh = this.frameBounds.height * this.scale.y;
return camera.intersects(this.bounds, this.bounds.length);
} 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() { public postUpdate() {
this.animations.update(); this.animations.update();
@@ -143,10 +229,17 @@ module Phaser {
return this.animations.frameName; 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 { public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number): bool {
// Render checks // 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; return false;
} }
@@ -154,54 +247,55 @@ module Phaser {
// Alpha // Alpha
if (this.alpha !== 1) if (this.alpha !== 1)
{ {
var globalAlpha = this._game.stage.context.globalAlpha; var globalAlpha = this.context.globalAlpha;
this._game.stage.context.globalAlpha = this.alpha; this.context.globalAlpha = this.alpha;
} }
this._sx = 0; this._sx = 0;
this._sy = 0; this._sy = 0;
this._sw = this.bounds.width; this._sw = this.frameBounds.width;
this._sh = this.bounds.height; this._sh = this.frameBounds.height;
this._dx = cameraOffsetX + (this.bounds.topLeft.x - camera.worldView.x);
this._dy = cameraOffsetY + (this.bounds.topLeft.y - camera.worldView.y); this._dx = (cameraOffsetX * this.scrollFactor.x) + this.frameBounds.topLeft.x - (camera.worldView.x * this.scrollFactor.x);
this._dw = this.bounds.width * this.scale.x; this._dy = (cameraOffsetY * this.scrollFactor.y) + this.frameBounds.topLeft.y - (camera.worldView.y * this.scrollFactor.y);
this._dh = this.bounds.height * this.scale.y; this._dw = this.frameBounds.width * this.scale.x;
this._dh = this.frameBounds.height * this.scale.y;
if (this.align == GameObject.ALIGN_TOP_CENTER) 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) 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) 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) else if (this.align == GameObject.ALIGN_CENTER)
{ {
this._dx -= this.bounds.halfWidth * this.scale.x; this._dx -= this.frameBounds.halfWidth * this.scale.x;
this._dy -= this.bounds.halfHeight * this.scale.y; this._dy -= this.frameBounds.halfHeight * this.scale.y;
} }
else if (this.align == GameObject.ALIGN_CENTER_RIGHT) else if (this.align == GameObject.ALIGN_CENTER_RIGHT)
{ {
this._dx -= this.bounds.width * this.scale.x; this._dx -= this.frameBounds.width * this.scale.x;
this._dy -= this.bounds.halfHeight * this.scale.y; this._dy -= this.frameBounds.halfHeight * this.scale.y;
} }
else if (this.align == GameObject.ALIGN_BOTTOM_LEFT) 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) else if (this.align == GameObject.ALIGN_BOTTOM_CENTER)
{ {
this._dx -= this.bounds.halfWidth * this.scale.x; this._dx -= this.frameBounds.halfWidth * this.scale.x;
this._dy -= this.bounds.height * this.scale.y; this._dy -= this.frameBounds.height * this.scale.y;
} }
else if (this.align == GameObject.ALIGN_BOTTOM_RIGHT) else if (this.align == GameObject.ALIGN_BOTTOM_RIGHT)
{ {
this._dx -= this.bounds.width * this.scale.x; this._dx -= this.frameBounds.width * this.scale.x;
this._dy -= this.bounds.height * this.scale.y; this._dy -= this.frameBounds.height * this.scale.y;
} }
if (this._dynamicTexture == false && this.animations.currentFrame !== null) if (this._dynamicTexture == false && this.animations.currentFrame !== null)
@@ -217,21 +311,21 @@ module Phaser {
} }
// Apply camera difference // 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._dx -= (camera.worldView.x * this.scrollFactor.x);
this._dy -= (camera.worldView.y * this.scrollFactor.y); //this._dy -= (camera.worldView.y * this.scrollFactor.y);
} }
// Rotation - needs to work from origin point really, but for now from center // Rotation - needs to work from origin point really, but for now from center
if (this.angle !== 0 || this.rotationOffset !== 0 || this.flipped == true) if (this.angle !== 0 || this.rotationOffset !== 0 || this.flipped == true)
{ {
this._game.stage.context.save(); this.context.save();
this._game.stage.context.translate(this._dx + (this._dw / 2), this._dy + (this._dh / 2)); this.context.translate(this._dx + (this._dw / 2), this._dy + (this._dh / 2));
if (this.renderRotation == true && (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); this._dx = -(this._dw / 2);
@@ -239,7 +333,7 @@ module Phaser {
if (this.flipped == true) 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) if (this._dynamicTexture)
{ {
this._game.stage.context.drawImage( this.context.drawImage(
this._texture.canvas, // Source Image this._texture.canvas, // Source Image
this._sx, // Source X (location within the source image) this._sx, // Source X (location within the source image)
this._sy, // Source Y this._sy, // Source Y
@@ -270,7 +364,7 @@ module Phaser {
} }
else else
{ {
this._game.stage.context.drawImage( this.context.drawImage(
this._texture, // Source Image this._texture, // Source Image
this._sx, // Source X (location within the source image) this._sx, // Source X (location within the source image)
this._sy, // Source Y this._sy, // Source Y
@@ -285,64 +379,77 @@ module Phaser {
} }
else else
{ {
this._game.stage.context.fillStyle = 'rgb(255,255,255)'; this.context.fillStyle = this.fillColor;
this._game.stage.context.fillRect(this._dx, this._dy, this._dw, this._dh); this.context.fillRect(this._dx, this._dy, this._dw, this._dh);
} }
if (this.flipped === true || this.rotation !== 0 || this.rotationOffset !== 0) if (this.flipped === true || this.rotation !== 0 || this.rotationOffset !== 0)
{ {
//this._game.stage.context.translate(0, 0); //this.context.translate(0, 0);
this._game.stage.context.restore(); this.context.restore();
} }
if (this.renderDebug) if (this.renderDebug)
{ {
this.renderBounds(camera, cameraOffsetX, cameraOffsetY); this.renderBounds(camera, cameraOffsetX, cameraOffsetY);
//this.collisionMask.render(camera, cameraOffsetX, cameraOffsetY);
} }
if (globalAlpha > -1) if (globalAlpha > -1)
{ {
this._game.stage.context.globalAlpha = globalAlpha; this.context.globalAlpha = globalAlpha;
} }
return true; 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) { private renderBounds(camera:Camera, cameraOffsetX:number, cameraOffsetY:number) {
this._dx = cameraOffsetX + (this.bounds.topLeft.x - camera.worldView.x); this._dx = cameraOffsetX + (this.frameBounds.topLeft.x - camera.worldView.x);
this._dy = cameraOffsetY + (this.bounds.topLeft.y - camera.worldView.y); this._dy = cameraOffsetY + (this.frameBounds.topLeft.y - camera.worldView.y);
this._game.stage.context.fillStyle = this.renderDebugColor; this.context.fillStyle = this.renderDebugColor;
this._game.stage.context.fillRect(this._dx, this._dy, this._dw, this._dh); this.context.fillRect(this._dx, this._dy, this.frameBounds.width, this.frameBounds.height);
this._game.stage.context.fillStyle = this.renderDebugPointColor;
var hw = this.bounds.halfWidth * this.scale.x; //this.context.fillStyle = this.renderDebugPointColor;
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._game.stage.context.fillRect(this._dx, this._dy, 1, 1); // top left //var hw = this.frameBounds.halfWidth * this.scale.x;
this._game.stage.context.fillRect(this._dx + hw, this._dy, 1, 1); // top center //var hh = this.frameBounds.halfHeight * this.scale.y;
this._game.stage.context.fillRect(this._dx + sw, this._dy, 1, 1); // top right //var sw = (this.frameBounds.width * this.scale.x) - 1;
this._game.stage.context.fillRect(this._dx, this._dy + hh, 1, 1); // left center //var sh = (this.frameBounds.height * this.scale.y) - 1;
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.context.fillRect(this._dx, this._dy, 1, 1); // top left
this._game.stage.context.fillRect(this._dx, this._dy + sh, 1, 1); // bottom left //this.context.fillRect(this._dx + hw, this._dy, 1, 1); // top center
this._game.stage.context.fillRect(this._dx + hw, this._dy + sh, 1, 1); // bottom center //this.context.fillRect(this._dx + sw, this._dy, 1, 1); // top right
this._game.stage.context.fillRect(this._dx + sw, this._dy + sh, 1, 1); // bottom 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)') { public renderDebugInfo(x: number, y: number, color?: string = 'rgb(255,255,255)') {
this._game.stage.context.fillStyle = color; this.context.fillStyle = color;
this._game.stage.context.fillText('Sprite: ' + this.name + ' (' + this.bounds.width + ' x ' + this.bounds.height + ')', x, y); this.context.fillText('Sprite: ' + this.name + ' (' + this.frameBounds.width + ' x ' + this.frameBounds.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.context.fillText('x: ' + this.frameBounds.x.toFixed(1) + ' y: ' + this.frameBounds.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.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.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;
}
}
+186 -16
View File
@@ -14,6 +14,18 @@ module Phaser {
export class Tilemap extends GameObject { 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) { constructor(game: Game, key: string, mapData: string, format: number, resizeWorld: bool = true, tileWidth?: number = 0, tileHeight?: number = 0) {
super(game); super(game);
@@ -43,18 +55,66 @@ module Phaser {
} }
private _tempCollisionData;
/**
* Tilemap data format enum: CSV.
* @type {number}
*/
public static FORMAT_CSV: number = 0; public static FORMAT_CSV: number = 0;
/**
* Tilemap data format enum: Tiled JSON.
* @type {number}
*/
public static FORMAT_TILED_JSON: number = 1; public static FORMAT_TILED_JSON: number = 1;
/**
* Array contains tile objects of this map.
* @type {Tile[]}
*/
public tiles : Tile[]; public tiles : Tile[];
/**
* Array contains tilemap layer objects of this map.
* @type {TilemapLayer[]}
*/
public layers : TilemapLayer[]; public layers : TilemapLayer[];
/**
* Current tilemap layer.
* @type {TilemapLayer}
*/
public currentLayer: TilemapLayer; public currentLayer: TilemapLayer;
/**
* The tilemap layer for collision.
* @type {TilemapLayer}
*/
public collisionLayer: 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; public mapFormat: number;
/**
* Inherited update method.
*/
public update() { 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) { public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number) {
if (this.cameraBlacklist.indexOf(camera.ID) == -1) if (this.cameraBlacklist.indexOf(camera.ID) == -1)
@@ -68,6 +128,13 @@ module Phaser {
} }
/**
* 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) { private parseCSV(data: string, key: string, tileWidth: number, tileHeight: number) {
var layer: TilemapLayer = new TilemapLayer(this._game, this, 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);
@@ -99,6 +166,11 @@ module Phaser {
} }
/**
* 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) { private parseTiledJSON(data: string, key: string) {
// Trim any rogue whitespace from the data // Trim any rogue whitespace from the data
@@ -151,6 +223,10 @@ module Phaser {
} }
/**
* Create tiles of given quantity.
* @param qty {number} Quentity of tiles to be generated.
*/
private generateTiles(qty:number) { private generateTiles(qty:number) {
for (var i = 0; i < qty; i++) for (var i = 0; i < qty; i++)
@@ -170,32 +246,91 @@ module Phaser {
// Tile Collision // Tile Collision
public setCollisionRange(start: number, end: number, collision?:number = Collision.ANY, resetCollisions: bool = false) { /**
* 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++) for (var i = start; i < end; i++)
{ {
this.tiles[i].setCollision(collision, resetCollisions); this.tiles[i].setCollision(collision, resetCollisions, separateX, separateY);
} }
} }
public setCollisionByIndex(values:number[], collision?:number = Collision.ANY, resetCollisions: bool = false) { /**
* 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++) for (var i = 0; i < values.length; i++)
{ {
this.tiles[values[i]].setCollision(collision, resetCollisions); this.tiles[values[i]].setCollision(collision, resetCollisions, separateX, separateY);
} }
} }
// Tile Management // 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 { public getTile(x: number, y: number, layer?: number = 0):Tile {
return this.tiles[this.layers[layer].getTileIndex(x, y)]; 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 { public getTileFromWorldXY(x: number, y: number, layer?: number = 0):Tile {
return this.tiles[this.layers[layer].getTileFromWorldXY(x, y)]; return this.tiles[this.layers[layer].getTileFromWorldXY(x, y)];
@@ -204,10 +339,15 @@ module Phaser {
public getTileFromInputXY(layer?: number = 0):Tile { public getTileFromInputXY(layer?: number = 0):Tile {
return this.tiles[this.layers[layer].getTileFromWorldXY(this._game.input.worldX, this._game.input.worldY)]; 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) { public getTileOverlaps(object: GameObject) {
return this.currentLayer.getTileOverlaps(object); return this.currentLayer.getTileOverlaps(object);
@@ -215,7 +355,20 @@ module Phaser {
} }
// COLLIDE // COLLIDE
public collide(objectOrGroup = null, callback = null): bool { /**
* 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) if (objectOrGroup == null)
{ {
@@ -225,24 +378,32 @@ module Phaser {
// Group? // Group?
if (objectOrGroup.isGroup == false) if (objectOrGroup.isGroup == false)
{ {
return this.collideGameObject(objectOrGroup); this.collideGameObject(objectOrGroup);
} }
else else
{ {
objectOrGroup.forEachAlive(this, this.collideGameObject, true); objectOrGroup.forEachAlive(this, this.collideGameObject, true);
} }
return 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 { public collideGameObject(object: GameObject): bool {
if (object == this) { return false; } if (object !== this && object.immovable == false && object.exists == true && object.allowCollisions != Collision.NONE)
if (object.immovable == false && object.exists == true && object.allowCollisions != Collision.NONE)
{ {
return this.collisionLayer.getTileOverlaps(object); 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 else
{ {
@@ -251,15 +412,24 @@ module Phaser {
} }
/**
* 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 current layer
// Set layer order? // Set layer order?
// Get block of tiles
// Swap tiles around
// Delete tiles of certain type // Delete tiles of certain type
// Erase tiles // 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;
}
}
+19 -9
View File
@@ -14,18 +14,21 @@ 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. * 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 * @class Circle
* @constructor * @constructor
* @param {Number} x The x 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} [y] The y coordinate of the center of the circle.
* @param {Number} [diameter] The diameter of the circle.
* @return {Circle} This circle object * @return {Circle} This circle object
**/ **/
constructor(x: number = 0, y: number = 0, diameter: number = 0) { constructor(x: number = 0, y: number = 0, diameter: number = 0) {
this._pos = new Vector2;
this.setTo(x, y, diameter); this.setTo(x, y, diameter);
} }
private _diameter: number = 0; private _diameter: number = 0;
private _radius: number = 0; private _radius: number = 0;
private _pos: Vector2;
/** /**
* The x coordinate of the center of the circle * The x coordinate of the center of the circle
@@ -41,15 +44,22 @@ module Phaser {
**/ **/
public y: number = 0; 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. * The diameter of the circle. The largest distance between any two points on the circle. The same as the radius * 2.
* @method diameter * @method diameter
* @return {Number} * @return {Number}
**/ **/
get diameter(): number { get diameter(): number {
return this._diameter; return this._diameter;
} }
/** /**
@@ -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. * Returns a new Circle object with the same values for the x, y, width, and height properties as the original Circle object.
* @method clone * @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} * @return {Phaser.Circle}
**/ **/
public clone(output?: Circle = new Circle): 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) * 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 * @method distanceFrom
* @param {Circle/Point} target - The destination Point object. * @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. * @return {Number} The distance between this Point object and the destination Point object.
**/ **/
public distanceTo(target: any, round?: bool = false): number { 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. * Returns a Point object containing the coordinates of a point on the circumference of this Circle based on the given angle.
* @method circumferencePoint * @method circumferencePoint
* @param {Number} The angle in radians (unless asDegrees is true) to return the point from. * @param {Number} angle 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 {Boolean} asDegrees 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 {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. * @return {Phaser.Point} The Point object holding the result.
**/ **/
public circumferencePoint(angle: number, asDegrees: bool = false, output?: Point = new Point): Point { 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? * Did they intersect or not?
* @property result * @property result
* @type Boolean * @type {Boolean}
*/ */
result: bool = false; result: bool = false;
/** /**
* @property x * @property x
* @type Number * @type {Number}
*/ */
x: number; x: number;
/** /**
* @property y * @property y
* @type Number * @type {Number}
*/ */
y: number; y: number;
/** /**
* @property x1 * @property x1
* @type Number * @type {Number}
*/ */
x1: number; x1: number;
/** /**
* @property y1 * @property y1
* @type Number * @type {Number}
*/ */
y1: number; y1: number;
/** /**
* @property x2 * @property x2
* @type Number * @type {Number}
*/ */
x2: number; x2: number;
/** /**
* @property y2 * @property y2
* @type Number * @type {Number}
*/ */
y2: number; y2: number;
/** /**
* @property width * @property width
* @type Number * @type {Number}
*/ */
width: number; width: number;
/** /**
* @property height * @property height
* @type Number * @type {Number}
*/ */
height: 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;
}
}
+4 -4
View File
@@ -28,28 +28,28 @@ module Phaser {
/** /**
* *
* @property x1 * @property x1
* @type Number * @type {Number}
*/ */
public x1: number = 0; public x1: number = 0;
/** /**
* *
* @property y1 * @property y1
* @type Number * @type {Number}
*/ */
public y1: number = 0; public y1: number = 0;
/** /**
* *
* @property x2 * @property x2
* @type Number * @type {Number}
*/ */
public x2: number = 0; public x2: number = 0;
/** /**
* *
* @property y2 * @property y2
* @type Number * @type {Number}
*/ */
public y2: number = 0; public y2: number = 0;
+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;
}
}
+4 -4
View File
@@ -36,7 +36,7 @@ module Phaser {
/** /**
* The x coordinate of the top-left corner of the rectangle * The x coordinate of the top-left corner of the rectangle
* @property x * @property x
* @type Number * @type {Number}
**/ **/
public get x(): number { public get x(): number {
@@ -47,7 +47,7 @@ module Phaser {
/** /**
* The y coordinate of the top-left corner of the rectangle * The y coordinate of the top-left corner of the rectangle
* @property y * @property y
* @type Number * @type {Number}
**/ **/
public get y(): number { public get y(): number {
@@ -58,7 +58,7 @@ module Phaser {
/** /**
* The x coordinate of the top-left corner of the rectangle * The x coordinate of the top-left corner of the rectangle
* @property x * @property x
* @type Number * @type {Number}
**/ **/
public set x(value: number) { public set x(value: number) {
@@ -74,7 +74,7 @@ module Phaser {
/** /**
* The y coordinate of the top-left corner of the rectangle * The y coordinate of the top-left corner of the rectangle
* @property y * @property y
* @type Number * @type {Number}
**/ **/
public set y(value: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;
}
}
+28 -2
View File
@@ -26,14 +26,14 @@ module Phaser {
/** /**
* The horizontal position of this point (default 0) * The horizontal position of this point (default 0)
* @property x * @property x
* @type Number * @type {Number}
**/ **/
public x: number; public x: number;
/** /**
* The vertical position of this point (default 0) * The vertical position of this point (default 0)
* @property y * @property y
* @type Number * @type {Number}
**/ **/
public y: 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. * Sets the x and y values of this Point object to the given coordinates.
* @method setTo * @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;
}
}
+79 -5
View File
@@ -1,4 +1,5 @@
/// <reference path="../Game.ts" /> /// <reference path="../Game.ts" />
/// <reference path="Polygon.ts" />
/** /**
* Phaser - Quad * Phaser - Quad
@@ -19,7 +20,7 @@ module Phaser {
* @param {Number} y The y coordinate of the top-left corner of the quad. * @param {Number} y The y coordinate of the top-left corner of the quad.
* @param {Number} width The width of the quad. * @param {Number} width The width of the quad.
* @param {Number} height The height 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) { constructor(x: number = 0, y: number = 0, width: number = 0, height: number = 0) {
@@ -80,13 +81,86 @@ module Phaser {
* Determines whether the object specified intersects (overlaps) with this Quad object. * 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. * 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 * @method intersects
* @param {Object} q The object to check for intersection with this Quad. Must have left/right/top/bottom properties (Rectangle, Quad). * @param {Object} quad The object to check for intersection with this Quad. Must have left/right/top/bottom properties (Rectangle, Quad).
* @param {Number} t A tolerance value to allow for an intersection test with padding, default to 0 * @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. * @return {Boolean} A value of true if the specified object intersects with this Quad; otherwise false.
**/ **/
public intersects(q, 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;
}
}
+26 -26
View File
@@ -60,7 +60,7 @@ module Phaser {
/** /**
* The x coordinate of the top-left corner of the rectangle * The x coordinate of the top-left corner of the rectangle
* @property x * @property x
* @type Number * @type {Number}
**/ **/
public get x(): number { public get x(): number {
@@ -71,7 +71,7 @@ module Phaser {
/** /**
* The y coordinate of the top-left corner of the rectangle * The y coordinate of the top-left corner of the rectangle
* @property y * @property y
* @type Number * @type {Number}
**/ **/
public get y(): number { public get y(): number {
@@ -82,7 +82,7 @@ module Phaser {
/** /**
* The x coordinate of the top-left corner of the rectangle * The x coordinate of the top-left corner of the rectangle
* @property x * @property x
* @type Number * @type {Number}
**/ **/
public set x(value: number) { public set x(value: number) {
@@ -93,7 +93,7 @@ module Phaser {
/** /**
* The y coordinate of the top-left corner of the rectangle * The y coordinate of the top-left corner of the rectangle
* @property y * @property y
* @type Number * @type {Number}
**/ **/
public set y(value:number) { public set y(value:number) {
@@ -104,98 +104,98 @@ module Phaser {
/** /**
* The x and y coordinate of the top-left corner of the rectangle (same as x/y) * The x and y coordinate of the top-left corner of the rectangle (same as x/y)
* @property topLeft * @property topLeft
* @type MicroPoint * @type {MicroPoint}
**/ **/
public topLeft: MicroPoint; public topLeft: MicroPoint;
/** /**
* The x and y coordinate of the top-center of the rectangle * The x and y coordinate of the top-center of the rectangle
* @property topCenter * @property topCenter
* @type MicroPoint * @type {MicroPoint}
**/ **/
public topCenter: MicroPoint; public topCenter: MicroPoint;
/** /**
* The x and y coordinate of the top-right corner of the rectangle * The x and y coordinate of the top-right corner of the rectangle
* @property topRight * @property topRight
* @type MicroPoint * @type {MicroPoint}
**/ **/
public topRight: MicroPoint; public topRight: MicroPoint;
/** /**
* The x and y coordinate of the left-center of the rectangle * The x and y coordinate of the left-center of the rectangle
* @property leftCenter * @property leftCenter
* @type MicroPoint * @type {MicroPoint}
**/ **/
public leftCenter: MicroPoint; public leftCenter: MicroPoint;
/** /**
* The x and y coordinate of the center of the rectangle * The x and y coordinate of the center of the rectangle
* @property center * @property center
* @type MicroPoint * @type {MicroPoint}
**/ **/
public center: MicroPoint; public center: MicroPoint;
/** /**
* The x and y coordinate of the right-center of the rectangle * The x and y coordinate of the right-center of the rectangle
* @property rightCenter * @property rightCenter
* @type MicroPoint * @type {MicroPoint}
**/ **/
public rightCenter: MicroPoint; public rightCenter: MicroPoint;
/** /**
* The x and y coordinate of the bottom-left corner of the rectangle * The x and y coordinate of the bottom-left corner of the rectangle
* @property bottomLeft * @property bottomLeft
* @type MicroPoint * @type {MicroPoint}
**/ **/
public bottomLeft: MicroPoint; public bottomLeft: MicroPoint;
/** /**
* The x and y coordinate of the bottom-center of the rectangle * The x and y coordinate of the bottom-center of the rectangle
* @property bottomCenter * @property bottomCenter
* @type MicroPoint * @type {MicroPoint}
**/ **/
public bottomCenter: MicroPoint; public bottomCenter: MicroPoint;
/** /**
* The x and y coordinate of the bottom-right corner of the rectangle * The x and y coordinate of the bottom-right corner of the rectangle
* @property bottomRight * @property bottomRight
* @type MicroPoint * @type {MicroPoint}
**/ **/
public bottomRight: MicroPoint; public bottomRight: MicroPoint;
/** /**
* The width of the rectangle * The width of the rectangle
* @property width * @property width
* @type Number * @type {Number}
**/ **/
private _width: number = 0; private _width: number = 0;
/** /**
* The height of the rectangle * The height of the rectangle
* @property height * @property height
* @type Number * @type {Number}
**/ **/
private _height: number = 0; private _height: number = 0;
/** /**
* Half of the width of the rectangle * Half of the width of the rectangle
* @property halfWidth * @property halfWidth
* @type Number * @type {Number}
**/ **/
private _halfWidth: number = 0; private _halfWidth: number = 0;
/** /**
* Half of the height of the rectangle * Half of the height of the rectangle
* @property halfHeight * @property halfHeight
* @type Number * @type {Number}
**/ **/
private _halfHeight: number = 0; private _halfHeight: number = 0;
/** /**
* The size of the longest side (width or height) * The size of the longest side (width or height)
* @property length * @property length
* @type Number * @type {Number}
**/ **/
public length: number = 0; public length: number = 0;
@@ -267,7 +267,7 @@ module Phaser {
/** /**
* The width of the rectangle * The width of the rectangle
* @property width * @property width
* @type Number * @type {Number}
**/ **/
public set width(value: number) { public set width(value: number) {
@@ -280,7 +280,7 @@ module Phaser {
/** /**
* The height of the rectangle * The height of the rectangle
* @property height * @property height
* @type Number * @type {Number}
**/ **/
public set height(value: number) { public set height(value: number) {
@@ -293,7 +293,7 @@ module Phaser {
/** /**
* The width of the rectangle * The width of the rectangle
* @property width * @property width
* @type Number * @type {Number}
**/ **/
public get width(): number { public get width(): number {
@@ -304,7 +304,7 @@ module Phaser {
/** /**
* The height of the rectangle * The height of the rectangle
* @property height * @property height
* @type Number * @type {Number}
**/ **/
public get height(): number { public get height(): number {
@@ -315,7 +315,7 @@ module Phaser {
/** /**
* Half of the width of the rectangle * Half of the width of the rectangle
* @property halfWidth * @property halfWidth
* @type Number * @type {Number}
**/ **/
public get halfWidth(): number { public get halfWidth(): number {
@@ -326,7 +326,7 @@ module Phaser {
/** /**
* Half of the height of the rectangle * Half of the height of the rectangle
* @property halfHeight * @property halfHeight
* @type Number * @type {Number}
**/ **/
public get halfHeight(): number { public get halfHeight(): number {
@@ -372,7 +372,7 @@ module Phaser {
* Changing the left property of a Rectangle object has no effect on the y and height properties. * 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. * However it does affect the width property, whereas changing the x value does not affect the width property.
* @method left * @method left
* @ return {number} * @ return {Number}
**/ **/
public get left(): number { public get left(): number {
@@ -797,7 +797,7 @@ module Phaser {
/** /**
* Returns a string representation of this object. * Returns a string representation of this object.
* @method toString * @method toString
* @return {string} a string representation of the instance. * @return {String} a string representation of the instance.
**/ **/
public toString(): string { 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
View File
@@ -1,3 +0,0 @@
node_modules
.npm-debug.log
tmp
-5
View File
@@ -1,5 +0,0 @@
language: node_js
node_js:
- 0.8
before_script:
- npm install -g grunt-cli
-4
View File
@@ -1,4 +0,0 @@
"Cowboy" Ben Alman (http://benalman.com/)
Kyle Robinson Young (http://dontkry.com/)
Tyler Kellen (http://goingslowly.com)
Sindre Sorhus (http://sindresorhus.com)
-23
View File
@@ -1,23 +0,0 @@
v0.4.1:
date: 2013-03-13
changes:
- Fix path.join thrown errors with expandMapping rename. Closes gh-725.
- Update copyright date to 2013. Closes gh-660.
- Remove some side effects from manually requiring Grunt. Closes gh-605.
- grunt.log: add formatting support and implicitly cast msg to a string. Closes gh-703.
- Update js-yaml to version 2. Closes gh-683.
- The grunt.util.spawn method now falls back to stdout when the `grunt` option is set. Closes gh-691.
- Making --verbose "Files:" warnings less scary. Closes gh-657.
- Fixing typo: the grunt.fatal method now defaults to FATAL_ERROR. Closes gh-656, gh-707.
- Removed a duplicate line. Closes gh-702.
- Gruntfile name should no longer be case sensitive. Closes gh-685.
- The grunt.file.delete method warns and returns false if file doesn't exist. Closes gh-635, gh-714.
- The grunt.package property is now resolved via require(). Closes gh-704.
- The grunt.util.spawn method no longer breaks on multibyte stdio. Closes gh-710.
- Fix "path.join arguments must be strings" error in file.expand/recurse when options.cwd is not set. Closes gh-722.
- Adding a fairly relevant keyword to package.json (task).
v0.4.0:
date: 2013-02-18
changes:
- Initial release of 0.4.0.
- See http://gruntjs.com/upgrading-from-0.3-to-0.4 for a list of changes / migration guide.
-1
View File
@@ -1 +0,0 @@
Please see the [Contributing to grunt](http://gruntjs.com/contributing) guide for information on contributing to this project.
-22
View File
@@ -1,22 +0,0 @@
Copyright (c) 2013 "Cowboy" Ben Alman
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
-13
View File
@@ -1,13 +0,0 @@
# Grunt: The JavaScript Task Runner [![Build Status](https://secure.travis-ci.org/gruntjs/grunt.png?branch=master)](http://travis-ci.org/gruntjs/grunt)
### Documentation
Visit the [gruntjs.com](http://gruntjs.com/) website for all the things.
### Support / Contributing
Before you make an issue, please read our [Contributing](http://gruntjs.com/contributing) guide.
You can find the grunt team in [#grunt on irc.freenode.net](irc://irc.freenode.net/#grunt).
### Release History
See the [CHANGELOG](CHANGELOG).
-1
View File
@@ -1 +0,0 @@
Visit the [gruntjs.com](http://gruntjs.com/) website for all the things.
-1
View File
@@ -1 +0,0 @@
../coffee-script/bin/cake
-1
View File
@@ -1 +0,0 @@
../coffee-script/bin/coffee
-1
View File
@@ -1 +0,0 @@
../js-yaml/bin/js-yaml.js
-1
View File
@@ -1 +0,0 @@
../lodash/build.js
-1
View File
@@ -1 +0,0 @@
../nopt/bin/nopt.js
-1
View File
@@ -1 +0,0 @@
../which/bin/which
@@ -1,9 +0,0 @@
[submodule "deps/nodeunit"]
path = deps/nodeunit
url = git://github.com/caolan/nodeunit.git
[submodule "deps/UglifyJS"]
path = deps/UglifyJS
url = https://github.com/mishoo/UglifyJS.git
[submodule "deps/nodelint"]
path = deps/nodelint
url = https://github.com/tav/nodelint.git
-4
View File
@@ -1,4 +0,0 @@
deps
dist
test
nodelint.cfg
-19
View File
@@ -1,19 +0,0 @@
Copyright (c) 2010 Caolan McMahon
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

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