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

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 531 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 809 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

+84 -11
View File
@@ -2,7 +2,43 @@ module.exports = function (grunt) {
grunt.loadNpmTasks('grunt-typescript');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-copy');
var wrapPhaserInUmd = function(content, isAddon) {
var replacement = [
'(function (root, factory) {',
' if (typeof exports === \'object\') {',
' module.exports = factory();',
' } else if (typeof define === \'function\' && define.amd) {',
' define(factory);',
' } else {',
' root.Phaser = factory();',
' }',
'}(this, function () {',
content,
'return Phaser;',
'}));'
];
return replacement.join('\n');
};
var wrapAddonInUmd = function(content) {
var replacement = [
'(function (root, factory) {',
' if (typeof exports === \'object\') {',
' module.exports = factory(require(\'phaser\'));',
' } else if (typeof define === \'function\' && define.amd) {',
' define([\'phaser\'], factory);',
' } else {',
' factory(root.Phaser);',
' }',
'}(this, function (Phaser) {',
content,
'return Phaser;',
'}));'
];
return replacement.join('\n');
};
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
typescript: {
@@ -10,22 +46,59 @@ module.exports = function (grunt) {
src: ['Phaser/**/*.ts'],
dest: 'build/phaser.js',
options: {
target: 'ES5'
target: 'ES5',
declaration: true,
comments: true
}
},
fx: {
src: ['SpecialFX/**/*.ts'],
dest: 'build/phaser-fx.js',
options: {
target: 'ES5',
declaration: true,
comments: true
}
}
},
copy: {
main: {
files: [{
src: 'build/phaser.js',
dest: 'Tests/phaser.js'
}]
},
fx: {
files: [{
src: 'build/phaser-fx.js',
dest: 'Tests/phaser-fx.js'
}]
},
mainAmd: {
files: [{
src: 'build/phaser.js',
dest: 'build/phaser.amd.js'
}],
options: {
processContent: wrapPhaserInUmd
}
},
fxAmd: {
files: [{
src: 'build/phaser-fx.js',
dest: 'build/phaser-fx.amd.js'
}],
options: {
processContent: wrapAddonInUmd
}
}
},
copy: {
main: {
files: [
{src: 'build/phaser.js', dest: 'Tests/phaser.js'}
]}
},
watch: {
files: '**/*.ts',
tasks: ['typescript', 'copy']
}
});
grunt.registerTask('default', ['watch']);
grunt.registerTask('default', ['typescript', 'copy', 'watch']);
}
+28
View File
@@ -0,0 +1,28 @@
/// <reference path="Game.d.ts" />
/// <reference path="gameobjects/Sprite.d.ts" />
/// <reference path="system/animation/Animation.d.ts" />
/// <reference path="system/animation/AnimationLoader.d.ts" />
/// <reference path="system/animation/Frame.d.ts" />
/// <reference path="system/animation/FrameData.d.ts" />
module Phaser {
class AnimationManager {
constructor(game: Game, parent: Sprite);
private _game;
private _parent;
private _anims;
private _frameIndex;
private _frameData;
public currentAnim: Animation;
public currentFrame: Frame;
public loadFrameData(frameData: FrameData): void;
public add(name: string, frames?: any[], frameRate?: number, loop?: bool, useNumericIndex?: bool): void;
private validateFrames(frames, useNumericIndex);
public play(name: string, frameRate?: number, loop?: bool): void;
public stop(name: string): void;
public update(): void;
public frameData : FrameData;
public frameTotal : number;
public frame : number;
public frameName : string;
}
}
+96 -8
View File
@@ -16,6 +16,12 @@ module Phaser {
export class AnimationManager {
/**
* AnimationManager constructor
* Create a new <code>AnimationManager</code>.
*
* @param parent {Sprite} Owner sprite of this manager.
*/
constructor(game: Game, parent: Sprite) {
this._game = game;
@@ -24,16 +30,47 @@ module Phaser {
}
/**
* Local private reference to game.
*/
private _game: Game;
/**
* Local private reference to its owner sprite.
*/
private _parent: Sprite;
/**
* Animation key-value container.
*/
private _anims: {};
/**
* Index of current frame.
* @type {number}
*/
private _frameIndex: number;
/**
* Data contains animation frames.
* @type {FrameData}
*/
private _frameData: FrameData = null;
/**
* Keeps track of the current animation being played.
*/
public currentAnim: Animation;
/**
* Keeps track of the current frame of animation.
*/
public currentFrame: Frame = null;
/**
* Load animation frame data.
* @param frameData Data to be loaded.
*/
public loadFrameData(frameData: FrameData) {
this._frameData = frameData;
@@ -42,7 +79,16 @@ module Phaser {
}
public add(name: string, frames: any[] = null, frameRate: number = 60, loop: bool = false, useNumericIndex: bool = true) {
/**
* Add a new animation.
* @param name {string} What this animation should be called (e.g. "run").
* @param frames {any[]} An array of numbers/strings indicating what frames to play in what order (e.g. [1, 2, 3] or ['run0', 'run1', run2]).
* @param frameRate {number} The speed in frames per second that the animation should play at (e.g. 60 fps).
* @param loop {boolean} Whether or not the animation is looped or just plays once.
* @param useNumericIndex {boolean} Use number indexes instead of string indexes?
* @return {Animation} The Animation that was created
*/
public add(name: string, frames: any[] = null, frameRate: number = 60, loop: bool = false, useNumericIndex: bool = true): Animation {
if (this._frameData == null)
{
@@ -72,8 +118,16 @@ module Phaser {
this.currentAnim = this._anims[name];
this.currentFrame = this.currentAnim.currentFrame;
return this._anims[name];
}
/**
* Check whether the frames is valid.
* @param frames {any[]} Frames to be validated.
* @param useNumericIndex {boolean} Does these frames use number indexes or string indexes?
* @return {boolean} True if they're valid, otherwise return false.
*/
private validateFrames(frames: any[], useNumericIndex: bool): bool {
for (var i = 0; i < frames.length; i++)
@@ -98,6 +152,12 @@ module Phaser {
}
/**
* Play animation with specific name.
* @param name {string} The string name of the animation you want to play.
* @param frameRate {number} FrameRate you want to specify instead of using default.
* @param loop {boolean} Whether or not the animation is looped or just plays once.
*/
public play(name: string, frameRate?: number = null, loop?: bool) {
if (this._anims[name])
@@ -118,6 +178,10 @@ module Phaser {
}
/**
* Stop animation by name.
* Current animation will be automatically set to the stopped one.
*/
public stop(name: string) {
if (this._anims[name])
@@ -128,13 +192,16 @@ module Phaser {
}
/**
* Update animation and parent sprite's bounds.
*/
public update() {
if (this.currentAnim && this.currentAnim.update() == true)
{
this.currentFrame = this.currentAnim.currentFrame;
this._parent.bounds.width = this.currentFrame.width;
this._parent.bounds.height = this.currentFrame.height;
this._parent.frameBounds.width = this.currentFrame.width;
this._parent.frameBounds.height = this.currentFrame.height;
}
}
@@ -144,7 +211,15 @@ module Phaser {
}
public get frameTotal(): number {
return this._frameData.total;
if (this._frameData)
{
return this._frameData.total;
}
else
{
return -1;
}
}
public get frame(): number {
@@ -157,8 +232,8 @@ module Phaser {
{
this.currentFrame = this._frameData.getFrame(value);
this._parent.bounds.width = this.currentFrame.width;
this._parent.bounds.height = this.currentFrame.height;
this._parent.frameBounds.width = this.currentFrame.width;
this._parent.frameBounds.height = this.currentFrame.height;
this._frameIndex = value;
}
@@ -174,13 +249,26 @@ module Phaser {
{
this.currentFrame = this._frameData.getFrameByName(value);
this._parent.bounds.width = this.currentFrame.width;
this._parent.bounds.height = this.currentFrame.height;
this._parent.frameBounds.width = this.currentFrame.width;
this._parent.frameBounds.height = this.currentFrame.height;
this._frameIndex = this.currentFrame.index;
}
}
/**
* Removes all related references
*/
public destroy() {
this._anims = {};
this._frameData = null;
this._frameIndex = 0;
this.currentAnim = null;
this.currentFrame = null;
}
}
}
+23
View File
@@ -0,0 +1,23 @@
/// <reference path="Game.d.ts" />
module Phaser {
class Basic {
constructor(game: Game);
public _game: Game;
public name: string;
public ID: number;
public isGroup: bool;
public exists: bool;
public active: bool;
public visible: bool;
public alive: bool;
public ignoreDrawDebug: bool;
public destroy(): void;
public preUpdate(): void;
public update(): void;
public postUpdate(): void;
public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number): void;
public kill(): void;
public revive(): void;
public toString(): string;
}
}
+14 -2
View File
@@ -23,6 +23,8 @@ module Phaser {
this.visible = true;
this.alive = true;
this.isGroup = false;
this.ignoreGlobalUpdate = false;
this.ignoreGlobalRender = false;
this.ignoreDrawDebug = false;
}
@@ -70,6 +72,16 @@ module Phaser {
*/
public alive: bool;
/**
* Setting this to true will prevent the object from being updated during the main game loop (you will have to call update on it yourself)
*/
public ignoreGlobalUpdate: bool;
/**
* Setting this to true will prevent the object from being rendered during the main game loop (you will have to call render on it yourself)
*/
public ignoreGlobalRender: bool;
/**
* Setting this to true will prevent the object from appearing
* when the visual debug mode in the debugger overlay is toggled on.
@@ -93,7 +105,7 @@ module Phaser {
* Override this to update your class's position and appearance.
* This is where most of your game rules and behavioral code will go.
*/
public update() {
public update(forceUpdate?: bool = false) {
}
/**
@@ -102,7 +114,7 @@ module Phaser {
public postUpdate() {
}
public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number) {
public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number, forceRender?: bool = false) {
}
/**
+26
View File
@@ -0,0 +1,26 @@
/// <reference path="Game.d.ts" />
module Phaser {
class Cache {
constructor(game: Game);
private _game;
private _canvases;
private _images;
private _sounds;
private _text;
public addCanvas(key: string, canvas: HTMLCanvasElement, context: CanvasRenderingContext2D): void;
public addSpriteSheet(key: string, url: string, data, frameWidth: number, frameHeight: number, frameMax: number): void;
public addTextureAtlas(key: string, url: string, data, jsonData): void;
public addImage(key: string, url: string, data): void;
public addSound(key: string, url: string, data): void;
public decodedSound(key: string, data): void;
public addText(key: string, url: string, data): void;
public getCanvas(key: string);
public getImage(key: string);
public getFrameData(key: string): FrameData;
public getSound(key: string);
public isSoundDecoded(key: string): bool;
public isSpriteSheet(key: string): bool;
public getText(key: string);
public destroy(): void;
}
}
+116 -2
View File
@@ -11,6 +11,9 @@ module Phaser {
export class Cache {
/**
* Cache constructor
*/
constructor(game: Game) {
this._game = game;
@@ -22,19 +25,53 @@ module Phaser {
}
/**
* Local private reference to game.
*/
private _game: Game;
/**
* Canvas key-value container.
* @type {object}
*/
private _canvases;
/**
* Image key-value container.
* @type {object}
*/
private _images;
/**
* Sound key-value container.
* @type {object}
*/
private _sounds;
/**
* Text key-value container.
* @type {object}
*/
private _text;
/**
* Add a new canvas.
* @param key {string} Asset key for this canvas.
* @param canvas {HTMLCanvasElement} Canvas DOM element.
* @param context {CanvasRenderingContext2D} Render context of this canvas.
*/
public addCanvas(key: string, canvas: HTMLCanvasElement, context: CanvasRenderingContext2D) {
this._canvases[key] = { canvas: canvas, context: context };
}
/**
* Add a new sprite sheet.
* @param key {string} Asset key for the sprite sheet.
* @param url {string} URL of this sprite sheet file.
* @param data {object} Extra sprite sheet data.
* @param frameWidth {number} Width of the sprite sheet.
* @param frameHeight {number} Height of the sprite sheet.
* @param frameMax {number} How many frames stored in the sprite sheet.
*/
public addSpriteSheet(key: string, url: string, data, frameWidth: number, frameHeight: number, frameMax: number) {
this._images[key] = { url: url, data: data, spriteSheet: true, frameWidth: frameWidth, frameHeight: frameHeight };
@@ -42,25 +79,58 @@ module Phaser {
}
public addTextureAtlas(key: string, url: string, data, jsonData) {
/**
* Add a new texture atlas.
* @param key {string} Asset key for the texture atlas.
* @param url {string} URL of this texture atlas file.
* @param data {object} Extra texture atlas data.
* @param atlasData {object} Texture atlas frames data.
*/
public addTextureAtlas(key: string, url: string, data, atlasData, format) {
this._images[key] = { url: url, data: data, spriteSheet: true };
this._images[key].frameData = AnimationLoader.parseJSONData(this._game, jsonData);
if (format == Phaser.Loader.TEXTURE_ATLAS_JSON_ARRAY)
{
this._images[key].frameData = AnimationLoader.parseJSONData(this._game, atlasData);
}
else if (format == Phaser.Loader.TEXTURE_ATLAS_XML_STARLING)
{
this._images[key].frameData = AnimationLoader.parseXMLData(this._game, atlasData, format);
}
}
/**
* Add a new image.
* @param key {string} Asset key for the image.
* @param url {string} URL of this image file.
* @param data {object} Extra image data.
*/
public addImage(key: string, url: string, data) {
this._images[key] = { url: url, data: data, spriteSheet: false };
}
/**
* Add a new sound.
* @param key {string} Asset key for the sound.
* @param url {string} URL of this sound file.
* @param data {object} Extra sound data.
*/
public addSound(key: string, url: string, data) {
this._sounds[key] = { url: url, data: data, decoded: false };
}
/**
* Add a new decoded sound.
* @param key {string} Asset key for the sound.
* @param url {string} URL of this sound file.
* @param data {object} Extra sound data.
*/
public decodedSound(key: string, data) {
this._sounds[key].data = data;
@@ -68,12 +138,23 @@ module Phaser {
}
/**
* Add a new text data.
* @param key {string} Asset key for the text data.
* @param url {string} URL of this text data file.
* @param data {object} Extra text data.
*/
public addText(key: string, url: string, data) {
this._text[key] = { url: url, data: data };
}
/**
* Get canvas by key.
* @param key Asset key of the canvas you want.
* @return {object} The canvas you want.
*/
public getCanvas(key: string) {
if (this._canvases[key])
@@ -85,6 +166,11 @@ module Phaser {
}
/**
* Get image data by key.
* @param key Asset key of the image you want.
* @return {object} The image data you want.
*/
public getImage(key: string) {
if (this._images[key])
@@ -96,6 +182,11 @@ module Phaser {
}
/**
* Get frame data by key.
* @param key Asset key of the frame data you want.
* @return {object} The frame data you want.
*/
public getFrameData(key: string): FrameData {
if (this._images[key] && this._images[key].spriteSheet == true)
@@ -107,6 +198,11 @@ module Phaser {
}
/**
* Get sound data by key.
* @param key Asset key of the sound you want.
* @return {object} The sound data you want.
*/
public getSound(key: string) {
if (this._sounds[key])
@@ -118,6 +214,11 @@ module Phaser {
}
/**
* Check whether an asset is decoded sound.
* @param key Asset key of the sound you want.
* @return {object} The sound data you want.
*/
public isSoundDecoded(key: string): bool {
if (this._sounds[key])
@@ -127,6 +228,11 @@ module Phaser {
}
/**
* Check whether an asset is sprite sheet.
* @param key Asset key of the sprite sheet you want.
* @return {object} The sprite sheet data you want.
*/
public isSpriteSheet(key: string): bool {
if (this._images[key])
@@ -136,6 +242,11 @@ module Phaser {
}
/**
* Get text data by key.
* @param key Asset key of the text data you want.
* @return {object} The text data you want.
*/
public getText(key: string) {
if (this._text[key])
@@ -147,6 +258,9 @@ module Phaser {
}
/**
* Clean up cache memory.
*/
public destroy() {
for (var item in this._canvases)
+17
View File
@@ -0,0 +1,17 @@
/// <reference path="Game.d.ts" />
/// <reference path="system/Camera.d.ts" />
module Phaser {
class CameraManager {
constructor(game: Game, x: number, y: number, width: number, height: number);
private _game;
private _cameras;
private _cameraInstance;
public current: Camera;
public getAll(): Camera[];
public update(): void;
public render(): void;
public addCamera(x: number, y: number, width: number, height: number): Camera;
public removeCamera(id: number): bool;
public destroy(): void;
}
}
+52 -3
View File
@@ -6,15 +6,21 @@
*
* Your game only has one CameraManager instance and it's responsible for looking after, creating and destroying
* all of the cameras in the world.
*
* TODO: If the Camera is larger than the Stage size then the rotation offset isn't correct
* TODO: Texture Repeat doesn't scroll, because it's part of the camera not the world, need to think about this more
*/
module Phaser {
export class CameraManager {
/**
* CameraManager constructor
* This will create a new <code>Camera</code> with position and size.
*
* @param x {number} X Position of the created camera.
* @param y {number} y Position of the created camera.
* @param width {number} Width of the created camera.
* @param height {number} Height of the created camera.
*/
constructor(game: Game, x: number, y: number, width: number, height: number) {
this._game = game;
@@ -25,24 +31,58 @@ module Phaser {
}
/**
* Local private reference to Game.
*/
private _game: Game;
/**
* Local container for storing cameras.
*/
private _cameras: Camera[];
/**
* Local helper stores index of next created camera.
*/
private _cameraInstance: number = 0;
/**
* Currently used camera.
*/
public current: Camera;
/**
* Get all the cameras.
*
* @returns {Camera[]} An array contains all the cameras.
*/
public getAll(): Camera[] {
return this._cameras;
}
/**
* Update cameras.
*/
public update() {
this._cameras.forEach((camera) => camera.update());
}
/**
* Render cameras.
*/
public render() {
this._cameras.forEach((camera) => camera.render());
}
/**
* Create a new camera with specific position and size.
*
* @param x {number} X position of the new camera.
* @param y {number} Y position of the new camera.
* @param width {number} Width of the new camera.
* @param height {number} Height of the new camera.
* @returns {Camera} The newly created camera object.
*/
public addCamera(x: number, y: number, width: number, height: number): Camera {
var newCam: Camera = new Camera(this._game, this._cameraInstance, x, y, width, height);
@@ -55,6 +95,12 @@ module Phaser {
}
/**
* Remove a new camera with its id.
*
* @param id {number} ID of the camera you want to remove.
* @returns {boolean} True if successfully removed the camera, otherwise return false.
*/
public removeCamera(id: number): bool {
for (var c = 0; c < this._cameras.length; c++)
@@ -76,6 +122,9 @@ module Phaser {
}
/**
* Clean up memory.
*/
public destroy() {
this._cameras.length = 0;
+53
View File
@@ -0,0 +1,53 @@
/// <reference path="Game.d.ts" />
/// <reference path="geom/Point.d.ts" />
/// <reference path="geom/Rectangle.d.ts" />
/// <reference path="geom/Quad.d.ts" />
/// <reference path="geom/Circle.d.ts" />
/// <reference path="geom/Line.d.ts" />
/// <reference path="geom/IntersectResult.d.ts" />
/// <reference path="system/QuadTree.d.ts" />
module Phaser {
class Collision {
constructor(game: Game);
private _game;
static LEFT: number;
static RIGHT: number;
static UP: number;
static DOWN: number;
static NONE: number;
static CEILING: number;
static FLOOR: number;
static WALL: number;
static ANY: number;
static OVERLAP_BIAS: number;
static TILE_OVERLAP: bool;
static _tempBounds: Quad;
static lineToLine(line1: Line, line2: Line, output?: IntersectResult): IntersectResult;
static lineToLineSegment(line: Line, seg: Line, output?: IntersectResult): IntersectResult;
static lineToRawSegment(line: Line, x1: number, y1: number, x2: number, y2: number, output?: IntersectResult): IntersectResult;
static lineToRay(line1: Line, ray: Line, output?: IntersectResult): IntersectResult;
static lineToCircle(line: Line, circle: Circle, output?: IntersectResult): IntersectResult;
static lineToRectangle(line: Line, rect: Rectangle, output?: IntersectResult): IntersectResult;
static lineSegmentToLineSegment(line1: Line, line2: Line, output?: IntersectResult): IntersectResult;
static lineSegmentToRay(line: Line, ray: Line, output?: IntersectResult): IntersectResult;
static lineSegmentToCircle(seg: Line, circle: Circle, output?: IntersectResult): IntersectResult;
static lineSegmentToRectangle(seg: Line, rect: Rectangle, output?: IntersectResult): IntersectResult;
static rayToRectangle(ray: Line, rect: Rectangle, output?: IntersectResult): IntersectResult;
static rayToLineSegment(rayX1, rayY1, rayX2, rayY2, lineX1, lineY1, lineX2, lineY2, output?: IntersectResult): IntersectResult;
static pointToRectangle(point, rect: Rectangle, output?: IntersectResult): IntersectResult;
static rectangleToRectangle(rect1: Rectangle, rect2: Rectangle, output?: IntersectResult): IntersectResult;
static rectangleToCircle(rect: Rectangle, circle: Circle, output?: IntersectResult): IntersectResult;
static circleToCircle(circle1: Circle, circle2: Circle, output?: IntersectResult): IntersectResult;
static circleToRectangle(circle: Circle, rect: Rectangle, output?: IntersectResult): IntersectResult;
static circleContainsPoint(circle: Circle, point, output?: IntersectResult): IntersectResult;
public overlap(object1?: Basic, object2?: Basic, notifyCallback?, processCallback?): bool;
static separate(object1, object2): bool;
static separateTile(object: GameObject, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool, collideUp: bool, collideDown: bool): bool;
static separateTileX(object: GameObject, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool): bool;
static separateTileY(object: GameObject, x: number, y: number, width: number, height: number, mass: number, collideUp: bool, collideDown: bool): bool;
static separateX(object1, object2): bool;
static separateY(object1, object2): bool;
static distance(x1: number, y1: number, x2: number, y2: number): number;
static distanceSquared(x1: number, y1: number, x2: number, y2: number): number;
}
}
+740 -125
View File
File diff suppressed because it is too large Load Diff
+32
View File
@@ -0,0 +1,32 @@
/// <reference path="Game.d.ts" />
module Phaser {
class DynamicTexture {
constructor(game: Game, width: number, height: number);
private _game;
private _sx;
private _sy;
private _sw;
private _sh;
private _dx;
private _dy;
private _dw;
private _dh;
public bounds: Rectangle;
public canvas: HTMLCanvasElement;
public context: CanvasRenderingContext2D;
public getPixel(x: number, y: number): number;
public getPixel32(x: number, y: number): number;
public getPixels(rect: Rectangle): ImageData;
public setPixel(x: number, y: number, color: number): void;
public setPixel32(x: number, y: number, color: number): void;
public setPixels(rect: Rectangle, input): void;
public fillRect(rect: Rectangle, color: number): void;
public pasteImage(key: string, frame?: number, destX?: number, destY?: number, destWidth?: number, destHeight?: number): void;
public copyPixels(sourceTexture: DynamicTexture, sourceRect: Rectangle, destPoint: Point): void;
public clear(): void;
public width : number;
public height : number;
private getColor32(alpha, red, green, blue);
private getColor(red, green, blue);
}
}
+125 -24
View File
@@ -13,6 +13,14 @@ module Phaser {
export class DynamicTexture {
/**
* DynamicTexture constructor
* Create a new <code>DynamicTexture</code>.
*
* @param game {Phaser.Game} Current game instance.
* @param width {number} Init width of this texture.
* @param height {number} Init height of this texture.
*/
constructor(game: Game, width: number, height: number) {
this._game = game;
@@ -26,6 +34,9 @@ module Phaser {
}
/**
* Local private reference to game.
*/
private _game: Game;
private _sx: number = 0;
@@ -39,10 +50,30 @@ module Phaser {
// Input / Output nodes?
/**
* Bound of this texture with width and height info.
* @type {Rectangle}
*/
public bounds: Rectangle;
/**
* This class is actually a wrapper of canvas.
* @type {HTMLCanvasElement}
*/
public canvas: HTMLCanvasElement;
/**
* Canvas context of this object.
* @type {CanvasRenderingContext2D}
*/
public context: CanvasRenderingContext2D;
/**
* Get a color of a specific pixel.
* @param x {number} X position of the pixel in this texture.
* @param y {number} Y position of the pixel in this texture.
* @return {number} A native color value integer (format: 0xRRGGBB)
*/
public getPixel(x: number, y: number): number {
//r = imageData.data[0];
@@ -55,6 +86,12 @@ module Phaser {
}
/**
* Get a color of a specific pixel (including alpha value).
* @param x {number} X position of the pixel in this texture.
* @param y {number} Y position of the pixel in this texture.
* @return A native color value integer (format: 0xAARRGGBB)
*/
public getPixel32(x: number, y: number) {
var imageData = this.context.getImageData(x, y, 1, 1);
@@ -63,20 +100,36 @@ module Phaser {
}
// Returns a CanvasPixelArray
/**
* Get pixels in array in a specific rectangle.
* @param rect {Rectangle} The specific rectangle.
* @returns {array} CanvasPixelArray.
*/
public getPixels(rect: Rectangle) {
return this.context.getImageData(rect.x, rect.y, rect.width, rect.height);
}
public setPixel(x: number, y: number, color: number) {
/**
* Set color of a specific pixel.
* @param x {number} X position of the target pixel.
* @param y {number} Y position of the target pixel.
* @param color {number} Native integer with color value. (format: 0xRRGGBB)
*/
public setPixel(x: number, y: number, color: string) {
this.context.fillStyle = color;
this.context.fillRect(x, y, 1, 1);
}
/**
* Set color (with alpha) of a specific pixel.
* @param x {number} X position of the target pixel.
* @param y {number} Y position of the target pixel.
* @param color {number} Native integer with color value. (format: 0xAARRGGBB)
*/
public setPixel32(x: number, y: number, color: number) {
this.context.fillStyle = color;
@@ -84,12 +137,22 @@ module Phaser {
}
/**
* Set image data to a specific rectangle.
* @param rect {Rectangle} Target rectangle.
* @param input {object} Source image data.
*/
public setPixels(rect: Rectangle, input) {
this.context.putImageData(input, rect.x, rect.y);
}
/**
* Fill a given rectangle with specific color.
* @param rect {Rectangle} Target rectangle you want to fill.
* @param color {number} A native number with color value. (format: 0xRRGGBB)
*/
public fillRect(rect: Rectangle, color: number) {
this.context.fillStyle = color;
@@ -97,6 +160,9 @@ module Phaser {
}
/**
*
*/
public pasteImage(key: string, frame?: number = -1, destX?: number = 0, destY?: number = 0, destWidth?: number = null, destHeight?: number = null) {
var texture = null;
@@ -138,21 +204,27 @@ module Phaser {
if (texture != null)
{
this.context.drawImage(
texture, // Source Image
this._sx, // Source X (location within the source image)
this._sy, // Source Y
this._sw, // Source Width
this._sh, // Source Height
this._dx, // Destination X (where on the canvas it'll be drawn)
this._dy, // Destination Y
this._dw, // Destination Width (always same as Source Width unless scaled)
this._dh // Destination Height (always same as Source Height unless scaled)
texture, // Source Image
this._sx, // Source X (location within the source image)
this._sy, // Source Y
this._sw, // Source Width
this._sh, // Source Height
this._dx, // Destination X (where on the canvas it'll be drawn)
this._dy, // Destination Y
this._dw, // Destination Width (always same as Source Width unless scaled)
this._dh // Destination Height (always same as Source Height unless scaled)
);
}
}
// TODO - Add in support for: alphaBitmapData: BitmapData = null, alphaPoint: Point = null, mergeAlpha: bool = false
/**
* Copy pixel from another DynamicTexture to this texture.
* @param sourceTexture {DynamicTexture} Source texture object.
* @param sourceRect {Rectangle} The specific region rectangle to be copied to this in the source.
* @param destPoint {Point} Top-left point the target image data will be paste at.
*/
public copyPixels(sourceTexture: DynamicTexture, sourceRect: Rectangle, destPoint: Point) {
// Swap for drawImage if the sourceRect is the same size as the sourceTexture to avoid a costly getImageData call
@@ -167,12 +239,41 @@ module Phaser {
}
/**
* Given an array of GameObjects it will update each of them so that their canvas/contexts reference this DynamicTexture
* @param objects {Array} An array of GameObjects, or objects that inherit from it such as Sprites
*/
public assignCanvasToGameObjects(objects: GameObject[]) {
for (var i = 0; i < objects.length; i++)
{
objects[i].canvas = this.canvas;
objects[i].context = this.context;
}
}
/**
* Clear the whole canvas.
*/
public clear() {
this.context.clearRect(0, 0, this.bounds.width, this.bounds.height);
}
/**
* Renders this DynamicTexture to the Stage at the given x/y coordinates
*
* @param x {number} The X coordinate to render on the stage to (given in screen coordinates, not world)
* @param y {number} The Y coordinate to render on the stage to (given in screen coordinates, not world)
*/
public render(x?: number = 0, y?: number = 0) {
this._game.stage.context.drawImage(this.canvas, x, y);
}
public get width(): number {
return this.bounds.width;
}
@@ -183,13 +284,13 @@ module Phaser {
/**
* Given an alpha and 3 color values this will return an integer representation of it
*
* @param alpha The Alpha value (between 0 and 255)
* @param red The Red channel value (between 0 and 255)
* @param green The Green channel value (between 0 and 255)
* @param blue The Blue channel value (between 0 and 255)
*
* @return A native color value integer (format: 0xAARRGGBB)
*
* @param alpha {number} The Alpha value (between 0 and 255)
* @param red {number} The Red channel value (between 0 and 255)
* @param green {number} The Green channel value (between 0 and 255)
* @param blue {number} The Blue channel value (between 0 and 255)
*
* @return A native color value integer (format: 0xAARRGGBB)
*/
private getColor32(alpha: number, red: number, green: number, blue: number): number {
@@ -199,12 +300,12 @@ module Phaser {
/**
* Given 3 color values this will return an integer representation of it
*
* @param red The Red channel value (between 0 and 255)
* @param green The Green channel value (between 0 and 255)
* @param blue The Blue channel value (between 0 and 255)
*
* @return A native color value integer (format: 0xRRGGBB)
*
* @param red {number} The Red channel value (between 0 and 255)
* @param green {number} The Green channel value (between 0 and 255)
* @param blue {number} The Blue channel value (between 0 and 255)
*
* @return A native color value integer (format: 0xRRGGBB)
*/
private getColor(red: number, green: number, blue: number): number {
+18
View File
@@ -0,0 +1,18 @@
/// <reference path="Game.d.ts" />
module Phaser {
class FXManager {
constructor(game: Game);
private _fx;
private _length;
private _game;
public active: bool;
public visible: bool;
public add(effect): any;
public preUpdate(): void;
public postUpdate(): void;
public preRender(camera: Camera, cameraX: number, cameraY: number, cameraWidth: number, cameraHeight: number): void;
public render(camera: Camera, cameraX: number, cameraY: number, cameraWidth: number, cameraHeight: number): void;
public postRender(camera: Camera, cameraX: number, cameraY: number, cameraWidth: number, cameraHeight: number): void;
public destroy(): void;
}
}
+232
View File
@@ -0,0 +1,232 @@
/// <reference path="Game.ts" />
/**
* Phaser - FXManager
*
* The FXManager controls all special effects applied to game objects such as Cameras.
*/
module Phaser {
export class FXManager {
constructor(game: Game, parent) {
this._game = game;
this._parent = parent;
this._fx = [];
this.active = true;
this.visible = true;
}
/**
* The essential reference to the main game object.
*/
private _game: Game;
/**
* A reference to the object that owns this FXManager instance.
*/
private _parent;
/**
* The array in which we keep all of the registered FX
*/
private _fx;
/**
* Holds the size of the _fx array
*/
private _length: number;
/**
* Controls whether any of the FX have preUpdate, update or postUpdate called
*/
public active: bool;
/**
* Controls whether any of the FX have preRender, render or postRender called
*/
public visible: bool;
/**
* Adds a new FX to the FXManager.
* The effect must be an object with at least one of the following methods: preUpdate, postUpdate, preRender, render or postRender.
* A new instance of the effect will be created and a reference to Game will be passed to the object constructor.
* @param {object} effect
* @return {any}
*/
public add(effect): any {
var result: bool = false;
var newEffect = { effect: {}, preUpdate: false, postUpdate: false, preRender: false, render: false, postRender: false };
if (typeof effect === 'function')
{
newEffect.effect = new effect(this._game, this._parent);
}
else
{
throw new Error("Invalid object given to Phaser.FXManager.add");
}
// Check for methods now to avoid having to do this every loop
if (typeof newEffect.effect['preUpdate'] === 'function')
{
newEffect.preUpdate = true;
result = true;
}
if (typeof newEffect.effect['postUpdate'] === 'function')
{
newEffect.postUpdate = true;
result = true;
}
if (typeof newEffect.effect['preRender'] === 'function')
{
newEffect.preRender = true;
result = true;
}
if (typeof newEffect.effect['render'] === 'function')
{
newEffect.render = true;
result = true;
}
if (typeof newEffect.effect['postRender'] === 'function')
{
newEffect.postRender = true;
result = true;
}
if (result == true)
{
this._length = this._fx.push(newEffect);
return newEffect.effect;
}
else
{
return result;
}
}
/**
* Pre-update is called at the start of the objects update cycle, before any other updates have taken place.
*/
public preUpdate() {
if (this.active)
{
for (var i = 0; i < this._length; i++)
{
if (this._fx[i].preUpdate)
{
this._fx[i].effect.preUpdate();
}
}
}
}
/**
* Post-update is called at the end of the objects update cycle, after other update logic has taken place.
*/
public postUpdate() {
if (this.active)
{
for (var i = 0; i < this._length; i++)
{
if (this._fx[i].postUpdate)
{
this._fx[i].effect.postUpdate();
}
}
}
}
/**
* Pre-render is called at the start of the object render cycle, before any transforms have taken place.
* It happens directly AFTER a canvas context.save has happened if added to a Camera.
* @param {Camera} camera
* @param {number} cameraX
* @param {number} cameraY
* @param {number} cameraWidth
* @param {number} cameraHeight
*/
public preRender(camera:Camera, cameraX: number, cameraY: number, cameraWidth: number, cameraHeight: number) {
if (this.visible)
{
for (var i = 0; i < this._length; i++)
{
if (this._fx[i].preRender)
{
this._fx[i].effect.preRender(camera, cameraX, cameraY, cameraWidth, cameraHeight);
}
}
}
}
/**
* render is called during the objects render cycle, right after all transforms have finished, but before any children/image data is rendered.
* @param {Camera} camera
* @param {number} cameraX
* @param {number} cameraY
* @param {number} cameraWidth
* @param {number} cameraHeight
*/
public render(camera:Camera, cameraX: number, cameraY: number, cameraWidth: number, cameraHeight: number) {
if (this.visible)
{
for (var i = 0; i < this._length; i++)
{
if (this._fx[i].preRender)
{
this._fx[i].effect.preRender(camera, cameraX, cameraY, cameraWidth, cameraHeight);
}
}
}
}
/**
* Post-render is called during the objects render cycle, after the children/image data has been rendered.
* It happens directly BEFORE a canvas context.restore has happened if added to a Camera.
*/
public postRender(camera:Camera, cameraX: number, cameraY: number, cameraWidth: number, cameraHeight: number) {
if (this.visible)
{
for (var i = 0; i < this._length; i++)
{
if (this._fx[i].postRender)
{
this._fx[i].effect.postRender(camera, cameraX, cameraY, cameraWidth, cameraHeight);
}
}
}
}
/**
* Clear down this FXManager and null out references
*/
public destroy() {
this._game = null;
this._fx = null;
}
}
}
+88
View File
@@ -0,0 +1,88 @@
/// <reference path="AnimationManager.d.ts" />
/// <reference path="Basic.d.ts" />
/// <reference path="Cache.d.ts" />
/// <reference path="CameraManager.d.ts" />
/// <reference path="Collision.d.ts" />
/// <reference path="DynamicTexture.d.ts" />
/// <reference path="FXManager.d.ts" />
/// <reference path="GameMath.d.ts" />
/// <reference path="Group.d.ts" />
/// <reference path="Loader.d.ts" />
/// <reference path="Motion.d.ts" />
/// <reference path="Signal.d.ts" />
/// <reference path="SignalBinding.d.ts" />
/// <reference path="SoundManager.d.ts" />
/// <reference path="Stage.d.ts" />
/// <reference path="Time.d.ts" />
/// <reference path="TweenManager.d.ts" />
/// <reference path="World.d.ts" />
/// <reference path="system/Device.d.ts" />
/// <reference path="system/RandomDataGenerator.d.ts" />
/// <reference path="system/RequestAnimationFrame.d.ts" />
/// <reference path="system/input/Input.d.ts" />
/// <reference path="system/input/Keyboard.d.ts" />
/// <reference path="system/input/Mouse.d.ts" />
/// <reference path="system/input/Touch.d.ts" />
/// <reference path="gameobjects/Emitter.d.ts" />
/// <reference path="gameobjects/GameObject.d.ts" />
/// <reference path="gameobjects/GeomSprite.d.ts" />
/// <reference path="gameobjects/Particle.d.ts" />
/// <reference path="gameobjects/Sprite.d.ts" />
/// <reference path="gameobjects/Tilemap.d.ts" />
/// <reference path="gameobjects/ScrollZone.d.ts" />
module Phaser {
class Game {
constructor(callbackContext, parent?: string, width?: number, height?: number, initCallback?, createCallback?, updateCallback?, renderCallback?);
private _raf;
private _maxAccumulation;
private _accumulator;
private _step;
private _loadComplete;
private _paused;
private _pendingState;
public callbackContext;
public onInitCallback;
public onCreateCallback;
public onUpdateCallback;
public onRenderCallback;
public onPausedCallback;
public cache: Cache;
public collision: Collision;
public input: Input;
public loader: Loader;
public math: GameMath;
public motion: Motion;
public sound: SoundManager;
public stage: Stage;
public time: Time;
public tweens: TweenManager;
public world: World;
public rnd: RandomDataGenerator;
public device: Device;
public isBooted: bool;
public isRunning: bool;
private boot(parent, width, height);
private loadComplete();
private bootLoop();
private pausedLoop();
private loop();
private startState();
public setCallbacks(initCallback?, createCallback?, updateCallback?, renderCallback?): void;
public switchState(state, clearWorld?: bool, clearCache?: bool): void;
public destroy(): void;
public paused : bool;
public framerate : number;
public createCamera(x: number, y: number, width: number, height: number): Camera;
public createGeomSprite(x: number, y: number): GeomSprite;
public createSprite(x: number, y: number, key?: string): Sprite;
public createDynamicTexture(width: number, height: number): DynamicTexture;
public createGroup(MaxSize?: number): Group;
public createParticle(): Particle;
public createEmitter(x?: number, y?: number, size?: number): Emitter;
public createScrollZone(key: string, x?: number, y?: number, width?: number, height?: number): ScrollZone;
public createTilemap(key: string, mapData: string, format: number, resizeWorld?: bool, tileWidth?: number, tileHeight?: number): Tilemap;
public createTween(obj): Tween;
public collide(objectOrGroup1?: Basic, objectOrGroup2?: Basic, notifyCallback?): bool;
public camera : Camera;
}
}
+306 -83
View File
@@ -4,7 +4,9 @@
/// <reference path="CameraManager.ts" />
/// <reference path="Collision.ts" />
/// <reference path="DynamicTexture.ts" />
/// <reference path="FXManager.ts" />
/// <reference path="GameMath.ts" />
/// <reference path="GameObjectFactory.ts" />
/// <reference path="Group.ts" />
/// <reference path="Loader.ts" />
/// <reference path="Motion.ts" />
@@ -14,13 +16,16 @@
/// <reference path="Stage.ts" />
/// <reference path="Time.ts" />
/// <reference path="TweenManager.ts" />
/// <reference path="VerletManager.ts" />
/// <reference path="World.ts" />
/// <reference path="geom/Vector2.ts" />
/// <reference path="system/Device.ts" />
/// <reference path="system/RandomDataGenerator.ts" />
/// <reference path="system/RequestAnimationFrame.ts" />
/// <reference path="system/input/Input.ts" />
/// <reference path="system/input/Keyboard.ts" />
/// <reference path="system/input/Mouse.ts" />
/// <reference path="system/input/MSPointer.ts" />
/// <reference path="system/input/Touch.ts" />
/// <reference path="gameobjects/Emitter.ts" />
/// <reference path="gameobjects/GameObject.ts" />
@@ -33,7 +38,7 @@
/**
* Phaser - Game
*
* This is where the magic happens. The Game object is the heart of your game,
* This is where the magic happens. The Game object is the heart of your game,
* providing quick access to common functions and handling the boot process.
*
* "Hell, there are no rules here - we're trying to accomplish something."
@@ -44,13 +49,29 @@ module Phaser {
export class Game {
constructor(callbackContext, parent?: string = '', width?: number = 800, height?: number = 600, initCallback = null, createCallback = null, updateCallback = null, renderCallback = null) {
/**
* Game constructor
*
* Instantiate a new <code>Phaser.Game</code> object.
*
* @param callbackContext Which context will the callbacks be called with.
* @param parent {string} ID of its parent DOM element.
* @param width {number} The width of your game in game pixels.
* @param height {number} The height of your game in game pixels.
* @param initCallback {function} Init callback invoked when init default screen.
* @param createCallback {function} Create callback invoked when create default screen.
* @param updateCallback {function} Update callback invoked when update default screen.
* @param renderCallback {function} Render callback invoked when render default screen.
* @param destroyCallback {function} Destroy callback invoked when state is destroyed.
*/
constructor(callbackContext, parent?: string = '', width?: number = 800, height?: number = 600, initCallback = null, createCallback = null, updateCallback = null, renderCallback = null, destroyCallback = null) {
this.callbackContext = callbackContext;
this.onInitCallback = initCallback;
this.onCreateCallback = createCallback;
this.onUpdateCallback = updateCallback;
this.onRenderCallback = renderCallback;
this.onDestroyCallback = destroyCallback;
if (document.readyState === 'complete' || document.readyState === 'interactive')
{
@@ -64,39 +85,202 @@ module Phaser {
}
private _raf: RequestAnimationFrame;
/**
* Game loop trigger wrapper.
*/
public _raf: RequestAnimationFrame;
/**
* Max allowable accumulation.
* @type {number}
*/
private _maxAccumulation: number = 32;
/**
* Total number of milliseconds elapsed since last update loop.
* @type {number}
*/
private _accumulator: number = 0;
/**
* Milliseconds of time per step of the game loop.
* @type {number}
*/
private _step: number = 0;
/**
* Whether loader complete loading or not.
* @type {boolean}
*/
private _loadComplete: bool = false;
/**
* Game is paused?
* @type {boolean}
*/
private _paused: bool = false;
/**
* The state to be switched to in the next frame.
* @type {State}
*/
private _pendingState = null;
// Event callbacks
/**
* The current State object (defaults to null)
* @type {State}
*/
public state = null;
/**
* Context for calling the callbacks.
*/
public callbackContext;
/**
* This will be called when init states. (loading assets...)
* @type {function}
*/
public onInitCallback = null;
/**
* This will be called when create states. (setup states...)
* @type {function}
*/
public onCreateCallback = null;
/**
* This will be called when update states.
* @type {function}
*/
public onUpdateCallback = null;
/**
* This will be called when render states.
* @type {function}
*/
public onRenderCallback = null;
/**
* This will be called when states paused.
* @type {function}
*/
public onPausedCallback = null;
public camera: Camera; // quick reference to the default created camera, access the rest via .world
/**
* This will be called when the state is destroyed (i.e. swapping to a new state)
* @type {function}
*/
public onDestroyCallback = null;
/**
* Reference to the GameObject Factory.
* @type {GameObjectFactory}
*/
public add: GameObjectFactory;
/**
* Reference to the assets cache.
* @type {Cache}
*/
public cache: Cache;
/**
* Reference to the collision helper.
* @type {Collision}
*/
public collision: Collision;
/**
* Reference to the input manager
* @type {Input}
*/
public input: Input;
/**
* Reference to the assets loader.
* @type {Loader}
*/
public loader: Loader;
/**
* Reference to the math helper.
* @type {GameMath}
*/
public math: GameMath;
/**
* Reference to the motion helper.
* @type {Motion}
*/
public motion: Motion;
/**
* Reference to the sound manager.
* @type {SoundManager}
*/
public sound: SoundManager;
/**
* Reference to the stage.
* @type {Stage}
*/
public stage: Stage;
/**
* Reference to game clock.
* @type {Time}
*/
public time: Time;
/**
* Reference to the tween manager.
* @type {TweenManager}
*/
public tweens: TweenManager;
/**
* Reference to the verlet manager.
* @type {VerletManager}
*/
public verlet: Phaser.Verlet.VerletManager;
/**
* Reference to the world.
* @type {World}
*/
public world: World;
/**
* Instance of repeatable random data generator helper.
* @type {RandomDataGenerator}
*/
public rnd: RandomDataGenerator;
/**
* Contains device information and capabilities.
* @type {Device}
*/
public device: Device;
/**
* Whether the game engine is booted, aka available.
* @type {boolean}
*/
public isBooted: bool = false;
/**
* Is game running or paused?
* @type {boolean}
*/
public isRunning: bool = false;
/**
* Initialize engine sub modules and start the game.
* @param parent {string} ID of parent Dom element.
* @param width {number} Width of the game screen.
* @param height {number} Height of the game screen.
*/
private boot(parent: string, width: number, height: number) {
if (this.isBooted == true)
@@ -115,6 +299,7 @@ module Phaser {
this.math = new GameMath(this);
this.stage = new Stage(this, parent, width, height);
this.world = new World(this, width, height);
this.add = new GameObjectFactory(this);
this.sound = new SoundManager(this);
this.cache = new Cache(this);
this.collision = new Collision(this);
@@ -123,21 +308,23 @@ module Phaser {
this.tweens = new TweenManager(this);
this.input = new Input(this);
this.rnd = new RandomDataGenerator([(Date.now() * Math.random()).toString()]);
this.verlet = new Phaser.Verlet.VerletManager(this, width, height);
this.framerate = 60;
this.isBooted = true;
this.input.start();
// Display the default game screen?
if (this.onInitCallback == null && this.onCreateCallback == null && this.onUpdateCallback == null && this.onRenderCallback == null && this._pendingState == null)
{
this.isBooted = false;
this.stage.drawInitScreen();
this._raf = new RequestAnimationFrame(this, this.bootLoop);
}
else
{
this.isBooted = true;
this.isRunning = true;
this._loadComplete = false;
this._raf = new RequestAnimationFrame(this.loop, this);
this._raf = new RequestAnimationFrame(this, this.loop);
if (this._pendingState)
{
@@ -154,32 +341,52 @@ module Phaser {
}
/**
* Called when the loader has finished after init was run.
*/
private loadComplete() {
// Called when the loader has finished after init was run
this._loadComplete = true;
}
private loop() {
/**
* Game loop method will be called when it's booting.
*/
private bootLoop() {
this.time.update();
this.tweens.update();
if (this._paused == true)
{
if (this.onPausedCallback !== null)
{
this.onPausedCallback.call(this.callbackContext);
}
return;
}
this.input.update();
this.stage.update();
}
/**
* Game loop method will be called when it's paused.
*/
private pausedLoop() {
this.tweens.update();
this.input.update();
this.stage.update();
if (this.onPausedCallback !== null)
{
this.onPausedCallback.call(this.callbackContext);
}
}
/**
* Game loop method will be called when it's running.
*/
private loop() {
this.tweens.update();
this.input.update();
this.stage.update();
this.verlet.update();
this._accumulator += this.time.delta;
if (this._accumulator > this._maxAccumulation)
@@ -208,6 +415,9 @@ module Phaser {
}
/**
* Start current state.
*/
private startState() {
if (this.onInitCallback !== null)
@@ -240,15 +450,30 @@ module Phaser {
}
public setCallbacks(initCallback = null, createCallback = null, updateCallback = null, renderCallback = null) {
/**
* Set all state callbacks (init, create, update, render).
* @param initCallback {function} Init callback invoked when init state.
* @param createCallback {function} Create callback invoked when create state.
* @param updateCallback {function} Update callback invoked when update state.
* @param renderCallback {function} Render callback invoked when render state.
* @param destroyCallback {function} Destroy callback invoked when state is destroyed.
*/
public setCallbacks(initCallback = null, createCallback = null, updateCallback = null, renderCallback = null, destroyCallback = null) {
this.onInitCallback = initCallback;
this.onCreateCallback = createCallback;
this.onUpdateCallback = updateCallback;
this.onRenderCallback = renderCallback;
this.onDestroyCallback = destroyCallback;
}
/**
* Switch to a new State.
* @param state {State} The state you want to switch to.
* @param [clearWorld] {boolean} clear everything in the world? (Default to true)
* @param [clearCache] {boolean} clear asset cache? (Default to false and ONLY available when clearWorld=true)
*/
public switchState(state, clearWorld: bool = true, clearCache: bool = false) {
if (this.isBooted == false)
@@ -257,47 +482,61 @@ module Phaser {
return;
}
// Destroy current state?
if (this.onDestroyCallback !== null)
{
this.onDestroyCallback.call(this.callbackContext);
}
this.input.reset(true);
// Prototype?
if (typeof state === 'function')
{
state = new state(this);
this.state = new state(this);
}
// Ok, have we got the right functions?
if (state['create'] || state['update'])
if (this.state['create'] || this.state['update'])
{
this.callbackContext = state;
this.callbackContext = this.state;
this.onInitCallback = null;
this.onCreateCallback = null;
this.onUpdateCallback = null;
this.onRenderCallback = null;
this.onPausedCallback = null;
this.onDestroyCallback = null;
// Bingo, let's set them up
if (state['init'])
if (this.state['init'])
{
this.onInitCallback = state['init'];
this.onInitCallback = this.state['init'];
}
if (state['create'])
if (this.state['create'])
{
this.onCreateCallback = state['create'];
this.onCreateCallback = this.state['create'];
}
if (state['update'])
if (this.state['update'])
{
this.onUpdateCallback = state['update'];
this.onUpdateCallback = this.state['update'];
}
if (state['render'])
if (this.state['render'])
{
this.onRenderCallback = state['render'];
this.onRenderCallback = this.state['render'];
}
if (state['paused'])
if (this.state['paused'])
{
this.onPausedCallback = state['paused'];
this.onPausedCallback = this.state['paused'];
}
if (this.state['destroy'])
{
this.onDestroyCallback = this.state['destroy'];
}
if (clearWorld)
@@ -321,7 +560,9 @@ module Phaser {
}
// Nuke the whole game from orbit
/**
* Nuke the whole game from orbit
*/
public destroy() {
this.callbackContext = null;
@@ -330,7 +571,7 @@ module Phaser {
this.onUpdateCallback = null;
this.onRenderCallback = null;
this.onPausedCallback = null;
this.camera = null;
this.onDestroyCallback = null;
this.cache = null;
this.input = null;
this.loader = null;
@@ -351,12 +592,22 @@ module Phaser {
if (value == true && this._paused == false)
{
this._paused = true;
this._raf.callback = this.pausedLoop;
}
else if (value == false && this._paused == true)
{
this._paused = false;
this.time.time = Date.now();
//this.time.time = window.performance.now ? (performance.now() + performance.timing.navigationStart) : Date.now();
this.input.reset();
if (this.isRunning == false)
{
this._raf.callback = this.bootLoop;
}
else
{
this._raf.callback = this.loop;
}
}
}
@@ -376,50 +627,22 @@ module Phaser {
}
// Handy Proxy methods
public createCamera(x: number, y: number, width: number, height: number): Camera {
return this.world.createCamera(x, y, width, height);
/**
* Checks for overlaps between two objects using the world QuadTree. Can be GameObject vs. GameObject, GameObject vs. Group or Group vs. Group.
* Note: Does not take the objects scrollFactor into account. All overlaps are check in world space.
* @param object1 The first GameObject or Group to check. If null the world.group is used.
* @param object2 The second GameObject or Group to check.
* @param notifyCallback A callback function that is called if the objects overlap. The two objects will be passed to this function in the same order in which you passed them to Collision.overlap.
* @param processCallback A callback function that lets you perform additional checks against the two objects if they overlap. If this is set then notifyCallback will only be called if processCallback returns true.
* @param context The context in which the callbacks will be called
* @returns {boolean} true if the objects overlap, otherwise false.
*/
public collide(objectOrGroup1: Basic = null, objectOrGroup2: Basic = null, notifyCallback = null, context? = this.callbackContext): bool {
return this.collision.overlap(objectOrGroup1, objectOrGroup2, notifyCallback, Collision.separate, context);
}
public createGeomSprite(x: number, y: number): GeomSprite {
return this.world.createGeomSprite(x, y);
}
public createSprite(x: number, y: number, key?: string = ''): Sprite {
return this.world.createSprite(x, y, key);
}
public createDynamicTexture(width: number, height: number): DynamicTexture {
return this.world.createDynamicTexture(width, height);
}
public createGroup(MaxSize?: number = 0): Group {
return this.world.createGroup(MaxSize);
}
public createParticle(): Particle {
return this.world.createParticle();
}
public createEmitter(x?: number = 0, y?: number = 0, size?: number = 0): Emitter {
return this.world.createEmitter(x, y, size);
}
public createScrollZone(key: string, x?: number = 0, y?: number = 0, width?: number = 0, height?: number = 0): ScrollZone {
return this.world.createScrollZone(key, x, y, width, height);
}
public createTilemap(key: string, mapData: string, format: number, resizeWorld: bool = true, tileWidth?: number = 0, tileHeight?: number = 0): Tilemap {
return this.world.createTilemap(key, mapData, format, resizeWorld, tileWidth, tileHeight);
}
public createTween(obj): Tween {
return this.tweens.create(obj);
}
public collide(objectOrGroup1: Basic = null, objectOrGroup2: Basic = null, notifyCallback = null): bool {
return this.collision.overlap(objectOrGroup1, objectOrGroup2, notifyCallback, Collision.separate);
public get camera(): Camera {
return this.world.cameras.current;
}
}
+110
View File
@@ -0,0 +1,110 @@
/// <reference path="Game.d.ts" />
module Phaser {
class GameMath {
constructor(game: Game);
private _game;
static PI: number;
static PI_2: number;
static PI_4: number;
static PI_8: number;
static PI_16: number;
static TWO_PI: number;
static THREE_PI_2: number;
static E: number;
static LN10: number;
static LN2: number;
static LOG10E: number;
static LOG2E: number;
static SQRT1_2: number;
static SQRT2: number;
static DEG_TO_RAD: number;
static RAD_TO_DEG: number;
static B_16: number;
static B_31: number;
static B_32: number;
static B_48: number;
static B_53: number;
static B_64: number;
static ONE_THIRD: number;
static TWO_THIRDS: number;
static ONE_SIXTH: number;
static COS_PI_3: number;
static SIN_2PI_3: number;
static CIRCLE_ALPHA: number;
static ON: bool;
static OFF: bool;
static SHORT_EPSILON: number;
static PERC_EPSILON: number;
static EPSILON: number;
static LONG_EPSILON: number;
public cosTable: any[];
public sinTable: any[];
public fuzzyEqual(a: number, b: number, epsilon?: number): bool;
public fuzzyLessThan(a: number, b: number, epsilon?: number): bool;
public fuzzyGreaterThan(a: number, b: number, epsilon?: number): bool;
public fuzzyCeil(val: number, epsilon?: number): number;
public fuzzyFloor(val: number, epsilon?: number): number;
public average(...args: any[]): number;
public slam(value: number, target: number, epsilon?: number): number;
public percentageMinMax(val: number, max: number, min?: number): number;
public sign(n: number): number;
public truncate(n: number): number;
public shear(n: number): number;
public wrap(val: number, max: number, min?: number): number;
public arithWrap(value: number, max: number, min?: number): number;
public clamp(input: number, max: number, min?: number): number;
public snapTo(input: number, gap: number, start?: number): number;
public snapToFloor(input: number, gap: number, start?: number): number;
public snapToCeil(input: number, gap: number, start?: number): number;
public snapToInArray(input: number, arr: number[], sort?: bool): number;
public roundTo(value: number, place?: number, base?: number): number;
public floorTo(value: number, place?: number, base?: number): number;
public ceilTo(value: number, place?: number, base?: number): number;
public interpolateFloat(a: number, b: number, weight: number): number;
public radiansToDegrees(angle: number): number;
public degreesToRadians(angle: number): number;
public angleBetween(x1: number, y1: number, x2: number, y2: number): number;
public normalizeAngle(angle: number, radians?: bool): number;
public nearestAngleBetween(a1: number, a2: number, radians?: bool): number;
public normalizeAngleToAnother(dep: number, ind: number, radians?: bool): number;
public normalizeAngleAfterAnother(dep: number, ind: number, radians?: bool): number;
public normalizeAngleBeforeAnother(dep: number, ind: number, radians?: bool): number;
public interpolateAngles(a1: number, a2: number, weight: number, radians?: bool, ease?): number;
public logBaseOf(value: number, base: number): number;
public GCD(m: number, n: number): number;
public LCM(m: number, n: number): number;
public factorial(value: number): number;
public gammaFunction(value: number): number;
public fallingFactorial(base: number, exp: number): number;
public risingFactorial(base: number, exp: number): number;
public binCoef(n: number, k: number): number;
public risingBinCoef(n: number, k: number): number;
public chanceRoll(chance?: number): bool;
public maxAdd(value: number, amount: number, max: number): number;
public minSub(value: number, amount: number, min: number): number;
public wrapValue(value: number, amount: number, max: number): number;
public randomSign(): number;
public isOdd(n: number): bool;
public isEven(n: number): bool;
public wrapAngle(angle: number): number;
public angleLimit(angle: number, min: number, max: number): number;
public linearInterpolation(v, k);
public bezierInterpolation(v, k): number;
public catmullRomInterpolation(v, k);
public linear(p0, p1, t);
public bernstein(n, i): number;
public catmullRom(p0, p1, p2, p3, t);
public difference(a: number, b: number): number;
public globalSeed: number;
public random(): number;
public srand(Seed: number): number;
public getRandom(Objects, StartIndex?: number, Length?: number);
public floor(Value: number): number;
public ceil(Value: number): number;
public sinCosGenerator(length: number, sinAmplitude?: number, cosAmplitude?: number, frequency?: number): any[];
public shiftSinTable(): number;
public shiftCosTable(): number;
public vectorLength(dx: number, dy: number): number;
public dotProduct(ax: number, ay: number, bx: number, by: number): number;
}
}
+137 -75
View File
@@ -152,7 +152,7 @@ module Phaser {
/**
* force a value within the boundaries of two values
*
*
* if max < min, min is returned
*/
public clamp(input: number, max: number, min: number = 0): number {
@@ -161,12 +161,12 @@ module Phaser {
/**
* Snap a value to nearest grid slice, using rounding.
*
*
* example if you have an interval gap of 5 and a position of 12... you will snap to 10. Where as 14 will snap to 15
*
*
* @param input - the value to snap
* @param gap - the interval gap of the grid
* @param start - optional starting offset for gap
* @param [start] - optional starting offset for gap
*/
public snapTo(input: number, gap: number, start: number = 0): number {
if (gap == 0) return input;
@@ -178,12 +178,12 @@ module Phaser {
/**
* Snap a value to nearest grid slice, using floor.
*
*
* example if you have an interval gap of 5 and a position of 12... you will snap to 10. As will 14 snap to 10... but 16 will snap to 15
*
*
* @param input - the value to snap
* @param gap - the interval gap of the grid
* @param start - optional starting offset for gap
* @param [start] - optional starting offset for gap
*/
public snapToFloor(input: number, gap: number, start: number = 0): number {
if (gap == 0) return input;
@@ -195,12 +195,12 @@ module Phaser {
/**
* Snap a value to nearest grid slice, using ceil.
*
*
* example if you have an interval gap of 5 and a position of 12... you will snap to 15. As will 14 will snap to 15... but 16 will snap to 20
*
*
* @param input - the value to snap
* @param gap - the interval gap of the grid
* @param start - optional starting offset for gap
* @param [start] - optional starting offset for gap
*/
public snapToCeil(input: number, gap: number, start: number = 0): number {
if (gap == 0) return input;
@@ -231,17 +231,17 @@ module Phaser {
/**
* roundTo some place comparative to a 'base', default is 10 for decimal place
*
*
* 'place' is represented by the power applied to 'base' to get that place
*
*
* @param value - the value to round
* @param place - the place to round to
* @param base - the base to round in... default is 10 for decimal
*
*
* e.g.
*
*
* 2000/7 ~= 285.714285714285714285714 ~= (bin)100011101.1011011011011011
*
*
* roundTo(2000/7,3) == 0
* roundTo(2000/7,2) == 300
* roundTo(2000/7,1) == 290
@@ -251,7 +251,7 @@ module Phaser {
* roundTo(2000/7,-3) == 285.714
* roundTo(2000/7,-4) == 285.7143
* roundTo(2000/7,-5) == 285.71429
*
*
* roundTo(2000/7,3,2) == 288 -- 100100000
* roundTo(2000/7,2,2) == 284 -- 100011100
* roundTo(2000/7,1,2) == 286 -- 100011110
@@ -261,8 +261,8 @@ module Phaser {
* roundTo(2000/7,-3,2) == 285.75 -- 100011101.11
* roundTo(2000/7,-4,2) == 285.6875 -- 100011101.1011
* roundTo(2000/7,-5,2) == 285.71875 -- 100011101.10111
*
* note what occurs when we round to the 3rd space (8ths place), 100100000, this is to be assumed
*
* note what occurs when we round to the 3rd space (8ths place), 100100000, this is to be assumed
* because we are rounding 100011.1011011011011011 which rounds up.
*/
public roundTo(value: number, place: number = 0, base: number = 10): number {
@@ -336,7 +336,7 @@ module Phaser {
/**
* normalizes independent and then sets dep to the nearest value respective to independent
*
*
* for instance if dep=-170 and ind=170 then 190 will be returned as an alternative to -170
*/
public normalizeAngleToAnother(dep: number, ind: number, radians: bool = true): number {
@@ -345,7 +345,7 @@ module Phaser {
/**
* normalize independent and dependent and then set dependent to an angle relative to 'after/clockwise' independent
*
*
* for instance dep=-170 and ind=170, then 190 will be reutrned as alternative to -170
*/
public normalizeAngleAfterAnother(dep: number, ind: number, radians: bool = true): number {
@@ -356,7 +356,7 @@ module Phaser {
/**
* normalizes indendent and dependent and then sets dependent to an angle relative to 'before/counterclockwise' independent
*
*
* for instance dep = 190 and ind = 170, then -170 will be returned as an alternative to 190
*/
public normalizeAngleBeforeAnother(dep: number, ind: number, radians: bool = true): number {
@@ -378,17 +378,17 @@ module Phaser {
/**
* Compute the logarithm of any value of any base
*
* a logarithm is the exponent that some constant (base) would have to be raised to
*
* a logarithm is the exponent that some constant (base) would have to be raised to
* to be equal to value.
*
*
* i.e.
* 4 ^ x = 16
* can be rewritten as to solve for x
* logB4(16) = x
* which with this function would be
* which with this function would be
* LoDMath.logBaseOf(16,4)
*
*
* which would return 2, because 4^2 = 16
*/
public logBaseOf(value: number, base: number): number {
@@ -434,9 +434,9 @@ module Phaser {
/**
* Factorial - N!
*
*
* simple product series
*
*
* by definition:
* 0! == 1
*/
@@ -455,7 +455,7 @@ module Phaser {
/**
* gamma function
*
*
* defined: gamma(N) == (N - 1)!
*/
public gammaFunction(value: number): number {
@@ -464,9 +464,9 @@ module Phaser {
/**
* falling factorial
*
*
* defined: (N)! / (N - x)!
*
*
* written subscript: (N)x OR (base)exp
*/
public fallingFactorial(base: number, exp: number): number {
@@ -475,9 +475,9 @@ module Phaser {
/**
* rising factorial
*
*
* defined: (N + x - 1)! / (N - 1)!
*
*
* written superscript N^(x) OR base^(exp)
*/
public risingFactorial(base: number, exp: number): number {
@@ -487,7 +487,7 @@ module Phaser {
/**
* binomial coefficient
*
*
* defined: N! / (k!(N-k)!)
* reduced: N! / (N-k)! == (N)k (fallingfactorial)
* reduced: (N)k / k!
@@ -498,10 +498,10 @@ module Phaser {
/**
* rising binomial coefficient
*
* as one can notice in the analysis of binCoef(...) that
* binCoef is the (N)k divided by k!. Similarly rising binCoef
* is merely N^(k) / k!
*
* as one can notice in the analysis of binCoef(...) that
* binCoef is the (N)k divided by k!. Similarly rising binCoef
* is merely N^(k) / k!
*/
public risingBinCoef(n: number, k: number): number {
return this.risingFactorial(n, k) / this.factorial(k);
@@ -542,7 +542,7 @@ module Phaser {
/**
* Adds the given amount to the value, but never lets the value go over the specified maximum
*
*
* @param value The value to add the amount to
* @param amount The amount to add to the value
* @param max The maximum the value is allowed to be
@@ -563,7 +563,7 @@ module Phaser {
/**
* Subtracts the given amount from the value, but never lets the value go below the specified minimum
*
*
* @param value The base value
* @param amount The amount to subtract from the base value
* @param min The minimum the value is allowed to be
@@ -584,7 +584,7 @@ module Phaser {
/**
* Adds value to amount and ensures that the result always stays between 0 and max, by wrapping the value around.
* <p>Values must be positive integers, and are passed through Math.abs</p>
*
*
* @param value The value to add the amount to
* @param amount The amount to add to the value
* @param max The maximum the value is allowed to be
@@ -606,7 +606,7 @@ module Phaser {
/**
* Randomly returns either a 1 or -1
*
*
* @return 1 or -1
*/
public randomSign(): number {
@@ -615,9 +615,9 @@ module Phaser {
/**
* Returns true if the number given is odd.
*
*
* @param n The number to check
*
*
* @return True if the given number is odd. False if the given number is even.
*/
public isOdd(n: number): bool {
@@ -635,9 +635,9 @@ module Phaser {
/**
* Returns true if the number given is even.
*
*
* @param n The number to check
*
*
* @return True if the given number is even. False if the given number is odd.
*/
public isEven(n: number): bool {
@@ -656,9 +656,9 @@ module Phaser {
/**
* Keeps an angle value between -180 and +180<br>
* Should be called whenever the angle is updated on the Sprite to stop it from going insane.
*
*
* @param angle The angle value to check
*
*
* @return The new angle value, returns the same as the input angle if it was within bounds
*/
public wrapAngle(angle: number): number {
@@ -685,11 +685,11 @@ module Phaser {
/**
* Keeps an angle value between the given min and max values
*
*
* @param angle The angle value to check. Must be between -180 and +180
* @param min The minimum angle that is allowed (must be -180 or greater)
* @param max The maximum angle that is allowed (must be 180 or less)
*
*
* @return The new angle value, returns the same as the input angle if it was within bounds
*/
public angleLimit(angle: number, min: number, max: number): number {
@@ -832,7 +832,7 @@ module Phaser {
/**
* Generates a random number. Deterministic, meaning safe
* to use if you want to record replays in random environments.
*
*
* @return A <code>Number</code> between 0 and 1.
*/
public random(): number {
@@ -841,9 +841,9 @@ module Phaser {
/**
* Generates a random number based on the seed provided.
*
*
* @param Seed A number between 0 and 1, used to generate a predictable random number (very optional).
*
*
* @return A <code>Number</code> between 0 and 1.
*/
public srand(Seed: number): number {
@@ -855,29 +855,27 @@ module Phaser {
/**
* Fetch a random entry from the given array.
* Will return null if random selection is missing, or array has no entries.
* <code>G.getRandom()</code> is deterministic and safe for use with replays/recordings.
* HOWEVER, <code>U.getRandom()</code> is NOT deterministic and unsafe for use with replays/recordings.
*
* @param Objects An array of objects.
* @param StartIndex Optional offset off the front of the array. Default value is 0, or the beginning of the array.
* @param Length Optional restriction on the number of values you want to randomly select from.
*
*
* @param objects An array of objects.
* @param startIndex Optional offset off the front of the array. Default value is 0, or the beginning of the array.
* @param length Optional restriction on the number of values you want to randomly select from.
*
* @return The random object that was selected.
*/
public getRandom(Objects, StartIndex: number = 0, Length: number = 0) {
public getRandom(objects, startIndex: number = 0, length: number = 0) {
if (Objects != null)
if (objects != null)
{
var l: number = Length;
var l: number = length;
if ((l == 0) || (l > Objects.length - StartIndex))
if ((l == 0) || (l > objects.length - startIndex))
{
l = Objects.length - StartIndex;
l = objects.length - startIndex;
}
if (l > 0)
{
return Objects[StartIndex + Math.floor(Math.random() * l)];
return objects[startIndex + Math.floor(Math.random() * l)];
}
}
@@ -887,9 +885,9 @@ module Phaser {
/**
* Round down to the next whole number. E.g. floor(1.7) == 1, and floor(-2.7) == -2.
*
*
* @param Value Any number.
*
*
* @return The rounded value of that number.
*/
public floor(Value: number): number {
@@ -899,9 +897,9 @@ module Phaser {
/**
* Round up to the next whole number. E.g. ceil(1.3) == 2, and ceil(-2.3) == -3.
*
*
* @param Value Any number.
*
*
* @return The rounded value of that number.
*/
public ceil(Value: number): number {
@@ -979,25 +977,25 @@ module Phaser {
/**
* Finds the length of the given vector
*
*
* @param dx
* @param dy
*
*
* @return
*/
public vectorLength(dx:number, dy:number):number
{
return Math.sqrt(dx * dx + dy * dy);
}
/**
* Finds the dot product value of two vectors
*
*
* @param ax Vector X
* @param ay Vector Y
* @param bx Vector X
* @param by Vector Y
*
*
* @return Dot product
*/
public dotProduct(ax:number, ay:number, bx:number, by:number):number
@@ -1005,6 +1003,70 @@ module Phaser {
return ax * bx + ay * by;
}
/**
* Shuffles the data in the given array into a new order
* @param array The array to shuffle
* @return The array
*/
public shuffleArray(array) {
for (var i = array.length - 1; i > 0; i--)
{
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
/**
* Returns the distance from this Point object to the given Point object.
* @method distanceFrom
* @param {Point} target - The destination Point object.
* @param {Boolean} round - Round the distance to the nearest integer (default false)
* @return {Number} The distance between this Point object and the destination Point object.
**/
public static distanceBetween(x1: number, y1: number, x2: number, y2: number): number {
var dx = x1 - x2;
var dy = y1 - y2;
return Math.sqrt(dx * dx + dy * dy);
}
/**
* Rotates the point around the x/y coordinates given to the desired angle and distance
* @param point {Object} Any object with exposed x and y properties
* @param x {number} The x coordinate of the anchor point
* @param y {number} The y coordinate of the anchor point
* @param {Number} angle The angle in radians (unless asDegrees is true) to return the point from.
* @param {Boolean} asDegrees Is the given angle in radians (false) or degrees (true)?
* @param {Number} distance An optional distance constraint between the point and the anchor
* @return The modified point object
*/
public rotatePoint(point, x1: number, y1: number, angle: number, asDegrees: bool = false, distance?:number = null) {
if (asDegrees)
{
angle = angle * GameMath.DEG_TO_RAD;
}
// Get distance from origin to the point
if (distance === null)
{
distance = Math.sqrt(((x1 - point.x) * (x1 - point.x)) + ((y1 - point.y) * (y1 - point.y)));
}
point.x = x1 + distance * Math.cos(angle);
point.y = y1 + distance * Math.sin(angle);
return point;
}
}
+219
View File
@@ -0,0 +1,219 @@
/// <reference path="Game.ts" />
/**
* Phaser - GameObjectFactory
*
* A quick way to create new world objects and add existing objects to the current world.
*/
module Phaser {
export class GameObjectFactory {
/**
* GameObjectFactory constructor
* @param game {Game} A reference to the current Game.
*/
constructor(game: Phaser.Game) {
this._game = game;
this._world = this._game.world;
}
/**
* Local private reference to Game
*/
private _game: Phaser.Game;
/**
* Local private reference to World
*/
private _world: Phaser.World;
/**
* Create a new camera with specific position and size.
*
* @param x {number} X position of the new camera.
* @param y {number} Y position of the new camera.
* @param width {number} Width of the new camera.
* @param height {number} Height of the new camera.
* @returns {Camera} The newly created camera object.
*/
public camera(x: number, y: number, width: number, height: number): Camera {
return this._world.createCamera(x, y, width, height);
}
/**
* Create a new GeomSprite with specific position.
*
* @param x {number} X position of the new geom sprite.
* @param y {number} Y position of the new geom sprite.
* @returns {GeomSprite} The newly created geom sprite object.
*/
public geomSprite(x: number, y: number): GeomSprite {
return this._world.createGeomSprite(x, y);
}
/**
* Create a new Sprite with specific position and sprite sheet key.
*
* @param x {number} X position of the new sprite.
* @param y {number} Y position of the new sprite.
* @param key {string} Optional, key for the sprite sheet you want it to use.
* @returns {Sprite} The newly created sprite object.
*/
public sprite(x: number, y: number, key?: string = ''): Sprite {
return this._world.createSprite(x, y, key);
}
/**
* Create a new DynamicTexture with specific size.
*
* @param width {number} Width of the texture.
* @param height {number} Height of the texture.
* @returns {DynamicTexture} The newly created dynamic texture object.
*/
public dynamicTexture(width: number, height: number): DynamicTexture {
return this._world.createDynamicTexture(width, height);
}
/**
* Create a new object container.
*
* @param maxSize {number} Optional, capacity of this group.
* @returns {Group} The newly created group.
*/
public group(maxSize?: number = 0): Group {
return this._world.createGroup(maxSize);
}
/**
* Create a new Particle.
*
* @return {Particle} The newly created particle object.
*/
public particle(): Particle {
return this._world.createParticle();
}
/**
* Create a new Emitter.
*
* @param x {number} Optional, x position of the emitter.
* @param y {number} Optional, y position of the emitter.
* @param size {number} Optional, size of this emitter.
* @return {Emitter} The newly created emitter object.
*/
public emitter(x?: number = 0, y?: number = 0, size?: number = 0): Emitter {
return this._world.createEmitter(x, y, size);
}
/**
* Create a new ScrollZone object with image key, position and size.
*
* @param key {string} Key to a image you wish this object to use.
* @param x {number} X position of this object.
* @param y {number} Y position of this object.
* @param width number} Width of this object.
* @param height {number} Height of this object.
* @returns {ScrollZone} The newly created scroll zone object.
*/
public scrollZone(key: string, x?: number = 0, y?: number = 0, width?: number = 0, height?: number = 0): ScrollZone {
return this._world.createScrollZone(key, x, y, width, height);
}
/**
* Create a new Tilemap.
*
* @param key {string} Key for tileset image.
* @param mapData {string} Data of this tilemap.
* @param format {number} Format of map data. (Tilemap.FORMAT_CSV or Tilemap.FORMAT_TILED_JSON)
* @param [resizeWorld] {boolean} resize the world to make same as tilemap?
* @param [tileWidth] {number} width of each tile.
* @param [tileHeight] {number} height of each tile.
* @return {Tilemap} The newly created tilemap object.
*/
public tilemap(key: string, mapData: string, format: number, resizeWorld: bool = true, tileWidth?: number = 0, tileHeight?: number = 0): Tilemap {
return this._world.createTilemap(key, mapData, format, resizeWorld, tileWidth, tileHeight);
}
/**
* Create a tween object for a specific object.
*
* @param obj Object you wish the tween will affect.
* @return {Phaser.Tween} The newly created tween object.
*/
public tween(obj): Tween {
return this._game.tweens.create(obj);
}
/**
* Add an existing Sprite to the current world.
* Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
*
* @param sprite The Sprite to add to the Game World
* @return {Phaser.Sprite} The Sprite object
*/
public existingSprite(sprite: Sprite): Sprite {
return this._world.group.add(sprite);
}
/**
* Add an existing GeomSprite to the current world.
* Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
*
* @param sprite The GeomSprite to add to the Game World
* @return {Phaser.GeomSprite} The GeomSprite object
*/
public existingGeomSprite(sprite: GeomSprite): GeomSprite {
return this._world.group.add(sprite);
}
/**
* Add an existing Emitter to the current world.
* Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
*
* @param emitter The Emitter to add to the Game World
* @return {Phaser.Emitter} The Emitter object
*/
public existingEmitter(emitter: Emitter): Emitter {
return this._world.group.add(emitter);
}
/**
* Add an existing ScrollZone to the current world.
* Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
*
* @param scrollZone The ScrollZone to add to the Game World
* @return {Phaser.ScrollZone} The ScrollZone object
*/
public existingScrollZone(scrollZone: ScrollZone): ScrollZone {
return this._world.group.add(scrollZone);
}
/**
* Add an existing Tilemap to the current world.
* Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
*
* @param tilemap The Tilemap to add to the Game World
* @return {Phaser.Tilemap} The Tilemap object
*/
public existingTilemap(tilemap: Tilemap): Tilemap {
return this._world.group.add(tilemap);
}
/**
* Add an existing Tween to the current world.
* Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
*
* @param tween The Tween to add to the Game World
* @return {Phaser.Tween} The Tween object
*/
public existingTween(tween: Tween): Tween {
return this._game.tweens.add(tween);
}
}
}
+39
View File
@@ -0,0 +1,39 @@
/// <reference path="Basic.d.ts" />
/// <reference path="Game.d.ts" />
module Phaser {
class Group extends Basic {
constructor(game: Game, MaxSize?: number);
static ASCENDING: number;
static DESCENDING: number;
public members: Basic[];
public length: number;
private _maxSize;
private _marker;
private _sortIndex;
private _sortOrder;
public destroy(): void;
public update(): void;
public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number): void;
public maxSize : number;
public add(Object: Basic): Basic;
public recycle(ObjectClass?);
public remove(Object: Basic, Splice?: bool): Basic;
public replace(OldObject: Basic, NewObject: Basic): Basic;
public sort(Index?: string, Order?: number): void;
public setAll(VariableName: string, Value: Object, Recurse?: bool): void;
public callAll(FunctionName: string, Recurse?: bool): void;
public forEach(callback, recursive?: bool): void;
public forEachAlive(context, callback, recursive?: bool): void;
public getFirstAvailable(ObjectClass?);
public getFirstNull(): number;
public getFirstExtant(): Basic;
public getFirstAlive(): Basic;
public getFirstDead(): Basic;
public countLiving(): number;
public countDead(): number;
public getRandom(StartIndex?: number, Length?: number): Basic;
public clear(): void;
public kill(): void;
public sortHandler(Obj1: Basic, Obj2: Basic): number;
}
}
+191 -88
View File
@@ -5,7 +5,6 @@
* Phaser - Group
*
* This class is used for organising, updating and sorting game objects.
*
*/
module Phaser {
@@ -22,9 +21,31 @@ module Phaser {
this._maxSize = MaxSize;
this._marker = 0;
this._sortIndex = null;
this.cameraBlacklist = [];
}
/**
* Internal tracker for the maximum capacity of the group.
* Default is 0, or no max capacity.
*/
private _maxSize: number;
/**
* Internal helper variable for recycling objects a la <code>Emitter</code>.
*/
private _marker: number;
/**
* Helper for sort.
*/
private _sortIndex: string;
/**
* Helper for sort.
*/
private _sortOrder: number;
/**
* Use with <code>sort()</code> to sort in ascending order.
*/
@@ -48,25 +69,62 @@ module Phaser {
public length: number;
/**
* Internal tracker for the maximum capacity of the group.
* Default is 0, or no max capacity.
* You can set a globalCompositeOperation that will be applied before the render method is called on this Groups children.
* This is useful if you wish to apply an effect like 'lighten' to a whole group of children as it saves doing it one-by-one.
* If this value is set it will call a canvas context save and restore before and after the render pass.
* Set to null to disable.
*/
private _maxSize: number;
public globalCompositeOperation: string = null;
/**
* Internal helper variable for recycling objects a la <code>Emitter</code>.
* You can set an alpha value on this Group that will be applied before the render method is called on this Groups children.
* This is useful if you wish to alpha a whole group of children as it saves doing it one-by-one.
* Set to 0 to disable.
*/
private _marker: number;
public alpha: number = 0;
/**
* Helper for sort.
* An Array of Cameras to which this Group, or any of its children, won't render
* @type {Array}
*/
private _sortIndex: string;
public cameraBlacklist: number[];
/**
* Helper for sort.
* If you do not wish this object to be visible to a specific camera, pass the camera here.
*
* @param camera {Camera} The specific camera.
*/
public hideFromCamera(camera: Camera) {
if (this.cameraBlacklist.indexOf(camera.ID) == -1)
{
this.cameraBlacklist.push(camera.ID);
}
}
/**
* Make this object only visible to a specific camera.
*
* @param camera {Camera} The camera you wish it to be visible.
*/
public showToCamera(camera: Camera) {
if (this.cameraBlacklist.indexOf(camera.ID) !== -1)
{
this.cameraBlacklist.slice(this.cameraBlacklist.indexOf(camera.ID), 1);
}
}
/**
* This clears the camera black list, making the GameObject visible to all cameras.
*/
private _sortOrder: number;
public clearCameraList() {
this.cameraBlacklist.length = 0;
}
/**
* Override this function to handle any deleting or "shutdown" type operations you might need,
@@ -99,7 +157,12 @@ module Phaser {
/**
* Automatically goes through and calls update on everything you added.
*/
public update() {
public update(forceUpdate?: bool = false) {
if (this.ignoreGlobalUpdate && forceUpdate == false)
{
return;
}
var basic: Basic;
var i: number = 0;
@@ -108,10 +171,10 @@ module Phaser {
{
basic = this.members[i++];
if ((basic != null) && basic.exists && basic.active)
if ((basic != null) && basic.exists && basic.active && basic.ignoreGlobalUpdate == false)
{
basic.preUpdate();
basic.update();
basic.update(forceUpdate);
basic.postUpdate();
}
}
@@ -120,7 +183,29 @@ module Phaser {
/**
* Automatically goes through and calls render on everything you added.
*/
public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number) {
public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number, forceRender?: bool = false) {
if (this.cameraBlacklist.indexOf(camera.ID) !== -1)
{
return;
}
if (this.ignoreGlobalRender && forceRender == false)
{
return;
}
if (this.globalCompositeOperation)
{
this._game.stage.context.save();
this._game.stage.context.globalCompositeOperation = this.globalCompositeOperation;
}
if (this.alpha > 0)
{
var prevAlpha: number = this._game.stage.context.globalAlpha;
this._game.stage.context.globalAlpha = this.alpha;
}
var basic: Basic;
var i: number = 0;
@@ -129,11 +214,21 @@ module Phaser {
{
basic = this.members[i++];
if ((basic != null) && basic.exists && basic.visible)
if ((basic != null) && basic.exists && basic.visible && basic.ignoreGlobalRender == false)
{
basic.render(camera, cameraOffsetX, cameraOffsetY);
basic.render(camera, cameraOffsetX, cameraOffsetY, forceRender);
}
}
if (this.alpha > 0)
{
this._game.stage.context.globalAlpha = prevAlpha;
}
if (this.globalCompositeOperation)
{
this._game.stage.context.restore();
}
}
/**
@@ -179,7 +274,7 @@ module Phaser {
}
/**
* Adds a new <code>Basic</code> subclass (Basic, Basic, Enemy, etc) to the group.
* Adds a new <code>Basic</code> subclass (Basic, GameObject, Sprite, etc) to the group.
* Group will try to replace a null member of the array first.
* Failing that, Group will add it to the end of the member array,
* assuming there is room for it, and doubling the size of the array if necessary.
@@ -187,11 +282,10 @@ module Phaser {
* <p>WARNING: If the group has a maxSize that has already been met,
* the object will NOT be added to the group!</p>
*
* @param Object The object you want to add to the group.
*
* @return The same <code>Basic</code> object that was passed in.
* @param {Basic} Object The object you want to add to the group.
* @return {Basic} The same <code>Basic</code> object that was passed in.
*/
public add(Object: Basic) {
public add(Object: Basic): any {
//Don't bother adding an object twice.
if (this.members.indexOf(Object) >= 0)
@@ -252,26 +346,26 @@ module Phaser {
/**
* Recycling is designed to help you reuse game objects without always re-allocating or "newing" them.
*
*
* <p>If you specified a maximum size for this group (like in Emitter),
* then recycle will employ what we're calling "rotating" recycling.
* Recycle() will first check to see if the group is at capacity yet.
* If group is not yet at capacity, recycle() returns a new object.
* If the group IS at capacity, then recycle() just returns the next object in line.</p>
*
*
* <p>If you did NOT specify a maximum size for this group,
* then recycle() will employ what we're calling "grow-style" recycling.
* Recycle() will return either the first object with exists == false,
* or, finding none, add a new object to the array,
* doubling the size of the array if necessary.</p>
*
*
* <p>WARNING: If this function needs to create a new object,
* and no object class was provided, it will return null
* instead of a valid object!</p>
*
* @param ObjectClass The class type you want to recycle (e.g. Basic, EvilRobot, etc). Do NOT "new" the class in the parameter!
*
* @return A reference to the object that was created. Don't forget to cast it back to the Class you want (e.g. myObject = myGroup.recycle(myObjectClass) as myObjectClass;).
*
* @param {class} ObjectClass The class type you want to recycle (e.g. Basic, EvilRobot, etc). Do NOT "new" the class in the parameter!
*
* @return {any} A reference to the object that was created. Don't forget to cast it back to the Class you want (e.g. myObject = myGroup.recycle(myObjectClass) as myObjectClass;).
*/
public recycle(ObjectClass = null) {
@@ -320,22 +414,22 @@ module Phaser {
/**
* Removes an object from the group.
*
* @param Object The <code>Basic</code> you want to remove.
* @param Splice Whether the object should be cut from the array entirely or not.
*
* @return The removed object.
*
* @param {Basic} object The <code>Basic</code> you want to remove.
* @param {boolean} splice Whether the object should be cut from the array entirely or not.
*
* @return {Basic} The removed object.
*/
public remove(Object: Basic, Splice: bool = false): Basic {
public remove(object: Basic, splice: bool = false): Basic {
var index: number = this.members.indexOf(Object);
var index: number = this.members.indexOf(object);
if ((index < 0) || (index >= this.members.length))
{
return null;
}
if (Splice)
if (splice)
{
this.members.splice(index, 1);
this.length--;
@@ -345,30 +439,30 @@ module Phaser {
this.members[index] = null;
}
return Object;
return object;
}
/**
* Replaces an existing <code>Basic</code> with a new one.
*
* @param OldObject The object you want to replace.
* @param NewObject The new object you want to use instead.
*
* @return The new object.
*
* @param {Basic} oldObject The object you want to replace.
* @param {Basic} newObject The new object you want to use instead.
*
* @return {Basic} The new object.
*/
public replace(OldObject: Basic, NewObject: Basic): Basic {
public replace(oldObject: Basic, newObject: Basic): Basic {
var index: number = this.members.indexOf(OldObject);
var index: number = this.members.indexOf(oldObject);
if ((index < 0) || (index >= this.members.length))
{
return null;
}
this.members[index] = NewObject;
this.members[index] = newObject;
return NewObject;
return newObject;
}
@@ -378,24 +472,24 @@ module Phaser {
* <code>myGroup.sort("y",Group.ASCENDING)</code> at the bottom of your
* <code>State.update()</code> override. To sort all existing objects after
* a big explosion or bomb attack, you might call <code>myGroup.sort("exists",Group.DESCENDING)</code>.
*
* @param Index The <code>string</code> name of the member variable you want to sort on. Default value is "y".
* @param Order A <code>Group</code> constant that defines the sort order. Possible values are <code>Group.ASCENDING</code> and <code>Group.DESCENDING</code>. Default value is <code>Group.ASCENDING</code>.
*
* @param {string} index The <code>string</code> name of the member variable you want to sort on. Default value is "y".
* @param {number} order A <code>Group</code> constant that defines the sort order. Possible values are <code>Group.ASCENDING</code> and <code>Group.DESCENDING</code>. Default value is <code>Group.ASCENDING</code>.
*/
public sort(Index: string = "y", Order: number = Group.ASCENDING) {
public sort(index: string = "y", order: number = Group.ASCENDING) {
this._sortIndex = Index;
this._sortOrder = Order;
this._sortIndex = index;
this._sortOrder = order;
this.members.sort(this.sortHandler);
}
/**
* Go through and set the specified variable to the specified value on all members of the group.
*
* @param VariableName The string representation of the variable name you want to modify, for example "visible" or "scrollFactor".
* @param Value The value you want to assign to that variable.
* @param Recurse Default value is true, meaning if <code>setAll()</code> encounters a member that is a group, it will call <code>setAll()</code> on that group rather than modifying its variable.
*
* @param {string} VariableName The string representation of the variable name you want to modify, for example "visible" or "scrollFactor".
* @param {Object} Value The value you want to assign to that variable.
* @param {boolean} Recurse Default value is true, meaning if <code>setAll()</code> encounters a member that is a group, it will call <code>setAll()</code> on that group rather than modifying its variable.
*/
public setAll(VariableName: string, Value: Object, Recurse: bool = true) {
@@ -423,9 +517,9 @@ module Phaser {
/**
* Go through and call the specified function on all members of the group.
* Currently only works on functions that have no required parameters.
*
* @param FunctionName The string representation of the function you want to call on each object, for example "kill()" or "init()".
* @param Recurse Default value is true, meaning if <code>callAll()</code> encounters a member that is a group, it will call <code>callAll()</code> on that group rather than calling the group's function.
*
* @param {string} FunctionName The string representation of the function you want to call on each object, for example "kill()" or "init()".
* @param {boolean} Recurse Default value is true, meaning if <code>callAll()</code> encounters a member that is a group, it will call <code>callAll()</code> on that group rather than calling the group's function.
*/
public callAll(FunctionName: string, Recurse: bool = true) {
@@ -450,6 +544,10 @@ module Phaser {
}
}
/**
* @param {function} callback
* @param {boolean} recursive
*/
public forEach(callback, recursive: bool = false) {
var basic;
@@ -474,7 +572,12 @@ module Phaser {
}
public forEachAlive(callback, recursive: bool = false) {
/**
* @param {any} context
* @param {function} callback
* @param {boolean} recursive
*/
public forEachAlive(context, callback, recursive: bool = false) {
var basic;
var i: number = 0;
@@ -487,11 +590,11 @@ module Phaser {
{
if (recursive && (basic.isGroup == true))
{
basic.forEachAlive(callback, true);
basic.forEachAlive(context, callback, true);
}
else
{
callback.call(this, basic);
callback.call(context, basic);
}
}
}
@@ -501,10 +604,10 @@ module Phaser {
/**
* Call this function to retrieve the first object with exists == false in the group.
* This is handy for recycling in general, e.g. respawning enemies.
*
* @param ObjectClass An optional parameter that lets you narrow the results to instances of this particular class.
*
* @return A <code>Basic</code> currently flagged as not existing.
*
* @param {any} [ObjectClass] An optional parameter that lets you narrow the results to instances of this particular class.
*
* @return {any} A <code>Basic</code> currently flagged as not existing.
*/
public getFirstAvailable(ObjectClass = null) {
@@ -528,8 +631,8 @@ module Phaser {
/**
* Call this function to retrieve the first index set to 'null'.
* Returns -1 if no index stores a null object.
*
* @return An <code>int</code> indicating the first null slot in the group.
*
* @return {number} An <code>int</code> indicating the first null slot in the group.
*/
public getFirstNull(): number {
@@ -556,8 +659,8 @@ module Phaser {
/**
* Call this function to retrieve the first object with exists == true in the group.
* This is handy for checking if everything's wiped out, or choosing a squad leader, etc.
*
* @return A <code>Basic</code> currently flagged as existing.
*
* @return {Basic} A <code>Basic</code> currently flagged as existing.
*/
public getFirstExtant(): Basic {
@@ -581,8 +684,8 @@ module Phaser {
/**
* Call this function to retrieve the first object with dead == false in the group.
* This is handy for checking if everything's wiped out, or choosing a squad leader, etc.
*
* @return A <code>Basic</code> currently flagged as not dead.
*
* @return {Basic} A <code>Basic</code> currently flagged as not dead.
*/
public getFirstAlive(): Basic {
@@ -606,8 +709,8 @@ module Phaser {
/**
* Call this function to retrieve the first object with dead == true in the group.
* This is handy for checking if everything's wiped out, or choosing a squad leader, etc.
*
* @return A <code>Basic</code> currently flagged as dead.
*
* @return {Basic} A <code>Basic</code> currently flagged as dead.
*/
public getFirstDead(): Basic {
@@ -630,8 +733,8 @@ module Phaser {
/**
* Call this function to find out how many members of the group are not dead.
*
* @return The number of <code>Basic</code>s flagged as not dead. Returns -1 if group is empty.
*
* @return {number} The number of <code>Basic</code>s flagged as not dead. Returns -1 if group is empty.
*/
public countLiving(): number {
@@ -663,8 +766,8 @@ module Phaser {
/**
* Call this function to find out how many members of the group are dead.
*
* @return The number of <code>Basic</code>s flagged as dead. Returns -1 if group is empty.
*
* @return {number} The number of <code>Basic</code>s flagged as dead. Returns -1 if group is empty.
*/
public countDead(): number {
@@ -696,11 +799,11 @@ module Phaser {
/**
* Returns a member at random from the group.
*
* @param StartIndex Optional offset off the front of the array. Default value is 0, or the beginning of the array.
* @param Length Optional restriction on the number of values you want to randomly select from.
*
* @return A <code>Basic</code> from the members list.
*
* @param {number} StartIndex Optional offset off the front of the array. Default value is 0, or the beginning of the array.
* @param {number} Length Optional restriction on the number of values you want to randomly select from.
*
* @return {Basic} A <code>Basic</code> from the members list.
*/
public getRandom(StartIndex: number = 0, Length: number = 0): Basic {
@@ -743,11 +846,11 @@ module Phaser {
/**
* Helper function for the sort process.
*
* @param Obj1 The first object being sorted.
* @param Obj2 The second object being sorted.
*
* @return An integer value: -1 (Obj1 before Obj2), 0 (same), or 1 (Obj1 after Obj2).
*
* @param {Basic} Obj1 The first object being sorted.
* @param {Basic} Obj2 The second object being sorted.
*
* @return {number} An integer value: -1 (Obj1 before Obj2), 0 (same), or 1 (Obj1 after Obj2).
*/
public sortHandler(Obj1: Basic, Obj2: Basic): number {
+34
View File
@@ -0,0 +1,34 @@
/// <reference path="Game.d.ts" />
module Phaser {
class Loader {
constructor(game: Game, callback);
private _game;
private _keys;
private _fileList;
private _gameCreateComplete;
private _onComplete;
private _onFileLoad;
private _progressChunk;
private _xhr;
private _queueSize;
public hasLoaded: bool;
public progress: number;
public reset(): void;
public queueSize : number;
public addImageFile(key: string, url: string): void;
public addSpriteSheet(key: string, url: string, frameWidth: number, frameHeight: number, frameMax?: number): void;
public addTextureAtlas(key: string, url: string, jsonURL?: string, jsonData?): void;
public addAudioFile(key: string, url: string): void;
public addTextFile(key: string, url: string): void;
public removeFile(key: string): void;
public removeAll(): void;
public load(onFileLoadCallback?, onCompleteCallback?): void;
private loadFile();
private fileError(key);
private fileComplete(key);
private jsonLoadComplete(key);
private jsonLoadError(key);
private nextFile(previousKey, success);
private checkKeyExists(key);
}
}
+237 -34
View File
@@ -11,6 +11,12 @@ module Phaser {
export class Loader {
/**
* Loader constructor
*
* @param game {Phaser.Game} Current game instance.
* @param callback {function} This will be called when assets completely loaded.
*/
constructor(game: Game, callback) {
this._game = game;
@@ -22,19 +28,70 @@ module Phaser {
}
/**
* Local private reference to game.
*/
private _game: Game;
/**
* Array stors assets keys. So you can get that asset by its unique key.
*/
private _keys: string[];
/**
* Contains all the assets file infos.
*/
private _fileList;
/**
* Game initialial assets loading callback.
*/
private _gameCreateComplete;
private _onComplete;
private _onFileLoad;
/**
* Indicates assets loading progress. (from 0 to 100)
* @type {number}
*/
private _progressChunk: number;
private _xhr: XMLHttpRequest;
/**
* Length of assets queue.
* @type {number}
*/
private _queueSize: number;
/**
* True if game is completely loaded.
* @type {boolean}
*/
public hasLoaded: bool;
/**
* Loading progress (from 0 to 1)
* @type {number}
*/
public progress: number;
/**
* The crossOrigin value applied to loaded images
* @type {string}
*/
public crossOrigin: string = '';
/**
* TextureAtlas data format constants
*/
public static TEXTURE_ATLAS_JSON_ARRAY: number = 0;
public static TEXTURE_ATLAS_JSON_HASH: number = 1;
public static TEXTURE_ATLAS_XML_STARLING: number = 2;
/**
* Reset loader, this will remove all loaded assets.
*/
public reset() {
this._queueSize = 0;
}
@@ -45,6 +102,11 @@ module Phaser {
}
/**
* Add a new image asset loading request with key and url.
* @param key {string} Unique asset key of this image file.
* @param url {string} URL of image file.
*/
public addImageFile(key: string, url: string) {
if (this.checkKeyExists(key) === false)
@@ -56,6 +118,14 @@ module Phaser {
}
/**
* Add a new sprite sheet loading request.
* @param key {string} Unique asset key of the sheet file.
* @param url {string} URL of sheet file.
* @param frameWidth {number} Width of each single frame.
* @param frameHeight {number} Height of each single frame.
* @param frameMax {number} How many frames in this sprite sheet.
*/
public addSpriteSheet(key: string, url: string, frameWidth: number, frameHeight: number, frameMax?: number = -1) {
if (this.checkKeyExists(key) === false)
@@ -67,40 +137,78 @@ module Phaser {
}
public addTextureAtlas(key: string, url: string, jsonURL?: string = null, jsonData? = null) {
/**
* Add a new texture atlas loading request.
* @param key {string} Unique asset key of the texture atlas file.
* @param textureURL {string} The url of the texture atlas image file.
* @param [atlasURL] {string} The url of the texture atlas data file (json/xml)
* @param [atlasData] {object} A JSON or XML data object.
* @param [format] {number} A value describing the format of the data.
*/
public addTextureAtlas(key: string, textureURL: string, atlasURL?: string = null, atlasData? = null, format?:number = Loader.TEXTURE_ATLAS_JSON_ARRAY) {
if (this.checkKeyExists(key) === false)
{
if (jsonURL !== null)
if (atlasURL !== null)
{
// A URL to a json file has been given
// A URL to a json/xml file has been given
this._queueSize++;
this._fileList[key] = { type: 'textureatlas', key: key, url: url, data: null, jsonURL: jsonURL, jsonData: null, error: false, loaded: false };
this._fileList[key] = { type: 'textureatlas', key: key, url: textureURL, atlasURL: atlasURL, data: null, format: format, error: false, loaded: false };
this._keys.push(key);
}
else
{
// A json string or object has been given
if (typeof jsonData === 'string')
if (format == Loader.TEXTURE_ATLAS_JSON_ARRAY)
{
var data = JSON.parse(jsonData);
// Malformed?
if (data['frames'])
// A json string or object has been given
if (typeof atlasData === 'string')
{
this._queueSize++;
this._fileList[key] = { type: 'textureatlas', key: key, url: url, data: null, jsonURL: null, jsonData: data['frames'], error: false, loaded: false };
this._keys.push(key);
atlasData = JSON.parse(atlasData);
}
this._queueSize++;
this._fileList[key] = { type: 'textureatlas', key: key, url: textureURL, data: null, atlasURL: null, atlasData: atlasData['frames'], format: format, error: false, loaded: false };
this._keys.push(key);
}
else
else if (format == Loader.TEXTURE_ATLAS_XML_STARLING)
{
// Malformed?
if (jsonData['frames'])
// An xml string or object has been given
if (typeof atlasData === 'string')
{
this._queueSize++;
this._fileList[key] = { type: 'textureatlas', key: key, url: url, data: null, jsonURL: null, jsonData: jsonData['frames'], error: false, loaded: false };
this._keys.push(key);
var xml;
try
{
if (window['DOMParser'])
{
var domparser = new DOMParser();
xml = domparser.parseFromString(atlasData, "text/xml");
}
else
{
xml = new ActiveXObject("Microsoft.XMLDOM");
xml.async = 'false';
xml.loadXML(atlasData);
}
}
catch (e)
{
xml = undefined;
}
if (!xml || !xml.documentElement || xml.getElementsByTagName("parsererror").length)
{
throw new Error("Phaser.Loader. Invalid Texture Atlas XML given");
}
else
{
atlasData = xml;
}
}
this._queueSize++;
this._fileList[key] = { type: 'textureatlas', key: key, url: textureURL, data: null, atlasURL: null, atlasData: atlasData, format: format, error: false, loaded: false };
this._keys.push(key);
}
}
@@ -109,6 +217,11 @@ module Phaser {
}
/**
* Add a new audio file loading request.
* @param key {string} Unique asset key of the audio file.
* @param url {string} URL of audio file.
*/
public addAudioFile(key: string, url: string) {
if (this.checkKeyExists(key) === false)
@@ -120,6 +233,11 @@ module Phaser {
}
/**
* Add a new text file loading request.
* @param key {string} Unique asset key of the text file.
* @param url {string} URL of text file.
*/
public addTextFile(key: string, url: string) {
if (this.checkKeyExists(key) === false)
@@ -131,18 +249,30 @@ module Phaser {
}
/**
* Remove loading request of a file.
* @param key {string} Key of the file you want to remove.
*/
public removeFile(key: string) {
delete this._fileList[key];
}
/**
* Remove all file loading requests.
*/
public removeAll() {
this._fileList = {};
}
/**
* Load assets.
* @param onFileLoadCallback {function} Called when each file loaded successfully.
* @param onCompleteCallback {function} Called when all assets completely loaded.
*/
public load(onFileLoadCallback = null, onCompleteCallback = null) {
this.progress = 0;
@@ -176,6 +306,9 @@ module Phaser {
}
/**
* Load files. Private method ONLY used by loader.
*/
private loadFile() {
var file = this._fileList[this._keys.pop()];
@@ -191,6 +324,7 @@ module Phaser {
file.data.name = file.key;
file.data.onload = () => this.fileComplete(file.key);
file.data.onerror = () => this.fileError(file.key);
file.data.crossOrigin = this.crossOrigin;
file.data.src = file.url;
break;
@@ -213,6 +347,10 @@ module Phaser {
}
/**
* Error occured when load a file.
* @param key {string} Key of the error loading file.
*/
private fileError(key: string) {
this._fileList[key].loaded = true;
@@ -222,6 +360,10 @@ module Phaser {
}
/**
* Called when a file is successfully loaded.
* @param key {string} Key of the successfully loaded file.
*/
private fileComplete(key: string) {
this._fileList[key].loaded = true;
@@ -240,18 +382,27 @@ module Phaser {
break;
case 'textureatlas':
if (file.jsonURL == null)
if (file.atlasURL == null)
{
this._game.cache.addTextureAtlas(file.key, file.url, file.data, file.jsonData);
this._game.cache.addTextureAtlas(file.key, file.url, file.data, file.atlasData, file.format);
}
else
{
// Load the JSON before carrying on with the next file
// Load the JSON or XML before carrying on with the next file
loadNext = false;
this._xhr.open("GET", file.jsonURL, true);
this._xhr.open("GET", file.atlasURL, true);
this._xhr.responseType = "text";
this._xhr.onload = () => this.jsonLoadComplete(file.key);
this._xhr.onerror = () => this.jsonLoadError(file.key);
if (file.format == Loader.TEXTURE_ATLAS_JSON_ARRAY)
{
this._xhr.onload = () => this.jsonLoadComplete(file.key);
}
else if (file.format == Loader.TEXTURE_ATLAS_XML_STARLING)
{
this._xhr.onload = () => this.xmlLoadComplete(file.key);
}
this._xhr.onerror = () => this.dataLoadError(file.key);
this._xhr.send();
}
break;
@@ -274,36 +425,83 @@ module Phaser {
}
/**
* Successfully loaded a JSON file.
* @param key {string} Key of the loaded JSON file.
*/
private jsonLoadComplete(key: string) {
var data = JSON.parse(this._xhr.response);
var file = this._fileList[key];
// Malformed?
if (data['frames'])
{
var file = this._fileList[key];
this._game.cache.addTextureAtlas(file.key, file.url, file.data, data['frames']);
}
this._game.cache.addTextureAtlas(file.key, file.url, file.data, data['frames'], file.format);
this.nextFile(key, true);
}
private jsonLoadError(key: string) {
/**
* Error occured when load a JSON.
* @param key {string} Key of the error loading JSON file.
*/
private dataLoadError(key: string) {
var file = this._fileList[key];
file.error = true;
this.nextFile(key, true);
}
private xmlLoadComplete(key: string) {
var atlasData = this._xhr.response;
var xml;
try
{
if (window['DOMParser'])
{
var domparser = new DOMParser();
xml = domparser.parseFromString(atlasData, "text/xml");
}
else
{
xml = new ActiveXObject("Microsoft.XMLDOM");
xml.async = 'false';
xml.loadXML(atlasData);
}
}
catch (e)
{
xml = undefined;
}
if (!xml || !xml.documentElement || xml.getElementsByTagName("parsererror").length)
{
throw new Error("Phaser.Loader. Invalid Texture Atlas XML given");
}
var file = this._fileList[key];
this._game.cache.addTextureAtlas(file.key, file.url, file.data, xml, file.format);
this.nextFile(key, true);
}
/**
* Handle loading next file.
* @param previousKey {string} Key of previous loaded asset.
* @param success {boolean} Whether the previous asset loaded successfully or not.
*/
private nextFile(previousKey: string, success: bool) {
this.progress = Math.round(this.progress + this._progressChunk);
if (this.progress > 1)
if (this.progress > 100)
{
this.progress = 1;
this.progress = 100;
}
if (this._onFileLoad)
@@ -329,6 +527,11 @@ module Phaser {
}
/**
* Check whether asset exists with a specific key.
* @param key {string} Key of the asset you want to check.
* @return {boolean} Return true if exists, otherwise return false.
*/
private checkKeyExists(key: string): bool {
if (this._fileList[key])
+23
View File
@@ -0,0 +1,23 @@
/// <reference path="Game.d.ts" />
/// <reference path="gameobjects/GameObject.d.ts" />
module Phaser {
class Motion {
constructor(game: Game);
private _game;
public computeVelocity(Velocity: number, Acceleration?: number, Drag?: number, Max?: number): number;
public velocityFromAngle(angle: number, speed: number): Point;
public moveTowardsObject(source: GameObject, dest: GameObject, speed?: number, maxTime?: number): void;
public accelerateTowardsObject(source: GameObject, dest: GameObject, speed: number, xSpeedMax: number, ySpeedMax: number): void;
public moveTowardsMouse(source: GameObject, speed?: number, maxTime?: number): void;
public accelerateTowardsMouse(source: GameObject, speed: number, xSpeedMax: number, ySpeedMax: number): void;
public moveTowardsPoint(source: GameObject, target: Point, speed?: number, maxTime?: number): void;
public accelerateTowardsPoint(source: GameObject, target: Point, speed: number, xSpeedMax: number, ySpeedMax: number): void;
public distanceBetween(a: GameObject, b: GameObject): number;
public distanceToPoint(a: GameObject, target: Point): number;
public distanceToMouse(a: GameObject): number;
public angleBetweenPoint(a: GameObject, target: Point, asDegrees?: bool): number;
public angleBetween(a: GameObject, b: GameObject, asDegrees?: bool): number;
public velocityFromFacing(parent: GameObject, speed: number): Point;
public angleBetweenMouse(a: GameObject, asDegrees?: bool): number;
}
}
+104 -104
View File
@@ -21,13 +21,13 @@ module Phaser {
/**
* A tween-like function that takes a starting velocity and some other factors and returns an altered velocity.
*
* @param Velocity Any component of velocity (e.g. 20).
* @param Acceleration Rate at which the velocity is changing.
* @param Drag Really kind of a deceleration, this is how much the velocity changes if Acceleration is not set.
* @param Max An absolute value cap for the velocity.
*
* @return The altered Velocity value.
*
* @param {number} Velocity Any component of velocity (e.g. 20).
* @param {number} Acceleration Rate at which the velocity is changing.
* @param {number} Drag Really kind of a deceleration, this is how much the velocity changes if Acceleration is not set.
* @param {number} Max An absolute value cap for the velocity.
*
* @return {number} The altered Velocity value.
*/
public computeVelocity(Velocity: number, Acceleration: number = 0, Drag: number = 0, Max: number = 10000): number {
@@ -71,11 +71,11 @@ module Phaser {
/**
* Given the angle and speed calculate the velocity and return it as a Point
*
* @param angle The angle (in degrees) calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative)
* @param speed The speed it will move, in pixels per second sq
*
* @return A Point where Point.x contains the velocity x value and Point.y contains the velocity y value
*
* @param {number} angle The angle (in degrees) calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative)
* @param {number} speed The speed it will move, in pixels per second sq
*
* @return {Point} A Point where Point.x contains the velocity x value and Point.y contains the velocity y value
*/
public velocityFromAngle(angle: number, speed: number): Point {
@@ -97,24 +97,24 @@ module Phaser {
* The source object doesn't stop moving automatically should it ever reach the destination coordinates.<br>
* If you need the object to accelerate, see accelerateTowardsObject() instead
* Note: Doesn't take into account acceleration, maxVelocity or drag (if you set drag or acceleration too high this object may not move at all)
*
* @param source The Sprite on which the velocity will be set
* @param dest The Sprite where the source object will move to
* @param speed The speed it will move, in pixels per second (default is 60 pixels/sec)
* @param maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms
*
* @param {GameObject} source The Sprite on which the velocity will be set
* @param {GameObject} dest The Sprite where the source object will move to
* @param {number} speed The speed it will move, in pixels per second (default is 60 pixels/sec)
* @param {number} maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms
*/
public moveTowardsObject(source:GameObject, dest:GameObject, speed:number= 60, maxTime:number = 0)
{
var a:number = this.angleBetween(source, dest);
if (maxTime > 0)
{
var d:number = this.distanceBetween(source, dest);
// We know how many pixels we need to move, but how fast?
speed = d / (maxTime / 1000);
}
source.velocity.x = Math.cos(a) * speed;
source.velocity.y = Math.sin(a) * speed;
@@ -124,23 +124,23 @@ module Phaser {
* Sets the x/y acceleration on the source Sprite so it will move towards the destination Sprite at the speed given (in pixels per second)<br>
* You must give a maximum speed value, beyond which the Sprite won't go any faster.<br>
* If you don't need acceleration look at moveTowardsObject() instead.
*
* @param source The Sprite on which the acceleration will be set
* @param dest The Sprite where the source object will move towards
* @param speed The speed it will accelerate in pixels per second
* @param xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally
* @param ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically
*
* @param {GameObject} source The Sprite on which the acceleration will be set
* @param {GameObject} dest The Sprite where the source object will move towards
* @param {number} speed The speed it will accelerate in pixels per second
* @param {number} xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally
* @param {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically
*/
public accelerateTowardsObject(source:GameObject, dest:GameObject, speed:number, xSpeedMax:number, ySpeedMax:number)
{
var a:number = this.angleBetween(source, dest);
source.velocity.x = 0;
source.velocity.y = 0;
source.acceleration.x = Math.cos(a) * speed;
source.acceleration.y = Math.sin(a) * speed;
source.maxVelocity.x = xSpeedMax;
source.maxVelocity.y = ySpeedMax;
@@ -151,23 +151,23 @@ module Phaser {
* If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds.<br>
* Timings are approximate due to the way Flash timers work, and irrespective of SWF frame rate. Allow for a variance of +- 50ms.<br>
* The source object doesn't stop moving automatically should it ever reach the destination coordinates.<br>
*
* @param source The Sprite to move
* @param speed The speed it will move, in pixels per second (default is 60 pixels/sec)
* @param maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms
*
* @param {GameObject} source The Sprite to move
* @param {number} speed The speed it will move, in pixels per second (default is 60 pixels/sec)
* @param {number} maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms
*/
public moveTowardsMouse(source:GameObject, speed:number = 60, maxTime:number = 0)
{
var a:number = this.angleBetweenMouse(source);
if (maxTime > 0)
{
var d:number = this.distanceToMouse(source);
// We know how many pixels we need to move, but how fast?
speed = d / (maxTime / 1000);
}
source.velocity.x = Math.cos(a) * speed;
source.velocity.y = Math.sin(a) * speed;
@@ -177,22 +177,22 @@ module Phaser {
* Sets the x/y acceleration on the source Sprite so it will move towards the mouse coordinates at the speed given (in pixels per second)<br>
* You must give a maximum speed value, beyond which the Sprite won't go any faster.<br>
* If you don't need acceleration look at moveTowardsMouse() instead.
*
* @param source The Sprite on which the acceleration will be set
* @param speed The speed it will accelerate in pixels per second
* @param xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally
* @param ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically
*
* @param {GameObject} source The Sprite on which the acceleration will be set
* @param {number} speed The speed it will accelerate in pixels per second
* @param {number} xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally
* @param {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically
*/
public accelerateTowardsMouse(source:GameObject, speed:number, xSpeedMax:number, ySpeedMax:number)
{
var a:number = this.angleBetweenMouse(source);
source.velocity.x = 0;
source.velocity.y = 0;
source.acceleration.x = Math.cos(a) * speed;
source.acceleration.y = Math.sin(a) * speed;
source.maxVelocity.x = xSpeedMax;
source.maxVelocity.y = ySpeedMax;
}
@@ -202,24 +202,24 @@ module Phaser {
* If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds.<br>
* Timings are approximate due to the way Flash timers work, and irrespective of SWF frame rate. Allow for a variance of +- 50ms.<br>
* The source object doesn't stop moving automatically should it ever reach the destination coordinates.<br>
*
* @param source The Sprite to move
* @param target The Point coordinates to move the source Sprite towards
* @param speed The speed it will move, in pixels per second (default is 60 pixels/sec)
* @param maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms
*
* @param {GameObject} source The Sprite to move
* @param {Point} target The Point coordinates to move the source Sprite towards
* @param {number} speed The speed it will move, in pixels per second (default is 60 pixels/sec)
* @param {number} maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms
*/
public moveTowardsPoint(source:GameObject, target:Point, speed:number = 60, maxTime:number = 0)
{
var a:number = this.angleBetweenPoint(source, target);
if (maxTime > 0)
{
var d:number = this.distanceToPoint(source, target);
// We know how many pixels we need to move, but how fast?
speed = d / (maxTime / 1000);
}
source.velocity.x = Math.cos(a) * speed;
source.velocity.y = Math.sin(a) * speed;
}
@@ -228,87 +228,87 @@ module Phaser {
* Sets the x/y acceleration on the source Sprite so it will move towards the target coordinates at the speed given (in pixels per second)<br>
* You must give a maximum speed value, beyond which the Sprite won't go any faster.<br>
* If you don't need acceleration look at moveTowardsPoint() instead.
*
* @param source The Sprite on which the acceleration will be set
* @param target The Point coordinates to move the source Sprite towards
* @param speed The speed it will accelerate in pixels per second
* @param xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally
* @param ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically
*
* @param {GameObject} source The Sprite on which the acceleration will be set
* @param {Point} target The Point coordinates to move the source Sprite towards
* @param {number} speed The speed it will accelerate in pixels per second
* @param {number} xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally
* @param {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically
*/
public accelerateTowardsPoint(source:GameObject, target:Point, speed:number, xSpeedMax:number, ySpeedMax:number)
{
var a:number = this.angleBetweenPoint(source, target);
source.velocity.x = 0;
source.velocity.y = 0;
source.acceleration.x = Math.cos(a) * speed;
source.acceleration.y = Math.sin(a) * speed;
source.maxVelocity.x = xSpeedMax;
source.maxVelocity.y = ySpeedMax;
}
/**
* Find the distance (in pixels, rounded) between two Sprites, taking their origin into account
*
* @param a The first Sprite
* @param b The second Sprite
* @return int Distance (in pixels)
*
* @param {GameObject} a The first Sprite
* @param {GameObject} b The second Sprite
* @return {number} int Distance (in pixels)
*/
public distanceBetween(a:GameObject, b:GameObject):number
{
var dx:number = (a.x + a.origin.x) - (b.x + b.origin.x);
var dy:number = (a.y + a.origin.y) - (b.y + b.origin.y);
return this._game.math.vectorLength(dx, dy);
}
/**
* Find the distance (in pixels, rounded) from an Sprite to the given Point, taking the source origin into account
*
* @param a The Sprite
* @param target The Point
* @return int Distance (in pixels)
*
* @param {GameObject} a The Sprite
* @param {Point} target The Point
* @return {number} Distance (in pixels)
*/
public distanceToPoint(a:GameObject, target:Point):number
{
var dx:number = (a.x + a.origin.x) - (target.x);
var dy:number = (a.y + a.origin.y) - (target.y);
return this._game.math.vectorLength(dx, dy);
}
/**
* Find the distance (in pixels, rounded) from the object x/y and the mouse x/y
*
* @param a The Sprite to test against
* @return int The distance between the given sprite and the mouse coordinates
*
* @param {GameObject} a Sprite to test against
* @return {number} The distance between the given sprite and the mouse coordinates
*/
public distanceToMouse(a:GameObject):number
{
var dx: number = (a.x + a.origin.x) - this._game.input.x;
var dy: number = (a.y + a.origin.y) - this._game.input.y;
return this._game.math.vectorLength(dx, dy);
}
/**
* Find the angle (in radians) between an Sprite and an Point. The source sprite takes its x/y and origin into account.
* The angle is calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative)
*
* @param a The Sprite to test from
* @param target The Point to angle the Sprite towards
* @param asDegrees If you need the value in degrees instead of radians, set to true
*
* @return Number The angle (in radians unless asDegrees is true)
*
* @param {GameObject} a The Sprite to test from
* @param {Point} target The Point to angle the Sprite towards
* @param {boolean} asDegrees If you need the value in degrees instead of radians, set to true
*
* @return {number} The angle (in radians unless asDegrees is true)
*/
public angleBetweenPoint(a:GameObject, target:Point, asDegrees:bool = false):number
{
var dx:number = (target.x) - (a.x + a.origin.x);
var dy:number = (target.y) - (a.y + a.origin.y);
if (asDegrees)
{
return this._game.math.radiansToDegrees(Math.atan2(dy, dx));
@@ -322,18 +322,18 @@ module Phaser {
/**
* Find the angle (in radians) between the two Sprite, taking their x/y and origin into account.
* The angle is calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative)
*
* @param a The Sprite to test from
* @param b The Sprite to test to
* @param asDegrees If you need the value in degrees instead of radians, set to true
*
* @return Number The angle (in radians unless asDegrees is true)
*
* @param {GameObject} a The Sprite to test from
* @param {GameObject} b The Sprite to test to
* @param {boolean} asDegrees If you need the value in degrees instead of radians, set to true
*
* @return {number} The angle (in radians unless asDegrees is true)
*/
public angleBetween(a:GameObject, b:GameObject, asDegrees:bool = false):number
{
var dx:number = (b.x + b.origin.x) - (a.x + a.origin.x);
var dy:number = (b.y + b.origin.y) - (a.y + a.origin.y);
if (asDegrees)
{
return this._game.math.radiansToDegrees(Math.atan2(dy, dx));
@@ -346,16 +346,16 @@ module Phaser {
/**
* Given the GameObject and speed calculate the velocity and return it as an Point based on the direction the sprite is facing
*
* @param parent The Sprite to get the facing value from
* @param speed The speed it will move, in pixels per second sq
*
* @return An Point where Point.x contains the velocity x value and Point.y contains the velocity y value
*
* @param {GameObject} parent The Sprite to get the facing value from
* @param {number} speed The speed it will move, in pixels per second sq
*
* @return {Point} An Point where Point.x contains the velocity x value and Point.y contains the velocity y value
*/
public velocityFromFacing(parent:GameObject, speed:number):Point
{
var a:number;
if (parent.facing == Collision.LEFT)
{
a = this._game.math.degreesToRadians(180);
@@ -372,28 +372,28 @@ module Phaser {
{
a = this._game.math.degreesToRadians(90);
}
return new Point(Math.cos(a) * speed, Math.sin(a) * speed);
}
/**
* Find the angle (in radians) between an Sprite and the mouse, taking their x/y and origin into account.
* The angle is calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative)
*
* @param a The Object to test from
* @param asDegrees If you need the value in degrees instead of radians, set to true
*
* @return Number The angle (in radians unless asDegrees is true)
*
* @param {GameObject} a The Object to test from
* @param {boolean} asDegrees If you need the value in degrees instead of radians, set to true
*
* @return {number} The angle (in radians unless asDegrees is true)
*/
public angleBetweenMouse(a:GameObject, asDegrees:bool = false):number
{
// In order to get the angle between the object and mouse, we need the objects screen coordinates (rather than world coordinates)
var p:MicroPoint = a.getScreenXY();
var dx:number = a._game.input.x - p.x;
var dy:number = a._game.input.y - p.y;
if (asDegrees)
{
return this._game.math.radiansToDegrees(Math.atan2(dy, dx));
+70 -4
View File
@@ -47,12 +47,14 @@
<TypeScriptIncludeComments>true</TypeScriptIncludeComments>
<TypeScriptSourceMap>false</TypeScriptSourceMap>
<TypeScriptOutFile>../build/phaser.js</TypeScriptOutFile>
<TypeScriptGeneratesDeclarations>true</TypeScriptGeneratesDeclarations>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<TypeScriptTarget>ES5</TypeScriptTarget>
<TypeScriptIncludeComments>false</TypeScriptIncludeComments>
<TypeScriptSourceMap>false</TypeScriptSourceMap>
<TypeScriptOutFile>../build/phaser.js</TypeScriptOutFile>
<TypeScriptGeneratesDeclarations>true</TypeScriptGeneratesDeclarations>
</PropertyGroup>
<ItemGroup>
<Folder Include="plugins\" />
@@ -67,12 +69,20 @@
<Content Include="DynamicTexture.js">
<DependentUpon>DynamicTexture.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="FXManager.ts" />
<Content Include="FXManager.js">
<DependentUpon>FXManager.ts</DependentUpon>
</Content>
<Content Include="Game.js">
<DependentUpon>Game.ts</DependentUpon>
</Content>
<Content Include="GameMath.js">
<DependentUpon>GameMath.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="GameObjectFactory.ts" />
<Content Include="GameObjectFactory.js">
<DependentUpon>GameObjectFactory.ts</DependentUpon>
</Content>
<Content Include="gameobjects\Emitter.js">
<DependentUpon>Emitter.ts</DependentUpon>
</Content>
@@ -99,9 +109,33 @@
<Content Include="gameobjects\Tilemap.js">
<DependentUpon>Tilemap.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="verlet\AngleConstraint.ts" />
<TypeScriptCompile Include="VerletManager.ts" />
<TypeScriptCompile Include="geom\Polygon.ts" />
<Content Include="geom\Polygon.js">
<DependentUpon>Polygon.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="geom\Response.ts" />
<Content Include="geom\Response.js">
<DependentUpon>Response.ts</DependentUpon>
</Content>
<Content Include="VerletManager.js">
<DependentUpon>VerletManager.ts</DependentUpon>
</Content>
<Content Include="verlet\AngleConstraint.js">
<DependentUpon>AngleConstraint.ts</DependentUpon>
</Content>
<Content Include="geom\Circle.js">
<DependentUpon>Circle.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="verlet\DistanceConstraint.ts" />
<TypeScriptCompile Include="verlet\Composite.ts" />
<Content Include="verlet\Composite.js">
<DependentUpon>Composite.ts</DependentUpon>
</Content>
<Content Include="verlet\DistanceConstraint.js">
<DependentUpon>DistanceConstraint.ts</DependentUpon>
</Content>
<Content Include="geom\IntersectResult.js">
<DependentUpon>IntersectResult.ts</DependentUpon>
</Content>
@@ -112,6 +146,14 @@
<Content Include="geom\MicroPoint.js">
<DependentUpon>MicroPoint.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="verlet\PinConstraint.ts" />
<TypeScriptCompile Include="verlet\Particle.ts" />
<Content Include="verlet\Particle.js">
<DependentUpon>Particle.ts</DependentUpon>
</Content>
<Content Include="verlet\PinConstraint.js">
<DependentUpon>PinConstraint.ts</DependentUpon>
</Content>
<Content Include="geom\Point.js">
<DependentUpon>Point.ts</DependentUpon>
</Content>
@@ -122,9 +164,37 @@
<Content Include="geom\Rectangle.js">
<DependentUpon>Rectangle.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="geom\Vector2.ts" />
<Content Include="geom\Vector2.js">
<DependentUpon>Vector2.ts</DependentUpon>
</Content>
<Content Include="SoundManager.js">
<DependentUpon>SoundManager.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="system\screens\PauseScreen.ts" />
<TypeScriptCompile Include="system\screens\BootScreen.ts" />
<TypeScriptCompile Include="system\input\MSPointer.ts" />
<TypeScriptCompile Include="system\input\Gestures.ts" />
<TypeScriptCompile Include="system\CollisionMask.ts" />
<Content Include="system\CollisionMask.js">
<DependentUpon>CollisionMask.ts</DependentUpon>
</Content>
<Content Include="system\input\Gestures.js">
<DependentUpon>Gestures.ts</DependentUpon>
</Content>
<Content Include="system\input\MSPointer.js">
<DependentUpon>MSPointer.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="system\input\Pointer.ts" />
<Content Include="system\input\Pointer.js">
<DependentUpon>Pointer.ts</DependentUpon>
</Content>
<Content Include="system\screens\BootScreen.js">
<DependentUpon>BootScreen.ts</DependentUpon>
</Content>
<Content Include="system\screens\PauseScreen.js">
<DependentUpon>PauseScreen.ts</DependentUpon>
</Content>
<Content Include="system\Sound.js">
<DependentUpon>Sound.ts</DependentUpon>
</Content>
@@ -215,9 +285,6 @@
<Content Include="system\easing\Sinusoidal.js">
<DependentUpon>Sinusoidal.ts</DependentUpon>
</Content>
<Content Include="system\input\Finger.js">
<DependentUpon>Finger.ts</DependentUpon>
</Content>
<Content Include="system\input\Input.js">
<DependentUpon>Input.ts</DependentUpon>
</Content>
@@ -234,7 +301,6 @@
<TypeScriptCompile Include="system\input\Mouse.ts" />
<TypeScriptCompile Include="system\input\Keyboard.ts" />
<TypeScriptCompile Include="system\input\Input.ts" />
<TypeScriptCompile Include="system\input\Finger.ts" />
<TypeScriptCompile Include="system\easing\Sinusoidal.ts" />
<TypeScriptCompile Include="system\easing\Quintic.ts" />
<TypeScriptCompile Include="system\easing\Quartic.ts" />
+3
View File
@@ -0,0 +1,3 @@
module Phaser {
var VERSION: string;
}
+3 -3
View File
@@ -1,13 +1,13 @@
/**
* Phaser
*
* v0.9.4 - April 24th 2013
* v0.9.6 - May 21st 2013
*
* A small and feature-packed 2D canvas game framework born from the firey pits of Flixel and Kiwi.
*
* Richard Davey (@photonstorm)
*
* Many thanks to Adam Saltsman (@ADAMATOMIC) for the original Flixel AS3 code on which Phaser is based.
* Many thanks to Adam Saltsman (@ADAMATOMIC) for releasing Flixel on which Phaser took a lot of inspiration.
*
* "If you want your children to be intelligent, read them fairy tales."
* "If you want them to be more intelligent, read them more fairy tales."
@@ -16,6 +16,6 @@
module Phaser {
export var VERSION: string = 'Phaser version 0.9.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)
{
this._bindings[i]._destroy(); //no reason to a SignalBinding exist if it isn't attached to a signal
this._bindings[i]._destroy();
this._bindings.splice(i, 1);
}
@@ -224,14 +224,17 @@ module Phaser {
*/
public removeAll() {
var n: number = this._bindings.length;
while (n--)
if (this._bindings)
{
this._bindings[n]._destroy();
}
var n: number = this._bindings.length;
this._bindings.length = 0;
while (n--)
{
this._bindings[n]._destroy();
}
this._bindings.length = 0;
}
}
+21
View File
@@ -0,0 +1,21 @@
/// <reference path="Signal.d.ts" />
module Phaser {
class SignalBinding {
constructor(signal: Signal, listener, isOnce: bool, listenerContext, priority?: number);
private _listener;
private _isOnce;
public context;
private _signal;
public priority: number;
public active: bool;
public params;
public execute(paramsArr?: any[]);
public detach();
public isBound(): bool;
public isOnce(): bool;
public getListener();
public getSignal(): Signal;
public _destroy(): void;
public toString(): string;
}
}
+16
View File
@@ -0,0 +1,16 @@
/// <reference path="Game.d.ts" />
/// <reference path="system/Sound.d.ts" />
module Phaser {
class SoundManager {
constructor(game: Game);
private _game;
private _context;
private _gainNode;
private _volume;
public mute(): void;
public unmute(): void;
public volume : number;
public decode(key: string, callback?, sound?: Sound): void;
public play(key: string, volume?: number, loop?: bool): Sound;
}
}
+39 -1
View File
@@ -11,6 +11,10 @@ module Phaser {
export class SoundManager {
/**
* SoundManager constructor
* Create a new <code>SoundManager</code>.
*/
constructor(game: Game) {
this._game = game;
@@ -36,18 +40,39 @@ module Phaser {
}
/**
* Local private reference to game.
*/
private _game: Game;
/**
* Reference to AudioContext instance.
*/
private _context = null;
/**
* Gain node created from audio context.
*/
private _gainNode;
/**
* Volume of sounds.
* @type {number}
*/
private _volume: number;
/**
* Mute sounds.
*/
public mute() {
this._gainNode.gain.value = 0;
}
/**
* Enable sounds.
*/
public unmute() {
this._gainNode.gain.value = this._volume;
@@ -65,6 +90,12 @@ module Phaser {
return this._volume;
}
/**
* Decode a sound with its assets key.
* @param key {string} Assets key of the sound to be decoded.
* @param callback {function} This will be invoked when finished decoding.
* @param [sound] {Sound} its bufer will be set to decoded data.
*/
public decode(key: string, callback = null, sound?: Sound = null) {
var soundData = this._game.cache.getSound(key);
@@ -90,6 +121,13 @@ module Phaser {
}
/**
* Play a sound with its assets key.
* @param key {string} Assets key of the sound you want to play.
* @param [volume] {number} volume of the sound you want to play.
* @param [loop] {boolean} loop when it finished playing? (Default to false)
* @return {Sound} The playing sound object.
*/
public play(key: string, volume?: number = 1, loop?: bool = false): Sound {
if (this._context === null)
@@ -111,7 +149,7 @@ module Phaser {
var tempSound: Sound = new Sound(this._context, this._gainNode, null, volume, loop);
// this is an async process, so we can return the Sound object anyway, it just won't be playing yet
this.decode(key, () => this.play(key), tempSound);
this.decode(key, () => tempSound.play(), tempSound);
return tempSound;
}
+47
View File
@@ -0,0 +1,47 @@
/// <reference path="Phaser.d.ts" />
/// <reference path="Game.d.ts" />
/// <reference path="system/StageScaleMode.d.ts" />
/// <reference path="system/screens/BootScreen.d.ts" />
/// <reference path="system/screens/PauseScreen.d.ts" />
module Phaser {
class Stage {
constructor(game: Game, parent: string, width: number, height: number);
private _game;
private _bgColor;
private _bootScreen;
private _pauseScreen;
static ORIENTATION_LANDSCAPE: number;
static ORIENTATION_PORTRAIT: number;
public bounds: Rectangle;
public aspectRatio: number;
public clear: bool;
public canvas: HTMLCanvasElement;
public context: CanvasRenderingContext2D;
public disablePauseScreen: bool;
public disableBootScreen: bool;
public offset: Point;
public scale: StageScaleMode;
public scaleMode: number;
public minScaleX: number;
public maxScaleX: number;
public minScaleY: number;
public maxScaleY: number;
public update(): void;
private visibilityChange(event);
private getOffset(element);
public strokeStyle: string;
public lineWidth: number;
public fillStyle: string;
public saveCanvasValues(): void;
public restoreCanvasValues(): void;
public backgroundColor : string;
public x : number;
public y : number;
public width : number;
public height : number;
public centerX : number;
public centerY : number;
public randomX : number;
public randomY : number;
}
}
+155 -77
View File
@@ -1,6 +1,8 @@
/// <reference path="Phaser.ts" />
/// <reference path="Game.ts" />
/// <reference path="system/StageScaleMode.ts" />
/// <reference path="system/screens/BootScreen.ts" />
/// <reference path="system/screens/PauseScreen.ts" />
/**
* Phaser - Stage
@@ -13,6 +15,15 @@ module Phaser {
export class Stage {
/**
* Stage constructor
*
* Create a new <code>Stage</code> with specific width and height.
*
* @param parent {number} ID of parent DOM element.
* @param width {number} Width of the stage.
* @param height {number} Height of the stage.
*/
constructor(game: Game, parent: string, width: number, height: number) {
this._game = game;
@@ -33,16 +44,22 @@ module Phaser {
// Consume default actions on the canvas
this.canvas.style.msTouchAction = 'none';
this.canvas.style['ms-touch-action'] = 'none';
this.canvas.style['touch-action'] = 'none';
this.canvas.style.backgroundColor = 'rgb(0,0,0)';
this.canvas.oncontextmenu = function(event) { event.preventDefault(); };
this.context = this.canvas.getContext('2d');
this.offset = this.getOffset(this.canvas);
this.bounds = new Rectangle(this.offset.x, this.offset.y, width, height);
this.bounds = new Quad(this.offset.x, this.offset.y, width, height);
this.aspectRatio = width / height;
this.scaleMode = StageScaleMode.NO_SCALE;
this.scale = new StageScaleMode(this._game);
this._bootScreen = new BootScreen(this._game);
this._pauseScreen = new PauseScreen(this._game, width, height);
document.addEventListener('visibilitychange', (event) => this.visibilityChange(event), false);
document.addEventListener('webkitvisibilitychange', (event) => this.visibilityChange(event), false);
window.onblur = (event) => this.visibilityChange(event);
@@ -50,28 +67,96 @@ module Phaser {
}
/**
* Local private reference to game.
*/
private _game: Game;
private _bgColor: string;
/**
* Background color of the stage (defaults to black)
* @type {string}
*/
private _bgColor: string = 'rgb(0,0,0)';
public static ORIENTATION_LANDSCAPE: number = 0;
public static ORIENTATION_PORTRAIT: number = 1;
/**
* This will be displayed when Phaser is started without any default functions or State
* @type {BootScreen}
*/
private _bootScreen;
public bounds: Rectangle;
/**
* This will be displayed whenever the game loses focus or the player switches to another browser tab.
* @type {PauseScreen}
*/
private _pauseScreen;
/**
* Bound of this stage.
* @type {Quad}
*/
public bounds: Quad;
/**
* Asperct ratio, thus: width / height.
* @type {number}
*/
public aspectRatio: number;
/**
* Clear the whole stage every frame? (Default to true)
* @type {boolean}
*/
public clear: bool = true;
/**
* Canvas element used by engine.
* @type {HTMLCanvasElement}
*/
public canvas: HTMLCanvasElement;
/**
* Render context of stage's canvas.
* @type {CanvasRenderingContext2D}
*/
public context: CanvasRenderingContext2D;
/**
* Do not use pause screen when game is paused?
* (Default to false, aka always use PauseScreen)
* @type {boolean}
*/
public disablePauseScreen: bool = false;
public offset: Point;
/**
* Do not use boot screen when engine starts?
* (Default to false, aka always use BootScreen)
* @type {boolean}
*/
public disableBootScreen: bool = false;
/**
* Offset from this stage to the canvas element.
* @type {MicroPoint}
*/
public offset: MicroPoint;
/**
* This object manages scaling of the game, see(StageScaleMode).
* @type {StageScaleMode}
*/
public scale: StageScaleMode;
/**
* Which mode will the game be scaled.
* Available: StageScaleMode.EXACT_FIT, StageScaleMode.NO_SCALE, StageScaleMode.SHOW_ALL.
* @type {number}
*/
public scaleMode: number;
public minScaleX: number = null;
public maxScaleX: number = null;
public minScaleY: number = null;
public maxScaleY: number = null;
/**
* Update stage for rendering. This will handle scaling, clearing
* and PauseScreen/BootScreen updating and rendering.
*/
public update() {
this.scale.update();
@@ -82,92 +167,67 @@ module Phaser {
this.context.clearRect(0, 0, this.width, this.height);
}
}
if (this._game.isRunning == false && this.disableBootScreen == false)
{
this._bootScreen.update();
this._bootScreen.render();
}
public renderDebugInfo() {
this.context.fillStyle = 'rgb(255,255,255)';
this.context.fillText(Phaser.VERSION, 10, 20);
this.context.fillText('Game Size: ' + this.width + ' x ' + this.height, 10, 40);
this.context.fillText('x: ' + this.x + ' y: ' + this.y, 10, 60);
if (this._game.paused == true && this.disablePauseScreen == false)
{
this._pauseScreen.update();
this._pauseScreen.render();
}
}
//if (document['hidden'] === true || document['webkitHidden'] === true)
/**
* This method is called when the canvas elements visibility is changed.
*/
private visibilityChange(event) {
//console.log(event);
if (this.disablePauseScreen)
{
return;
}
if (event.type == 'blur' && this._game.paused == false && this._game.isBooted == true)
if (event.type == 'blur' || document['hidden'] == true || document['webkitHidden'] == true)
{
this._game.paused = true;
this.drawPauseScreen();
if (this._game.paused == false)
{
this.pauseGame();
}
}
else if (event.type == 'focus')
else
{
this._game.paused = false;
if (this._game.paused == true)
{
this.resumeGame();
}
}
}
public drawInitScreen() {
this.context.fillStyle = 'rgb(40, 40, 40)';
this.context.fillRect(0, 0, this.width, this.height);
this.context.fillStyle = 'rgb(255,255,255)';
this.context.font = 'bold 18px Arial';
this.context.textBaseline = 'top';
this.context.fillText(Phaser.VERSION, 54, 32);
this.context.fillText('Game Size: ' + this.width + ' x ' + this.height, 32, 64);
this.context.fillText('www.photonstorm.com', 32, 96);
this.context.font = '16px Arial';
this.context.fillText('You are seeing this screen because you didn\'t specify any default', 32, 160);
this.context.fillText('functions in the Game constructor, or use Game.loadState()', 32, 184);
var image = new Image();
var that = this;
image.onload = function () {
that.context.drawImage(image, 32, 32);
};
image.src = this._logo;
}
private drawPauseScreen() {
public pauseGame() {
this._pauseScreen.onPaused();
this.saveCanvasValues();
this.context.fillStyle = 'rgba(0, 0, 0, 0.4)';
this.context.fillRect(0, 0, this.width, this.height);
// Draw a 'play' arrow
var arrowWidth = Math.round(this.width / 2);
var arrowHeight = Math.round(this.height / 2);
var sx = this.centerX - arrowWidth / 2;
var sy = this.centerY - arrowHeight / 2;
this.context.beginPath();
this.context.moveTo(sx, sy);
this.context.lineTo(sx, sy + arrowHeight);
this.context.lineTo(sx + arrowWidth, this.centerY);
this.context.fillStyle = 'rgba(255, 255, 255, 0.8)';
this.context.fill();
this.context.closePath();
this.restoreCanvasValues();
this._game.paused = true;
}
private getOffset(element): Point {
public resumeGame() {
this._pauseScreen.onResume();
this.restoreCanvasValues();
this._game.paused = false;
}
/**
* Get the DOM offset values of the given element
*/
private getOffset(element): MicroPoint {
var box = element.getBoundingClientRect();
@@ -176,14 +236,31 @@ module Phaser {
var scrollTop = window.pageYOffset || element.scrollTop || document.body.scrollTop;
var scrollLeft = window.pageXOffset || element.scrollLeft || document.body.scrollLeft;
return new Point(box.left + scrollLeft - clientLeft, box.top + scrollTop - clientTop);
return new MicroPoint(box.left + scrollLeft - clientLeft, box.top + scrollTop - clientTop);
}
/**
* Canvas strokeStyle.
* @type {string}
*/
public strokeStyle: string;
/**
* Canvas lineWidth.
* @type {number}
*/
public lineWidth: number;
/**
* Canvas fillStyle.
* @type {string}
*/
public fillStyle: string;
/**
* Save current canvas properties (strokeStyle, lineWidth and fillStyle) for later using.
*/
public saveCanvasValues() {
this.strokeStyle = this.context.strokeStyle;
@@ -192,6 +269,9 @@ module Phaser {
}
/**
* Restore current canvas values (strokeStyle, lineWidth and fillStyle) with saved values.
*/
public restoreCanvasValues() {
this.context.strokeStyle = this.strokeStyle;
@@ -240,8 +320,6 @@ module Phaser {
return Math.round(Math.random() * this.bounds.height);
}
private _logo: string = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAO1JREFUeNpi/P//PwM6YGRkxBQEAqBaRnQxFmwa10d6MAjrMqMofHv5L1we2SBGmAtAktg0ogOQQYHLd8ANYYFpPtTmzUAMAFmwnsEDrAdkCAvMZlIAsiFMMAEYsKvaSrQhIMCELkGsV2AAbIC8gCQYgwKIUABiNYBf9yoYH7n7n6CzN274g2IYEyFbsNmKLIaSkHpP7WSwUfbA0ASzFQRslBlxp0RcAF0TRhggA3zhAJIDpUKU5A9KyshpHDkjFZu5g2nJMFcwXVJSgqIGnBKx5bKenh4w/XzVbgbPtlIUcVgSxuoCUgHIIIAAAwArtXwJBABO6QAAAABJRU5ErkJggg==";
}
}
+111 -44
View File
@@ -10,10 +10,15 @@ module Phaser {
export class State {
/**
* State constructor
* Create a new <code>State</code>.
*/
constructor(game: Game) {
this.game = game;
this.add = game.add;
this.camera = game.camera;
this.cache = game.cache;
this.collision = game.collision;
@@ -29,73 +34,135 @@ module Phaser {
}
/**
* Reference to Game.
*/
public game: Game;
/**
* Currently used camera.
* @type {Camera}
*/
public camera: Camera;
/**
* Reference to the assets cache.
* @type {Cache}
*/
public cache: Cache;
/**
* Reference to the collision helper.
* @type {Collision}
*/
public collision: Collision;
/**
* Reference to the GameObject Factory.
* @type {GameObjectFactory}
*/
public add: GameObjectFactory;
/**
* Reference to the input manager
* @type {Input}
*/
public input: Input;
/**
* Reference to the assets loader.
* @type {Loader}
*/
public loader: Loader;
/**
* Reference to the math helper.
* @type {GameMath}
*/
public math: GameMath;
/**
* Reference to the motion helper.
* @type {Motion}
*/
public motion: Motion;
/**
* Reference to the sound manager.
* @type {SoundManager}
*/
public sound: SoundManager;
/**
* Reference to the stage.
* @type {Stage}
*/
public stage: Stage;
/**
* Reference to game clock.
* @type {Time}
*/
public time: Time;
/**
* Reference to the tween manager.
* @type {TweenManager}
*/
public tweens: TweenManager;
/**
* Reference to the world.
* @type {World}
*/
public world: World;
// Override these in your own States
// Overload these in your own States
/**
* Override this method to add some load operations.
* If you need to use the loader, you may need to use them here.
*/
public init() { }
/**
* This method is called after the game engine successfully switches states.
* Feel free to add any setup code here.(Do not load anything here, override init() instead)
*/
public create() { }
/**
* Put update logic here.
*/
public update() { }
/**
* Put render operations here.
*/
public render() { }
/**
* This method will be called when game paused.
*/
public paused() { }
// Handy Proxy methods
/**
* This method will be called when the state is destroyed
*/
public destroy() { }
public createCamera(x: number, y: number, width: number, height: number): Camera {
return this.game.world.createCamera(x, y, width, height);
}
public createGeomSprite(x: number, y: number): GeomSprite {
return this.world.createGeomSprite(x, y);
}
public createSprite(x: number, y: number, key?: string = ''): Sprite {
return this.game.world.createSprite(x, y, key);
}
public createDynamicTexture(width: number, height: number): DynamicTexture {
return this.game.world.createDynamicTexture(width, height);
}
public createGroup(MaxSize?: number = 0): Group {
return this.game.world.createGroup(MaxSize);
}
public createParticle(): Particle {
return this.game.world.createParticle();
}
public createEmitter(x?: number = 0, y?: number = 0, size?: number = 0): Emitter {
return this.game.world.createEmitter(x, y, size);
}
public createScrollZone(key: string, x?: number = 0, y?: number = 0, width?: number = 0, height?: number = 0): ScrollZone {
return this.game.world.createScrollZone(key, x, y, width, height);
}
public createTilemap(key: string, mapData: string, format: number, resizeWorld: bool = true, tileWidth?: number = 0, tileHeight?: number = 0): Tilemap {
return this.game.world.createTilemap(key, mapData, format, resizeWorld, tileWidth, tileHeight);
}
public createTween(obj): Tween {
return this.game.tweens.create(obj);
}
public collide(ObjectOrGroup1: Basic = null, ObjectOrGroup2: Basic = null, NotifyCallback = null): bool {
return this.collision.overlap(ObjectOrGroup1, ObjectOrGroup2, NotifyCallback, Collision.separate);
/**
* Checks for overlaps between two objects using the world QuadTree. Can be GameObject vs. GameObject, GameObject vs. Group or Group vs. Group.
* Note: Does not take the objects scrollFactor into account. All overlaps are check in world space.
* @param object1 The first GameObject or Group to check. If null the world.group is used.
* @param object2 The second GameObject or Group to check.
* @param notifyCallback A callback function that is called if the objects overlap. The two objects will be passed to this function in the same order in which you passed them to Collision.overlap.
* @param processCallback A callback function that lets you perform additional checks against the two objects if they overlap. If this is set then notifyCallback will only be called if processCallback returns true.
* @param context The context in which the callbacks will be called
* @returns {boolean} true if the objects overlap, otherwise false.
*/
public collide(objectOrGroup1: Basic = null, objectOrGroup2: Basic = null, notifyCallback = null, context? = this.game.callbackContext): bool {
return this.collision.overlap(objectOrGroup1, objectOrGroup2, notifyCallback, Collision.separate, context);
}
}
+25
View File
@@ -0,0 +1,25 @@
/// <reference path="Game.d.ts" />
module Phaser {
class Time {
constructor(game: Game);
private _game;
private _started;
public timeScale: number;
public elapsed: number;
public time: number;
public now: number;
public delta: number;
public totalElapsedSeconds : number;
public fps: number;
public fpsMin: number;
public fpsMax: number;
public msMin: number;
public msMax: number;
public frames: number;
private _timeLastSecond;
public update(): void;
public elapsedSince(since: number): number;
public elapsedSecondsSince(since: number): number;
public reset(): void;
}
}
+92 -39
View File
@@ -10,40 +10,64 @@ module Phaser {
export class Time {
/**
* Time constructor
* Create a new <code>Time</code>.
*
* @param game {Phaser.Game} Current game instance.
*/
constructor(game: Game) {
this._started = Date.now();
this._started = 0;
this._timeLastSecond = this._started;
this.time = this._started;
this._game = game;
}
/**
* Local private reference to game.
*/
private _game: Game;
/**
* Time when this object created.
* @param {number}
*/
private _started: number;
/**
* Time scale factor.
* Set it to 0.5 for slow motion, to 2.0 makes game twice faster.
* @type {number}
*/
public timeScale: number = 1.0;
/**
* Elapsed since last frame.
* @type {number}
*/
public elapsed: number = 0;
/**
*
* @property time
* @type Number
*/
* Game time counter.
* @property time
* @type {number}
*/
public time: number = 0;
/**
*
* @property now
* @type Number
*/
* Time of current frame.
* @property now
* @type {number}
*/
public now: number = 0;
/**
*
* @property delta
* @type Number
*/
* Elapsed time since last frame.
* @property delta
* @type {number}
*/
public delta: number = 0;
/**
@@ -57,23 +81,58 @@ module Phaser {
}
/**
* Frames per second.
* @type {number}
*/
public fps: number = 0;
/**
* Minimal fps.
* @type {number}
*/
public fpsMin: number = 1000;
/**
* Maximal fps.
* @type {number}
*/
public fpsMax: number = 0;
/**
* Mininal duration between 2 frames.
* @type {number}
*/
public msMin: number = 1000;
/**
* Maximal duration between 2 frames.
* @type {number}
*/
public msMax: number = 0;
/**
* How many frames in last second.
* @type {number}
*/
public frames: number = 0;
/**
* Time of last second.
* @type {number}
*/
private _timeLastSecond: number = 0;
/**
*
* @method update
*/
public update() {
* Update clock and calculate the fps.
* This is called automatically by Game._raf
* @method update
* @param {number} raf The current timestamp, either performance.now or Date.now
*/
public update(raf: number) {
// Can we use performance.now() ?
this.now = Date.now(); // mark
this.now = raf; // mark
//this.now = Date.now(); // mark
this.delta = this.now - this.time; // elapsedMS
this.msMin = Math.min(this.msMin, this.delta);
@@ -93,20 +152,14 @@ module Phaser {
this.time = this.now; // _total
//// Lock the delta at 0.1 to minimise fps tunneling
//if (this.delta > 0.1)
//{
// this.delta = 0.1;
//}
}
/**
*
* @method elapsedSince
* @param {Number} since
* @return {Number}
*/
* How long has passed since given time.
* @method elapsedSince
* @param {number} since The time you want to measure.
* @return {number} Duration between given time and now.
*/
public elapsedSince(since: number): number {
return this.now - since;
@@ -114,11 +167,11 @@ module Phaser {
}
/**
*
* @method elapsedSecondsSince
* @param {Number} since
* @return {Number}
*/
* How long has passed since give time (in seconds).
* @method elapsedSecondsSince
* @param {number} since The time you want to measure (in seconds).
* @return {number} Duration between given time and now (in seconds).
*/
public elapsedSecondsSince(since: number): number {
return (this.now - since) * 0.001;
@@ -126,9 +179,9 @@ module Phaser {
}
/**
*
* @method reset
*/
* Set the start time to now.
* @method reset
*/
public reset() {
this._started = this.now;
+15
View File
@@ -0,0 +1,15 @@
/// <reference path="Game.d.ts" />
/// <reference path="system/Tween.d.ts" />
module Phaser {
class TweenManager {
constructor(game: Game);
private _game;
private _tweens;
public getAll(): Tween[];
public removeAll(): void;
public create(object): Tween;
public add(tween: Tween): Tween;
public remove(tween: Tween): void;
public update(): bool;
}
}
+41 -1
View File
@@ -7,7 +7,7 @@
* The Game has a single instance of the TweenManager through which all Tween objects are created and updated.
* Tweens are hooked into the game clock and pause system, adjusting based on the game state.
* TweenManager is based heavily on tween.js by sole (http://soledadpenades.com).
* I converted it to TypeScript, swapped the callbacks for signals and patched a few issues with regard
* I converted it to TypeScript, swapped the callbacks for signals and patched a few issues with regard
* to properties and completion errors. Please see https://github.com/sole/tween.js for a full list of contributors.
*/
@@ -15,6 +15,10 @@ module Phaser {
export class TweenManager {
/**
* TweenManager constructor
* @param game {Game} A reference to the current Game.
*/
constructor(game: Phaser.Game) {
this._game = game;
@@ -22,27 +26,53 @@ module Phaser {
}
/**
* Local private reference to Game
*/
private _game: Phaser.Game;
/**
* Local private array which is the container of all tween objects.
*/
private _tweens: Phaser.Tween[];
/**
* Get all the tween objects in an array.
* @return {Phaser.Tween[]} Array with all tween objects.
*/
public getAll() {
return this._tweens;
}
/**
* Remove all tween objects.
*/
public removeAll() {
this._tweens.length = 0;
}
/**
* Create a tween object for a specific object.
*
* @param object {object} Object you wish the tween will affect.
* @return {Phaser.Tween} The newly created tween object.
*/
public create(object): Phaser.Tween {
return new Phaser.Tween(object, this._game);
}
/**
* Add an exist tween object to the manager.
*
* @param tween {Phaser.Tween} The tween object you want to add.
* @return {Phaser.Tween} The tween object you added to the manager.
*/
public add(tween: Phaser.Tween) {
tween.parent = this._game;
@@ -53,6 +83,11 @@ module Phaser {
}
/**
* Remove a tween from this manager.
*
* @param tween {Phaser.Tween} The tween object you want to remove.
*/
public remove(tween: Phaser.Tween) {
var i = this._tweens.indexOf(tween);
@@ -64,6 +99,11 @@ module Phaser {
}
/**
* Update all the tween objects you added to this manager.
*
* @return {boolean} Return false if there's no tween to update, otherwise return true.
*/
public update() {
if (this._tweens.length === 0)
+411
View File
@@ -0,0 +1,411 @@
/// <reference path="Game.ts" />
/// <reference path="geom/Vector2.ts" />
/// <reference path="verlet/Composite.ts" />
/// <reference path="verlet/Particle.ts" />
/// <reference path="verlet/DistanceConstraint.ts" />
/// <reference path="verlet/PinConstraint.ts" />
/// <reference path="verlet/AngleConstraint.ts" />
/**
* Phaser - Verlet
*
* Based on verlet-js by Sub Protocol released under MIT
*/
module Phaser.Verlet {
export class VerletManager {
/**
* Creates a new Vector2 object.
* @class Vector2
* @constructor
* @param {Number} x The x coordinate of vector2
* @param {Number} y The y coordinate of vector2
* @return {Vector2} This object
**/
constructor(game: Game, width: number, height: number) {
this._game = game;
this.width = width;
this.height = height;
this.gravity = new Vector2(0, 0.2);
this.friction = 0.99;
this.groundFriction = 0.8;
this.canvas = game.stage.canvas;
this.context = game.stage.context;
this._game.input.onDown.add(this.mouseDownHandler, this);
this._game.input.onUp.add(this.mouseUpHandler, this);
}
private _game: Game;
private _v = new Phaser.Vector2;
public composites = [];
public width: number;
public height: number;
public step: number = 16;
public gravity: Vector2;
public friction: number;
public groundFriction: number;
public selectionRadius: number = 20;
public draggedEntity = null;
public highlightColor = '#4f545c';
/**
* A reference to the canvas this renders to
* @type {HTMLCanvasElement}
*/
public canvas: HTMLCanvasElement;
/**
* A reference to the context this renders to
* @type {CanvasRenderingContext2D}
*/
public context: CanvasRenderingContext2D;
/**
* Computes time of intersection of a particle with a wall
*
* @param {Vec2} line walls root position
* @param {Vec2} p particle position
* @param {Vec2} dir walls direction
* @param {Vec2} v particles velocity
*/
public intersectionTime(wall, p, dir, v) {
if (dir.x != 0)
{
var denominator = v.y - dir.y * v.x / dir.x;
if (denominator == 0) return undefined; // Movement is parallel to wall
var numerator = wall.y + dir.y * (p.x - wall.x) / dir.x - p.y;
return numerator / denominator;
}
else
{
if (v.x == 0) return undefined; // parallel again
var denominator = v.x;
var numerator = wall.x - p.x;
return numerator / denominator;
}
}
public intersectionPoint(wall, p, dir, v) {
var t = this.intersectionTime(wall, p, dir, v);
return new Phaser.Vector2(p.x + v.x * t, p.y + v.y * t);
}
public bounds(particle: Phaser.Verlet.Particle) {
this._v.mutableSet(particle.pos);
this._v.mutableSub(particle.lastPos);
if (particle.pos.y > this.height - 1)
{
particle.pos.mutableSet(this.intersectionPoint(new Phaser.Vector2(0, this.height - 1), particle.lastPos, new Phaser.Vector2(1, 0), this._v));
}
if (particle.pos.x < 0)
{
particle.pos.mutableSet(this.intersectionPoint(new Phaser.Vector2(0, 0), particle.pos, new Phaser.Vector2(0, 1), this._v));
}
if (particle.pos.x > this.width - 1)
{
particle.pos.mutableSet(this.intersectionPoint(new Phaser.Vector2(this.width - 1, 0), particle.pos, new Phaser.Vector2(0, 1), this._v));
}
}
public createPoint(pos: Vector2) {
var composite = new Phaser.Verlet.Composite(this._game);
composite.particles.push(new Phaser.Verlet.Particle(pos));
this.composites.push(composite);
return composite;
}
public createLineSegments(vertices, stiffness) {
var composite = new Phaser.Verlet.Composite(this._game);
var i;
for (i in vertices)
{
composite.particles.push(new Phaser.Verlet.Particle(vertices[i]));
if (i > 0)
{
composite.constraints.push(new Phaser.Verlet.DistanceConstraint(composite.particles[i], composite.particles[i - 1], stiffness));
}
}
this.composites.push(composite);
return composite;
}
public createCloth(origin, width, height, segments, pinMod, stiffness) {
var composite = new Phaser.Verlet.Composite(this._game);
var xStride = width / segments;
var yStride = height / segments;
var x;
var y;
for (y = 0; y < segments; ++y)
{
for (x = 0; x < segments; ++x)
{
var px = origin.x + x * xStride - width / 2 + xStride / 2;
var py = origin.y + y * yStride - height / 2 + yStride / 2;
composite.particles.push(new Phaser.Verlet.Particle(new Vector2(px, py)));
if (x > 0)
{
composite.constraints.push(new Phaser.Verlet.DistanceConstraint(composite.particles[y * segments + x], composite.particles[y * segments + x - 1], stiffness));
}
if (y > 0)
{
composite.constraints.push(new Phaser.Verlet.DistanceConstraint(composite.particles[y * segments + x], composite.particles[(y - 1) * segments + x], stiffness));
}
}
}
for (x = 0; x < segments; ++x)
{
if (x % pinMod == 0)
{
composite.pin(x);
}
}
this.composites.push(composite);
return composite;
}
public createTire(origin, radius, segments, spokeStiffness, treadStiffness) {
var stride = (2 * Math.PI) / segments;
var i;
var composite = new Phaser.Verlet.Composite(this._game);
// particles
for (i = 0; i < segments; ++i)
{
var theta = i * stride;
composite.particles.push(new Particle(new Vector2(origin.x + Math.cos(theta) * radius, origin.y + Math.sin(theta) * radius)));
}
var center = new Particle(origin);
composite.particles.push(center);
// constraints
for (i = 0; i < segments; ++i)
{
composite.constraints.push(new DistanceConstraint(composite.particles[i], composite.particles[(i + 1) % segments], treadStiffness));
composite.constraints.push(new DistanceConstraint(composite.particles[i], center, spokeStiffness))
composite.constraints.push(new DistanceConstraint(composite.particles[i], composite.particles[(i + 5) % segments], treadStiffness));
}
this.composites.push(composite);
return composite;
}
public update() {
if (this.composites.length == 0)
{
return;
}
var i, j, c;
for (c in this.composites)
{
for (i in this.composites[c].particles)
{
var particles = this.composites[c].particles;
// calculate velocity
var velocity = particles[i].pos.sub(particles[i].lastPos).scale(this.friction);
// ground friction
if (particles[i].pos.y >= this.height - 1 && velocity.length2() > 0.000001)
{
var m = velocity.length();
velocity.x /= m;
velocity.y /= m;
velocity.mutableScale(m * this.groundFriction);
}
// save last good state
particles[i].lastPos.mutableSet(particles[i].pos);
// gravity
particles[i].pos.mutableAdd(this.gravity);
// inertia
particles[i].pos.mutableAdd(velocity);
}
}
// handle dragging of entities
if (this.draggedEntity)
{
this.draggedEntity.pos.mutableSet(this._game.input.position);
}
// relax
var stepCoef = 1 / this.step;
for (c in this.composites)
{
var constraints = this.composites[c].constraints;
for (i = 0; i < this.step; ++i)
{
for (j in constraints)
{
constraints[j].relax(stepCoef);
}
}
}
// bounds checking
for (c in this.composites)
{
var particles = this.composites[c].particles;
for (i in particles)
{
this.bounds(particles[i]);
}
}
}
private mouseDownHandler() {
var nearest = this.nearestEntity();
if (nearest)
{
this.draggedEntity = nearest;
}
}
private mouseUpHandler() {
this.draggedEntity = null;
}
public nearestEntity() {
var c, i;
var d2Nearest = 0;
var entity = null;
var constraintsNearest = null;
// find nearest point
for (c in this.composites)
{
var particles = this.composites[c].particles;
for (i in particles)
{
var d2 = particles[i].pos.distance2(this._game.input.position);
if (d2 <= this.selectionRadius * this.selectionRadius && (entity == null || d2 < d2Nearest))
{
entity = particles[i];
constraintsNearest = this.composites[c].constraints;
d2Nearest = d2;
}
}
}
// search for pinned constraints for this entity
for (i in constraintsNearest)
{
if (constraintsNearest[i] instanceof PinConstraint && constraintsNearest[i].a == entity)
{
entity = constraintsNearest[i];
}
}
return entity;
}
public hideNearestEntityCircle: bool = false;
public render() {
var i, c;
for (c in this.composites)
{
// draw constraints
if (this.composites[c].drawConstraints)
{
this.composites[c].drawConstraints(this.context, this.composites[c]);
}
else
{
var constraints = this.composites[c].constraints;
for (i in constraints)
{
constraints[i].render(this.context);
}
}
// draw particles
if (this.composites[c].drawParticles)
{
this.composites[c].drawParticles(this.context, this.composites[c]);
}
else
{
var particles = this.composites[c].particles;
for (i in particles)
{
particles[i].render(this.context);
}
}
}
// highlight nearest / dragged entity
var nearest = this.draggedEntity || this.nearestEntity();
if (nearest && this.hideNearestEntityCircle == false)
{
this.context.beginPath();
this.context.arc(nearest.pos.x, nearest.pos.y, 8, 0, 2 * Math.PI);
this.context.strokeStyle = this.highlightColor;
this.context.stroke();
this.context.closePath();
}
}
}
}
+32
View File
@@ -0,0 +1,32 @@
/// <reference path="Game.d.ts" />
module Phaser {
class World {
constructor(game: Game, width: number, height: number);
private _game;
public cameras: CameraManager;
public group: Group;
public bounds: Rectangle;
public worldDivisions: number;
public update(): void;
public render(): void;
public destroy(): void;
public setSize(width: number, height: number, updateCameraBounds?: bool): void;
public width : number;
public height : number;
public centerX : number;
public centerY : number;
public randomX : number;
public randomY : number;
public createCamera(x: number, y: number, width: number, height: number): Camera;
public removeCamera(id: number): bool;
public getAllCameras(): Camera[];
public createSprite(x: number, y: number, key?: string): Sprite;
public createGeomSprite(x: number, y: number): GeomSprite;
public createDynamicTexture(width: number, height: number): DynamicTexture;
public createGroup(MaxSize?: number): Group;
public createScrollZone(key: string, x?: number, y?: number, width?: number, height?: number): ScrollZone;
public createTilemap(key: string, mapData: string, format: number, resizeWorld?: bool, tileWidth?: number, tileHeight?: number): Tilemap;
public createParticle(): Particle;
public createEmitter(x?: number, y?: number, size?: number): Emitter;
}
}
+147 -13
View File
@@ -3,6 +3,8 @@
/**
* Phaser - World
*
* "This world is but a canvas to our imagination." - Henry David Thoreau
*
* A game has only one world. The world is an abstract place in which all game objects live. It is not bound
* by stage limits and can be any size or dimension. You look into the world via cameras and all game objects
* live within the world at world-based coordinates. By default a world is created the same size as your Stage.
@@ -12,13 +14,18 @@ module Phaser {
export class World {
/**
* World constructor
* Create a new <code>World</code> with specific width and height.
*
* @param width {number} Width of the world bound.
* @param height {number} Height of the world bound.
*/
constructor(game: Game, width: number, height: number) {
this._game = game;
this._cameras = new CameraManager(this._game, 0, 0, width, height);
this._game.camera = this._cameras.current;
this.cameras = new CameraManager(this._game, 0, 0, width, height);
this.group = new Group(this._game, 0);
@@ -28,41 +35,80 @@ module Phaser {
}
/**
* Local private reference to game.
*/
private _game: Game;
private _cameras: CameraManager;
/**
* Camera manager of this world.
* @type {CameraManager}
*/
public cameras: CameraManager;
/**
* Object container stores every object created with `create*` methods.
* @type {Group}
*/
public group: Group;
/**
* Bound of this world that objects can not escape from.
* @type {Rectangle}
*/
public bounds: Rectangle;
/**
* @type {number}
*/
public worldDivisions: number;
/**
* This is called automatically every frame, and is where main logic performs.
*/
public update() {
this.group.preUpdate();
this.group.update();
this.group.postUpdate();
this._cameras.update();
this.cameras.update();
}
/**
* Render every thing to the screen, automatically called after update().
*/
public render() {
// Unlike in flixel our render process is camera driven, not group driven
this._cameras.render();
this.cameras.render();
}
/**
* Clean up memory.
*/
public destroy() {
this.group.destroy();
this._cameras.destroy();
this.cameras.destroy();
}
// World methods
public setSize(width: number, height: number, updateCameraBounds: bool = true) {
/**
* Update size of this world with specific width and height.
* You can choose update camera bounds and verlet manager automatically or not.
*
* @param width {number} New width of the world.
* @param height {number} New height of the world.
* @param [updateCameraBounds] {boolean} update camera bounds automatically or not. Default to true.
* @param [updateVerletBounds] {boolean} update verlet bounds automatically or not. Default to true.
*/
public setSize(width: number, height: number, updateCameraBounds: bool = true, updateVerletBounds: bool = true) {
this.bounds.width = width;
this.bounds.height = height;
@@ -72,6 +118,12 @@ module Phaser {
this._game.camera.setBounds(0, 0, width, height);
}
if (updateVerletBounds == true)
{
this._game.verlet.width = width;
this._game.verlet.height = height;
}
}
public get width(): number {
@@ -108,48 +160,130 @@ module Phaser {
// Cameras
/**
* Create a new camera with specific position and size.
*
* @param x {number} X position of the new camera.
* @param y {number} Y position of the new camera.
* @param width {number} Width of the new camera.
* @param height {number} Height of the new camera.
* @returns {Camera} The newly created camera object.
*/
public createCamera(x: number, y: number, width: number, height: number): Camera {
return this._cameras.addCamera(x, y, width, height);
return this.cameras.addCamera(x, y, width, height);
}
/**
* Remove a new camera with its id.
*
* @param id {number} ID of the camera you want to remove.
* @returns {boolean} True if successfully removed the camera, otherwise return false.
*/
public removeCamera(id: number): bool {
return this._cameras.removeCamera(id);
return this.cameras.removeCamera(id);
}
/**
* Get all the cameras.
*
* @returns {array} An array contains all the cameras.
*/
public getAllCameras(): Camera[] {
return this._cameras.getAll();
return this.cameras.getAll();
}
// Game Objects
/**
* Create a new Sprite with specific position and sprite sheet key.
*
* @param x {number} X position of the new sprite.
* @param y {number} Y position of the new sprite.
* @param [key] {string} key for the sprite sheet you want it to use.
* @returns {Sprite} The newly created sprite object.
*/
public createSprite(x: number, y: number, key?: string = ''): Sprite {
return <Sprite> this.group.add(new Sprite(this._game, x, y, key));
}
/**
* Create a new GeomSprite with specific position.
*
* @param x {number} X position of the new geom sprite.
* @param y {number} Y position of the new geom sprite.
* @returns {GeomSprite} The newly created geom sprite object.
*/
public createGeomSprite(x: number, y: number): GeomSprite {
return <GeomSprite> this.group.add(new GeomSprite(this._game, x, y));
}
/**
* Create a new DynamicTexture with specific size.
*
* @param width {number} Width of the texture.
* @param height {number} Height of the texture.
* @returns {DynamicTexture} The newly created dynamic texture object.
*/
public createDynamicTexture(width: number, height: number): DynamicTexture {
return new DynamicTexture(this._game, width, height);
}
public createGroup(MaxSize?: number = 0): Group {
return <Group> this.group.add(new Group(this._game, MaxSize));
/**
* Create a new object container.
*
* @param [maxSize] {number} capacity of this group.
* @returns {Group} The newly created group.
*/
public createGroup(maxSize?: number = 0): Group {
return <Group> this.group.add(new Group(this._game, maxSize));
}
/**
* Create a new ScrollZone object with image key, position and size.
*
* @param key {number} Key to a image you wish this object to use.
* @param x {number} X position of this object.
* @param y {number} Y position of this object.
* @param width {number} Width of this object.
* @param height {number} Height of this object.
* @returns {ScrollZone} The newly created scroll zone object.
*/
public createScrollZone(key: string, x?: number = 0, y?: number = 0, width?: number = 0, height?: number = 0): ScrollZone {
return <ScrollZone> this.group.add(new ScrollZone(this._game, key, x, y, width, height));
}
/**
* Create a new Tilemap.
*
* @param key {string} Key for tileset image.
* @param mapData {string} Data of this tilemap.
* @param format {number} Format of map data. (Tilemap.FORMAT_CSV or Tilemap.FORMAT_TILED_JSON)
* @param [resizeWorld] {boolean} resize the world to make same as tilemap?
* @param [tileWidth] {number} width of each tile.
* @param [tileHeight] {number} height of each tile.
* @return {Tilemap} The newly created tilemap object.
*/
public createTilemap(key: string, mapData: string, format: number, resizeWorld: bool = true, tileWidth?: number = 0, tileHeight?: number = 0): Tilemap {
return <Tilemap> this.group.add(new Tilemap(this._game, key, mapData, format, resizeWorld, tileWidth, tileHeight));
}
/**
* Create a new Particle.
*
* @return {Particle} The newly created particle object.
*/
public createParticle(): Particle {
return new Particle(this._game);
}
/**
* Create a new Emitter.
*
* @param [x] {number} x position of the emitter.
* @param [y] {number} y position of the emitter.
* @param [size] {number} size of this emitter.
* @return {Emitter} The newly created emitter object.
*/
public createEmitter(x?: number = 0, y?: number = 0, size?: number = 0): Emitter {
return <Emitter> this.group.add(new Emitter(this._game, x, y, size));
}
+38
View File
@@ -0,0 +1,38 @@
/// <reference path="../Game.d.ts" />
/// <reference path="../Group.d.ts" />
module Phaser {
class Emitter extends Group {
constructor(game: Game, X?: number, Y?: number, Size?: number);
public x: number;
public y: number;
public width: number;
public height: number;
public minParticleSpeed: MicroPoint;
public maxParticleSpeed: MicroPoint;
public particleDrag: MicroPoint;
public minRotation: number;
public maxRotation: number;
public gravity: number;
public on: bool;
public frequency: number;
public lifespan: number;
public bounce: number;
public particleClass;
private _quantity;
private _explode;
private _timer;
private _counter;
private _point;
public destroy(): void;
public makeParticles(Graphics, Quantity?: number, BakedRotations?: number, Multiple?: bool, Collide?: number): Emitter;
public update(): void;
public kill(): void;
public start(Explode?: bool, Lifespan?: number, Frequency?: number, Quantity?: number): void;
public emitParticle(): void;
public setSize(Width: number, Height: number): void;
public setXSpeed(Min?: number, Max?: number): void;
public setYSpeed(Min?: number, Max?: number): void;
public setRotation(Min?: number, Max?: number): void;
public at(Object): void;
}
}
+75 -72
View File
@@ -16,24 +16,26 @@ module Phaser {
/**
* Creates a new <code>Emitter</code> object at a specific position.
* Does NOT automatically generate or attach particles!
*
* @param X The X position of the emitter.
* @param Y The Y position of the emitter.
* @param Size Optional, specifies a maximum capacity for this emitter.
*
* @param x {number} The X position of the emitter.
* @param y {number} The Y position of the emitter.
* @param [size] {number} Specifies a maximum capacity for this emitter.
*/
constructor(game: Game, X: number = 0, Y: number = 0, Size: number = 0) {
super(game, Size);
this.x = X;
this.y = Y;
constructor(game: Game, x: number = 0, y: number = 0, size: number = 0) {
super(game, size);
this.x = x;
this.y = y;
this.width = 0;
this.height = 0;
this.minParticleSpeed = new Point(-100, -100);
this.maxParticleSpeed = new Point(100, 100);
this.minParticleSpeed = new MicroPoint(-100, -100);
this.maxParticleSpeed = new MicroPoint(100, 100);
this.minRotation = -360;
this.maxRotation = 360;
this.gravity = 0;
this.particleClass = null;
this.particleDrag = new Point();
this.particleDrag = new MicroPoint();
this.frequency = 0.1;
this.lifespan = 3;
this.bounce = 0;
@@ -41,7 +43,8 @@ module Phaser {
this._counter = 0;
this._explode = true;
this.on = false;
this._point = new Point();
this._point = new MicroPoint();
}
/**
@@ -68,18 +71,18 @@ module Phaser {
* The minimum possible velocity of a particle.
* The default value is (-100,-100).
*/
public minParticleSpeed: Point;
public minParticleSpeed: MicroPoint;
/**
* The maximum possible velocity of a particle.
* The default value is (100,100).
*/
public maxParticleSpeed: Point;
public maxParticleSpeed: MicroPoint;
/**
* The X and Y drag component of particles launched from the emitter.
*/
public particleDrag: Point;
public particleDrag: MicroPoint;
/**
* The minimum possible angular velocity of a particle. The default value is -360.
@@ -149,7 +152,7 @@ module Phaser {
/**
* Internal point object, handy for reusing for memory mgmt purposes.
*/
private _point: Point;
private _point: MicroPoint;
/**
* Clean up memory.
@@ -165,24 +168,23 @@ module Phaser {
/**
* This function generates a new array of particle sprites to attach to the emitter.
*
* @param Graphics If you opted to not pre-configure an array of Sprite objects, you can simply pass in a particle image or sprite sheet.
* @param Quantity The number of particles to generate when using the "create from image" option.
* @param BakedRotations How many frames of baked rotation to use (boosts performance). Set to zero to not use baked rotations.
* @param Multiple Whether the image in the Graphics param is a single particle or a bunch of particles (if it's a bunch, they need to be square!).
* @param Collide Whether the particles should be flagged as not 'dead' (non-colliding particles are higher performance). 0 means no collisions, 0-1 controls scale of particle's bounding box.
*
* @return This Emitter instance (nice for chaining stuff together, if you're into that).
*
* @param graphics If you opted to not pre-configure an array of Sprite objects, you can simply pass in a particle image or sprite sheet.
* @param quantity {number} The number of particles to generate when using the "create from image" option.
* @param multiple {boolean} Whether the image in the Graphics param is a single particle or a bunch of particles (if it's a bunch, they need to be square!).
* @param collide {number} Whether the particles should be flagged as not 'dead' (non-colliding particles are higher performance). 0 means no collisions, 0-1 controls scale of particle's bounding box.
*
* @return This Emitter instance (nice for chaining stuff together, if you're into that).
*/
public makeParticles(Graphics, Quantity: number = 50, BakedRotations: number = 16, Multiple: bool = false, Collide: number = 0.8): Emitter {
public makeParticles(graphics, quantity: number = 50, multiple: bool = false, collide: number = 0): Emitter {
this.maxSize = Quantity;
this.maxSize = quantity;
var totalFrames: number = 1;
/*
if(Multiple)
{
{
var sprite:Sprite = new Sprite(this._game);
sprite.loadGraphic(Graphics,true);
totalFrames = sprite.frames;
@@ -194,7 +196,7 @@ module Phaser {
var particle: Particle;
var i: number = 0;
while (i < Quantity)
while (i < quantity)
{
if (this.particleClass == null)
{
@@ -205,7 +207,7 @@ module Phaser {
particle = new this.particleClass(this._game);
}
if (Multiple)
if (multiple)
{
/*
randomFrame = this._game.math.random()*totalFrames;
@@ -227,17 +229,18 @@ module Phaser {
particle.loadGraphic(Graphics);
*/
if (Graphics)
if (graphics)
{
particle.loadGraphic(Graphics);
particle.loadGraphic(graphics);
}
}
if (Collide > 0)
if (collide > 0)
{
particle.width *= Collide;
particle.height *= Collide;
particle.allowCollisions = Collision.ANY;
particle.width *= collide;
particle.height *= collide;
//particle.centerOffsets();
}
else
@@ -317,23 +320,23 @@ module Phaser {
/**
* Call this function to start emitting particles.
*
* @param Explode Whether the particles should all burst out at once.
* @param Lifespan How long each particle lives once emitted. 0 = forever.
* @param Frequency Ignored if Explode is set to true. Frequency is how often to emit a particle. 0 = never emit, 0.1 = 1 particle every 0.1 seconds, 5 = 1 particle every 5 seconds.
* @param Quantity How many particles to launch. 0 = "all of the particles".
*
* @param explode {boolean} Whether the particles should all burst out at once.
* @param lifespan {number} How long each particle lives once emitted. 0 = forever.
* @param frequency {number} Ignored if Explode is set to true. Frequency is how often to emit a particle. 0 = never emit, 0.1 = 1 particle every 0.1 seconds, 5 = 1 particle every 5 seconds.
* @param quantity {number} How many particles to launch. 0 = "all of the particles".
*/
public start(Explode: bool = true, Lifespan: number = 0, Frequency: number = 0.1, Quantity: number = 0) {
public start(explode: bool = true, lifespan: number = 0, frequency: number = 0.1, quantity: number = 0) {
this.revive();
this.visible = true;
this.on = true;
this._explode = Explode;
this.lifespan = Lifespan;
this.frequency = Frequency;
this._quantity += Quantity;
this._explode = explode;
this.lifespan = lifespan;
this.frequency = frequency;
this._quantity += quantity;
this._counter = 0;
this._timer = 0;
@@ -394,55 +397,55 @@ module Phaser {
/**
* A more compact way of setting the width and height of the emitter.
*
* @param Width The desired width of the emitter (particles are spawned randomly within these dimensions).
* @param Height The desired height of the emitter.
*
* @param width {number} The desired width of the emitter (particles are spawned randomly within these dimensions).
* @param height {number} The desired height of the emitter.
*/
public setSize(Width: number, Height: number) {
this.width = Width;
this.height = Height;
public setSize(width: number, height: number) {
this.width = width;
this.height = height;
}
/**
* A more compact way of setting the X velocity range of the emitter.
*
* @param Min The minimum value for this range.
* @param Max The maximum value for this range.
*
* @param Min {number} The minimum value for this range.
* @param Max {number} The maximum value for this range.
*/
public setXSpeed(Min: number = 0, Max: number = 0) {
this.minParticleSpeed.x = Min;
this.maxParticleSpeed.x = Max;
public setXSpeed(min: number = 0, max: number = 0) {
this.minParticleSpeed.x = min;
this.maxParticleSpeed.x = max;
}
/**
* A more compact way of setting the Y velocity range of the emitter.
*
* @param Min The minimum value for this range.
* @param Max The maximum value for this range.
*
* @param Min {number} The minimum value for this range.
* @param Max {number} The maximum value for this range.
*/
public setYSpeed(Min: number = 0, Max: number = 0) {
this.minParticleSpeed.y = Min;
this.maxParticleSpeed.y = Max;
public setYSpeed(min: number = 0, max: number = 0) {
this.minParticleSpeed.y = min;
this.maxParticleSpeed.y = max;
}
/**
* A more compact way of setting the angular velocity constraints of the emitter.
*
* @param Min The minimum value for this range.
* @param Max The maximum value for this range.
*
* @param Min {number} The minimum value for this range.
* @param Max {number} The maximum value for this range.
*/
public setRotation(Min: number = 0, Max: number = 0) {
this.minRotation = Min;
this.maxRotation = Max;
public setRotation(min: number = 0, max: number = 0) {
this.minRotation = min;
this.maxRotation = max;
}
/**
* Change the emitter's midpoint to match the midpoint of a <code>Object</code>.
*
* @param Object The <code>Object</code> that you want to sync up with.
*
* @param Object {object} The <code>Object</code> that you want to sync up with.
*/
public at(Object) {
Object.getMidpoint(this._point);
public at(object) {
object.getMidpoint(this._point);
this.x = this._point.x - (this.width >> 1);
this.y = this._point.y - (this.height >> 1);
}
+84
View File
@@ -0,0 +1,84 @@
/// <reference path="../Game.d.ts" />
/// <reference path="../Basic.d.ts" />
/// <reference path="../Signal.d.ts" />
module Phaser {
class GameObject extends Basic {
constructor(game: Game, x?: number, y?: number, width?: number, height?: number);
private _angle;
static ALIGN_TOP_LEFT: number;
static ALIGN_TOP_CENTER: number;
static ALIGN_TOP_RIGHT: number;
static ALIGN_CENTER_LEFT: number;
static ALIGN_CENTER: number;
static ALIGN_CENTER_RIGHT: number;
static ALIGN_BOTTOM_LEFT: number;
static ALIGN_BOTTOM_CENTER: number;
static ALIGN_BOTTOM_RIGHT: number;
static OUT_OF_BOUNDS_STOP: number;
static OUT_OF_BOUNDS_KILL: number;
public _point: MicroPoint;
public cameraBlacklist: number[];
public bounds: Rectangle;
public worldBounds: Quad;
public outOfBoundsAction: number;
public align: number;
public facing: number;
public alpha: number;
public scale: MicroPoint;
public origin: MicroPoint;
public z: number;
public rotationOffset: number;
public renderRotation: bool;
public immovable: bool;
public velocity: MicroPoint;
public mass: number;
public elasticity: number;
public acceleration: MicroPoint;
public drag: MicroPoint;
public maxVelocity: MicroPoint;
public angularVelocity: number;
public angularAcceleration: number;
public angularDrag: number;
public maxAngular: number;
public scrollFactor: MicroPoint;
public health: number;
public moves: bool;
public touching: number;
public wasTouching: number;
public allowCollisions: number;
public last: MicroPoint;
public inputEnabled: bool;
private _inputOver;
public onInputOver: Signal;
public onInputOut: Signal;
public onInputDown: Signal;
public onInputUp: Signal;
public preUpdate(): void;
public update(): void;
public postUpdate(): void;
private updateInput();
private updateMotion();
public overlaps(ObjectOrGroup, InScreenSpace?: bool, Camera?: Camera): bool;
public overlapsAt(X: number, Y: number, ObjectOrGroup, InScreenSpace?: bool, Camera?: Camera): bool;
public overlapsPoint(point: Point, InScreenSpace?: bool, Camera?: Camera): bool;
public onScreen(Camera?: Camera): bool;
public getScreenXY(point?: MicroPoint, Camera?: Camera): MicroPoint;
public solid : bool;
public getMidpoint(point?: MicroPoint): MicroPoint;
public reset(X: number, Y: number): void;
public isTouching(Direction: number): bool;
public justTouched(Direction: number): bool;
public hurt(Damage: number): void;
public setBounds(x: number, y: number, width: number, height: number): void;
public hideFromCamera(camera: Camera): void;
public showToCamera(camera: Camera): void;
public clearCameraList(): void;
public destroy(): void;
public x : number;
public y : number;
public rotation : number;
public angle : number;
public width : number;
public height : number;
}
}
+432 -160
View File
@@ -1,6 +1,7 @@
/// <reference path="../Game.ts" />
/// <reference path="../Basic.ts" />
/// <reference path="../Signal.ts" />
/// <reference path="../system/CollisionMask.ts" />
/**
* Phaser - GameObject
@@ -13,11 +14,24 @@ module Phaser {
export class GameObject extends Basic {
/**
* GameObject constructor
*
* Create a new <code>GameObject</code> object at specific position with specific width and height.
*
* @param [x] {number} The x position of the object.
* @param [y] {number} The y position of the object.
* @param [width] {number} The width of the object.
* @param [height] {number} The height of the object.
*/
constructor(game: Game, x?: number = 0, y?: number = 0, width?: number = 16, height?: number = 16) {
super(game);
this.bounds = new Rectangle(x, y, width, height);
this.canvas = game.stage.canvas;
this.context = game.stage.context;
this.frameBounds = new Rectangle(x, y, width, height);
this.exists = true;
this.active = true;
this.visible = true;
@@ -27,10 +41,9 @@ module Phaser {
this.scale = new MicroPoint(1, 1);
this.last = new MicroPoint(x, y);
this.origin = new MicroPoint(this.bounds.halfWidth, this.bounds.halfHeight);
this.align = GameObject.ALIGN_TOP_LEFT;
this.mass = 1.0;
this.elasticity = 0.0;
this.mass = 1;
this.elasticity = 0;
this.health = 1;
this.immovable = false;
this.moves = true;
@@ -52,70 +65,303 @@ module Phaser {
this.maxAngular = 10000;
this.cameraBlacklist = [];
this.scrollFactor = new MicroPoint(1.0, 1.0);
this.scrollFactor = new MicroPoint(1, 1);
this.collisionMask = new CollisionMask(game, this, x, y, width, height);
}
/**
* Angle of this object.
* @type {number}
*/
private _angle: number = 0;
/**
* Pivot position enum: at the top-left corner.
* @type {number}
*/
public static ALIGN_TOP_LEFT: number = 0;
/**
* Pivot position enum: at the top-center corner.
* @type {number}
*/
public static ALIGN_TOP_CENTER: number = 1;
/**
* Pivot position enum: at the top-right corner.
* @type {number}
*/
public static ALIGN_TOP_RIGHT: number = 2;
/**
* Pivot position enum: at the center-left corner.
* @type {number}
*/
public static ALIGN_CENTER_LEFT: number = 3;
/**
* Pivot position enum: at the center corner.
* @type {number}
*/
public static ALIGN_CENTER: number = 4;
/**
* Pivot position enum: at the center-right corner.
* @type {number}
*/
public static ALIGN_CENTER_RIGHT: number = 5;
/**
* Pivot position enum: at the bottom-left corner.
* @type {number}
*/
public static ALIGN_BOTTOM_LEFT: number = 6;
/**
* Pivot position enum: at the bottom-center corner.
* @type {number}
*/
public static ALIGN_BOTTOM_CENTER: number = 7;
/**
* Pivot position enum: at the bottom-right corner.
* @type {number}
*/
public static ALIGN_BOTTOM_RIGHT: number = 8;
/**
* Enum value for outOfBoundsAction. Stop the object when is out of world bounds.
* @type {number}
*/
public static OUT_OF_BOUNDS_STOP: number = 0;
/**
* Enum value for outOfBoundsAction. Kill the object when is out of world bounds.
* @type {number}
*/
public static OUT_OF_BOUNDS_KILL: number = 1;
/**
* A reference to the Canvas this GameObject will render to
* @type {HTMLCanvasElement}
*/
public canvas: HTMLCanvasElement;
/**
* A reference to the Canvas Context2D this GameObject will render to
* @type {CanvasRenderingContext2D}
*/
public context: CanvasRenderingContext2D;
/**
* Position of this object after scrolling.
* @type {MicroPoint}
*/
public _point: MicroPoint;
/**
* An Array of Cameras to which this GameObject won't render
* @type {Array}
*/
public cameraBlacklist: number[];
public bounds: Rectangle;
/**
* Rectangle container of this object.
* @type {Rectangle}
*/
public frameBounds: Rectangle;
/**
* This objects CollisionMask
* @type {CollisionMask}
*/
public collisionMask: CollisionMask;
/**
* A rectangular area which is object is allowed to exist within. If it travels outside of this area it will perform the outOfBoundsAction.
* @type {Quad}
*/
public worldBounds: Quad;
/**
* What action will be performed when object is out of the worldBounds.
* This will default to GameObject.OUT_OF_BOUNDS_STOP.
* @type {number}
*/
public outOfBoundsAction: number = 0;
/**
* At which point the graphic of this object will align to.
* Align of the object will default to GameObject.ALIGN_TOP_LEFT.
* @type {number}
*/
public align: number;
/**
* Orientation of the object.
* @type {number}
*/
public facing: number;
/**
* Set alpha to a number between 0 and 1 to change the opacity.
* @type {number}
*/
public alpha: number;
/**
* Scale factor of the object.
* @type {MicroPoint}
*/
public scale: MicroPoint;
/**
* Origin is the anchor point that the object will rotate by.
* The origin will default to its center.
* @type {MicroPoint}
*/
public origin: MicroPoint;
/**
* Z-order value of the object.
*/
public z: number = 0;
// This value is added to the angle of the GameObject.
// For example if you had a sprite drawn facing straight up then you could set
// rotationOffset to 90 and it would correspond correctly with Phasers rotation system
/**
* This value is added to the angle of the GameObject.
* For example if you had a sprite drawn facing straight up then you could set
* rotationOffset to 90 and it would correspond correctly with Phasers rotation system
* @type {number}
*/
public rotationOffset: number = 0;
/**
* Controls if the GameObject is rendered rotated or not.
* If renderRotation is false then the object can still rotate but it will never be rendered rotated.
* @type {boolean}
*/
public renderRotation: bool = true;
// Physics properties
/**
* Whether this object will be moved by impacts with other objects or not.
* @type {boolean}
*/
public immovable: bool;
// Velocity is given in pixels per second. Therefore a velocity of
// 100 will move at a rate of 100 pixels every 1000 ms (1sec). It's not balls-on
// accurate due to the way timers work, but it's pretty close. Expect tolerance
// of +- 10 px. Also that speed assumes no drag
/**
* Basic speed of this object.
*
* Velocity is given in pixels per second. Therefore a velocity of
* 100 will move at a rate of 100 pixels every 1000 ms (1sec). It's not balls-on
* accurate due to the way timers work, but it's pretty close. Expect tolerance
* of +- 10 px. Also that speed assumes no drag.
*
* @type {MicroPoint}
*/
public velocity: MicroPoint;
/**
* The virtual mass of the object.
* @type {number}
*/
public mass: number;
/**
* The bounciness of the object.
* @type {number}
*/
public elasticity: number;
/**
* How fast the speed of this object is changing.
* @type {number}
*/
public acceleration: MicroPoint;
/**
* This isn't drag exactly, more like deceleration that is only applied
* when acceleration is not affecting the sprite.
* @type {MicroPoint}
*/
public drag: MicroPoint;
/**
* It will cap the speed automatically if you use the acceleration
* to change its velocity.
* @type {MicroPoint}
*/
public maxVelocity: MicroPoint;
/**
* How fast this object is rotating.
* @type {number}
*/
public angularVelocity: number;
/**
* How fast angularVelocity of this object is changing.
* @type {number}
*/
public angularAcceleration: number;
/**
* Deacceleration of angularVelocity will be applied when it's rotating.
* @type {number}
*/
public angularDrag: number;
/**
* It will cap the rotate speed automatically if you use the angularAcceleration
* to change its angularVelocity.
* @type {number}
*/
public maxAngular: number;
/**
* A point that can store numbers from 0 to 1 (for X and Y independently)
* which governs how much this object is affected by the camera .
* @type {MicroPoint}
*/
public scrollFactor: MicroPoint;
/**
* Handy for storing health percentage or armor points or whatever.
* @type {number}
*/
public health: number;
/**
* Set this to false if you want to skip the automatic motion/movement stuff
* (see updateMotion()).
* @type {boolean}
*/
public moves: bool = true;
/**
* Bit field of flags (use with UP, DOWN, LEFT, RIGHT, etc) indicating surface contacts.
* @type {number}
*/
public touching: number;
/**
* Bit field of flags (use with UP, DOWN, LEFT, RIGHT, etc) indicating surface contacts from the previous game loop step.
* @type {number}
*/
public wasTouching: number;
/**
* Bit field of flags (use with UP, DOWN, LEFT, RIGHT, etc) indicating collision directions.
* @type {number}
*/
public allowCollisions: number;
/**
* Important variable for collision processing.
* @type {MicroPoint}
*/
public last: MicroPoint;
// Input
@@ -127,18 +373,27 @@ module Phaser {
public onInputDown: Phaser.Signal;
public onInputUp: Phaser.Signal;
/**
* Pre-update is called right before update() on each object in the game loop.
*/
public preUpdate() {
// flicker time
this.last.x = this.frameBounds.x;
this.last.y = this.frameBounds.y;
this.last.x = this.bounds.x;
this.last.y = this.bounds.y;
this.collisionMask.preUpdate();
}
/**
* Override this function to update your class's position and appearance.
*/
public update() {
}
/**
* Automatically called after update() by the game loop.
*/
public postUpdate() {
if (this.moves)
@@ -176,6 +431,8 @@ module Phaser {
}
}
}
this.collisionMask.update();
if (this.inputEnabled)
{
@@ -187,9 +444,15 @@ module Phaser {
}
/**
* Update input.
*/
private updateInput() {
}
/**
* Internal function for updating the position and speed of this object.
*/
private updateMotion() {
var delta: number;
@@ -204,13 +467,13 @@ module Phaser {
this.velocity.x += velocityDelta;
delta = this.velocity.x * this._game.time.elapsed;
this.velocity.x += velocityDelta;
this.bounds.x += delta;
this.frameBounds.x += delta;
velocityDelta = (this._game.motion.computeVelocity(this.velocity.y, this.acceleration.y, this.drag.y, this.maxVelocity.y) - this.velocity.y) / 2;
this.velocity.y += velocityDelta;
delta = this.velocity.y * this._game.time.elapsed;
this.velocity.y += velocityDelta;
this.bounds.y += delta;
this.frameBounds.y += delta;
}
@@ -218,24 +481,24 @@ module Phaser {
* Checks to see if some <code>GameObject</code> overlaps this <code>GameObject</code> or <code>Group</code>.
* If the group has a LOT of things in it, it might be faster to use <code>Collision.overlaps()</code>.
* WARNING: Currently tilemaps do NOT support screen space overlap checks!
*
* @param ObjectOrGroup The object or group being tested.
* @param InScreenSpace Whether to take scroll factors numbero account when checking for overlap. Default is false, or "only compare in world space."
* @param Camera Specify which game camera you want. If null getScreenXY() will just grab the first global camera.
*
* @return Whether or not the two objects overlap.
*
* @param objectOrGroup {object} The object or group being tested.
* @param inScreenSpace {boolean} Whether to take scroll factors numbero account when checking for overlap. Default is false, or "only compare in world space."
* @param camera {Camera} Specify which game camera you want. If null getScreenXY() will just grab the first global camera.
*
* @return {boolean} Whether or not the objects overlap this.
*/
public overlaps(ObjectOrGroup, InScreenSpace: bool = false, Camera: Camera = null): bool {
public overlaps(objectOrGroup, inScreenSpace: bool = false, camera: Camera = null): bool {
if (ObjectOrGroup.isGroup)
if (objectOrGroup.isGroup)
{
var results: bool = false;
var i: number = 0;
var members = <Group> ObjectOrGroup.members;
var members = <Group> objectOrGroup.members;
while (i < length)
{
if (this.overlaps(members[i++], InScreenSpace, Camera))
if (this.overlaps(members[i++], inScreenSpace, camera))
{
results = true;
}
@@ -245,61 +508,50 @@ module Phaser {
}
/*
if (typeof ObjectOrGroup === 'Tilemap')
if (!inScreenSpace)
{
//Since tilemap's have to be the caller, not the target, to do proper tile-based collisions,
// we redirect the call to the tilemap overlap here.
return ObjectOrGroup.overlaps(this, InScreenSpace, Camera);
}
*/
//var object: GameObject = ObjectOrGroup;
if (!InScreenSpace)
{
return (ObjectOrGroup.x + ObjectOrGroup.width > this.x) && (ObjectOrGroup.x < this.x + this.width) &&
(ObjectOrGroup.y + ObjectOrGroup.height > this.y) && (ObjectOrGroup.y < this.y + this.height);
return (objectOrGroup.x + objectOrGroup.width > this.x) && (objectOrGroup.x < this.x + this.width) &&
(objectOrGroup.y + objectOrGroup.height > this.y) && (objectOrGroup.y < this.y + this.height);
}
if (Camera == null)
if (camera == null)
{
Camera = this._game.camera;
camera = this._game.camera;
}
var objectScreenPos: Point = ObjectOrGroup.getScreenXY(null, Camera);
var objectScreenPos: Point = objectOrGroup.getScreenXY(null, camera);
this.getScreenXY(this._point, Camera);
this.getScreenXY(this._point, camera);
return (objectScreenPos.x + ObjectOrGroup.width > this._point.x) && (objectScreenPos.x < this._point.x + this.width) &&
(objectScreenPos.y + ObjectOrGroup.height > this._point.y) && (objectScreenPos.y < this._point.y + this.height);
return (objectScreenPos.x + objectOrGroup.width > this._point.x) && (objectScreenPos.x < this._point.x + this.width) &&
(objectScreenPos.y + objectOrGroup.height > this._point.y) && (objectScreenPos.y < this._point.y + this.height);
}
/**
* Checks to see if this <code>GameObject</code> were located at the given position, would it overlap the <code>GameObject</code> or <code>Group</code>?
* This is distinct from overlapsPoint(), which just checks that point, rather than taking the object's size numbero account.
* WARNING: Currently tilemaps do NOT support screen space overlap checks!
*
* @param X The X position you want to check. Pretends this object (the caller, not the parameter) is located here.
* @param Y The Y position you want to check. Pretends this object (the caller, not the parameter) is located here.
* @param ObjectOrGroup The object or group being tested.
* @param InScreenSpace Whether to take scroll factors numbero account when checking for overlap. Default is false, or "only compare in world space."
* @param Camera Specify which game camera you want. If null getScreenXY() will just grab the first global camera.
*
* @return Whether or not the two objects overlap.
*
* @param X {number} The X position you want to check. Pretends this object (the caller, not the parameter) is located here.
* @param Y {number} The Y position you want to check. Pretends this object (the caller, not the parameter) is located here.
* @param objectOrGroup {object} The object or group being tested.
* @param inScreenSpace {boolean} Whether to take scroll factors numbero account when checking for overlap. Default is false, or "only compare in world space."
* @param camera {Camera} Specify which game camera you want. If null getScreenXY() will just grab the first global camera.
*
* @return {boolean} Whether or not the two objects overlap.
*/
public overlapsAt(X: number, Y: number, ObjectOrGroup, InScreenSpace: bool = false, Camera: Camera = null): bool {
public overlapsAt(X: number, Y: number, objectOrGroup, inScreenSpace: bool = false, camera: Camera = null): bool {
if (ObjectOrGroup.isGroup)
if (objectOrGroup.isGroup)
{
var results: bool = false;
var basic;
var i: number = 0;
var members = ObjectOrGroup.members;
var members = objectOrGroup.members;
while (i < length)
{
if (this.overlapsAt(X, Y, members[i++], InScreenSpace, Camera))
if (this.overlapsAt(X, Y, members[i++], inScreenSpace, camera))
{
results = true;
}
@@ -308,67 +560,53 @@ module Phaser {
return results;
}
/*
if (typeof ObjectOrGroup === 'Tilemap')
if (!inScreenSpace)
{
//Since tilemap's have to be the caller, not the target, to do proper tile-based collisions,
// we redirect the call to the tilemap overlap here.
//However, since this is overlapsAt(), we also have to invent the appropriate position for the tilemap.
//So we calculate the offset between the player and the requested position, and subtract that from the tilemap.
var tilemap: Tilemap = ObjectOrGroup;
return tilemap.overlapsAt(tilemap.x - (X - this.x), tilemap.y - (Y - this.y), this, InScreenSpace, Camera);
}
*/
//var object: GameObject = ObjectOrGroup;
if (!InScreenSpace)
{
return (ObjectOrGroup.x + ObjectOrGroup.width > X) && (ObjectOrGroup.x < X + this.width) &&
(ObjectOrGroup.y + ObjectOrGroup.height > Y) && (ObjectOrGroup.y < Y + this.height);
return (objectOrGroup.x + objectOrGroup.width > X) && (objectOrGroup.x < X + this.width) &&
(objectOrGroup.y + objectOrGroup.height > Y) && (objectOrGroup.y < Y + this.height);
}
if (Camera == null)
if (camera == null)
{
Camera = this._game.camera;
camera = this._game.camera;
}
var objectScreenPos: Point = ObjectOrGroup.getScreenXY(null, Camera);
var objectScreenPos: Point = objectOrGroup.getScreenXY(null, Camera);
this._point.x = X - Camera.scroll.x * this.scrollFactor.x; //copied from getScreenXY()
this._point.y = Y - Camera.scroll.y * this.scrollFactor.y;
this._point.x = X - camera.scroll.x * this.scrollFactor.x; //copied from getScreenXY()
this._point.y = Y - camera.scroll.y * this.scrollFactor.y;
this._point.x += (this._point.x > 0) ? 0.0000001 : -0.0000001;
this._point.y += (this._point.y > 0) ? 0.0000001 : -0.0000001;
return (objectScreenPos.x + ObjectOrGroup.width > this._point.x) && (objectScreenPos.x < this._point.x + this.width) &&
(objectScreenPos.y + ObjectOrGroup.height > this._point.y) && (objectScreenPos.y < this._point.y + this.height);
return (objectScreenPos.x + objectOrGroup.width > this._point.x) && (objectScreenPos.x < this._point.x + this.width) &&
(objectScreenPos.y + objectOrGroup.height > this._point.y) && (objectScreenPos.y < this._point.y + this.height);
}
/**
* Checks to see if a point in 2D world space overlaps this <code>GameObject</code>.
*
* @param Point The point in world space you want to check.
* @param InScreenSpace Whether to take scroll factors numbero account when checking for overlap.
* @param Camera Specify which game camera you want. If null getScreenXY() will just grab the first global camera.
*
* @return Whether or not the point overlaps this object.
*
* @param point {Point} The point in world space you want to check.
* @param inScreenSpace {boolean} Whether to take scroll factors into account when checking for overlap.
* @param camera {Camera} Specify which game camera you want. If null getScreenXY() will just grab the first global camera.
*
* @return Whether or not the point overlaps this object.
*/
public overlapsPoint(point: Point, InScreenSpace: bool = false, Camera: Camera = null): bool {
public overlapsPoint(point: Point, inScreenSpace: bool = false, camera: Camera = null): bool {
if (!InScreenSpace)
if (!inScreenSpace)
{
return (point.x > this.x) && (point.x < this.x + this.width) && (point.y > this.y) && (point.y < this.y + this.height);
}
if (Camera == null)
if (camera == null)
{
Camera = this._game.camera;
camera = this._game.camera;
}
var X: number = point.x - Camera.scroll.x;
var Y: number = point.y - Camera.scroll.y;
var X: number = point.x - camera.scroll.x;
var Y: number = point.y - camera.scroll.y;
this.getScreenXY(this._point, Camera);
this.getScreenXY(this._point, camera);
return (X > this._point.x) && (X < this._point.x + this.width) && (Y > this._point.y) && (Y < this._point.y + this.height);
@@ -376,46 +614,46 @@ module Phaser {
/**
* Check and see if this object is currently on screen.
*
* @param Camera Specify which game camera you want. If null getScreenXY() will just grab the first global camera.
*
* @return Whether the object is on screen or not.
*
* @param camera {Camera} Specify which game camera you want. If null getScreenXY() will just grab the first global camera.
*
* @return {boolean} Whether the object is on screen or not.
*/
public onScreen(Camera: Camera = null): bool {
public onScreen(camera: Camera = null): bool {
if (Camera == null)
if (camera == null)
{
Camera = this._game.camera;
camera = this._game.camera;
}
this.getScreenXY(this._point, Camera);
this.getScreenXY(this._point, camera);
return (this._point.x + this.width > 0) && (this._point.x < Camera.width) && (this._point.y + this.height > 0) && (this._point.y < Camera.height);
return (this._point.x + this.width > 0) && (this._point.x < camera.width) && (this._point.y + this.height > 0) && (this._point.y < camera.height);
}
/**
* Call this to figure out the on-screen position of the object.
*
* @param Camera Specify which game camera you want. If null getScreenXY() will just grab the first global camera.
* @param Point Takes a <code>MicroPoint</code> object and assigns the post-scrolled X and Y values of this object to it.
*
* @return The <code>MicroPoint</code> you passed in, or a new <code>Point</code> if you didn't pass one, containing the screen X and Y position of this object.
*
* @param point {Point} Takes a <code>MicroPoint</code> object and assigns the post-scrolled X and Y values of this object to it.
* @param camera {Camera} Specify which game camera you want. If null getScreenXY() will just grab the first global camera.
*
* @return {MicroPoint} The <code>MicroPoint</code> you passed in, or a new <code>Point</code> if you didn't pass one, containing the screen X and Y position of this object.
*/
public getScreenXY(point: MicroPoint = null, Camera: Camera = null): MicroPoint {
public getScreenXY(point: MicroPoint = null, camera: Camera = null): MicroPoint {
if (point == null)
{
point = new MicroPoint();
}
if (Camera == null)
if (camera == null)
{
Camera = this._game.camera;
camera = this._game.camera;
}
point.x = this.x - Camera.scroll.x * this.scrollFactor.x;
point.y = this.y - Camera.scroll.y * this.scrollFactor.y;
point.x = this.x - camera.scroll.x * this.scrollFactor.x;
point.y = this.y - camera.scroll.y * this.scrollFactor.y;
point.x += (point.x > 0) ? 0.0000001 : -0.0000001;
point.y += (point.y > 0) ? 0.0000001 : -0.0000001;
@@ -432,12 +670,9 @@ module Phaser {
return (this.allowCollisions & Collision.ANY) > Collision.NONE;
}
/**
* @private
*/
public set solid(Solid: bool) {
public set solid(value: bool) {
if (Solid)
if (value)
{
this.allowCollisions = Collision.ANY;
}
@@ -450,10 +685,10 @@ module Phaser {
/**
* Retrieve the midpoint of this object in world coordinates.
*
* @Point Allows you to pass in an existing <code>Point</code> object if you're so inclined. Otherwise a new one is created.
*
* @return A <code>Point</code> object containing the midpoint of this object in world coordinates.
*
* @param point {Point} Allows you to pass in an existing <code>Point</code> object if you're so inclined. Otherwise a new one is created.
*
* @return {MicroPoint} A <code>Point</code> object containing the midpoint of this object in world coordinates.
*/
public getMidpoint(point: MicroPoint = null): MicroPoint {
@@ -462,7 +697,7 @@ module Phaser {
point = new MicroPoint();
}
point.copyFrom(this.bounds.center);
point.copyFrom(this.frameBounds.center);
return point;
@@ -471,19 +706,19 @@ module Phaser {
/**
* Handy for reviving game objects.
* Resets their existence flags and position.
*
* @param X The new X position of this object.
* @param Y The new Y position of this object.
*
* @param x {number} The new X position of this object.
* @param y {number} The new Y position of this object.
*/
public reset(X: number, Y: number) {
public reset(x: number, y: number) {
this.revive();
this.touching = Collision.NONE;
this.wasTouching = Collision.NONE;
this.x = X;
this.y = Y;
this.last.x = X;
this.last.y = Y;
this.x = x;
this.y = y;
this.last.x = x;
this.last.y = y;
this.velocity.x = 0;
this.velocity.y = 0;
@@ -491,37 +726,37 @@ module Phaser {
/**
* Handy for checking if this object is touching a particular surface.
* For slightly better performance you can just &amp; the value directly numbero <code>touching</code>.
* For slightly better performance you can just &amp; the value directly into <code>touching</code>.
* However, this method is good for readability and accessibility.
*
* @param Direction Any of the collision flags (e.g. LEFT, FLOOR, etc).
*
* @return Whether the object is touching an object in (any of) the specified direction(s) this frame.
*
* @param Direction {number} Any of the collision flags (e.g. LEFT, FLOOR, etc).
*
* @return {boolean} Whether the object is touching an object in (any of) the specified direction(s) this frame.
*/
public isTouching(Direction: number): bool {
return (this.touching & Direction) > Collision.NONE;
public isTouching(direction: number): bool {
return (this.touching & direction) > Collision.NONE;
}
/**
* Handy for checking if this object is just landed on a particular surface.
*
* @param Direction Any of the collision flags (e.g. LEFT, FLOOR, etc).
*
* @return Whether the object just landed on (any of) the specified surface(s) this frame.
* Handy function for checking if this object just landed on a particular surface.
*
* @param Direction {number} Any of the collision flags (e.g. LEFT, FLOOR, etc).
*
* @returns {boolean} Whether the object just landed on any specicied surfaces.
*/
public justTouched(Direction: number): bool {
return ((this.touching & Direction) > Collision.NONE) && ((this.wasTouching & Direction) <= Collision.NONE);
public justTouched(direction: number): bool {
return ((this.touching & direction) > Collision.NONE) && ((this.wasTouching & direction) <= Collision.NONE);
}
/**
* Reduces the "health" variable of this sprite by the amount specified in Damage.
* Calls kill() if health drops to or below zero.
*
* @param Damage How much health to take away (use a negative number to give a health bonus).
*
* @param Damage {number} How much health to take away (use a negative number to give a health bonus).
*/
public hurt(Damage: number) {
public hurt(damage: number) {
this.health = this.health - Damage;
this.health = this.health - damage;
if (this.health <= 0)
{
@@ -534,6 +769,11 @@ module Phaser {
* Set the world bounds that this GameObject can exist within. By default a GameObject can exist anywhere
* in the world. But by setting the bounds (which are given in world dimensions, not screen dimensions)
* it can be stopped from leaving the world, or a section of it.
*
* @param x {number} x position of the bound
* @param y {number} y position of the bound
* @param width {number} width of its bound
* @param height {number} height of its bound
*/
public setBounds(x: number, y: number, width: number, height: number) {
@@ -541,8 +781,22 @@ module Phaser {
}
/**
* Set the world bounds that this GameObject can exist within based on the size of the current game world.
*
* @param action {number} The action to take if the object hits the world bounds, either OUT_OF_BOUNDS_KILL or OUT_OF_BOUNDS_STOP
*/
public setBoundsFromWorld(action?: number = GameObject.OUT_OF_BOUNDS_STOP) {
this.setBounds(this._game.world.bounds.x, this._game.world.bounds.y, this._game.world.bounds.width, this._game.world.bounds.height);
this.outOfBoundsAction = action;
}
/**
* If you do not wish this object to be visible to a specific camera, pass the camera here.
*
* @param camera {Camera} The specific camera.
*/
public hideFromCamera(camera: Camera) {
@@ -553,6 +807,12 @@ module Phaser {
}
/**
* Make this object only visible to a specific camera.
*
* @param camera {Camera} The camera you wish it to be visible.
*/
public showToCamera(camera: Camera) {
if (this.cameraBlacklist.indexOf(camera.ID) !== -1)
@@ -562,30 +822,42 @@ module Phaser {
}
/**
* This clears the camera black list, making the GameObject visible to all cameras.
*/
public clearCameraList() {
this.cameraBlacklist.length = 0;
}
/**
* Clean up memory.
*/
public destroy() {
}
public setPosition(x: number, y: number) {
this.x = x;
this.y = y;
}
public get x(): number {
return this.bounds.x;
return this.frameBounds.x;
}
public set x(value: number) {
this.bounds.x = value;
this.frameBounds.x = value;
}
public get y(): number {
return this.bounds.y;
return this.frameBounds.y;
}
public set y(value: number) {
this.bounds.y = value;
this.frameBounds.y = value;
}
public get rotation(): number {
@@ -605,19 +877,19 @@ module Phaser {
}
public set width(value:number) {
this.bounds.width = value;
this.frameBounds.width = value;
}
public set height(value:number) {
this.bounds.height = value;
this.frameBounds.height = value;
}
public get width(): number {
return this.bounds.width;
return this.frameBounds.width;
}
public get height(): number {
return this.bounds.height;
return this.frameBounds.height;
}
}
+40
View File
@@ -0,0 +1,40 @@
/// <reference path="../Game.d.ts" />
module Phaser {
class GeomSprite extends GameObject {
constructor(game: Game, x?: number, y?: number);
private _dx;
private _dy;
private _dw;
private _dh;
public type: number;
static UNASSIGNED: number;
static CIRCLE: number;
static LINE: number;
static POINT: number;
static RECTANGLE: number;
public circle: Circle;
public line: Line;
public point: Point;
public rect: Rectangle;
public renderOutline: bool;
public renderFill: bool;
public lineWidth: number;
public lineColor: string;
public fillColor: string;
public loadCircle(circle: Circle): GeomSprite;
public loadLine(line: Line): GeomSprite;
public loadPoint(point: Point): GeomSprite;
public loadRectangle(rect: Rectangle): GeomSprite;
public createCircle(diameter: number): GeomSprite;
public createLine(x: number, y: number): GeomSprite;
public createPoint(): GeomSprite;
public createRectangle(width: number, height: number): GeomSprite;
public refresh(): void;
public update(): void;
public inCamera(camera: Rectangle): bool;
public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number): bool;
public renderPoint(offsetX, offsetY, point, size): void;
public renderDebugInfo(x: number, y: number, color?: string): void;
public collide(source: GeomSprite): bool;
}
}
+262 -77
View File
@@ -1,4 +1,5 @@
/// <reference path="../Game.ts" />
/// <reference path="../geom/Polygon.ts" />
/**
* Phaser - GeomSprite
@@ -12,6 +13,14 @@ module Phaser {
export class GeomSprite extends GameObject {
/**
* GeomSprite constructor
* Create a new <code>GeomSprite</code>.
*
* @param game {Phaser.Game} Current game instance.
* @param [x] {number} the initial x position of the sprite.
* @param [y] {number} the initial y position of the sprite.
*/
constructor(game: Game, x?: number = 0, y?: number = 0) {
super(game, x, y);
@@ -28,26 +37,112 @@ module Phaser {
private _dw: number = 0;
private _dh: number = 0;
/**
* Geom type of this sprite. (available: UNASSIGNED, CIRCLE, LINE, POINT, RECTANGLE)
* @type {number}
*/
public type: number = 0;
/**
* Not completely set yet. (the default type)
*/
public static UNASSIGNED: number = 0;
/**
* Circle.
* @type {number}
*/
public static CIRCLE: number = 1;
/**
* Line.
* @type {number}
*/
public static LINE: number = 2;
/**
* Point.
* @type {number}
*/
public static POINT: number = 3;
/**
* Rectangle.
* @type {number}
*/
public static RECTANGLE: number = 4;
/**
* Polygon.
* @type {number}
*/
public static POLYGON: number = 5;
/**
* Circle shape container. A Circle instance.
* @type {Circle}
*/
public circle: Circle;
/**
* Line shape container. A Line instance.
* @type {Line}
*/
public line: Line;
/**
* Point shape container. A Point instance.
* @type {Point}
*/
public point: Point;
/**
* Rectangle shape container. A Rectangle instance.
* @type {Rectangle}
*/
public rect: Rectangle;
/**
* Polygon shape container. A Polygon instance.
* @type {Polygon}
*/
public polygon: Polygon;
/**
* Render outline of this sprite or not. (default is true)
* @type {boolean}
*/
public renderOutline: bool = true;
/**
* Fill the shape or not. (default is true)
* @type {boolean}
*/
public renderFill: bool = true;
/**
* Width of outline. (default is 1)
* @type {number}
*/
public lineWidth: number = 1;
/**
* Width of outline. (default is 1)
* @type {number}
*/
public lineColor: string = 'rgb(0,255,0)';
/**
* The color of the filled area in rgb or rgba string format
* @type {string} Defaults to rgb(0,100,0) - a green color
*/
public fillColor: string = 'rgb(0,100,0)';
/**
* Just like Sprite.loadGraphic(), this will load a circle and set its shape to Circle.
* @param circle {Circle} Circle geometry define.
* @return {GeomSprite} GeomSprite instance itself.
*/
loadCircle(circle:Circle): GeomSprite {
this.refresh();
@@ -57,7 +152,11 @@ module Phaser {
}
/**
* Just like Sprite.loadGraphic(), this will load a line and set its shape to Line.
* @param line {Line} Line geometry define.
* @return {GeomSprite} GeomSprite instance itself.
*/
loadLine(line:Line): GeomSprite {
this.refresh();
@@ -67,6 +166,11 @@ module Phaser {
}
/**
* Just like Sprite.loadGraphic(), this will load a point and set its shape to Point.
* @param point {Point} Point geometry define.
* @return {GeomSprite} GeomSprite instance itself.
*/
loadPoint(point:Point): GeomSprite {
this.refresh();
@@ -76,6 +180,11 @@ module Phaser {
}
/**
* Just like Sprite.loadGraphic(), this will load a rect and set its shape to Rectangle.
* @param rect {Rectangle} Rectangle geometry define.
* @return {GeomSprite} GeomSprite instance itself.
*/
loadRectangle(rect:Rectangle): GeomSprite {
this.refresh();
@@ -85,47 +194,87 @@ module Phaser {
}
/**
* Create a circle shape with specific diameter.
* @param diameter {number} Diameter of the circle.
* @return {GeomSprite} GeomSprite instance itself.
*/
createCircle(diameter: number): GeomSprite {
this.refresh();
this.circle = new Circle(this.x, this.y, diameter);
this.type = GeomSprite.CIRCLE;
this.bounds.setTo(this.circle.x - this.circle.radius, this.circle.y - this.circle.radius, this.circle.diameter, this.circle.diameter);
this.frameBounds.setTo(this.circle.x - this.circle.radius, this.circle.y - this.circle.radius, this.circle.diameter, this.circle.diameter);
return this;
}
/**
* Create a line shape with specific end point.
* @param x {number} X position of the end point.
* @param y {number} Y position of the end point.
* @return {GeomSprite} GeomSprite instance itself.
*/
createLine(x: number, y: number): GeomSprite {
this.refresh();
this.line = new Line(this.x, this.y, x, y);
this.type = GeomSprite.LINE;
this.bounds.setTo(this.x, this.y, this.line.width, this.line.height);
this.frameBounds.setTo(this.x, this.y, this.line.width, this.line.height);
return this;
}
/**
* Create a point shape at spriter's position.
* @return {GeomSprite} GeomSprite instance itself.
*/
createPoint(): GeomSprite {
this.refresh();
this.point = new Point(this.x, this.y);
this.type = GeomSprite.POINT;
this.bounds.width = 1;
this.bounds.height = 1;
this.frameBounds.width = 1;
this.frameBounds.height = 1;
return this;
}
/**
* Create a rectangle shape of the given width and height size
* @param width {Number} Width of the rectangle
* @param height {Number} Height of the rectangle
* @return {GeomSprite} GeomSprite instance.
*/
createRectangle(width: number, height: number): GeomSprite {
this.refresh();
this.rect = new Rectangle(this.x, this.y, width, height);
this.type = GeomSprite.RECTANGLE;
this.bounds.copyFrom(this.rect);
this.frameBounds.copyFrom(this.rect);
return this;
}
/**
* Create a polygon object
* @param width {Number} Width of the rectangle
* @param height {Number} Height of the rectangle
* @return {GeomSprite} GeomSprite instance.
*/
createPolygon(points?: Vector2[] = []): GeomSprite {
this.refresh();
this.polygon = new Polygon(new Vector2(this.x, this.y), points);
this.type = GeomSprite.POLYGON;
//this.frameBounds.copyFrom(this.rect);
return this;
}
/**
* Destroy all geom shapes of this sprite.
*/
refresh() {
this.circle = null;
@@ -135,6 +284,9 @@ module Phaser {
}
/**
* Update bounds.
*/
update() {
// Update bounds and position?
@@ -146,14 +298,14 @@ module Phaser {
{
this.circle.x = this.x;
this.circle.y = this.y;
this.bounds.width = this.circle.diameter;
this.bounds.height = this.circle.diameter;
this.frameBounds.width = this.circle.diameter;
this.frameBounds.height = this.circle.diameter;
}
else if (this.type == GeomSprite.LINE)
{
this.line.x1 = this.x;
this.line.y1 = this.y;
this.bounds.setTo(this.x, this.y, this.line.width, this.line.height);
this.frameBounds.setTo(this.x, this.y, this.line.width, this.line.height);
}
else if (this.type == GeomSprite.POINT)
{
@@ -164,29 +316,41 @@ module Phaser {
{
this.rect.x = this.x;
this.rect.y = this.y;
this.bounds.copyFrom(this.rect);
this.frameBounds.copyFrom(this.rect);
}
}
/**
* Check whether this object is visible in a specific camera rectangle.
* @param camera {Rectangle} The rectangle you want to check.
* @return {boolean} Return true if bounds of this sprite intersects the given rectangle, otherwise return false.
*/
public inCamera(camera: Rectangle): bool {
if (this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0)
{
this._dx = this.bounds.x - (camera.x * this.scrollFactor.x);
this._dy = this.bounds.y - (camera.y * this.scrollFactor.x);
this._dw = this.bounds.width * this.scale.x;
this._dh = this.bounds.height * this.scale.y;
this._dx = this.frameBounds.x - (camera.x * this.scrollFactor.x);
this._dy = this.frameBounds.y - (camera.y * this.scrollFactor.x);
this._dw = this.frameBounds.width * this.scale.x;
this._dh = this.frameBounds.height * this.scale.y;
return (camera.right > this._dx) && (camera.x < this._dx + this._dw) && (camera.bottom > this._dy) && (camera.y < this._dy + this._dh);
}
else
{
return camera.intersects(this.bounds);
return camera.intersects(this.frameBounds);
}
}
/**
* Render this sprite to specific camera. Called by game loop after update().
* @param camera {Camera} Camera this sprite will be rendered to.
* @cameraOffsetX {number} X offset to the camera.
* @cameraOffsetY {number} Y offset to the camera.
* @return {boolean} Return false if not rendered, otherwise return true.
*/
public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number): bool {
// Render checks
@@ -198,21 +362,14 @@ module Phaser {
// Alpha
if (this.alpha !== 1)
{
var globalAlpha = this._game.stage.context.globalAlpha;
this._game.stage.context.globalAlpha = this.alpha;
var globalAlpha = this.context.globalAlpha;
this.context.globalAlpha = this.alpha;
}
this._dx = cameraOffsetX + (this.bounds.x - camera.worldView.x);
this._dy = cameraOffsetY + (this.bounds.y - camera.worldView.y);
this._dw = this.bounds.width * this.scale.x;
this._dh = this.bounds.height * this.scale.y;
// Circles are drawn center based
if (this.type == GeomSprite.CIRCLE)
{
this._dx += this.circle.radius;
this._dy += this.circle.radius;
}
this._dx = cameraOffsetX + (this.frameBounds.x - camera.worldView.x);
this._dy = cameraOffsetY + (this.frameBounds.y - camera.worldView.y);
this._dw = this.frameBounds.width * this.scale.x;
this._dh = this.frameBounds.height * this.scale.y;
// Apply camera difference
if (this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0)
@@ -225,9 +382,9 @@ module Phaser {
/*
if (this.angle !== 0)
{
this._game.stage.context.save();
this._game.stage.context.translate(this._dx + (this._dw / 2) - this.origin.x, this._dy + (this._dh / 2) - this.origin.y);
this._game.stage.context.rotate(this.angle * (Math.PI / 180));
this.context.save();
this.context.translate(this._dx + (this._dw / 2) - this.origin.x, this._dy + (this._dh / 2) - this.origin.y);
this.context.rotate(this.angle * (Math.PI / 180));
this._dx = -(this._dw / 2);
this._dy = -(this._dh / 2);
}
@@ -241,12 +398,12 @@ module Phaser {
this._game.stage.saveCanvasValues();
// Debug
//this._game.stage.context.fillStyle = 'rgba(255,0,0,0.5)';
//this._game.stage.context.fillRect(this.bounds.x, this.bounds.y, this.bounds.width, this.bounds.height);
//this.context.fillStyle = 'rgba(255,0,0,0.5)';
//this.context.fillRect(this.frameBounds.x, this.frameBounds.y, this.frameBounds.width, this.frameBounds.height);
this._game.stage.context.lineWidth = this.lineWidth;
this._game.stage.context.strokeStyle = this.lineColor;
this._game.stage.context.fillStyle = this.fillColor;
this.context.lineWidth = this.lineWidth;
this.context.strokeStyle = this.lineColor;
this.context.fillStyle = this.fillColor;
if (this._game.stage.fillStyle !== this.fillColor)
{
@@ -255,61 +412,74 @@ module Phaser {
// Primitive Renderer
if (this.type == GeomSprite.CIRCLE)
{
this._game.stage.context.beginPath();
this._game.stage.context.arc(this._dx, this._dy, this.circle.radius, 0, Math.PI * 2);
this._game.stage.context.stroke();
this.context.beginPath();
this.context.arc(this._dx, this._dy, this.circle.radius, 0, Math.PI * 2);
if (this.renderOutline)
{
this.context.stroke();
}
if (this.renderFill)
{
this._game.stage.context.fill();
this.context.fill();
}
this._game.stage.context.closePath();
this.context.closePath();
}
else if (this.type == GeomSprite.LINE)
{
this._game.stage.context.beginPath();
this._game.stage.context.moveTo(this._dx, this._dy);
this._game.stage.context.lineTo(this.line.x2, this.line.y2);
this._game.stage.context.stroke();
this._game.stage.context.closePath();
this.context.beginPath();
this.context.moveTo(this._dx, this._dy);
this.context.lineTo(this.line.x2, this.line.y2);
this.context.stroke();
this.context.closePath();
}
else if (this.type == GeomSprite.POINT)
{
this._game.stage.context.fillRect(this._dx, this._dy, 2, 2);
this.context.fillRect(this._dx, this._dy, 2, 2);
}
else if (this.type == GeomSprite.RECTANGLE)
{
// We can use the faster fillRect if we don't need the outline
if (this.renderOutline == false)
{
this._game.stage.context.fillRect(this._dx, this._dy, this.rect.width, this.rect.height);
this.context.fillRect(this._dx, this._dy, this.rect.width, this.rect.height);
}
else
{
this._game.stage.context.beginPath();
this._game.stage.context.rect(this._dx, this._dy, this.rect.width, this.rect.height);
this._game.stage.context.stroke();
this.context.beginPath();
this.context.rect(this._dx, this._dy, this.rect.width, this.rect.height);
this.context.stroke();
if (this.renderFill)
{
this._game.stage.context.fill();
this.context.fill();
}
this._game.stage.context.closePath();
this.context.closePath();
}
// And now the edge points
this._game.stage.context.fillStyle = 'rgb(255,255,255)';
this.renderPoint(this._dx, this._dy, this.rect.topLeft, 2);
this.renderPoint(this._dx, this._dy, this.rect.topCenter, 2);
this.renderPoint(this._dx, this._dy, this.rect.topRight, 2);
this.renderPoint(this._dx, this._dy, this.rect.leftCenter, 2);
this.renderPoint(this._dx, this._dy, this.rect.center, 2);
this.renderPoint(this._dx, this._dy, this.rect.rightCenter, 2);
this.renderPoint(this._dx, this._dy, this.rect.bottomLeft, 2);
this.renderPoint(this._dx, this._dy, this.rect.bottomCenter, 2);
this.renderPoint(this._dx, this._dy, this.rect.bottomRight, 2);
this.context.fillStyle = 'rgb(255,255,255)';
//this.renderPoint(this.rect.topLeft, this._dx, this._dy, 2);
//this.renderPoint(this.rect.topCenter, this._dx, this._dy, 2);
//this.renderPoint(this.rect.topRight, this._dx, this._dy, 2);
//this.renderPoint(this.rect.leftCenter, this._dx, this._dy, 2);
//this.renderPoint(this.rect.center, this._dx, this._dy, 2);
//this.renderPoint(this.rect.rightCenter, this._dx, this._dy, 2);
//this.renderPoint(this.rect.bottomLeft, this._dx, this._dy, 2);
//this.renderPoint(this.rect.bottomCenter, this._dx, this._dy, 2);
//this.renderPoint(this.rect.bottomRight, this._dx, this._dy, 2);
this.renderPoint(this.rect.topLeft, 0, 0, 2);
this.renderPoint(this.rect.topCenter, 0, 0, 2);
this.renderPoint(this.rect.topRight, 0, 0, 2);
this.renderPoint(this.rect.leftCenter, 0, 0, 2);
this.renderPoint(this.rect.center, 0, 0, 2);
this.renderPoint(this.rect.rightCenter, 0, 0, 2);
this.renderPoint(this.rect.bottomLeft, 0, 0, 2);
this.renderPoint(this.rect.bottomCenter, 0, 0, 2);
this.renderPoint(this.rect.bottomRight, 0, 0, 2);
}
@@ -317,39 +487,54 @@ module Phaser {
if (this.rotation !== 0)
{
this._game.stage.context.translate(0, 0);
this._game.stage.context.restore();
this.context.translate(0, 0);
this.context.restore();
}
if (globalAlpha > -1)
{
this._game.stage.context.globalAlpha = globalAlpha;
this.context.globalAlpha = globalAlpha;
}
return true;
}
public renderPoint(offsetX, offsetY, point, size) {
/**
* Render a point of geometry.
* @param point {Point} Position of the point.
* @param offsetX {number} X offset to its position.
* @param offsetY {number} Y offset to its position.
* @param [size] {number} point size.
*/
public renderPoint(point, offsetX?: number = 0, offsetY?: number = 0, size?: number = 1) {
offsetX = 0;
offsetY = 0;
this._game.stage.context.fillRect(offsetX + point.x, offsetY + point.y, 1, 1);
this.context.fillRect(offsetX + point.x, offsetY + point.y, size, size);
}
/**
* Render debug infos. (this method does not work now)
* @param x {number} X position of the debug info to be rendered.
* @param y {number} Y position of the debug info to be rendered.
* @param [color] {number} color of the debug info to be rendered. (format is css color string)
*/
public renderDebugInfo(x: number, y: number, color?: string = 'rgb(255,255,255)') {
//this._game.stage.context.fillStyle = color;
//this._game.stage.context.fillText('Sprite: ' + this.name + ' (' + this.bounds.width + ' x ' + this.bounds.height + ')', x, y);
//this._game.stage.context.fillText('x: ' + this.bounds.x.toFixed(1) + ' y: ' + this.bounds.y.toFixed(1) + ' rotation: ' + this.angle.toFixed(1), x, y + 14);
//this._game.stage.context.fillText('dx: ' + this._dx.toFixed(1) + ' dy: ' + this._dy.toFixed(1) + ' dw: ' + this._dw.toFixed(1) + ' dh: ' + this._dh.toFixed(1), x, y + 28);
//this._game.stage.context.fillText('sx: ' + this._sx.toFixed(1) + ' sy: ' + this._sy.toFixed(1) + ' sw: ' + this._sw.toFixed(1) + ' sh: ' + this._sh.toFixed(1), x, y + 42);
//this.context.fillStyle = color;
//this.context.fillText('Sprite: ' + this.name + ' (' + this.frameBounds.width + ' x ' + this.frameBounds.height + ')', x, y);
//this.context.fillText('x: ' + this.frameBounds.x.toFixed(1) + ' y: ' + this.frameBounds.y.toFixed(1) + ' rotation: ' + this.angle.toFixed(1), x, y + 14);
//this.context.fillText('dx: ' + this._dx.toFixed(1) + ' dy: ' + this._dy.toFixed(1) + ' dw: ' + this._dw.toFixed(1) + ' dh: ' + this._dh.toFixed(1), x, y + 28);
//this.context.fillText('sx: ' + this._sx.toFixed(1) + ' sy: ' + this._sy.toFixed(1) + ' sw: ' + this._sw.toFixed(1) + ' sh: ' + this._sh.toFixed(1), x, y + 42);
}
// Gives a basic boolean response to a geometric collision.
// If you need the details of the collision use the Collision functions instead and inspect the IntersectResult object.
/**
* Gives a basic boolean response to a geometric collision.
* If you need the details of the collision use the Collision functions instead and inspect the IntersectResult object.
* @param source {GeomSprite} Sprite you want to check.
* @return {boolean} Whether they overlaps or not.
*/
public collide(source: GeomSprite): bool {
// Circle vs. Circle
+11
View File
@@ -0,0 +1,11 @@
/// <reference path="../Game.d.ts" />
/// <reference path="Sprite.d.ts" />
module Phaser {
class Particle extends Sprite {
constructor(game: Game);
public lifespan: number;
public friction: number;
public update(): void;
public onEmit(): void;
}
}
+2
View File
@@ -22,6 +22,7 @@ module Phaser {
this.lifespan = 0;
this.friction = 500;
}
/**
@@ -43,6 +44,7 @@ module Phaser {
* be dead yet, and then has some special bounce behavior if there is some gravity on it.
*/
public update() {
//lifespan behavior
if (this.lifespan <= 0)
{
+22
View File
@@ -0,0 +1,22 @@
/// <reference path="../Game.d.ts" />
/// <reference path="../geom/Quad.d.ts" />
module Phaser {
class ScrollRegion {
constructor(x: number, y: number, width: number, height: number, speedX: number, speedY: number);
private _A;
private _B;
private _C;
private _D;
private _bounds;
private _scroll;
private _anchorWidth;
private _anchorHeight;
private _inverseWidth;
private _inverseHeight;
public visible: bool;
public scrollSpeed: MicroPoint;
public update(delta: number): void;
public render(context: CanvasRenderingContext2D, texture, dx: number, dy: number, dw: number, dh: number): void;
private crop(context, texture, srcX, srcY, srcW, srcH, destX, destY, destW, destH, offsetX, offsetY);
}
}
+49 -1
View File
@@ -10,8 +10,19 @@
module Phaser {
export class ScrollRegion{
export class ScrollRegion {
/**
* ScrollRegion constructor
* Create a new <code>ScrollRegion</code>.
*
* @param x {number} X position in world coordinate.
* @param y {number} Y position in world coordinate.
* @param width {number} Width of this object.
* @param height {number} Height of this object.
* @param speedX {number} X-axis scrolling speed.
* @param speedY {number} Y-axis scrolling speed.
*/
constructor(x: number, y: number, width: number, height: number, speedX:number, speedY:number) {
// Our seamless scrolling quads
@@ -38,9 +49,22 @@ module Phaser {
private _inverseWidth: number = 0;
private _inverseHeight: number = 0;
/**
* Will this region be rendered? (default to true)
* @type {boolean}
*/
public visible: bool = true;
/**
* Region scrolling speed.
* @type {MicroPoint}
*/
public scrollSpeed: MicroPoint;
/**
* Update region scrolling with tick time.
* @param delta {number} Elapsed time since last update.
*/
public update(delta: number) {
this._scroll.x += this.scrollSpeed.x;
@@ -102,6 +126,15 @@ module Phaser {
}
/**
* Render this region to specific context.
* @param context {CanvasRenderingContext2D} Canvas context this region will be rendered to.
* @param texture {object} The texture to be rendered.
* @param dx {number} X position in world coordinate.
* @param dy {number} Y position in world coordinate.
* @param width {number} Width of this region to be rendered.
* @param height {number} Height of this region to be rendered.
*/
public render(context:CanvasRenderingContext2D, texture, dx: number, dy: number, dw: number, dh: number) {
if (this.visible == false)
@@ -126,6 +159,21 @@ module Phaser {
}
/**
* Crop part of the texture and render it to the given context.
* @param context {CanvasRenderingContext2D} Canvas context the texture will be rendered to.
* @param texture {object} Texture to be rendered.
* @param srcX {number} Target region top-left x coordinate in the texture.
* @param srcX {number} Target region top-left y coordinate in the texture.
* @param srcW {number} Target region width in the texture.
* @param srcH {number} Target region height in the texture.
* @param destX {number} Render region top-left x coordinate in the context.
* @param destX {number} Render region top-left y coordinate in the context.
* @param destW {number} Target region width in the context.
* @param destH {number} Target region height in the context.
* @param offsetX {number} X offset to the context.
* @param offsetY {number} Y offset to the context.
*/
private crop(context, texture, srcX, srcY, srcW, srcH, destX, destY, destW, destH, offsetX, offsetY) {
offsetX += destX;
+23
View File
@@ -0,0 +1,23 @@
/// <reference path="../Game.d.ts" />
/// <reference path="../geom/Quad.d.ts" />
/// <reference path="ScrollRegion.d.ts" />
module Phaser {
class ScrollZone extends GameObject {
constructor(game: Game, key: string, x?: number, y?: number, width?: number, height?: number);
private _texture;
private _dynamicTexture;
private _dx;
private _dy;
private _dw;
private _dh;
public currentRegion: ScrollRegion;
public regions: ScrollRegion[];
public flipped: bool;
public addRegion(x: number, y: number, width: number, height: number, speedX?: number, speedY?: number): ScrollRegion;
public setSpeed(x: number, y: number): ScrollZone;
public update(): void;
public inCamera(camera: Rectangle): bool;
public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number): bool;
private createRepeatingTexture(regionWidth, regionHeight);
}
}
+105 -20
View File
@@ -15,6 +15,17 @@ module Phaser {
export class ScrollZone extends GameObject {
/**
* ScrollZone constructor
* Create a new <code>ScrollZone</code>.
*
* @param game {Phaser.Game} Current game instance.
* @param key {string} Asset key for image texture of this object.
* @param x {number} X position in world coordinate.
* @param y {number} Y position in world coordinate.
* @param [width] {number} width of this object.
* @param [height] {number} height of this object.
*/
constructor(game: Game, key:string, x: number = 0, y: number = 0, width?: number = 0, height?: number = 0) {
super(game, x, y, width, height);
@@ -49,19 +60,69 @@ module Phaser {
}
/**
* Texture of this object.
*/
private _texture;
/**
* If this zone is larger than texture image, this will be filled with a pattern of texture.
* @type {DynamicTexture}
*/
private _dynamicTexture: DynamicTexture = null;
// local rendering related temp vars to help avoid gc spikes
/**
* Local rendering related temp vars to help avoid gc spikes.
* @type {number}
*/
private _dx: number = 0;
/**
* Local rendering related temp vars to help avoid gc spikes.
* @type {number}
*/
private _dy: number = 0;
/**
* Local rendering related temp vars to help avoid gc spikes.
* @type {number}
*/
private _dw: number = 0;
/**
* Local rendering related temp vars to help avoid gc spikes.
* @type {number}
*/
private _dh: number = 0;
/**
* Current region this zone is scrolling.
* @type {ScrollRegion}
*/
public currentRegion: ScrollRegion;
/**
* Array contains all added regions.
* @type {ScrollRegion[]}
*/
public regions: ScrollRegion[];
/**
* Flip this zone vertically? (default to false)
* @type {boolean}
*/
public flipped: bool = false;
/**
* Add a new region to this zone.
* @param x {number} X position of the new region.
* @param y {number} Y position of the new region.
* @param width {number} Width of the new region.
* @param height {number} Height of the new region.
* @param [speedX] {number} x-axis scrolling speed.
* @param [speedY] {number} y-axis scrolling speed.
* @return {ScrollRegion} The newly added region.
*/
public addRegion(x: number, y: number, width: number, height: number, speedX?:number = 0, speedY?:number = 0):ScrollRegion {
if (x > this.width || y > this.height || x < 0 || y < 0 || (x + width) > this.width || (y + height) > this.height)
@@ -78,6 +139,11 @@ module Phaser {
}
/**
* Set scrolling speed of current region.
* @param x {number} X speed of current region.
* @param y {number} Y speed of current region.
*/
public setSpeed(x: number, y: number) {
if (this.currentRegion)
@@ -89,6 +155,9 @@ module Phaser {
}
/**
* Update regions.
*/
public update() {
for (var i = 0; i < this.regions.length; i++)
@@ -98,24 +167,36 @@ module Phaser {
}
/**
* Check whether this zone is visible in a specific camera rectangle.
* @param camera {Rectangle} The rectangle you want to check.
* @return {boolean} Return true if bound of this zone intersects the given rectangle, otherwise return false.
*/
public inCamera(camera: Rectangle): bool {
if (this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0)
{
this._dx = this.bounds.x - (camera.x * this.scrollFactor.x);
this._dy = this.bounds.y - (camera.y * this.scrollFactor.x);
this._dw = this.bounds.width * this.scale.x;
this._dh = this.bounds.height * this.scale.y;
this._dx = this.frameBounds.x - (camera.x * this.scrollFactor.x);
this._dy = this.frameBounds.y - (camera.y * this.scrollFactor.x);
this._dw = this.frameBounds.width * this.scale.x;
this._dh = this.frameBounds.height * this.scale.y;
return (camera.right > this._dx) && (camera.x < this._dx + this._dw) && (camera.bottom > this._dy) && (camera.y < this._dy + this._dh);
}
else
{
return camera.intersects(this.bounds, this.bounds.length);
return camera.intersects(this.frameBounds, this.frameBounds.length);
}
}
/**
* Render this zone object to a specific camera.
* @param camera {Camera} The camera this object will be render to.
* @param cameraOffsetX {number} X offset of camera.
* @param cameraOffsetY {number} Y offset of camera.
* @return Return false if not rendered, otherwise return true.
*/
public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number) {
// Render checks
@@ -127,14 +208,14 @@ module Phaser {
// Alpha
if (this.alpha !== 1)
{
var globalAlpha = this._game.stage.context.globalAlpha;
this._game.stage.context.globalAlpha = this.alpha;
var globalAlpha = this.context.globalAlpha;
this.context.globalAlpha = this.alpha;
}
this._dx = cameraOffsetX + (this.bounds.topLeft.x - camera.worldView.x);
this._dy = cameraOffsetY + (this.bounds.topLeft.y - camera.worldView.y);
this._dw = this.bounds.width * this.scale.x;
this._dh = this.bounds.height * this.scale.y;
this._dx = cameraOffsetX + (this.frameBounds.topLeft.x - camera.worldView.x);
this._dy = cameraOffsetY + (this.frameBounds.topLeft.y - camera.worldView.y);
this._dw = this.frameBounds.width * this.scale.x;
this._dh = this.frameBounds.height * this.scale.y;
// Apply camera difference
if (this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0)
@@ -146,12 +227,12 @@ module Phaser {
// Rotation - needs to work from origin point really, but for now from center
if (this.angle !== 0 || this.flipped == true)
{
this._game.stage.context.save();
this._game.stage.context.translate(this._dx + (this._dw / 2), this._dy + (this._dh / 2));
this.context.save();
this.context.translate(this._dx + (this._dw / 2), this._dy + (this._dh / 2));
if (this.angle !== 0)
{
this._game.stage.context.rotate(this.angle * (Math.PI / 180));
this.context.rotate(this.angle * (Math.PI / 180));
}
this._dx = -(this._dw / 2);
@@ -159,7 +240,7 @@ module Phaser {
if (this.flipped == true)
{
this._game.stage.context.scale(-1, 1);
this.context.scale(-1, 1);
}
}
@@ -172,23 +253,27 @@ module Phaser {
{
if (this._dynamicTexture)
{
this.regions[i].render(this._game.stage.context, this._dynamicTexture.canvas, this._dx, this._dy, this._dw, this._dh);
this.regions[i].render(this.context, this._dynamicTexture.canvas, this._dx, this._dy, this._dw, this._dh);
}
else
{
this.regions[i].render(this._game.stage.context, this._texture, this._dx, this._dy, this._dw, this._dh);
this.regions[i].render(this.context, this._texture, this._dx, this._dy, this._dw, this._dh);
}
}
if (globalAlpha > -1)
{
this._game.stage.context.globalAlpha = globalAlpha;
this.context.globalAlpha = globalAlpha;
}
return true;
}
/**
* Create repeating texture with _texture, and store it into the _dynamicTexture.
* Used to create texture when texture image is small than size of the zone.
*/
private createRepeatingTexture(regionWidth: number, regionHeight: number) {
// Work out how many we'll need of the source image to make it tile properly
+34
View File
@@ -0,0 +1,34 @@
/// <reference path="../Game.d.ts" />
/// <reference path="../AnimationManager.d.ts" />
/// <reference path="GameObject.d.ts" />
/// <reference path="../system/Camera.d.ts" />
module Phaser {
class Sprite extends GameObject {
constructor(game: Game, x?: number, y?: number, key?: string);
private _texture;
private _dynamicTexture;
private _sx;
private _sy;
private _sw;
private _sh;
private _dx;
private _dy;
private _dw;
private _dh;
public animations: AnimationManager;
public renderDebug: bool;
public renderDebugColor: string;
public renderDebugPointColor: string;
public flipped: bool;
public loadGraphic(key: string): Sprite;
public loadDynamicTexture(texture: DynamicTexture): Sprite;
public makeGraphic(width: number, height: number, color?: number): Sprite;
public inCamera(camera: Rectangle): bool;
public postUpdate(): void;
public frame : number;
public frameName : string;
public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number): bool;
private renderBounds(camera, cameraOffsetX, cameraOffsetY);
public renderDebugInfo(x: number, y: number, color?: string): void;
}
}
+188 -81
View File
@@ -14,6 +14,15 @@ module Phaser {
export class Sprite extends GameObject {
/**
* Sprite constructor
* Create a new <code>Sprite</code>.
*
* @param game {Phaser.Game} Current game instance.
* @param [x] {number} the initial x position of the sprite.
* @param [y] {number} the initial y position of the sprite.
* @param [key] {string} Key of the graphic you want to load for this sprite.
*/
constructor(game: Game, x?: number = 0, y?: number = 0, key?: string = null) {
super(game, x, y);
@@ -24,17 +33,26 @@ module Phaser {
if (key !== null)
{
this.cacheKey = key;
this.loadGraphic(key);
}
else
{
this.bounds.width = 16;
this.bounds.height = 16;
this.frameBounds.width = 16;
this.frameBounds.height = 16;
}
}
/**
* Texture of this sprite to be rendered.
*/
private _texture;
/**
* Texture of this sprite is DynamicTexture? (default to false)
* @type {boolean}
*/
private _dynamicTexture: bool = false;
// local rendering related temp vars to help avoid gc spikes
@@ -47,27 +65,76 @@ module Phaser {
private _dw: number = 0;
private _dh: number = 0;
/**
* This manages animations of the sprite. You can modify animations though it. (see AnimationManager)
* @type AnimationManager
*/
public animations: AnimationManager;
/**
* The cache key that was used for this texture (if any)
*/
public cacheKey: string;
/**
* Render bound of this sprite for debugging? (default to false)
* @type {boolean}
*/
public renderDebug: bool = false;
/**
* Color of the Sprite when no image is present. Format is a css color string.
* @type {string}
*/
public fillColor: string = 'rgb(255,255,255)';
/**
* Color of bound when render debug. (see renderDebug) Format is a css color string.
* @type {string}
*/
public renderDebugColor: string = 'rgba(0,255,0,0.5)';
/**
* Color of points when render debug. (see renderDebug) Format is a css color string.
* @type {string}
*/
public renderDebugPointColor: string = 'rgba(255,255,255,1)';
/**
* Flip the graphic horizontally? (defaults to false)
* @type {boolean}
*/
public flipped: bool = false;
public loadGraphic(key: string): Sprite {
/**
* Load graphic for this sprite. (graphic can be SpriteSheet or Texture)
* @param key {string} Key of the graphic you want to load for this sprite.
* @param clearAnimations {boolean} If this Sprite has a set of animation data already loaded you can choose to keep or clear it with this boolean
* @return {Sprite} Sprite instance itself.
*/
public loadGraphic(key: string, clearAnimations: bool = true): Sprite {
if (clearAnimations && this.animations.frameData !== null)
{
this.animations.destroy();
}
if (this._game.cache.getImage(key) !== null)
{
if (this._game.cache.isSpriteSheet(key) == false)
{
this._texture = this._game.cache.getImage(key);
this.bounds.width = this._texture.width;
this.bounds.height = this._texture.height;
this.frameBounds.width = this._texture.width;
this.frameBounds.height = this._texture.height;
this.collisionMask.width = this._texture.width;
this.collisionMask.height = this._texture.height;
}
else
{
this._texture = this._game.cache.getImage(key);
this.animations.loadFrameData(this._game.cache.getFrameData(key));
this.collisionMask.width = this.animations.currentFrame.width;
this.collisionMask.height = this.animations.currentFrame.height;
}
this._dynamicTexture = false;
@@ -77,12 +144,17 @@ module Phaser {
}
/**
* Load a DynamicTexture as its texture.
* @param texture {DynamicTexture} The texture object to be used by this sprite.
* @return {Sprite} Sprite instance itself.
*/
public loadDynamicTexture(texture: DynamicTexture): Sprite {
this._texture = texture;
this.bounds.width = this._texture.width;
this.bounds.height = this._texture.height;
this.frameBounds.width = this._texture.width;
this.frameBounds.height = this._texture.height;
this._dynamicTexture = true;
@@ -90,35 +162,49 @@ module Phaser {
}
public makeGraphic(width: number, height: number, color: number = 0xffffffff): Sprite {
/**
* This function creates a flat colored square image dynamically.
* @param width {number} The width of the sprite you want to generate.
* @param height {number} The height of the sprite you want to generate.
* @param [color] {number} specifies the color of the generated block. (format is 0xAARRGGBB)
* @return {Sprite} Sprite instance itself.
*/
public makeGraphic(width: number, height: number, color: string = 'rgb(255,255,255)'): Sprite {
this._texture = null;
this.width = width;
this.height = height;
this.fillColor = color;
this._dynamicTexture = false;
return this;
}
public inCamera(camera: Rectangle): bool {
if (this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0)
{
this._dx = this.bounds.x - (camera.x * this.scrollFactor.x);
this._dy = this.bounds.y - (camera.y * this.scrollFactor.x);
this._dw = this.bounds.width * this.scale.x;
this._dh = this.bounds.height * this.scale.y;
/**
* Check whether this object is visible in a specific camera rectangle.
* @param camera {Rectangle} The rectangle you want to check.
* @return {boolean} Return true if bounds of this sprite intersects the given rectangle, otherwise return false.
*/
public inCamera(camera: Rectangle, cameraOffsetX: number, cameraOffsetY: number): bool {
return (camera.right > this._dx) && (camera.x < this._dx + this._dw) && (camera.bottom > this._dy) && (camera.y < this._dy + this._dh);
}
else
// Object fixed in place regardless of the camera scrolling? Then it's always visible
if (this.scrollFactor.x == 0 && this.scrollFactor.y == 0)
{
return camera.intersects(this.bounds, this.bounds.length);
return true;
}
this._dx = (this.frameBounds.x - camera.x);
this._dy = (this.frameBounds.y - camera.y);
this._dw = this.frameBounds.width * this.scale.x;
this._dh = this.frameBounds.height * this.scale.y;
return (camera.right > this._dx) && (camera.x < this._dx + this._dw) && (camera.bottom > this._dy) && (camera.y < this._dy + this._dh);
}
/**
* Automatically called after update() by the game loop, this function just updates animations.
*/
public postUpdate() {
this.animations.update();
@@ -143,10 +229,17 @@ module Phaser {
return this.animations.frameName;
}
/**
* Render this sprite to specific camera. Called by game loop after update().
* @param camera {Camera} Camera this sprite will be rendered to.
* @cameraOffsetX {number} X offset to the camera.
* @cameraOffsetY {number} Y offset to the camera.
* @return {boolean} Return false if not rendered, otherwise return true.
*/
public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number): bool {
// Render checks
if (this.visible == false || this.scale.x == 0 || this.scale.y == 0 || this.alpha < 0.1 || this.cameraBlacklist.indexOf(camera.ID) !== -1 || this.inCamera(camera.worldView) == false)
if (this.visible == false || this.scale.x == 0 || this.scale.y == 0 || this.alpha < 0.1 || this.cameraBlacklist.indexOf(camera.ID) !== -1 || this.inCamera(camera.worldView, cameraOffsetX, cameraOffsetY) == false)
{
return false;
}
@@ -154,54 +247,55 @@ module Phaser {
// Alpha
if (this.alpha !== 1)
{
var globalAlpha = this._game.stage.context.globalAlpha;
this._game.stage.context.globalAlpha = this.alpha;
var globalAlpha = this.context.globalAlpha;
this.context.globalAlpha = this.alpha;
}
this._sx = 0;
this._sy = 0;
this._sw = this.bounds.width;
this._sh = this.bounds.height;
this._dx = cameraOffsetX + (this.bounds.topLeft.x - camera.worldView.x);
this._dy = cameraOffsetY + (this.bounds.topLeft.y - camera.worldView.y);
this._dw = this.bounds.width * this.scale.x;
this._dh = this.bounds.height * this.scale.y;
this._sw = this.frameBounds.width;
this._sh = this.frameBounds.height;
this._dx = (cameraOffsetX * this.scrollFactor.x) + this.frameBounds.topLeft.x - (camera.worldView.x * this.scrollFactor.x);
this._dy = (cameraOffsetY * this.scrollFactor.y) + this.frameBounds.topLeft.y - (camera.worldView.y * this.scrollFactor.y);
this._dw = this.frameBounds.width * this.scale.x;
this._dh = this.frameBounds.height * this.scale.y;
if (this.align == GameObject.ALIGN_TOP_CENTER)
{
this._dx -= this.bounds.halfWidth * this.scale.x;
this._dx -= this.frameBounds.halfWidth * this.scale.x;
}
else if (this.align == GameObject.ALIGN_TOP_RIGHT)
{
this._dx -= this.bounds.width * this.scale.x;
this._dx -= this.frameBounds.width * this.scale.x;
}
else if (this.align == GameObject.ALIGN_CENTER_LEFT)
{
this._dy -= this.bounds.halfHeight * this.scale.y;
this._dy -= this.frameBounds.halfHeight * this.scale.y;
}
else if (this.align == GameObject.ALIGN_CENTER)
{
this._dx -= this.bounds.halfWidth * this.scale.x;
this._dy -= this.bounds.halfHeight * this.scale.y;
this._dx -= this.frameBounds.halfWidth * this.scale.x;
this._dy -= this.frameBounds.halfHeight * this.scale.y;
}
else if (this.align == GameObject.ALIGN_CENTER_RIGHT)
{
this._dx -= this.bounds.width * this.scale.x;
this._dy -= this.bounds.halfHeight * this.scale.y;
this._dx -= this.frameBounds.width * this.scale.x;
this._dy -= this.frameBounds.halfHeight * this.scale.y;
}
else if (this.align == GameObject.ALIGN_BOTTOM_LEFT)
{
this._dy -= this.bounds.height * this.scale.y;
this._dy -= this.frameBounds.height * this.scale.y;
}
else if (this.align == GameObject.ALIGN_BOTTOM_CENTER)
{
this._dx -= this.bounds.halfWidth * this.scale.x;
this._dy -= this.bounds.height * this.scale.y;
this._dx -= this.frameBounds.halfWidth * this.scale.x;
this._dy -= this.frameBounds.height * this.scale.y;
}
else if (this.align == GameObject.ALIGN_BOTTOM_RIGHT)
{
this._dx -= this.bounds.width * this.scale.x;
this._dy -= this.bounds.height * this.scale.y;
this._dx -= this.frameBounds.width * this.scale.x;
this._dy -= this.frameBounds.height * this.scale.y;
}
if (this._dynamicTexture == false && this.animations.currentFrame !== null)
@@ -217,21 +311,21 @@ module Phaser {
}
// Apply camera difference
if (this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0)
if (this.scrollFactor.x !== 1 || this.scrollFactor.y !== 1)
{
this._dx -= (camera.worldView.x * this.scrollFactor.x);
this._dy -= (camera.worldView.y * this.scrollFactor.y);
//this._dx -= (camera.worldView.x * this.scrollFactor.x);
//this._dy -= (camera.worldView.y * this.scrollFactor.y);
}
// Rotation - needs to work from origin point really, but for now from center
if (this.angle !== 0 || this.rotationOffset !== 0 || this.flipped == true)
{
this._game.stage.context.save();
this._game.stage.context.translate(this._dx + (this._dw / 2), this._dy + (this._dh / 2));
this.context.save();
this.context.translate(this._dx + (this._dw / 2), this._dy + (this._dh / 2));
if (this.renderRotation == true && (this.angle !== 0 || this.rotationOffset !== 0))
{
this._game.stage.context.rotate((this.rotationOffset + this.angle) * (Math.PI / 180));
this.context.rotate((this.rotationOffset + this.angle) * (Math.PI / 180));
}
this._dx = -(this._dw / 2);
@@ -239,7 +333,7 @@ module Phaser {
if (this.flipped == true)
{
this._game.stage.context.scale(-1, 1);
this.context.scale(-1, 1);
}
}
@@ -256,7 +350,7 @@ module Phaser {
{
if (this._dynamicTexture)
{
this._game.stage.context.drawImage(
this.context.drawImage(
this._texture.canvas, // Source Image
this._sx, // Source X (location within the source image)
this._sy, // Source Y
@@ -270,7 +364,7 @@ module Phaser {
}
else
{
this._game.stage.context.drawImage(
this.context.drawImage(
this._texture, // Source Image
this._sx, // Source X (location within the source image)
this._sy, // Source Y
@@ -285,64 +379,77 @@ module Phaser {
}
else
{
this._game.stage.context.fillStyle = 'rgb(255,255,255)';
this._game.stage.context.fillRect(this._dx, this._dy, this._dw, this._dh);
this.context.fillStyle = this.fillColor;
this.context.fillRect(this._dx, this._dy, this._dw, this._dh);
}
if (this.flipped === true || this.rotation !== 0 || this.rotationOffset !== 0)
{
//this._game.stage.context.translate(0, 0);
this._game.stage.context.restore();
//this.context.translate(0, 0);
this.context.restore();
}
if (this.renderDebug)
{
this.renderBounds(camera, cameraOffsetX, cameraOffsetY);
//this.collisionMask.render(camera, cameraOffsetX, cameraOffsetY);
}
if (globalAlpha > -1)
{
this._game.stage.context.globalAlpha = globalAlpha;
this.context.globalAlpha = globalAlpha;
}
return true;
}
// Renders the bounding box around this Sprite and the contact points. Useful for visually debugging.
/**
* Renders the bounding box around this Sprite and the contact points. Useful for visually debugging.
* @param camera {Camera} Camera the bound will be rendered to.
* @param cameraOffsetX {number} X offset of bound to the camera.
* @param cameraOffsetY {number} Y offset of bound to the camera.
*/
private renderBounds(camera:Camera, cameraOffsetX:number, cameraOffsetY:number) {
this._dx = cameraOffsetX + (this.bounds.topLeft.x - camera.worldView.x);
this._dy = cameraOffsetY + (this.bounds.topLeft.y - camera.worldView.y);
this._dx = cameraOffsetX + (this.frameBounds.topLeft.x - camera.worldView.x);
this._dy = cameraOffsetY + (this.frameBounds.topLeft.y - camera.worldView.y);
this._game.stage.context.fillStyle = this.renderDebugColor;
this._game.stage.context.fillRect(this._dx, this._dy, this._dw, this._dh);
this._game.stage.context.fillStyle = this.renderDebugPointColor;
var hw = this.bounds.halfWidth * this.scale.x;
var hh = this.bounds.halfHeight * this.scale.y;
var sw = (this.bounds.width * this.scale.x) - 1;
var sh = (this.bounds.height * this.scale.y) - 1;
this.context.fillStyle = this.renderDebugColor;
this.context.fillRect(this._dx, this._dy, this.frameBounds.width, this.frameBounds.height);
this._game.stage.context.fillRect(this._dx, this._dy, 1, 1); // top left
this._game.stage.context.fillRect(this._dx + hw, this._dy, 1, 1); // top center
this._game.stage.context.fillRect(this._dx + sw, this._dy, 1, 1); // top right
this._game.stage.context.fillRect(this._dx, this._dy + hh, 1, 1); // left center
this._game.stage.context.fillRect(this._dx + hw, this._dy + hh, 1, 1); // center
this._game.stage.context.fillRect(this._dx + sw, this._dy + hh, 1, 1); // right center
this._game.stage.context.fillRect(this._dx, this._dy + sh, 1, 1); // bottom left
this._game.stage.context.fillRect(this._dx + hw, this._dy + sh, 1, 1); // bottom center
this._game.stage.context.fillRect(this._dx + sw, this._dy + sh, 1, 1); // bottom right
//this.context.fillStyle = this.renderDebugPointColor;
//var hw = this.frameBounds.halfWidth * this.scale.x;
//var hh = this.frameBounds.halfHeight * this.scale.y;
//var sw = (this.frameBounds.width * this.scale.x) - 1;
//var sh = (this.frameBounds.height * this.scale.y) - 1;
//this.context.fillRect(this._dx, this._dy, 1, 1); // top left
//this.context.fillRect(this._dx + hw, this._dy, 1, 1); // top center
//this.context.fillRect(this._dx + sw, this._dy, 1, 1); // top right
//this.context.fillRect(this._dx, this._dy + hh, 1, 1); // left center
//this.context.fillRect(this._dx + hw, this._dy + hh, 1, 1); // center
//this.context.fillRect(this._dx + sw, this._dy + hh, 1, 1); // right center
//this.context.fillRect(this._dx, this._dy + sh, 1, 1); // bottom left
//this.context.fillRect(this._dx + hw, this._dy + sh, 1, 1); // bottom center
//this.context.fillRect(this._dx + sw, this._dy + sh, 1, 1); // bottom right
}
/**
* Render debug infos. (including name, bounds info, position and some other properties)
* @param x {number} X position of the debug info to be rendered.
* @param y {number} Y position of the debug info to be rendered.
* @param [color] {number} color of the debug info to be rendered. (format is css color string)
*/
public renderDebugInfo(x: number, y: number, color?: string = 'rgb(255,255,255)') {
this._game.stage.context.fillStyle = color;
this._game.stage.context.fillText('Sprite: ' + this.name + ' (' + this.bounds.width + ' x ' + this.bounds.height + ')', x, y);
this._game.stage.context.fillText('x: ' + this.bounds.x.toFixed(1) + ' y: ' + this.bounds.y.toFixed(1) + ' rotation: ' + this.angle.toFixed(1), x, y + 14);
this._game.stage.context.fillText('dx: ' + this._dx.toFixed(1) + ' dy: ' + this._dy.toFixed(1) + ' dw: ' + this._dw.toFixed(1) + ' dh: ' + this._dh.toFixed(1), x, y + 28);
this._game.stage.context.fillText('sx: ' + this._sx.toFixed(1) + ' sy: ' + this._sy.toFixed(1) + ' sw: ' + this._sw.toFixed(1) + ' sh: ' + this._sh.toFixed(1), x, y + 42);
this.context.fillStyle = color;
this.context.fillText('Sprite: ' + this.name + ' (' + this.frameBounds.width + ' x ' + this.frameBounds.height + ')', x, y);
this.context.fillText('x: ' + this.frameBounds.x.toFixed(1) + ' y: ' + this.frameBounds.y.toFixed(1) + ' rotation: ' + this.angle.toFixed(1), x, y + 14);
this.context.fillText('dx: ' + this._dx.toFixed(1) + ' dy: ' + this._dy.toFixed(1) + ' dw: ' + this._dw.toFixed(1) + ' dh: ' + this._dh.toFixed(1), x, y + 28);
this.context.fillText('sx: ' + this._sx.toFixed(1) + ' sy: ' + this._sy.toFixed(1) + ' sw: ' + this._sw.toFixed(1) + ' sh: ' + this._sh.toFixed(1), x, y + 42);
}
+31
View File
@@ -0,0 +1,31 @@
/// <reference path="../Game.d.ts" />
/// <reference path="GameObject.d.ts" />
/// <reference path="../system/TilemapLayer.d.ts" />
/// <reference path="../system/Tile.d.ts" />
module Phaser {
class Tilemap extends GameObject {
constructor(game: Game, key: string, mapData: string, format: number, resizeWorld?: bool, tileWidth?: number, tileHeight?: number);
static FORMAT_CSV: number;
static FORMAT_TILED_JSON: number;
public tiles: Tile[];
public layers: TilemapLayer[];
public currentLayer: TilemapLayer;
public collisionLayer: TilemapLayer;
public mapFormat: number;
public update(): void;
public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number): void;
private parseCSV(data, key, tileWidth, tileHeight);
private parseTiledJSON(data, key);
private generateTiles(qty);
public widthInPixels : number;
public heightInPixels : number;
public setCollisionRange(start: number, end: number, collision?: number, resetCollisions?: bool): void;
public setCollisionByIndex(values: number[], collision?: number, resetCollisions?: bool): void;
public getTile(x: number, y: number, layer?: number): Tile;
public getTileFromWorldXY(x: number, y: number, layer?: number): Tile;
public getTileFromInputXY(layer?: number): Tile;
public getTileOverlaps(object: GameObject): bool;
public collide(objectOrGroup?, callback?): bool;
public collideGameObject(object: GameObject): bool;
}
}
+202 -18
View File
@@ -14,6 +14,18 @@ module Phaser {
export class Tilemap extends GameObject {
/**
* Tilemap constructor
* Create a new <code>Tilemap</code>.
*
* @param game {Phaser.Game} Current game instance.
* @param key {string} Asset key for this map.
* @param mapData {string} Data of this map. (a big 2d array, normally in csv)
* @param format {number} Format of this map data, available: Tilemap.FORMAT_CSV or Tilemap.FORMAT_TILED_JSON.
* @param resizeWorld {boolean} Resize the world bound automatically based on this tilemap?
* @param tileWidth {number} Width of tiles in this map.
* @param tileHeight {number} Height of tiles in this map.
*/
constructor(game: Game, key: string, mapData: string, format: number, resizeWorld: bool = true, tileWidth?: number = 0, tileHeight?: number = 0) {
super(game);
@@ -43,17 +55,66 @@ module Phaser {
}
private _tempCollisionData;
/**
* Tilemap data format enum: CSV.
* @type {number}
*/
public static FORMAT_CSV: number = 0;
/**
* Tilemap data format enum: Tiled JSON.
* @type {number}
*/
public static FORMAT_TILED_JSON: number = 1;
/**
* Array contains tile objects of this map.
* @type {Tile[]}
*/
public tiles : Tile[];
/**
* Array contains tilemap layer objects of this map.
* @type {TilemapLayer[]}
*/
public layers : TilemapLayer[];
/**
* Current tilemap layer.
* @type {TilemapLayer}
*/
public currentLayer: TilemapLayer;
/**
* The tilemap layer for collision.
* @type {TilemapLayer}
*/
public collisionLayer: TilemapLayer;
/**
* Tilemap collision callback.
* @type {function}
*/
public collisionCallback = null;
/**
* Context for the collision callback called with.
*/
public collisionCallbackContext;
/**
* Format of this tilemap data. Available values: Tilemap.FORMAT_CSV or Tilemap.FORMAT_TILED_JSON.
* @type {number}
*/
public mapFormat: number;
/**
* Inherited update method.
*/
public update() {
}
/**
* Render this tilemap to a specific camera with specific offset.
* @param camera {Camera} The camera this tilemap will be rendered to.
* @param cameraOffsetX {number} X offset of the camera.
* @param cameraOffsetY {number} Y offset of the camera.
*/
public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number) {
if (this.cameraBlacklist.indexOf(camera.ID) == -1)
@@ -67,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) {
var layer: TilemapLayer = new TilemapLayer(this._game, this, key, Tilemap.FORMAT_CSV, 'TileLayerCSV' + this.layers.length.toString(), tileWidth, tileHeight);
@@ -90,6 +158,7 @@ module Phaser {
var tileQuantity = layer.parseTileOffsets();
this.currentLayer = layer;
this.collisionLayer = layer;
this.layers.push(layer);
@@ -97,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) {
// Trim any rogue whitespace from the data
@@ -107,7 +181,7 @@ module Phaser {
for (var i = 0; i < json.layers.length; i++)
{
var layer: TilemapLayer = new TilemapLayer(this._game, this, key, Tilemap.FORMAT_TILED_JSON, json.layers[i].name, json.tilewidth, json.tileheight);
layer.alpha = json.layers[i].opacity;
layer.visible = json.layers[i].visible;
layer.tileMargin = json.tilesets[0].margin;
@@ -139,6 +213,7 @@ module Phaser {
var tileQuantity = layer.parseTileOffsets();
this.currentLayer = layer;
this.collisionLayer = layer;
this.layers.push(layer);
@@ -148,6 +223,10 @@ module Phaser {
}
/**
* Create tiles of given quantity.
* @param qty {number} Quentity of tiles to be generated.
*/
private generateTiles(qty:number) {
for (var i = 0; i < qty; i++)
@@ -167,32 +246,91 @@ module Phaser {
// Tile Collision
public setCollisionRange(start: number, end: number, collision?:number = Collision.ANY) {
/**
* Set callback to be called when this tilemap collides.
* @param context {object} Callback will be called with this context.
* @param callback {function} Callback function.
*/
public setCollisionCallback(context, callback) {
this.collisionCallbackContext = context;
this.collisionCallback = callback;
}
/**
* Set collision configs of tiles in a range index.
* @param start {number} First index of tiles.
* @param end {number} Last index of tiles.
* @param collision {number} Bit field of flags. (see Tile.allowCollision)
* @param resetCollisions {boolean} Reset collision flags before set.
* @param separateX {boolean} Enable seprate at x-axis.
* @param separateY {boolean} Enable seprate at y-axis.
*/
public setCollisionRange(start: number, end: number, collision?:number = Collision.ANY, resetCollisions?: bool = false, separateX?: bool = true, separateY?: bool = true) {
for (var i = start; i < end; i++)
{
this.tiles[i].allowCollisions = collision;
this.tiles[i].setCollision(collision, resetCollisions, separateX, separateY);
}
}
public setCollisionByIndex(values:number[], collision?:number = Collision.ANY) {
/**
* Set collision configs of tiles with given index.
* @param values {number[]} Index array which contains all tile indexes. The tiles with those indexes will be setup with rest parameters.
* @param collision {number} Bit field of flags. (see Tile.allowCollision)
* @param resetCollisions {boolean} Reset collision flags before set.
* @param separateX {boolean} Enable seprate at x-axis.
* @param separateY {boolean} Enable seprate at y-axis.
*/
public setCollisionByIndex(values:number[], collision?:number = Collision.ANY, resetCollisions?: bool = false, separateX?: bool = true, separateY?: bool = true) {
for (var i = 0; i < values.length; i++)
{
this.tiles[values[i]].allowCollisions = collision;
this.tiles[values[i]].setCollision(collision, resetCollisions, separateX, separateY);
}
}
// Tile Management
/**
* Get the tile by its index.
* @param value {number} Index of the tile you want to get.
* @return {Tile} The tile with given index.
*/
public getTileByIndex(value: number):Tile {
if (this.tiles[value])
{
return this.tiles[value];
}
return null;
}
/**
* Get the tile located at specific position and layer.
* @param x {number} X position of this tile located.
* @param y {number} Y position of this tile located.
* @param [layer] {number} layer of this tile located.
* @return {Tile} The tile with specific properties.
*/
public getTile(x: number, y: number, layer?: number = 0):Tile {
return this.tiles[this.layers[layer].getTileIndex(x, y)];
}
/**
* Get the tile located at specific position (in world coordinate) and layer. (thus you give a position of a point which is within the tile)
* @param x {number} X position of the point in target tile.
* @param x {number} Y position of the point in target tile.
* @param [layer] {number} layer of this tile located.
* @return {Tile} The tile with specific properties.
*/
public getTileFromWorldXY(x: number, y: number, layer?: number = 0):Tile {
return this.tiles[this.layers[layer].getTileFromWorldXY(x, y)];
@@ -201,10 +339,15 @@ module Phaser {
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) {
return this.currentLayer.getTileOverlaps(object);
@@ -212,7 +355,20 @@ module Phaser {
}
// 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)
{
@@ -222,30 +378,58 @@ module Phaser {
// Group?
if (objectOrGroup.isGroup == false)
{
if (objectOrGroup.exists && objectOrGroup.allowCollisions != Collision.NONE)
{
this.currentLayer.getTileOverlaps(objectOrGroup);
}
this.collideGameObject(objectOrGroup);
}
else
{
// todo
objectOrGroup.forEachAlive(this.currentLayer.getTileOverlaps);
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 {
if (object !== this && object.immovable == false && object.exists == true && object.allowCollisions != Collision.NONE)
{
this._tempCollisionData = this.collisionLayer.getTileOverlaps(object);
if (this.collisionCallback !== null && this._tempCollisionData.length > 0)
{
this.collisionCallback.call(this.collisionCallbackContext, object, this._tempCollisionData);
}
return true;
}
else
{
return false;
}
}
/**
* Set a tile to a specific layer.
* @param x {number} X position of this tile.
* @param y {number} Y position of this tile.
* @param index {number} The index of this tile type in the core map data.
* @param [layer] {number} which layer you want to set the tile to.
*/
public putTile(x: number, y: number, index: number, layer?: number = 0) {
this.layers[layer].putTile(x, y, index);
}
// Set current layer
// Set layer order?
// Get block of tiles
// Swap tiles around
// Delete tiles of certain type
// Erase tiles
}
}
+34
View File
@@ -0,0 +1,34 @@
/// <reference path="../Game.d.ts" />
module Phaser {
class Circle {
constructor(x?: number, y?: number, diameter?: number);
private _diameter;
private _radius;
public x: number;
public y: number;
public diameter : number;
public radius : number;
public circumference(): number;
public bottom : number;
public left : number;
public right : number;
public top : number;
public area : number;
public isEmpty : bool;
public intersectCircleLine(line: Line): bool;
public clone(output?: Circle): Circle;
public contains(x: number, y: number): bool;
public containsPoint(point: Point): bool;
public containsCircle(circle: Circle): bool;
public copyFrom(source: Circle): Circle;
public copyTo(target: Circle): Circle;
public distanceTo(target: any, round?: bool): number;
public equals(toCompare: Circle): bool;
public intersects(toIntersect: Circle): bool;
public circumferencePoint(angle: number, asDegrees?: bool, output?: Point): Point;
public offset(dx: number, dy: number): Circle;
public offsetPoint(point: Point): Circle;
public setTo(x: number, y: number, diameter: number): Circle;
public toString(): string;
}
}
+22 -12
View File
@@ -14,42 +14,52 @@ module Phaser {
* Creates a new Circle object with the center coordinate specified by the x and y parameters and the diameter specified by the diameter parameter. If you call this function without parameters, a circle with x, y, diameter and radius properties set to 0 is created.
* @class Circle
* @constructor
* @param {Number} x The x coordinate of the center of the circle.
* @param {Number} y The y coordinate of the center of the circle.
* @param {Number} [x] The x coordinate of the center of the circle.
* @param {Number} [y] The y coordinate of the center of the circle.
* @param {Number} [diameter] The diameter of the circle.
* @return {Circle} This circle object
**/
constructor(x: number = 0, y: number = 0, diameter: number = 0) {
this._pos = new Vector2;
this.setTo(x, y, diameter);
}
private _diameter: number = 0;
private _radius: number = 0;
private _pos: Vector2;
/**
/**
* The x coordinate of the center of the circle
* @property x
* @type Number
**/
public x: number = 0;
/**
/**
* The y coordinate of the center of the circle
* @property y
* @type Number
**/
public y: number = 0;
/**
* The position of this Circle object represented by a Vector2
* @property pos
* @type Vector2
**/
public get pos(): Vector2 {
return this._pos.setTo(this.x, this.y);
}
/**
* The diameter of the circle. The largest distance between any two points on the circle. The same as the radius * 2.
* @method diameter
* @return {Number}
**/
get diameter(): number {
return this._diameter;
}
/**
@@ -262,7 +272,7 @@ module Phaser {
**/
get isEmpty(): bool {
if (this._diameter < 1)
if (this._diameter <= 0)
{
return true;
}
@@ -287,7 +297,7 @@ module Phaser {
/**
* Returns a new Circle object with the same values for the x, y, width, and height properties as the original Circle object.
* @method clone
* @param {Circle} output Optional Circle object. If given the values will be set into the object, otherwise a brand new Circle object will be created and returned.
* @param {Circle} [optional] output Optional Circle object. If given the values will be set into the object, otherwise a brand new Circle object will be created and returned.
* @return {Phaser.Circle}
**/
public clone(output?: Circle = new Circle): Circle {
@@ -364,7 +374,7 @@ module Phaser {
* Returns the distance from the center of this Circle object to the given object (can be Circle, Point or anything with x/y values)
* @method distanceFrom
* @param {Circle/Point} target - The destination Point object.
* @param {Boolean} round - Round the distance to the nearest integer (default false)
* @param {Boolean} [optional] round - Round the distance to the nearest integer (default false)
* @return {Number} The distance between this Point object and the destination Point object.
**/
public distanceTo(target: any, round?: bool = false): number {
@@ -418,9 +428,9 @@ module Phaser {
/**
* Returns a Point object containing the coordinates of a point on the circumference of this Circle based on the given angle.
* @method circumferencePoint
* @param {Number} The angle in radians (unless asDegrees is true) to return the point from.
* @param {Boolean} Is the given angle in radians (false) or degrees (true)?
* @param {Phaser.Point} An optional Point object to put the result in to. If none specified a new Point object will be created.
* @param {Number} angle The angle in radians (unless asDegrees is true) to return the point from.
* @param {Boolean} asDegrees Is the given angle in radians (false) or degrees (true)?
* @param {Phaser.Point} [optional] output An optional Point object to put the result in to. If none specified a new Point object will be created.
* @return {Phaser.Point} The Point object holding the result.
**/
public circumferencePoint(angle: number, asDegrees: bool = false, output?: Point = new Point): Point {
+15
View File
@@ -0,0 +1,15 @@
/// <reference path="../Game.d.ts" />
module Phaser {
class IntersectResult {
public result: bool;
public x: number;
public y: number;
public x1: number;
public y1: number;
public x2: number;
public y2: number;
public width: number;
public height: number;
public setTo(x1: number, y1: number, x2?: number, y2?: number, width?: number, height?: number): void;
}
}
+9 -9
View File
@@ -13,55 +13,55 @@ module Phaser {
/**
* Did they intersect or not?
* @property result
* @type Boolean
* @type {Boolean}
*/
result: bool = false;
/**
* @property x
* @type Number
* @type {Number}
*/
x: number;
/**
* @property y
* @type Number
* @type {Number}
*/
y: number;
/**
* @property x1
* @type Number
* @type {Number}
*/
x1: number;
/**
* @property y1
* @type Number
* @type {Number}
*/
y1: number;
/**
* @property x2
* @type Number
* @type {Number}
*/
x2: number;
/**
* @property y2
* @type Number
* @type {Number}
*/
y2: number;
/**
* @property width
* @type Number
* @type {Number}
*/
width: number;
/**
* @property height
* @type Number
* @type {Number}
*/
height: number;
+27
View File
@@ -0,0 +1,27 @@
/// <reference path="../Game.d.ts" />
module Phaser {
class Line {
constructor(x1?: number, y1?: number, x2?: number, y2?: number);
public x1: number;
public y1: number;
public x2: number;
public y2: number;
public clone(output?: Line): Line;
public copyFrom(source: Line): Line;
public copyTo(target: Line): Line;
public setTo(x1?: number, y1?: number, x2?: number, y2?: number): Line;
public width : number;
public height : number;
public length : number;
public getY(x: number): number;
public angle : number;
public slope : number;
public perpSlope : number;
public yIntercept : number;
public isPointOnLine(x: number, y: number): bool;
public isPointOnLineSegment(x: number, y: number): bool;
public intersectLineLine(line): any;
public perp(x: number, y: number, output?: Line): Line;
public toString(): string;
}
}
+25 -25
View File
@@ -11,7 +11,7 @@ module Phaser {
export class Line {
/**
*
*
* @constructor
* @param {Number} x1
* @param {Number} y1
@@ -26,35 +26,35 @@ module Phaser {
}
/**
*
*
* @property x1
* @type Number
* @type {Number}
*/
public x1: number = 0;
/**
*
*
* @property y1
* @type Number
* @type {Number}
*/
public y1: number = 0;
/**
*
*
* @property x2
* @type Number
* @type {Number}
*/
public x2: number = 0;
/**
*
*
* @property y2
* @type Number
* @type {Number}
*/
public y2: number = 0;
/**
*
*
* @method clone
* @param {Phaser.Line} [output]
* @return {Phaser.Line}
@@ -66,7 +66,7 @@ module Phaser {
}
/**
*
*
* @method copyFrom
* @param {Phaser.Line} source
* @return {Phaser.Line}
@@ -78,7 +78,7 @@ module Phaser {
}
/**
*
*
* @method copyTo
* @param {Phaser.Line} target
* @return {Phaser.Line}
@@ -90,7 +90,7 @@ module Phaser {
}
/**
*
*
* @method setTo
* @param {Number} x1
* @param {Number} y1
@@ -122,7 +122,7 @@ module Phaser {
}
/**
*
*
* @method length
* @return {Number}
*/
@@ -133,7 +133,7 @@ module Phaser {
}
/**
*
*
* @method getY
* @param {Number} x
* @return {Number}
@@ -145,7 +145,7 @@ module Phaser {
}
/**
*
*
* @method angle
* @return {Number}
*/
@@ -156,7 +156,7 @@ module Phaser {
}
/**
*
*
* @method slope
* @return {Number}
*/
@@ -167,7 +167,7 @@ module Phaser {
}
/**
*
*
* @method perpSlope
* @return {Number}
*/
@@ -178,7 +178,7 @@ module Phaser {
}
/**
*
*
* @method yIntercept
* @return {Number}
*/
@@ -189,7 +189,7 @@ module Phaser {
}
/**
*
*
* @method isPointOnLine
* @param {Number} x
* @param {Number} y
@@ -209,7 +209,7 @@ module Phaser {
}
/**
*
*
* @method isPointOnLineSegment
* @param {Number} x
* @param {Number} y
@@ -234,7 +234,7 @@ module Phaser {
}
/**
*
*
* @method intersectLineLine
* @param {Any} line
* @return {Any}
@@ -244,7 +244,7 @@ module Phaser {
}
/**
*
*
* @method perp
* @param {Number} x
* @param {Number} y
@@ -285,12 +285,12 @@ module Phaser {
{
var perp = this.perp()
return Phaser.intersectLineCircle(this,circle);
}
*/
/**
*
*
* @method toString
* @return {String}
*/
+16
View File
@@ -0,0 +1,16 @@
/// <reference path="../Game.d.ts" />
module Phaser {
class MicroPoint {
constructor(x?: number, y?: number, parent?: any);
private _x;
private _y;
public parent: any;
public x : number;
public y : number;
public copyFrom(source: any): MicroPoint;
public copyTo(target: any): MicroPoint;
public setTo(x: number, y: number, callParent?: bool): MicroPoint;
public equals(toCompare): bool;
public toString(): string;
}
}
+8 -8
View File
@@ -33,10 +33,10 @@ module Phaser {
public parent: any;
/**
/**
* The x coordinate of the top-left corner of the rectangle
* @property x
* @type Number
* @type {Number}
**/
public get x(): number {
@@ -44,10 +44,10 @@ module Phaser {
}
/**
/**
* The y coordinate of the top-left corner of the rectangle
* @property y
* @type Number
* @type {Number}
**/
public get y(): number {
@@ -55,10 +55,10 @@ module Phaser {
}
/**
/**
* The x coordinate of the top-left corner of the rectangle
* @property x
* @type Number
* @type {Number}
**/
public set x(value: number) {
@@ -71,10 +71,10 @@ module Phaser {
}
/**
/**
* The y coordinate of the top-left corner of the rectangle
* @property y
* @type Number
* @type {Number}
**/
public set y(value:number) {
+28
View File
@@ -0,0 +1,28 @@
/// <reference path="../Game.d.ts" />
module Phaser {
class Point {
constructor(x?: number, y?: number);
public x: number;
public y: number;
public add(toAdd: Point, output?: Point): Point;
public addTo(x?: number, y?: number): Point;
public subtractFrom(x?: number, y?: number): Point;
public invert(): Point;
public clamp(min: number, max: number): Point;
public clampX(min: number, max: number): Point;
public clampY(min: number, max: number): Point;
public clone(output?: Point): Point;
public copyFrom(source: Point): Point;
public copyTo(target: Point): Point;
public distanceTo(target: Point, round?: bool): number;
static distanceBetween(pointA: Point, pointB: Point, round?: bool): number;
public distanceCompare(target: Point, distance: number): bool;
public equals(toCompare: Point): bool;
public interpolate(pointA, pointB, f): void;
public offset(dx: number, dy: number): Point;
public polar(length, angle): void;
public setTo(x: number, y: number): Point;
public subtract(point: Point, output?: Point): Point;
public toString(): string;
}
}
+30 -4
View File
@@ -23,17 +23,17 @@ module Phaser {
}
/**
/**
* The horizontal position of this point (default 0)
* @property x
* @type Number
* @type {Number}
**/
public x: number;
/**
/**
* The vertical position of this point (default 0)
* @property y
* @type Number
* @type {Number}
**/
public y: number;
@@ -296,6 +296,32 @@ module Phaser {
}
/**
* Rotates the point around the x/y coordinates given to the desired angle
* @param x {number} The x coordinate of the anchor point
* @param y {number} The y coordinate of the anchor point
* @param {Number} angle The angle in radians (unless asDegrees is true) to return the point from.
* @param {Boolean} asDegrees Is the given angle in radians (false) or degrees (true)?
* @param {Number} distance An optional distance constraint between the point and the anchor
* @return The modified point object
*/
public rotate(cx: number, cy: number, angle: number, asDegrees: bool = false, distance?:number = null) {
if (asDegrees)
{
angle = angle * GameMath.DEG_TO_RAD;
}
// Get distance from origin (cx/cy) to this point
if (distance === null)
{
distance = Math.sqrt(((cx - this.x) * (cx - this.x)) + ((cy - this.y) * (cy - this.y)));
}
return this.setTo(cx + distance * Math.cos(angle), cy + distance * Math.sin(angle));
}
/**
* Sets the x and y values of this Point object to the given coordinates.
* @method setTo
+60
View File
@@ -0,0 +1,60 @@
/// <reference path="../Game.ts" />
/**
* Phaser - Polygon
*
*/
module Phaser {
export class Polygon {
/**
* A *convex* clockwise polygon
* @class Polygon
* @constructor
* @param {Vector2} pos A vector representing the origin of the polygon (all other points are relative to this one)
* @param {Array.<Vector2>} points An Array of vectors representing the points in the polygon, in clockwise order.
**/
constructor(pos?: Vector2 = new Vector2, points?: Vector2[] = [], parent?:any = null) {
this.pos = pos;
this.points = points;
this.parent = parent;
this.recalc();
}
public parent: any;
public pos: Vector2;
public points: Vector2[];
public edges: Vector2[];
public normals: Vector2[];
/**
* Recalculate the edges and normals of the polygon. This
* MUST be called if the points array is modified at all and
* the edges or normals are to be accessed.
*/
public recalc() {
var points = this.points;
var len = points.length;
this.edges = [];
this.normals = [];
for (var i = 0; i < len; i++)
{
var p1 = points[i];
var p2 = i < len - 1 ? points[i + 1] : points[0];
var e = new Vector2().copyFrom(p2).sub(p1);
var n = new Vector2().copyFrom(e).perp().normalize();
this.edges.push(e);
this.normals.push(n);
}
}
}
}
+19
View File
@@ -0,0 +1,19 @@
/// <reference path="../Game.d.ts" />
module Phaser {
class Quad {
constructor(x?: number, y?: number, width?: number, height?: number);
public x: number;
public y: number;
public width: number;
public height: number;
public setTo(x: number, y: number, width: number, height: number): Quad;
public left : number;
public right : number;
public top : number;
public bottom : number;
public halfWidth : number;
public halfHeight : number;
public intersects(q, t?: number): bool;
public toString(): string;
}
}
+87 -5
View File
@@ -1,4 +1,5 @@
/// <reference path="../Game.ts" />
/// <reference path="Polygon.ts" />
/**
* Phaser - Quad
@@ -19,7 +20,7 @@ module Phaser {
* @param {Number} y The y coordinate of the top-left corner of the quad.
* @param {Number} width The width of the quad.
* @param {Number} height The height of the quad.
* @return {Quad } This object
* @return {Quad} This object
**/
constructor(x: number = 0, y: number = 0, width: number = 0, height: number = 0) {
@@ -68,17 +69,98 @@ module Phaser {
return this.y + this.height;
}
public get halfWidth(): number {
return this.width / 2;
}
public get halfHeight(): number {
return this.height / 2;
}
/**
* Determines whether the object specified intersects (overlaps) with this Quad object.
* This method checks the x, y, width, and height properties of the specified Quad object to see if it intersects with this Quad object.
* @method intersects
* @param {Object} q 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 {Object} quad The object to check for intersection with this Quad. Must have left/right/top/bottom properties (Rectangle, Quad).
* @param {Number} tolerance A tolerance value to allow for an intersection test with padding, default to 0
* @return {Boolean} A value of true if the specified object intersects with this Quad; otherwise false.
**/
public intersects(q, t?: number = 0): bool {
public intersects(quad, tolerance?: number = 0): bool {
return !(q.left > this.right + t || q.right < this.left - t || q.top > this.bottom + t || q.bottom < this.top - t);
return !(quad.left > this.right + tolerance || quad.right < this.left - tolerance || quad.top > this.bottom + tolerance || quad.bottom < this.top - tolerance);
}
/**
* Determines whether the object specified intersects (overlaps) with the given values.
* @method intersectsProps
* @param {Number} left
* @param {Number} right
* @param {Number} top
* @param {Number} bottomt
* @param {Number} tolerance A tolerance value to allow for an intersection test with padding, default to 0
* @return {Boolean} A value of true if the specified object intersects with this Quad; otherwise false.
**/
public intersectsRaw(left: number, right: number, top: number, bottom: number, tolerance?: number = 0): bool {
return !(left > this.right + tolerance || right < this.left - tolerance || top > this.bottom + tolerance || bottom < this.top - tolerance);
}
/**
* Determines whether the specified coordinates are contained within the region defined by this Quad object.
* @method contains
* @param {Number} x The x coordinate of the point to test.
* @param {Number} y The y coordinate of the point to test.
* @return {Boolean} A value of true if the Rectangle object contains the specified point; otherwise false.
**/
public contains(x: number, y: number): bool {
if (x >= this.x && x <= this.right && y >= this.y && y <= this.bottom)
{
return true;
}
return false;
}
/**
* Copies the x/y/width/height values from the source object into this Quad
* @method copyFrom
* @param {Any} source The source object to copy from. Can be a Quad, Rectangle or any object with exposed x/y/width/height properties
* @return {Quad} This object
**/
public copyFrom(source): Quad {
return this.setTo(source.x, source.y, source.width, source.height);
}
/**
* Copies the x/y/width/height values from this Quad into the given target object
* @method copyTo
* @param {Any} target The object to copy this quads values in to. Can be a Quad, Rectangle or any object with exposed x/y/width/height properties
* @return {Any} The target object
**/
public copyTo(target): any {
return target.copyFrom(this);
}
/**
* Creates and returns a Polygon that is the same as this Quad.
* @method toPolygon
* @return {Polygon} A new Polygon that represents this quad.
**/
public toPolygon(): Polygon {
return new Polygon(new Vector2(this.x, this.y), [
new Vector2(), new Vector2(this.width, 0),
new Vector2(this.width, this.height), new Vector2(0, this.height)
]);
}
+57
View File
@@ -0,0 +1,57 @@
/// <reference path="../Game.d.ts" />
/// <reference path="MicroPoint.d.ts" />
module Phaser {
class Rectangle {
constructor(x?: number, y?: number, width?: number, height?: number);
private _tempX;
private _tempY;
private _tempWidth;
private _tempHeight;
public x : number;
public y : number;
public topLeft: MicroPoint;
public topCenter: MicroPoint;
public topRight: MicroPoint;
public leftCenter: MicroPoint;
public center: MicroPoint;
public rightCenter: MicroPoint;
public bottomLeft: MicroPoint;
public bottomCenter: MicroPoint;
public bottomRight: MicroPoint;
private _width;
private _height;
private _halfWidth;
private _halfHeight;
public length: number;
public updateBounds(): void;
public width : number;
public height : number;
public halfWidth : number;
public halfHeight : number;
public bottom : number;
public left : number;
public right : number;
public size(output?: Point): Point;
public volume : number;
public perimeter : number;
public top : number;
public clone(output?: Rectangle): Rectangle;
public contains(x: number, y: number): bool;
public containsPoint(point: any): bool;
public containsRect(rect: Rectangle): bool;
public copyFrom(source: Rectangle): Rectangle;
public copyTo(target: Rectangle): Rectangle;
public equals(toCompare: Rectangle): bool;
public inflate(dx: number, dy: number): Rectangle;
public inflatePoint(point: Point): Rectangle;
public intersection(toIntersect: Rectangle, output?: Rectangle): Rectangle;
public intersects(r2: Rectangle, t?: number): bool;
public isEmpty : bool;
public offset(dx: number, dy: number): Rectangle;
public offsetPoint(point: Point): Rectangle;
public setEmpty(): Rectangle;
public setTo(x: number, y: number, width: number, height: number): Rectangle;
public union(toUnion: Rectangle, output?: Rectangle): Rectangle;
public toString(): string;
}
}
+60 -60
View File
@@ -57,10 +57,10 @@ module Phaser {
private _tempWidth: number = null;
private _tempHeight: number = null;
/**
/**
* The x coordinate of the top-left corner of the rectangle
* @property x
* @type Number
* @type {Number}
**/
public get x(): number {
@@ -68,10 +68,10 @@ module Phaser {
}
/**
/**
* The y coordinate of the top-left corner of the rectangle
* @property y
* @type Number
* @type {Number}
**/
public get y(): number {
@@ -79,10 +79,10 @@ module Phaser {
}
/**
/**
* The x coordinate of the top-left corner of the rectangle
* @property x
* @type Number
* @type {Number}
**/
public set x(value: number) {
@@ -90,10 +90,10 @@ module Phaser {
}
/**
/**
* The y coordinate of the top-left corner of the rectangle
* @property y
* @type Number
* @type {Number}
**/
public set y(value:number) {
@@ -101,105 +101,105 @@ module Phaser {
}
/**
/**
* The x and y coordinate of the top-left corner of the rectangle (same as x/y)
* @property topLeft
* @type MicroPoint
* @type {MicroPoint}
**/
public topLeft: MicroPoint;
/**
/**
* The x and y coordinate of the top-center of the rectangle
* @property topCenter
* @type MicroPoint
* @type {MicroPoint}
**/
public topCenter: MicroPoint;
/**
/**
* The x and y coordinate of the top-right corner of the rectangle
* @property topRight
* @type MicroPoint
* @type {MicroPoint}
**/
public topRight: MicroPoint;
/**
/**
* The x and y coordinate of the left-center of the rectangle
* @property leftCenter
* @type MicroPoint
* @type {MicroPoint}
**/
public leftCenter: MicroPoint;
/**
/**
* The x and y coordinate of the center of the rectangle
* @property center
* @type MicroPoint
* @type {MicroPoint}
**/
public center: MicroPoint;
/**
/**
* The x and y coordinate of the right-center of the rectangle
* @property rightCenter
* @type MicroPoint
* @type {MicroPoint}
**/
public rightCenter: MicroPoint;
/**
/**
* The x and y coordinate of the bottom-left corner of the rectangle
* @property bottomLeft
* @type MicroPoint
* @type {MicroPoint}
**/
public bottomLeft: MicroPoint;
/**
/**
* The x and y coordinate of the bottom-center of the rectangle
* @property bottomCenter
* @type MicroPoint
* @type {MicroPoint}
**/
public bottomCenter: MicroPoint;
/**
/**
* The x and y coordinate of the bottom-right corner of the rectangle
* @property bottomRight
* @type MicroPoint
* @type {MicroPoint}
**/
public bottomRight: MicroPoint;
/**
/**
* The width of the rectangle
* @property width
* @type Number
* @type {Number}
**/
private _width: number = 0;
/**
/**
* The height of the rectangle
* @property height
* @type Number
* @type {Number}
**/
private _height: number = 0;
/**
/**
* Half of the width of the rectangle
* @property halfWidth
* @type Number
* @type {Number}
**/
private _halfWidth: number = 0;
/**
/**
* Half of the height of the rectangle
* @property halfHeight
* @type Number
* @type {Number}
**/
private _halfHeight: number = 0;
/**
/**
* The size of the longest side (width or height)
* @property length
* @type Number
* @type {Number}
**/
public length: number = 0;
/**
/**
* Updates all of the MicroPoints based on the values of width and height.
* You should not normally call this directly.
**/
@@ -264,10 +264,10 @@ module Phaser {
}
/**
/**
* The width of the rectangle
* @property width
* @type Number
* @type {Number}
**/
public set width(value: number) {
@@ -277,10 +277,10 @@ module Phaser {
}
/**
/**
* The height of the rectangle
* @property height
* @type Number
* @type {Number}
**/
public set height(value: number) {
@@ -290,10 +290,10 @@ module Phaser {
}
/**
/**
* The width of the rectangle
* @property width
* @type Number
* @type {Number}
**/
public get width(): number {
@@ -301,10 +301,10 @@ module Phaser {
}
/**
/**
* The height of the rectangle
* @property height
* @type Number
* @type {Number}
**/
public get height(): number {
@@ -312,10 +312,10 @@ module Phaser {
}
/**
/**
* Half of the width of the rectangle
* @property halfWidth
* @type Number
* @type {Number}
**/
public get halfWidth(): number {
@@ -323,10 +323,10 @@ module Phaser {
}
/**
/**
* Half of the height of the rectangle
* @property halfHeight
* @type Number
* @type {Number}
**/
public get halfHeight(): number {
@@ -350,7 +350,7 @@ module Phaser {
* The sum of the y and height properties.
* Changing the bottom property of a Rectangle object has no effect on the x, y and width properties, but does change the height property.
* @method bottom
* @param {Number} value
* @param {Number} value
**/
public set bottom(value: number) {
@@ -372,7 +372,7 @@ module Phaser {
* Changing the left property of a Rectangle object has no effect on the y and height properties.
* However it does affect the width property, whereas changing the x value does not affect the width property.
* @method left
* @ return {number}
* @ return {Number}
**/
public get left(): number {
@@ -385,7 +385,7 @@ module Phaser {
* Changing the left property of a Rectangle object has no effect on the y and height properties.
* However it does affect the width property, whereas changing the x value does not affect the width property.
* @method left
* @param {Number} value
* @param {Number} value
**/
public set left(value: number) {
@@ -411,7 +411,7 @@ module Phaser {
* Changing the right property of a Rectangle object has no effect on the x, y and height properties.
* However it does affect the width property.
* @method right
* @return {Number}
* @return {Number}
**/
public get right(): number {
@@ -424,7 +424,7 @@ module Phaser {
* Changing the right property of a Rectangle object has no effect on the x, y and height properties.
* However it does affect the width property.
* @method right
* @param {Number} value
* @param {Number} value
**/
public set right(value: number) {
@@ -456,7 +456,7 @@ module Phaser {
/**
* The volume of the Rectangle object in pixels, derived from width * height
* @method volume
* @return {Number}
* @return {Number}
**/
public get volume(): number {
@@ -467,7 +467,7 @@ module Phaser {
/**
* The perimeter size of the Rectangle object in pixels. This is the sum of all 4 sides.
* @method perimeter
* @return {Number}
* @return {Number}
**/
public get perimeter(): number {
@@ -480,7 +480,7 @@ module Phaser {
* Changing the top property of a Rectangle object has no effect on the x and width properties.
* However it does affect the height property, whereas changing the y value does not affect the height property.
* @method top
* @return {Number}
* @return {Number}
**/
public get top(): number {
@@ -626,7 +626,7 @@ module Phaser {
/**
* Increases the size of the Rectangle object by the specified amounts.
* The center point of the Rectangle object stays the same, and its size increases to the left and right by the dx value,
* The center point of the Rectangle object stays the same, and its size increases to the left and right by the dx value,
* and to the top and the bottom by the dy value.
* @method inflate
* @param {Number} dx The amount to be added to the left side of this Rectangle.
@@ -661,7 +661,7 @@ module Phaser {
/**
* If the Rectangle object specified in the toIntersect parameter intersects with this Rectangle object,
* returns the area of intersection as a Rectangle object. If the rectangles do not intersect, this method
* returns the area of intersection as a Rectangle object. If the rectangles do not intersect, this method
* returns an empty Rectangle object with its properties set to 0.
* @method intersection
* @param {Rectangle} toIntersect The Rectangle object to compare against to see if it intersects with this Rectangle object.
@@ -797,7 +797,7 @@ module Phaser {
/**
* Returns a string representation of this object.
* @method toString
* @return {string} a string representation of the instance.
* @return {String} a string representation of the instance.
**/
public toString(): string {
+87
View File
@@ -0,0 +1,87 @@
/// <reference path="../Game.ts" />
/// <reference path="Polygon.ts" />
/**
* Phaser - Response
*
*/
module Phaser {
export class Response {
/**
* An object representing the result of an intersection. Contain information about:
* - The two objects participating in the intersection
* - The vector representing the minimum change necessary to extract the first object
* from the second one.
* - Whether the first object is entirely inside the second, or vice versa.
*
* @constructor
*/
constructor() {
this.a = null;
this.b = null;
this.overlapN = new Vector2;
this.overlapV = new Vector2;
this.clear();
}
/**
* The first object in the collision
*/
public a;
/**
* The second object in the collision
*/
public b;
/**
* The shortest colliding axis (unit-vector)
*/
public overlapN: Vector2;
/**
* The overlap vector (i.e. overlapN.scale(overlap, overlap)).
* If this vector is subtracted from the position of `a`, `a` and `b` will no longer be colliding.
*/
public overlapV: Vector2;
/**
* Whether the first object is completely inside the second.
*/
public aInB: bool;
/**
* Whether the second object is completely inside the first.
*/
public bInA: bool;
/**
* Magnitude of the overlap on the shortest colliding axis
*/
public overlap: number;
/**
* Set some values of the response back to their defaults. Call this between tests if
* you are going to reuse a single Response object for multiple intersection tests (recommented)
*
* @return {Response} This for chaining
*/
public clear() {
this.aInB = true;
this.bInA = true;
this.overlap = Number.MAX_VALUE;
return this;
}
}
}
+457
View File
@@ -0,0 +1,457 @@
/// <reference path="../Game.ts" />
/**
* Phaser - Vector2
*
* A two dimensional vector.
* Contains methods and ideas from verlet-js by Sub Protocol, SAT.js by Jim Riecken and N by Metanet Software. Brandon Jones, Colin MacKenzie IV
*/
module Phaser {
export class Vector2 {
/**
* Creates a new Vector2 object.
* @class Vector2
* @constructor
* @param {Number} x The x position of the vector
* @param {Number} y The y position of the vector
* @return {Vector2} This object
**/
constructor(x: number = 0, y: number = 0) {
//var GLMAT_ARRAY_TYPE = (typeof Float32Array !== 'undefined') ? Float32Array : Array;
this.x = x;
this.y = y;
}
public x: number;
public y: number;
public setTo(x: number, y: number): Vector2 {
this.x = x;
this.y = y;
return this;
}
/**
* Add this vector to the given one and return the result.
*
* @param {Vector2} v The other Vector.
* @param {Vector2} The output Vector.
* @return {Vector2} The new Vector
*/
public add(v: Vector2, output?:Vector2 = new Vector2): Vector2 {
return output.setTo(this.x + v.x, this.y + v.y);
}
/**
* Subtract this vector to the given one and return the result.
*
* @param {Vector2} v The other Vector.
* @param {Vector2} The output Vector.
* @return {Vector2} The new Vector
*/
public sub(v: Vector2, output?:Vector2 = new Vector2): Vector2 {
return output.setTo(this.x - v.x, this.y - v.y);
}
/**
* Multiply this vector with the given one and return the result.
*
* @param {Vector2} v The other Vector.
* @param {Vector2} The output Vector.
* @return {Vector2} The new Vector
*/
public mul(v: Vector2, output?:Vector2 = new Vector2): Vector2 {
return output.setTo(this.x * v.x, this.y * v.y);
}
/**
* Divide this vector by the given one and return the result.
*
* @param {Vector2} v The other Vector.
* @param {Vector2} The output Vector.
* @return {Vector2} The new Vector
*/
public div(v: Vector2, output?:Vector2 = new Vector2): Vector2 {
return output.setTo(this.x / v.x, this.y / v.y);
}
/**
* Scale this vector by the given values and return the result.
*
* @param {number} x The scaling factor in the x direction.
* @param {?number=} y The scaling factor in the y direction. If this
* is not specified, the x scaling factor will be used.
* @return {Vector} The new Vector
*/
public scale(x: number, y?:number = null, output?:Vector2 = new Vector2): Vector2 {
if (y === null)
{
y = x;
}
return output.setTo(this.x * x, this.y * y);
}
/**
* Rotate this vector by 90 degrees
*
* @return {Vector} This for chaining.
*/
public perp(output?: Vector2 = this): Vector2 {
var x = this.x;
return output.setTo(this.y, -x);
}
// Same as copyFrom, used by VerletManager
public mutableSet(v: Vector2): Vector2 {
this.x = v.x;
this.y = v.y;
return this;
}
/**
* Add another vector to this one.
*
* @param {Vector} other The other Vector.
* @return {Vector} This for chaining.
*/
public mutableAdd(v: Vector2): Vector2 {
this.x += v.x;
this.y += v.y;
return this;
}
/**
* Subtract another vector from this one.
*
* @param {Vector} other The other Vector.
* @return {Vector} This for chaining.
*/
public mutableSub(v: Vector2): Vector2 {
this.x -= v.x;
this.y -= v.y;
return this;
}
/**
* Multiply another vector with this one.
*
* @param {Vector} other The other Vector.
* @return {Vector} This for chaining.
*/
public mutableMul(v: Vector2): Vector2 {
this.x *= v.x;
this.y *= v.y;
return this;
}
/**
* Divide this vector by another one.
*
* @param {Vector} other The other Vector.
* @return {Vector} This for chaining.
*/
public mutableDiv(v: Vector2): Vector2 {
this.x /= v.x;
this.y /= v.y;
return this;
}
/**
* Scale this vector.
*
* @param {number} x The scaling factor in the x direction.
* @param {?number=} y The scaling factor in the y direction. If this
* is not specified, the x scaling factor will be used.
* @return {Vector} This for chaining.
*/
public mutableScale(x: number, y?:number): Vector2 {
this.x *= x;
this.y *= y || x;
return this;
}
/**
* Multiply this vector by the given scalar.
*
* @param {number} scalar
* @return {Vector2} This for chaining.
*/
public mutableMultiplyByScalar(scalar: number): Vector2 {
this.x *= scalar;
this.y *= scalar;
return this;
}
/**
* Divide this vector by the given scalar.
*
* @param {number} scalar
* @return {Vector2} This for chaining.
*/
public mutableDivideByScalar(scalar: number): Vector2 {
this.x /= scalar;
this.y /= scalar;
return this;
}
/**
* Reverse this vector.
*
* @return {Vector} This for chaining.
*/
public reverse(): Vector2 {
this.x = -this.x;
this.y = -this.y;
return this;
}
public edge(v: Vector2, output?: Vector2 = new Vector2): Vector2 {
return this.sub(v, output);
}
public equals(v: Vector2): bool {
return this.x == v.x && this.y == v.y;
}
public epsilonEquals(v: Vector2, epsilon:number): bool {
return Math.abs(this.x - v.x) <= epsilon && Math.abs(this.y - v.y) <= epsilon;
}
/**
* Get the length of this vector.
*
* @return {number} The length of this vector.
*/
public length(): number {
return Math.sqrt((this.x * this.x) + (this.y * this.y));
}
/**
* Get the length^2 of this vector.
*
* @return {number} The length^2 of this vector.
*/
public length2(): number {
return (this.x * this.x) + (this.y * this.y);
}
/**
* Get the distance between this vector and the given vector.
*
* @return {Vector2} v The vector to check
*/
public distance(v: Vector2): number {
return Math.sqrt(this.distance2(v));
}
/**
* Get the distance^2 between this vector and the given vector.
*
* @return {Vector2} v The vector to check
*/
public distance2(v: Vector2): number {
return ((v.x - this.x) * (v.x - this.x)) + ((v.y - this.y) * (v.y - this.y));
}
/**
* Project this vector on to another vector.
*
* @param {Vector} other The vector to project onto.
* @return {Vector} This for chaining.
*/
public project(other: Vector2): Vector2 {
var amt = this.dot(other) / other.length2();
if (amt != 0)
{
this.x = amt * other.x;
this.y = amt * other.y;
}
return this;
}
/**
* Project this vector onto a vector of unit length.
*
* @param {Vector} other The unit vector to project onto.
* @return {Vector} This for chaining.
*/
public projectN(other: Vector2): Vector2 {
var amt = this.dot(other);
if (amt != 0)
{
this.x = amt * other.x;
this.y = amt * other.y;
}
return this;
}
/**
* Reflect this vector on an arbitrary axis.
*
* @param {Vector} axis The vector representing the axis.
* @return {Vector} This for chaining.
*/
public reflect(axis): Vector2 {
var x = this.x;
var y = this.y;
this.project(axis).scale(2);
this.x -= x;
this.y -= y;
return this;
}
/**
* Reflect this vector on an arbitrary axis (represented by a unit vector)
*
* @param {Vector} axis The unit vector representing the axis.
* @return {Vector} This for chaining.
*/
public reflectN(axis): Vector2 {
var x = this.x;
var y = this.y;
this.projectN(axis).scale(2);
this.x -= x;
this.y -= y;
return this;
}
public getProjectionMagnitude(v: Vector2): number {
var den = v.dot(v);
if (den == 0)
{
return 0;
}
else
{
return Math.abs(this.dot(v) / den);
}
}
public direction(output?: Vector2 = new Vector2): Vector2 {
output.copyFrom(this);
return this.normalize(output);
}
public normalRightHand(output?: Vector2 = this): Vector2 {
return output.setTo(this.y * -1, this.x);
}
/**
* Normalize (make unit length) this vector.
*
* @return {Vector} This for chaining.
*/
public normalize(output?: Vector2 = this): Vector2 {
var m = this.length();
if (m != 0)
{
output.setTo(this.x / m, this.y / m);
}
return output;
}
public getMagnitude(): number {
return Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2));
}
/**
* Get the dot product of this vector against another.
*
* @param {Vector} other The vector to dot this one against.
* @return {number} The dot product.
*/
public dot(v: Vector2): number {
return ((this.x * v.x) + (this.y * v.y));
}
/**
* Get the cross product of this vector against another.
*
* @param {Vector} other The vector to cross this one against.
* @return {number} The cross product.
*/
public cross(v: Vector2): number {
return ((this.x * v.y) - (this.y * v.x));
}
/**
* Get the angle between this vector and the given vector.
*
* @return {Vector2} v The vector to check
*/
public angle(v: Vector2): number {
return Math.atan2(this.x * v.y - this.y * v.x, this.x * v.x + this.y * v.y);
}
public angle2(vLeft: Vector2, vRight: Vector2): number {
return vLeft.sub(this).angle(vRight.sub(this));
}
/**
* Rotate this vector around the origin to the given angle (theta) and return the result in a new Vector
*
* @return {Vector2} v The vector to check
*/
public rotate(origin, theta, output?: Vector2 = new Vector2): Vector2 {
var x = this.x - origin.x;
var y = this.y - origin.y;
return output.setTo(x * Math.cos(theta) - y * Math.sin(theta) + origin.x, x * Math.sin(theta) + y * Math.cos(theta) + origin.y);
}
public clone(output?: Vector2 = new Vector2): Vector2 {
return output.setTo(this.x, this.y);
}
public copyFrom(v: Vector2): Vector2 {
this.x = v.x;
this.y = v.y;
return this;
}
public copyTo(v: Vector2): Vector2 {
return v.setTo(this.x, this.y);
}
/**
* Returns a string representation of this object.
* @method toString
* @return {string} a string representation of the object.
**/
public toString(): string {
return "[{Vector2 (x=" + this.x + " y=" + this.y + ")}]";
}
}
}
-3
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

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