Merged N+ physics in and tidied up the Docs folder and logos.

This commit is contained in:
Richard Davey 2013-08-11 12:15:53 +01:00
parent aff7d99a8a
commit c2d7fb7fab
108 changed files with 17900 additions and 2017 deletions

View file

Before

Width:  |  Height:  |  Size: 6.9 MiB

After

Width:  |  Height:  |  Size: 6.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 493 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 KiB

View file

Before

Width:  |  Height:  |  Size: 809 B

After

Width:  |  Height:  |  Size: 809 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4 KiB

View file

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View file

Before

Width:  |  Height:  |  Size: 130 KiB

After

Width:  |  Height:  |  Size: 130 KiB

View file

Before

Width:  |  Height:  |  Size: 204 KiB

After

Width:  |  Height:  |  Size: 204 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 531 B

View file

@ -238,10 +238,6 @@ var Phaser;
}
};
Game.prototype.emptyCallback = function () {
// Called by onUpdateCallback etc
};
/**
* Game loop method will be called when it's running.
*/

View file

@ -2,7 +2,7 @@
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<ProjectGuid>{A90BE60F-CAEA-4747-904A-CDB097BA2459}</ProjectGuid>
<ProjectGuid>{BB30C59B-5B34-4F7C-B5CC-8D49EA280EDA}</ProjectGuid>
<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<OutputPath>bin</OutputPath>
@ -17,6 +17,122 @@
</PropertyGroup>
<ItemGroup>
<TypeScriptCompile Include="utils\CanvasUtils.ts" />
<TypeScriptCompile Include="particles\ParticlePool.ts" />
<TypeScriptCompile Include="particles\ParticleManager.ts" />
<TypeScriptCompile Include="particles\initialize\Mass.ts" />
<TypeScriptCompile Include="particles\initialize\Initialize.ts" />
<TypeScriptCompile Include="particles\behaviours\Behaviour.ts" />
<Content Include="particles\behaviours\Behaviour.js">
<DependentUpon>Behaviour.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="particles\behaviours\RandomDrift.ts" />
<Content Include="particles\behaviours\RandomDrift.js">
<DependentUpon>RandomDrift.ts</DependentUpon>
</Content>
<Content Include="particles\initialize\Initialize.js">
<DependentUpon>Initialize.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="particles\initialize\Life.ts" />
<Content Include="particles\initialize\Life.js">
<DependentUpon>Life.ts</DependentUpon>
</Content>
<Content Include="particles\initialize\Mass.js">
<DependentUpon>Mass.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="particles\initialize\Radius.ts" />
<TypeScriptCompile Include="particles\initialize\Position.ts" />
<Content Include="particles\initialize\Position.js">
<DependentUpon>Position.ts</DependentUpon>
</Content>
<Content Include="particles\initialize\Radius.js">
<DependentUpon>Radius.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="particles\initialize\Rate.ts" />
<Content Include="particles\initialize\Rate.js">
<DependentUpon>Rate.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="particles\initialize\Velocity.ts" />
<Content Include="particles\initialize\Velocity.js">
<DependentUpon>Velocity.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="particles\NumericalIntegration.ts" />
<Content Include="particles\NumericalIntegration.js">
<DependentUpon>NumericalIntegration.ts</DependentUpon>
</Content>
<Content Include="particles\ParticleManager.js">
<DependentUpon>ParticleManager.ts</DependentUpon>
</Content>
<Content Include="particles\ParticlePool.js">
<DependentUpon>ParticlePool.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="particles\ParticleUtils.ts" />
<Content Include="particles\ParticleUtils.js">
<DependentUpon>ParticleUtils.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="particles\Span.ts" />
<TypeScriptCompile Include="particles\Polar2D.ts" />
<Content Include="particles\Polar2D.js">
<DependentUpon>Polar2D.ts</DependentUpon>
</Content>
<Content Include="particles\Span.js">
<DependentUpon>Span.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="particles\zone\Zone.ts" />
<TypeScriptCompile Include="particles\zone\PointZone.ts" />
<Content Include="particles\zone\PointZone.js">
<DependentUpon>PointZone.ts</DependentUpon>
</Content>
<Content Include="particles\zone\Zone.js">
<DependentUpon>Zone.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="physics\PhysicsManager.ts" />
<TypeScriptCompile Include="physics\AABB.ts" />
<Content Include="physics\AABB.js">
<DependentUpon>AABB.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="physics\Circle.ts" />
<TypeScriptCompile Include="physics\aabb\ProjAABBFull.ts" />
<TypeScriptCompile Include="physics\aabb\ProjAABBConvex.ts" />
<TypeScriptCompile Include="physics\aabb\ProjAABBConcave.ts" />
<Content Include="physics\aabb\ProjAABBConcave.js">
<DependentUpon>ProjAABBConcave.ts</DependentUpon>
</Content>
<Content Include="physics\aabb\ProjAABBConvex.js">
<DependentUpon>ProjAABBConvex.ts</DependentUpon>
</Content>
<Content Include="physics\aabb\ProjAABBFull.js">
<DependentUpon>ProjAABBFull.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="physics\Body.ts" />
<Content Include="physics\Body.js">
<DependentUpon>Body.ts</DependentUpon>
</Content>
<Content Include="physics\Circle.js">
<DependentUpon>Circle.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="physics\circle\ProjCircleFull.ts" />
<TypeScriptCompile Include="physics\circle\ProjCircle45Deg.ts" />
<Content Include="physics\circle\ProjCircle45Deg.js">
<DependentUpon>ProjCircle45Deg.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="physics\circle\ProjCircleConcave.ts" />
<Content Include="physics\circle\ProjCircleConcave.js">
<DependentUpon>ProjCircleConcave.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="physics\circle\ProjCircleConvex.ts" />
<Content Include="physics\circle\ProjCircleConvex.js">
<DependentUpon>ProjCircleConvex.ts</DependentUpon>
</Content>
<Content Include="physics\circle\ProjCircleFull.js">
<DependentUpon>ProjCircleFull.ts</DependentUpon>
</Content>
<Content Include="physics\PhysicsManager.js">
<DependentUpon>PhysicsManager.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="physics\TileMapCell.ts" />
<Content Include="physics\TileMapCell.js">
<DependentUpon>TileMapCell.ts</DependentUpon>
</Content>
<Content Include="utils\CanvasUtils.js">
<DependentUpon>CanvasUtils.ts</DependentUpon>
</Content>
@ -285,10 +401,6 @@
<Content Include="tilemap\TilemapLayer.js">
<DependentUpon>TilemapLayer.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="physics\arcade\Body.ts" />
<Content Include="physics\arcade\Body.js">
<DependentUpon>Body.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="gameobjects\Events.ts" />
<Content Include="gameobjects\Events.js">
<DependentUpon>Events.ts</DependentUpon>
@ -398,6 +510,7 @@
<DependentUpon>Game.ts</DependentUpon>
</Content>
</ItemGroup>
<ItemGroup />
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>

View file

@ -78,8 +78,6 @@
/// <reference path="tilemap/Tilemap.ts" />
/// <reference path="tilemap/TilemapLayer.ts" />
/// <reference path="physics/arcade/Body.ts" />
/// <reference path="gameobjects/Events.ts" />
/// <reference path="gameobjects/Sprite.ts" />
/// <reference path="gameobjects/TransformManager.ts" />
@ -111,6 +109,38 @@
/// <reference path="renderers/canvas/TilemapRenderer.ts" />
/// <reference path="renderers/canvas/CanvasRenderer.ts" />
/// <reference path="physics/PhysicsManager.ts" />
/// <reference path="physics/Body.ts" />
/// <reference path="physics/AABB.ts" />
/// <reference path="physics/Circle.ts" />
/// <reference path="physics/TileMapCell.ts" />
/// <reference path="physics/aabb/ProjAABBFull.ts" />
/// <reference path="physics/aabb/ProjAABBConvex.ts" />
/// <reference path="physics/aabb/ProjAABBConcave.ts" />
/// <reference path="physics/circle/ProjCircleFull.ts" />
/// <reference path="physics/circle/ProjCircleConvex.ts" />
/// <reference path="physics/circle/ProjCircleConcave.ts" />
/// <reference path="physics/circle/ProjCircle45Deg.ts" />
/// <reference path="particles/ParticleManager.ts" />
/// <reference path="particles/Particle.ts" />
/// <reference path="particles/Emitter.ts" />
/// <reference path="particles/ParticlePool.ts" />
/// <reference path="particles/ParticleUtils.ts" />
/// <reference path="particles/Polar2D.ts" />
/// <reference path="particles/Span.ts" />
/// <reference path="particles/NumericalIntegration.ts" />
/// <reference path="particles/behaviours/Behaviour.ts" />
/// <reference path="particles/behaviours/RandomDrift.ts" />
/// <reference path="particles/initialize/Initialize.ts" />
/// <reference path="particles/initialize/Life.ts" />
/// <reference path="particles/initialize/Mass.ts" />
/// <reference path="particles/initialize/Position.ts" />
/// <reference path="particles/initialize/Rate.ts" />
/// <reference path="particles/initialize/Velocity.ts" />
/// <reference path="particles/zone/Zone.ts" />
/// <reference path="particles/zone/PointZone.ts" />
/// <reference path="World.ts" />
/// <reference path="Stage.ts" />
/// <reference path="State.ts" />

View file

@ -35,6 +35,7 @@ var Phaser;
this.modified = false;
this.game = game;
this.type = Phaser.Types.GROUP;
this.active = true;
this.exists = true;
this.visible = true;
@ -95,7 +96,9 @@ var Phaser;
this._member = this.members[this._i++];
if (this._member != null && this._member.exists && this._member.active) {
this._member.preUpdate();
if (this._member.type != Phaser.Types.GROUP) {
this._member.preUpdate();
}
this._member.update();
}
}

View file

@ -84,6 +84,19 @@ var Phaser;
return this.game.sound.add(key, volume, loop);
};
GameObjectFactory.prototype.circle = function (x, y, radius) {
return new Phaser.Physics.Circle(this.game, x, y, radius);
};
GameObjectFactory.prototype.aabb = function (x, y, width, height) {
return new Phaser.Physics.AABB(this.game, x, y, Math.floor(width / 2), Math.floor(height / 2));
};
GameObjectFactory.prototype.cell = function (x, y, width, height, state) {
if (typeof state === "undefined") { state = Phaser.Physics.TileMapCell.TID_FULL; }
return new Phaser.Physics.TileMapCell(this.game, x, y, width, height).SetState(state);
};
/**
* Create a new Sprite with the physics automatically created and set to DYNAMIC. The Sprite position offset is set to its center.
*
@ -125,10 +138,9 @@ var Phaser;
*
* @return {Particle} The newly created particle object.
*/
GameObjectFactory.prototype.particle = function () {
return new Phaser.ArcadeParticle(this.game);
};
//public particle(): Phaser.ArcadeParticle {
// return new Phaser.ArcadeParticle(this.game);
//}
/**
* Create a new Emitter.
*
@ -137,13 +149,9 @@ var Phaser;
* @param size {number} Optional, size of this emitter.
* @return {Emitter} The newly created emitter object.
*/
GameObjectFactory.prototype.emitter = function (x, y, size) {
if (typeof x === "undefined") { x = 0; }
if (typeof y === "undefined") { y = 0; }
if (typeof size === "undefined") { size = 0; }
return this._world.group.add(new Phaser.ArcadeEmitter(this.game, x, y, size));
};
//public emitter(x: number = 0, y: number = 0, size: number = 0): Phaser.ArcadeEmitter {
// return <Phaser.ArcadeEmitter> this._world.group.add(new Phaser.ArcadeEmitter(this.game, x, y, size));
//}
/**
* Create a new ScrollZone object with image key, position and size.
*
@ -242,10 +250,9 @@ var Phaser;
* @param emitter The Emitter to add to the Game World
* @return {Phaser.Emitter} The Emitter object
*/
GameObjectFactory.prototype.existingEmitter = function (emitter) {
return this._world.group.add(emitter);
};
//public existingEmitter(emitter: Phaser.ArcadeEmitter): Phaser.ArcadeEmitter {
// 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.

View file

@ -89,6 +89,18 @@ module Phaser {
return <Phaser.Sound> this.game.sound.add(key, volume, loop);
}
public circle(x: number, y: number, radius: number): Phaser.Physics.Circle {
return new Phaser.Physics.Circle(this.game, x, y, radius);
}
public aabb(x: number, y: number, width: number, height:number): Phaser.Physics.AABB {
return new Phaser.Physics.AABB(this.game, x, y, Math.floor(width / 2), Math.floor(height / 2));
}
public cell(x: number, y: number, width: number, height: number, state: number = Phaser.Physics.TileMapCell.TID_FULL): Phaser.Physics.TileMapCell {
return new Phaser.Physics.TileMapCell(this.game, x, y, width, height).SetState(state);
}
/**
* Create a new Sprite with the physics automatically created and set to DYNAMIC. The Sprite position offset is set to its center.
*
@ -130,9 +142,9 @@ module Phaser {
*
* @return {Particle} The newly created particle object.
*/
public particle(): Phaser.ArcadeParticle {
return new Phaser.ArcadeParticle(this.game);
}
//public particle(): Phaser.ArcadeParticle {
// return new Phaser.ArcadeParticle(this.game);
//}
/**
* Create a new Emitter.
@ -142,9 +154,9 @@ module Phaser {
* @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): Phaser.ArcadeEmitter {
return <Phaser.ArcadeEmitter> this._world.group.add(new Phaser.ArcadeEmitter(this.game, x, y, size));
}
//public emitter(x: number = 0, y: number = 0, size: number = 0): Phaser.ArcadeEmitter {
// return <Phaser.ArcadeEmitter> this._world.group.add(new Phaser.ArcadeEmitter(this.game, x, y, size));
//}
/**
* Create a new ScrollZone object with image key, position and size.
@ -237,9 +249,9 @@ module Phaser {
* @param emitter The Emitter to add to the Game World
* @return {Phaser.Emitter} The Emitter object
*/
public existingEmitter(emitter: Phaser.ArcadeEmitter): Phaser.ArcadeEmitter {
return this._world.group.add(emitter);
}
//public existingEmitter(emitter: Phaser.ArcadeEmitter): Phaser.ArcadeEmitter {
// return this._world.group.add(emitter);
//}
/**
* Add an existing ScrollZone to the current world.

View file

@ -144,8 +144,7 @@ var Phaser;
TransformManager.prototype.centerOn = function (x, y) {
this.parent.x = x + (this.parent.x - this.center.x);
this.parent.y = y + (this.parent.y - this.center.y);
this.setCache();
//this.setCache();
};
/**
@ -164,10 +163,8 @@ var Phaser;
this._size.y = this.parent.height;
this._origin.x = this.origin.x;
this._origin.y = this.origin.y;
this._sc.x = Math.sin((this.rotation + this.rotationOffset) * Phaser.GameMath.DEG_TO_RAD);
this._sc.y = Math.cos((this.rotation + this.rotationOffset) * Phaser.GameMath.DEG_TO_RAD);
this._scA.y = Math.cos((this.rotation + this.rotationOffset) * Phaser.GameMath.DEG_TO_RAD + this._angle);
this._scA.x = Math.sin((this.rotation + this.rotationOffset) * Phaser.GameMath.DEG_TO_RAD + this._angle);
this._scA.y = Math.cos((this.rotation + this.rotationOffset) * Phaser.GameMath.DEG_TO_RAD + this._angle);
this._prevRotation = this.rotation;
if (this.parent.texture && this.parent.texture.renderRotation) {
@ -188,6 +185,9 @@ var Phaser;
this._pos.x = this.parent.x;
this._pos.y = this.parent.y;
this._flippedX = this.parent.texture.flippedX;
this._flippedY = this.parent.texture.flippedY;
};
/**
@ -213,9 +213,7 @@ var Phaser;
this._dirty = true;
}
if (this.rotation != this._prevRotation) {
this._sc.x = Math.sin((this.rotation + this.rotationOffset) * Phaser.GameMath.DEG_TO_RAD);
this._sc.y = Math.cos((this.rotation + this.rotationOffset) * Phaser.GameMath.DEG_TO_RAD);
if (this.rotation != this._prevRotation || this._dirty) {
this._scA.y = Math.cos((this.rotation + this.rotationOffset) * Phaser.GameMath.DEG_TO_RAD + this._angle);
this._scA.x = Math.sin((this.rotation + this.rotationOffset) * Phaser.GameMath.DEG_TO_RAD + this._angle);
@ -243,27 +241,35 @@ var Phaser;
this._pos.x = this.parent.x;
this._pos.y = this.parent.y;
// Translate
this.local.data[2] = this.parent.x;
this.local.data[5] = this.parent.y;
}
if (this.parent.texture.flippedX) {
this.local.data[0] = this._sc.y * -this.scale.x;
this.local.data[3] = (this._sc.x * -this.scale.x) + this.skew.x;
} else {
this.local.data[0] = this._sc.y * this.scale.x;
this.local.data[3] = (this._sc.x * this.scale.x) + this.skew.x;
if (this._dirty || this._flippedX != this.parent.texture.flippedX) {
this._flippedX = this.parent.texture.flippedX;
if (this._flippedX) {
this.local.data[0] = this._sc.y * -this.scale.x;
this.local.data[3] = (this._sc.x * -this.scale.x) + this.skew.x;
} else {
this.local.data[0] = this._sc.y * this.scale.x;
this.local.data[3] = (this._sc.x * this.scale.x) + this.skew.x;
}
}
if (this.parent.texture.flippedY) {
this.local.data[4] = this._sc.y * -this.scale.y;
this.local.data[1] = -(this._sc.x * -this.scale.y) + this.skew.y;
} else {
this.local.data[4] = this._sc.y * this.scale.y;
this.local.data[1] = -(this._sc.x * this.scale.y) + this.skew.y;
}
if (this._dirty || this._flippedY != this.parent.texture.flippedY) {
this._flippedY = this.parent.texture.flippedY;
// Translate
this.local.data[2] = this.parent.x;
this.local.data[5] = this.parent.y;
if (this._flippedY) {
this.local.data[4] = this._sc.y * -this.scale.y;
this.local.data[1] = -(this._sc.x * -this.scale.y) + this.skew.y;
} else {
this.local.data[4] = this._sc.y * this.scale.y;
this.local.data[1] = -(this._sc.x * this.scale.y) + this.skew.y;
}
}
};
return TransformManager;
})();

View file

@ -57,6 +57,8 @@ module Phaser.Components {
private _angle: number;
private _distance: number;
private _prevRotation: number;
private _flippedX: boolean;
private _flippedY: boolean;
/**
* Reference to Phaser.Game
@ -197,7 +199,7 @@ module Phaser.Components {
this.parent.x = x + (this.parent.x - this.center.x);
this.parent.y = y + (this.parent.y - this.center.y);
this.setCache();
//this.setCache();
}
@ -218,10 +220,8 @@ module Phaser.Components {
this._size.y = this.parent.height;
this._origin.x = this.origin.x;
this._origin.y = this.origin.y;
this._sc.x = Math.sin((this.rotation + this.rotationOffset) * Phaser.GameMath.DEG_TO_RAD);
this._sc.y = Math.cos((this.rotation + this.rotationOffset) * Phaser.GameMath.DEG_TO_RAD);
this._scA.y = Math.cos((this.rotation + this.rotationOffset) * Phaser.GameMath.DEG_TO_RAD + this._angle);
this._scA.x = Math.sin((this.rotation + this.rotationOffset) * Phaser.GameMath.DEG_TO_RAD + this._angle);
this._scA.y = Math.cos((this.rotation + this.rotationOffset) * Phaser.GameMath.DEG_TO_RAD + this._angle);
this._prevRotation = this.rotation;
if (this.parent.texture && this.parent.texture.renderRotation)
@ -246,6 +246,9 @@ module Phaser.Components {
this._pos.x = this.parent.x;
this._pos.y = this.parent.y;
this._flippedX = this.parent.texture.flippedX;
this._flippedY = this.parent.texture.flippedY;
}
/**
@ -274,10 +277,8 @@ module Phaser.Components {
}
// 2) Rotation change
if (this.rotation != this._prevRotation)
if (this.rotation != this._prevRotation || this._dirty)
{
this._sc.x = Math.sin((this.rotation + this.rotationOffset) * Phaser.GameMath.DEG_TO_RAD);
this._sc.y = Math.cos((this.rotation + this.rotationOffset) * Phaser.GameMath.DEG_TO_RAD);
this._scA.y = Math.cos((this.rotation + this.rotationOffset) * Phaser.GameMath.DEG_TO_RAD + this._angle);
this._scA.x = Math.sin((this.rotation + this.rotationOffset) * Phaser.GameMath.DEG_TO_RAD + this._angle);
@ -297,7 +298,7 @@ module Phaser.Components {
this._dirty = true;
}
// If it has moved, update the edges and center
// 3) If it has moved (or any of the above) then update the edges and center
if (this._dirty || this.parent.x != this._pos.x || this.parent.y != this._pos.y)
{
this.center.x = this.parent.x + this._distance * this._scA.y;
@ -310,34 +311,44 @@ module Phaser.Components {
this._pos.x = this.parent.x;
this._pos.y = this.parent.y;
// Translate
this.local.data[2] = this.parent.x;
this.local.data[5] = this.parent.y;
}
// Scale and Skew
if (this.parent.texture.flippedX)
if (this._dirty || this._flippedX != this.parent.texture.flippedX)
{
this.local.data[0] = this._sc.y * -this.scale.x;
this.local.data[3] = (this._sc.x * -this.scale.x) + this.skew.x;
}
else
{
this.local.data[0] = this._sc.y * this.scale.x;
this.local.data[3] = (this._sc.x * this.scale.x) + this.skew.x;
this._flippedX = this.parent.texture.flippedX;
if (this._flippedX)
{
this.local.data[0] = this._sc.y * -this.scale.x;
this.local.data[3] = (this._sc.x * -this.scale.x) + this.skew.x;
}
else
{
this.local.data[0] = this._sc.y * this.scale.x;
this.local.data[3] = (this._sc.x * this.scale.x) + this.skew.x;
}
}
if (this.parent.texture.flippedY)
if (this._dirty || this._flippedY != this.parent.texture.flippedY)
{
this.local.data[4] = this._sc.y * -this.scale.y;
this.local.data[1] = -(this._sc.x * -this.scale.y) + this.skew.y;
}
else
{
this.local.data[4] = this._sc.y * this.scale.y;
this.local.data[1] = -(this._sc.x * this.scale.y) + this.skew.y;
}
this._flippedY = this.parent.texture.flippedY;
// Translate
this.local.data[2] = this.parent.x;
this.local.data[5] = this.parent.y;
if (this._flippedY)
{
this.local.data[4] = this._sc.y * -this.scale.y;
this.local.data[1] = -(this._sc.x * -this.scale.y) + this.skew.y;
}
else
{
this.local.data[4] = this._sc.y * this.scale.y;
this.local.data[1] = -(this._sc.x * this.scale.y) + this.skew.y;
}
}
}

View file

@ -1,327 +1,305 @@
/// <reference path="../_definitions.ts" />
var __extends = this.__extends || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
__.prototype = b.prototype;
d.prototype = new __();
};
/**
* Phaser - ArcadeEmitter
*
* Emitter is a lightweight particle emitter. It can be used for one-time explosions or for
* continuous effects like rain and fire. All it really does is launch Particle objects out
* at set intervals, and fixes their positions and velocities accorindgly.
*/
var Phaser;
(function (Phaser) {
var ArcadeEmitter = (function (_super) {
__extends(ArcadeEmitter, _super);
/**
* Creates a new <code>Emitter</code> object at a specific position.
* Does NOT automatically generate or attach particles!
*
* @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.
*/
function ArcadeEmitter(game, x, y, size) {
if (typeof x === "undefined") { x = 0; }
if (typeof y === "undefined") { y = 0; }
if (typeof size === "undefined") { size = 0; }
_super.call(this, game, size);
this.x = x;
this.y = y;
this.width = 0;
this.height = 0;
this.minParticleSpeed = new Phaser.Vec2(-100, -100);
this.maxParticleSpeed = new Phaser.Vec2(100, 100);
this.minRotation = -360;
this.maxRotation = 360;
this.gravity = 0;
this.particleClass = null;
this.particleDrag = new Phaser.Vec2();
this.frequency = 0.1;
this.lifespan = 3;
this.bounce = 0;
this._quantity = 0;
this._counter = 0;
this._explode = true;
this.on = false;
this.exists = true;
this.active = true;
this.visible = true;
}
/**
* Clean up memory.
*/
ArcadeEmitter.prototype.destroy = function () {
this.minParticleSpeed = null;
this.maxParticleSpeed = null;
this.particleDrag = null;
this.particleClass = null;
this._point = null;
_super.prototype.destroy.call(this);
};
/**
* 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 {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).
*/
ArcadeEmitter.prototype.makeParticles = function (graphics, quantity, multiple, collide) {
if (typeof quantity === "undefined") { quantity = 50; }
if (typeof multiple === "undefined") { multiple = false; }
if (typeof collide === "undefined") { collide = 0; }
this.maxSize = quantity;
var totalFrames = 1;
/*
if(Multiple)
{
var sprite:Sprite = new Sprite(this.game);
sprite.loadGraphic(Graphics,true);
totalFrames = sprite.frames;
sprite.destroy();
}
/// <reference path="../_definitions.ts" />
(function (Particles) {
var Emitter = (function () {
/**
* You can use this emit particles.
*
* It will dispatch follow events:
* Proton.PARTICLE_CREATED
* Proton.PARTICLE_UPDATA
* Proton.PARTICLE_DEAD
*
* @class Proton.Emitter
* @constructor
* @param {Object} pObj the parameters object;
* for example {damping:0.01,bindEmitter:false}
*/
var randomFrame;
var particle;
var i = 0;
function Emitter(pObj) {
this.initializes = [];
this.particles = [];
this.behaviours = [];
this.emitTime = 0;
this.emitTotalTimes = -1;
this.initializes = [];
this.particles = [];
this.behaviours = [];
this.emitTime = 0;
this.emitTotalTimes = -1;
while (i < quantity) {
if (this.particleClass == null) {
particle = new Phaser.ArcadeParticle(this.game);
} else {
particle = new this.particleClass(this.game);
}
/**
* The friction coefficient for all particle emit by This;
* @property damping
* @type {Number}
* @default 0.006
*/
this.damping = .006;
if (multiple) {
/*
randomFrame = this.game.math.random()*totalFrames;
*/
} else {
if (graphics) {
particle.texture.loadImage(graphics);
}
}
/**
* If bindEmitter the particles can bind this emitter's property;
* @property bindEmitter
* @type {Boolean}
* @default true
*/
this.bindEmitter = true;
if (collide > 0) {
//particle.body.allowCollisions = Types.ANY;
particle.body.type = Phaser.Types.BODY_DYNAMIC;
particle.width *= collide;
particle.height *= collide;
} else {
//particle.body.allowCollisions = Types.NONE;
}
/**
* The number of particles per second emit (a [particle]/b [s]);
* @property rate
* @type {Proton.Rate}
* @default Proton.Rate(1, .1)
*/
this.rate = new Phaser.Particles.Initializers.Rate(1, .1);
particle.exists = false;
// Center the origin for rotation assistance
//particle.transform.origin.setTo(particle.body.bounds.halfWidth, particle.body.bounds.halfHeight);
this.add(particle);
i++;
//Emitter._super_.call(this, pObj);
/**
* The emitter's id;
* @property id
* @type {String} id
*/
this.id = 'emitter_' + Emitter.ID++;
}
/**
* start emit particle
* @method emit
* @param {Number} emitTime begin emit time;
* @param {String} life the life of this emitter
*/
Emitter.prototype.emit = function (emitTime, life) {
this.emitTime = 0;
this.emitTotalTimes = Particles.ParticleUtils.initValue(emitTime, Infinity);
return this;
};
if (life == true || life == 'life' || life == 'destroy') {
if (emitTime == 'once')
this.life = 1;
else
this.life = this.emitTotalTimes;
} else if (!isNaN(life)) {
this.life = life;
}
ArcadeEmitter.prototype.preUpdate = function () {
};
ArcadeEmitter.prototype.postUpdate = function () {
};
this.rate.init();
};
/**
* Called automatically by the game loop, decides when to launch particles and when to "die".
*/
ArcadeEmitter.prototype.update = function () {
if (this.on) {
if (this._explode) {
this.on = false;
/**
* stop emiting
* @method stopEmit
*/
Emitter.prototype.stopEmit = function () {
this.emitTotalTimes = -1;
this.emitTime = 0;
};
var i = 0;
var l = this._quantity;
/**
* remove current all particles
* @method removeAllParticles
*/
Emitter.prototype.removeAllParticles = function () {
for (var i = 0; i < this.particles.length; i++)
this.particles[i].dead = true;
};
if ((l <= 0) || (l > this.length)) {
l = this.length;
}
/**
* create single particle;
*
* can use emit({x:10},new Gravity(10),{'particleUpdate',fun}) or emit([{x:10},new Initialize],new Gravity(10),{'particleUpdate',fun})
* @method removeAllParticles
*/
Emitter.prototype.createParticle = function (initialize, behaviour) {
if (typeof initialize === "undefined") { initialize = null; }
if (typeof behaviour === "undefined") { behaviour = null; }
var particle = Particles.ParticleManager.pool.get();
this.setupParticle(particle, initialize, behaviour);
while (i < l) {
this.emitParticle();
i++;
}
//this.dispatchEvent(new Proton.Event({
// type: Proton.PARTICLE_CREATED,
// particle: particle
//}));
return particle;
};
this._quantity = 0;
/**
* add initialize to this emitter
* @method addSelfInitialize
*/
Emitter.prototype.addSelfInitialize = function (pObj) {
if (pObj['init']) {
pObj.init(this);
} else {
this._timer += this.game.time.elapsed;
//this.initAll();
}
};
while ((this.frequency > 0) && (this._timer > this.frequency) && this.on) {
this._timer -= this.frequency;
this.emitParticle();
/**
* add the Initialize to particles;
*
* you can use initializes array:for example emitter.addInitialize(initialize1,initialize2,initialize3);
* @method addInitialize
* @param {Proton.Initialize} initialize like this new Proton.Radius(1, 12)
*/
Emitter.prototype.addInitialize = function () {
var length = arguments.length, i;
for (i = 0; i < length; i++) {
this.initializes.push(arguments[i]);
}
};
if ((this._quantity > 0) && (++this._counter >= this._quantity)) {
this.on = false;
this._quantity = 0;
/**
* remove the Initialize
* @method removeInitialize
* @param {Proton.Initialize} initialize a initialize
*/
Emitter.prototype.removeInitialize = function (initializer) {
var index = this.initializes.indexOf(initializer);
if (index > -1) {
this.initializes.splice(index, 1);
}
};
/**
* remove all Initializes
* @method removeInitializers
*/
Emitter.prototype.removeInitializers = function () {
Particles.ParticleUtils.destroyArray(this.initializes);
};
/**
* add the Behaviour to particles;
*
* you can use Behaviours array:emitter.addBehaviour(Behaviour1,Behaviour2,Behaviour3);
* @method addBehaviour
* @param {Proton.Behaviour} behaviour like this new Proton.Color('random')
*/
Emitter.prototype.addBehaviour = function () {
var length = arguments.length, i;
for (i = 0; i < length; i++) {
this.behaviours.push(arguments[i]);
if (arguments[i].hasOwnProperty("parents"))
arguments[i].parents.push(this);
}
};
/**
* remove the Behaviour
* @method removeBehaviour
* @param {Proton.Behaviour} behaviour a behaviour
*/
Emitter.prototype.removeBehaviour = function (behaviour) {
var index = this.behaviours.indexOf(behaviour);
if (index > -1)
this.behaviours.splice(index, 1);
};
/**
* remove all behaviours
* @method removeAllBehaviours
*/
Emitter.prototype.removeAllBehaviours = function () {
Particles.ParticleUtils.destroyArray(this.behaviours);
};
Emitter.prototype.integrate = function (time) {
var damping = 1 - this.damping;
Particles.ParticleManager.integrator.integrate(this, time, damping);
var length = this.particles.length, i;
for (i = 0; i < length; i++) {
var particle = this.particles[i];
particle.update(time, i);
Particles.ParticleManager.integrator.integrate(particle, time, damping);
//this.dispatchEvent(new Proton.Event({
// type: Proton.PARTICLE_UPDATE,
// particle: particle
//}));
}
};
Emitter.prototype.emitting = function (time) {
if (this.emitTotalTimes == 1) {
var length = this.rate.getValue(99999), i;
for (i = 0; i < length; i++) {
this.createParticle();
}
this.emitTotalTimes = 0;
} else if (!isNaN(this.emitTotalTimes)) {
this.emitTime += time;
if (this.emitTime < this.emitTotalTimes) {
var length = this.rate.getValue(time), i;
for (i = 0; i < length; i++) {
this.createParticle();
}
}
}
}
};
_super.prototype.update.call(this);
};
Emitter.prototype.update = function (time) {
this.age += time;
if (this.age >= this.life || this.dead) {
this.destroy();
}
/**
* Call this function to turn off all the particles and the emitter.
*/
ArcadeEmitter.prototype.kill = function () {
this.on = false;
this.alive = false;
this.exists = false;
};
this.emitting(time);
this.integrate(time);
var particle;
var length = this.particles.length, k;
for (k = length - 1; k >= 0; k--) {
particle = this.particles[k];
if (particle.dead) {
Particles.ParticleManager.pool.set(particle);
this.particles.splice(k, 1);
//this.dispatchEvent(new Proton.Event({
// type: Proton.PARTICLE_DEAD,
// particle: particle
//}));
}
}
};
/**
* Handy for bringing game objects "back to life". Just sets alive and exists back to true.
* In practice, this is most often called by <code>Object.reset()</code>.
*/
ArcadeEmitter.prototype.revive = function () {
this.alive = true;
this.exists = true;
};
Emitter.prototype.setupParticle = function (particle, initialize, behaviour) {
var initializes = this.initializes;
var behaviours = this.behaviours;
/**
* Call this function to start emitting 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".
*/
ArcadeEmitter.prototype.start = function (explode, lifespan, frequency, quantity) {
if (typeof explode === "undefined") { explode = true; }
if (typeof lifespan === "undefined") { lifespan = 0; }
if (typeof frequency === "undefined") { frequency = 0.1; }
if (typeof quantity === "undefined") { quantity = 0; }
this.revive();
if (initialize) {
if (initialize instanceof Array)
initializes = initialize;
else
initializes = [initialize];
}
this.visible = true;
this.on = true;
if (behaviour) {
if (behaviour instanceof Array)
behaviours = behaviour;
else
behaviours = [behaviour];
}
this._explode = explode;
this.lifespan = lifespan;
this.frequency = frequency;
this._quantity += quantity;
//Proton.InitializeUtil.initialize(this, particle, initializes);
particle.addBehaviours(behaviours);
particle.parent = this;
this.particles.push(particle);
};
this._counter = 0;
this._timer = 0;
};
/**
* Destory this Emitter
* @method destory
*/
Emitter.prototype.destroy = function () {
this.dead = true;
this.emitTotalTimes = -1;
if (this.particles.length == 0) {
this.removeInitializers();
this.removeAllBehaviours();
/**
* This function can be used both internally and externally to emit the next particle.
*/
ArcadeEmitter.prototype.emitParticle = function () {
var particle = this.recycle(Phaser.ArcadeParticle);
particle.lifespan = this.lifespan;
//particle.body.bounce.setTo(this.bounce, this.bounce);
Phaser.SpriteUtils.reset(particle, this.x - (particle.width >> 1) + this.game.rnd.integer * this.width, this.y - (particle.height >> 1) + this.game.rnd.integer * this.height);
particle.visible = true;
if (this.minParticleSpeed.x != this.maxParticleSpeed.x) {
particle.body.velocity.x = this.minParticleSpeed.x + this.game.rnd.integer * (this.maxParticleSpeed.x - this.minParticleSpeed.x);
} else {
particle.body.velocity.x = this.minParticleSpeed.x;
}
if (this.minParticleSpeed.y != this.maxParticleSpeed.y) {
particle.body.velocity.y = this.minParticleSpeed.y + this.game.rnd.integer * (this.maxParticleSpeed.y - this.minParticleSpeed.y);
} else {
particle.body.velocity.y = this.minParticleSpeed.y;
}
if (this.minRotation != this.maxRotation && this.minRotation !== 0 && this.maxRotation !== 0) {
particle.body.angularVelocity = this.minRotation + this.game.rnd.integer * (this.maxRotation - this.minRotation);
} else {
particle.body.angularVelocity = this.minRotation;
}
if (particle.body.angularVelocity != 0) {
particle.rotation = this.game.rnd.integer * 360 - 180;
}
//particle.body.drag.x = this.particleDrag.x;
//particle.body.drag.y = this.particleDrag.y;
particle.onEmit();
};
/**
* A more compact way of setting the width and 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.
*/
ArcadeEmitter.prototype.setSize = function (width, height) {
this.width = width;
this.height = height;
};
/**
* A more compact way of setting the X velocity range of the emitter.
*
* @param Min {number} The minimum value for this range.
* @param Max {number} The maximum value for this range.
*/
ArcadeEmitter.prototype.setXSpeed = function (min, max) {
if (typeof min === "undefined") { min = 0; }
if (typeof max === "undefined") { max = 0; }
this.minParticleSpeed.x = min;
this.maxParticleSpeed.x = max;
};
/**
* A more compact way of setting the Y velocity range of the emitter.
*
* @param Min {number} The minimum value for this range.
* @param Max {number} The maximum value for this range.
*/
ArcadeEmitter.prototype.setYSpeed = function (min, max) {
if (typeof min === "undefined") { min = 0; }
if (typeof max === "undefined") { max = 0; }
this.minParticleSpeed.y = min;
this.maxParticleSpeed.y = max;
};
/**
* A more compact way of setting the angular velocity constraints of the emitter.
*
* @param Min {number} The minimum value for this range.
* @param Max {number} The maximum value for this range.
*/
ArcadeEmitter.prototype.setRotation = function (min, max) {
if (typeof min === "undefined") { min = 0; }
if (typeof max === "undefined") { max = 0; }
this.minRotation = min;
this.maxRotation = max;
};
/**
* Change the emitter's midpoint to match the midpoint of a <code>Object</code>.
*
* @param Object {object} The <code>Object</code> that you want to sync up with.
*/
ArcadeEmitter.prototype.at = function (object) {
//this.x = object.body.bounds.halfWidth - (this.width >> 1);
//this.y = object.body.bounds.halfHeight - (this.height >> 1);
};
return ArcadeEmitter;
})(Phaser.Group);
Phaser.ArcadeEmitter = ArcadeEmitter;
if (this.parent)
this.parent.removeEmitter(this);
}
};
Emitter.ID = 0;
return Emitter;
})();
Particles.Emitter = Emitter;
})(Phaser.Particles || (Phaser.Particles = {}));
var Particles = Phaser.Particles;
})(Phaser || (Phaser = {}));

View file

@ -1,462 +1,333 @@
/// <reference path="../_definitions.ts" />
/**
* Phaser - ArcadeEmitter
*
* Emitter is a lightweight particle emitter. It can be used for one-time explosions or for
* continuous effects like rain and fire. All it really does is launch Particle objects out
* at set intervals, and fixes their positions and velocities accorindgly.
*/
module Phaser.Particles {
module Phaser {
export class ArcadeEmitter extends Phaser.Group {
export class Emitter {
/**
* Creates a new <code>Emitter</code> object at a specific position.
* Does NOT automatically generate or attach particles!
* You can use this emit particles.
*
* @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.
* It will dispatch follow events:
* Proton.PARTICLE_CREATED
* Proton.PARTICLE_UPDATA
* Proton.PARTICLE_DEAD
*
* @class Proton.Emitter
* @constructor
* @param {Object} pObj the parameters object;
* for example {damping:0.01,bindEmitter:false}
*/
constructor(game: Phaser.Game, x: number = 0, y: number = 0, size: number = 0) {
super(game, size);
constructor(pObj) {
this.x = x;
this.y = y;
this.width = 0;
this.height = 0;
this.minParticleSpeed = new Vec2(-100, -100);
this.maxParticleSpeed = new Vec2(100, 100);
this.minRotation = -360;
this.maxRotation = 360;
this.gravity = 0;
this.particleClass = null;
this.particleDrag = new Vec2();
this.frequency = 0.1;
this.lifespan = 3;
this.bounce = 0;
this._quantity = 0;
this._counter = 0;
this._explode = true;
this.on = false;
this.initializes = [];
this.particles = [];
this.behaviours = [];
this.emitTime = 0;
this.emitTotalTimes = -1;
/**
* The friction coefficient for all particle emit by This;
* @property damping
* @type {Number}
* @default 0.006
*/
this.damping = .006;
/**
* If bindEmitter the particles can bind this emitter's property;
* @property bindEmitter
* @type {Boolean}
* @default true
*/
this.bindEmitter = true;
/**
* The number of particles per second emit (a [particle]/b [s]);
* @property rate
* @type {Proton.Rate}
* @default Proton.Rate(1, .1)
*/
this.rate = new Phaser.Particles.Initializers.Rate(1, .1);
//Emitter._super_.call(this, pObj);
/**
* The emitter's id;
* @property id
* @type {String} id
*/
this.id = 'emitter_' + Emitter.ID++;
}
this.exists = true;
this.active = true;
this.visible = true;
static ID = 0;
id;
initializes = [];
particles = [];
behaviours = [];
emitTime = 0;
emitTotalTimes = -1;
damping;
bindEmitter;
rate;
life;
age;
dead;
parent;
/**
* start emit particle
* @method emit
* @param {Number} emitTime begin emit time;
* @param {String} life the life of this emitter
*/
emit(emitTime, life) {
this.emitTime = 0;
this.emitTotalTimes = ParticleUtils.initValue(emitTime, Infinity);
if (life == true || life == 'life' || life == 'destroy')
{
if (emitTime == 'once')
this.life = 1;
else
this.life = this.emitTotalTimes;
} else if (!isNaN(life))
{
this.life = life;
}
this.rate.init();
}
/**
* The X position of the top left corner of the emitter in world space.
* stop emiting
* @method stopEmit
*/
public x: number;
stopEmit() {
this.emitTotalTimes = -1;
this.emitTime = 0;
}
/**
* The Y position of the top left corner of emitter in world space.
* remove current all particles
* @method removeAllParticles
*/
public y: number;
/**
* The width of the emitter. Particles can be randomly generated from anywhere within this box.
*/
public width: number;
/**
* The height of the emitter. Particles can be randomly generated from anywhere within this box.
*/
public height: number;
removeAllParticles() {
for (var i = 0; i < this.particles.length; i++)
this.particles[i].dead = true;
}
/**
* create single particle;
*
* can use emit({x:10},new Gravity(10),{'particleUpdate',fun}) or emit([{x:10},new Initialize],new Gravity(10),{'particleUpdate',fun})
* @method removeAllParticles
*/
public alive: boolean;
createParticle(initialize=null, behaviour=null) {
var particle = ParticleManager.pool.get();
this.setupParticle(particle, initialize, behaviour);
//this.dispatchEvent(new Proton.Event({
// type: Proton.PARTICLE_CREATED,
// particle: particle
//}));
return particle;
}
/**
* add initialize to this emitter
* @method addSelfInitialize
*/
addSelfInitialize(pObj) {
if (pObj['init'])
{
pObj.init(this);
} else
{
//this.initAll();
}
}
/**
* add the Initialize to particles;
*
* you can use initializes array:for example emitter.addInitialize(initialize1,initialize2,initialize3);
* @method addInitialize
* @param {Proton.Initialize} initialize like this new Proton.Radius(1, 12)
*/
public active: boolean;
/**
* The minimum possible velocity of a particle.
* The default value is (-100,-100).
*/
public minParticleSpeed: Phaser.Vec2;
/**
* The maximum possible velocity of a particle.
* The default value is (100,100).
*/
public maxParticleSpeed: Phaser.Vec2;
/**
* The X and Y drag component of particles launched from the emitter.
*/
public particleDrag: Phaser.Vec2;
/**
* The minimum possible angular velocity of a particle. The default value is -360.
* NOTE: rotating particles are more expensive to draw than non-rotating ones!
*/
public minRotation: number;
/**
* The maximum possible angular velocity of a particle. The default value is 360.
* NOTE: rotating particles are more expensive to draw than non-rotating ones!
*/
public maxRotation: number;
/**
* Sets the <code>acceleration.y</code> member of each particle to this value on launch.
*/
public gravity: number;
/**
* Determines whether the emitter is currently emitting particles.
* It is totally safe to directly toggle this.
*/
public on: boolean;
/**
* How often a particle is emitted (if emitter is started with Explode == false).
*/
public frequency: number;
/**
* How long each particle lives once it is emitted.
* Set lifespan to 'zero' for particles to live forever.
*/
public lifespan: number;
/**
* How much each particle should bounce. 1 = full bounce, 0 = no bounce.
*/
public bounce: number;
/**
* Set your own particle class type here.
* Default is <code>Particle</code>.
*/
public particleClass;
/**
* Internal helper for deciding how many particles to launch.
*/
private _quantity: number;
/**
* Internal helper for the style of particle emission (all at once, or one at a time).
*/
private _explode: boolean;
/**
* Internal helper for deciding when to launch particles or kill them.
*/
private _timer: number;
/**
* Internal counter for figuring out how many particles to launch.
*/
private _counter: number;
/**
* Internal point object, handy for reusing for memory mgmt purposes.
*/
private _point: Phaser.Vec2;
/**
* Clean up memory.
*/
public destroy() {
this.minParticleSpeed = null;
this.maxParticleSpeed = null;
this.particleDrag = null;
this.particleClass = null;
this._point = null;
super.destroy();
addInitialize() {
var length = arguments.length, i;
for (i = 0; i < length; i++)
{
this.initializes.push(arguments[i]);
}
}
/**
* 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 {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).
* remove the Initialize
* @method removeInitialize
* @param {Proton.Initialize} initialize a initialize
*/
public makeParticles(graphics, quantity: number = 50, multiple: boolean = false, collide: number = 0): Phaser.ArcadeEmitter {
this.maxSize = quantity;
var totalFrames: number = 1;
/*
if(Multiple)
removeInitialize(initializer) {
var index = this.initializes.indexOf(initializer);
if (index > -1)
{
var sprite:Sprite = new Sprite(this.game);
sprite.loadGraphic(Graphics,true);
totalFrames = sprite.frames;
sprite.destroy();
this.initializes.splice(index, 1);
}
*/
var randomFrame: number;
var particle: Phaser.ArcadeParticle;
var i: number = 0;
while (i < quantity)
{
if (this.particleClass == null)
{
particle = new Phaser.ArcadeParticle(this.game);
}
else
{
particle = new this.particleClass(this.game);
}
if (multiple)
{
/*
randomFrame = this.game.math.random()*totalFrames;
*/
}
else
{
if (graphics)
{
particle.texture.loadImage(graphics);
}
}
if (collide > 0)
{
//particle.body.allowCollisions = Types.ANY;
particle.body.type = Phaser.Types.BODY_DYNAMIC;
particle.width *= collide;
particle.height *= collide;
}
else
{
//particle.body.allowCollisions = Types.NONE;
}
particle.exists = false;
// Center the origin for rotation assistance
//particle.transform.origin.setTo(particle.body.bounds.halfWidth, particle.body.bounds.halfHeight);
this.add(particle);
i++;
}
return this;
}
public preUpdate() { }
public postUpdate() { }
/**
* remove all Initializes
* @method removeInitializers
*/
removeInitializers() {
ParticleUtils.destroyArray(this.initializes);
}
/**
* Called automatically by the game loop, decides when to launch particles and when to "die".
* add the Behaviour to particles;
*
* you can use Behaviours array:emitter.addBehaviour(Behaviour1,Behaviour2,Behaviour3);
* @method addBehaviour
* @param {Proton.Behaviour} behaviour like this new Proton.Color('random')
*/
public update() {
if (this.on)
addBehaviour() {
var length = arguments.length, i;
for (i = 0; i < length; i++)
{
if (this._explode)
this.behaviours.push(arguments[i]);
if (arguments[i].hasOwnProperty("parents"))
arguments[i].parents.push(this);
}
}
/**
* remove the Behaviour
* @method removeBehaviour
* @param {Proton.Behaviour} behaviour a behaviour
*/
removeBehaviour(behaviour) {
var index = this.behaviours.indexOf(behaviour);
if (index > -1)
this.behaviours.splice(index, 1);
}
/**
* remove all behaviours
* @method removeAllBehaviours
*/
removeAllBehaviours() {
ParticleUtils.destroyArray(this.behaviours);
}
integrate(time) {
var damping = 1 - this.damping;
ParticleManager.integrator.integrate(this, time, damping);
var length = this.particles.length, i;
for (i = 0; i < length; i++)
{
var particle = this.particles[i];
particle.update(time, i);
ParticleManager.integrator.integrate(particle, time, damping);
//this.dispatchEvent(new Proton.Event({
// type: Proton.PARTICLE_UPDATE,
// particle: particle
//}));
}
}
emitting(time) {
if (this.emitTotalTimes == 1)
{
var length = this.rate.getValue(99999), i;
for (i = 0; i < length; i++)
{
this.on = false;
var i: number = 0;
var l: number = this._quantity;
if ((l <= 0) || (l > this.length))
{
l = this.length;
}
while (i < l)
{
this.emitParticle();
i++;
}
this._quantity = 0;
this.createParticle();
}
else
this.emitTotalTimes = 0;
} else if (!isNaN(this.emitTotalTimes))
{
this.emitTime += time;
if (this.emitTime < this.emitTotalTimes)
{
this._timer += this.game.time.elapsed;
while ((this.frequency > 0) && (this._timer > this.frequency) && this.on)
var length = this.rate.getValue(time), i;
for (i = 0; i < length; i++)
{
this._timer -= this.frequency;
this.emitParticle();
if ((this._quantity > 0) && (++this._counter >= this._quantity))
{
this.on = false;
this._quantity = 0;
}
this.createParticle();
}
}
}
super.update();
}
/**
* Call this function to turn off all the particles and the emitter.
*/
public kill() {
this.on = false;
this.alive = false;
this.exists = false;
}
/**
* Handy for bringing game objects "back to life". Just sets alive and exists back to true.
* In practice, this is most often called by <code>Object.reset()</code>.
*/
public revive() {
this.alive = true;
this.exists = true;
}
/**
* Call this function to start emitting 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: boolean = 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._counter = 0;
this._timer = 0;
}
/**
* This function can be used both internally and externally to emit the next particle.
*/
public emitParticle() {
var particle: ArcadeParticle = this.recycle(ArcadeParticle);
particle.lifespan = this.lifespan;
//particle.body.bounce.setTo(this.bounce, this.bounce);
SpriteUtils.reset(particle, this.x - (particle.width >> 1) + this.game.rnd.integer * this.width, this.y - (particle.height >> 1) + this.game.rnd.integer * this.height);
particle.visible = true;
if (this.minParticleSpeed.x != this.maxParticleSpeed.x)
update(time) {
this.age += time;
if (this.age >= this.life || this.dead)
{
particle.body.velocity.x = this.minParticleSpeed.x + this.game.rnd.integer * (this.maxParticleSpeed.x - this.minParticleSpeed.x);
}
else
{
particle.body.velocity.x = this.minParticleSpeed.x;
this.destroy();
}
if (this.minParticleSpeed.y != this.maxParticleSpeed.y)
this.emitting(time);
this.integrate(time);
var particle;
var length = this.particles.length, k;
for (k = length - 1; k >= 0; k--)
{
particle.body.velocity.y = this.minParticleSpeed.y + this.game.rnd.integer * (this.maxParticleSpeed.y - this.minParticleSpeed.y);
particle = this.particles[k];
if (particle.dead)
{
ParticleManager.pool.set(particle);
this.particles.splice(k, 1);
//this.dispatchEvent(new Proton.Event({
// type: Proton.PARTICLE_DEAD,
// particle: particle
//}));
}
}
else
}
setupParticle(particle, initialize, behaviour) {
var initializes = this.initializes;
var behaviours = this.behaviours;
if (initialize)
{
particle.body.velocity.y = this.minParticleSpeed.y;
if (initialize instanceof Array)
initializes = initialize;
else
initializes = [initialize];
}
//particle.body.acceleration.y = this.gravity;
if (this.minRotation != this.maxRotation && this.minRotation !== 0 && this.maxRotation !== 0)
if (behaviour)
{
particle.body.angularVelocity = this.minRotation + this.game.rnd.integer * (this.maxRotation - this.minRotation);
}
else
{
particle.body.angularVelocity = this.minRotation;
if (behaviour instanceof Array)
behaviours = behaviour;
else
behaviours = [behaviour];
}
if (particle.body.angularVelocity != 0)
{
particle.rotation = this.game.rnd.integer * 360 - 180;
}
//particle.body.drag.x = this.particleDrag.x;
//particle.body.drag.y = this.particleDrag.y;
particle.onEmit();
//Proton.InitializeUtil.initialize(this, particle, initializes);
particle.addBehaviours(behaviours);
particle.parent = this;
this.particles.push(particle);
}
/**
* A more compact way of setting the width and 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.
* Destory this Emitter
* @method destory
*/
public setSize(width: number, height: number) {
this.width = width;
this.height = height;
destroy() {
this.dead = true;
this.emitTotalTimes = -1;
if (this.particles.length == 0)
{
this.removeInitializers();
this.removeAllBehaviours();
if (this.parent)
this.parent.removeEmitter(this);
}
}
/**
* A more compact way of setting the X velocity range of the emitter.
*
* @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;
}
/**
* A more compact way of setting the Y velocity range of the emitter.
*
* @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;
}
/**
* A more compact way of setting the angular velocity constraints of the emitter.
*
* @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;
}
/**
* Change the emitter's midpoint to match the midpoint of a <code>Object</code>.
*
* @param Object {object} The <code>Object</code> that you want to sync up with.
*/
public at(object: Sprite) {
//this.x = object.body.bounds.halfWidth - (this.width >> 1);
//this.y = object.body.bounds.halfHeight - (this.height >> 1);
}
}
}

View file

@ -0,0 +1,30 @@
var Phaser;
(function (Phaser) {
/// <reference path="../_definitions.ts" />
(function (Particles) {
var NumericalIntegration = (function () {
function NumericalIntegration(type) {
this.type = Particles.ParticleUtils.initValue(type, Particles.ParticleManager.EULER);
}
NumericalIntegration.prototype.integrate = function (particles, time, damping) {
this.eulerIntegrate(particles, time, damping);
};
NumericalIntegration.prototype.eulerIntegrate = function (particle, time, damping) {
if (!particle.sleep) {
particle.old.p.copy(particle.p);
particle.old.v.copy(particle.v);
particle.a.multiplyScalar(1 / particle.mass);
particle.v.add(particle.a.multiplyScalar(time));
particle.p.add(particle.old.v.multiplyScalar(time));
if (damping)
particle.v.multiplyScalar(damping);
particle.a.clear();
}
};
return NumericalIntegration;
})();
Particles.NumericalIntegration = NumericalIntegration;
})(Phaser.Particles || (Phaser.Particles = {}));
var Particles = Phaser.Particles;
})(Phaser || (Phaser = {}));

View file

@ -0,0 +1,33 @@
/// <reference path="../_definitions.ts" />
module Phaser.Particles {
export class NumericalIntegration {
constructor(type) {
this.type = ParticleUtils.initValue(type, ParticleManager.EULER);
}
type;
integrate(particles, time, damping) {
this.eulerIntegrate(particles, time, damping);
}
eulerIntegrate(particle, time, damping) {
if (!particle.sleep)
{
particle.old.p.copy(particle.p);
particle.old.v.copy(particle.v);
particle.a.multiplyScalar(1 / particle.mass);
particle.v.add(particle.a.multiplyScalar(time));
particle.p.add(particle.old.v.multiplyScalar(time));
if (damping)
particle.v.multiplyScalar(damping);
particle.a.clear();
}
}
}
}

View file

@ -1,52 +1,157 @@
/// <reference path="../_definitions.ts" />
var __extends = this.__extends || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
__.prototype = b.prototype;
d.prototype = new __();
};
/**
* Phaser - ArcadeParticle
*
* This is a simple particle class that extends a Sprite to have a slightly more
* specialised behaviour. It is used exclusively by the Emitter class and can be extended as required.
*/
var Phaser;
(function (Phaser) {
var ArcadeParticle = (function (_super) {
__extends(ArcadeParticle, _super);
/**
* Instantiate a new particle. Like <code>Sprite</code>, all meaningful creation
* happens during <code>loadGraphic()</code> or <code>makeGraphic()</code> or whatever.
*/
function ArcadeParticle(game) {
_super.call(this, game);
this.body.type = Phaser.Types.BODY_DYNAMIC;
this.lifespan = 0;
}
/**
* The particle's main update logic. Basically it checks to see if it should be dead yet.
*/
ArcadeParticle.prototype.update = function () {
if (this.lifespan <= 0) {
return;
/// <reference path="../_definitions.ts" />
(function (Particles) {
var Particle = (function () {
/**
* the Particle class
*
* @class Proton.Particle
* @constructor
* @param {Object} pObj the parameters object;
* for example {life:3,dead:false}
*/
function Particle() {
this.life = Infinity;
this.age = 0;
this.energy = 1;
this.dead = false;
this.sleep = false;
this.target = null;
this.sprite = null;
this.parent = null;
this.mass = 1;
this.radius = 10;
this.alpha = 1;
this.scale = 1;
this.rotation = 0;
this.color = null;
this.easing = Phaser.Easing.Linear.None;
this.p = new Phaser.Vec2();
this.v = new Phaser.Vec2();
this.a = new Phaser.Vec2();
this.old = {
p: new Phaser.Vec2(),
v: new Phaser.Vec2(),
a: new Phaser.Vec2()
};
this.behaviours = [];
/**
* The particle's id;
* @property id
* @type {String} id
*/
this.id = 'particle_' + Particle.ID++;
this.reset(true);
}
Particle.prototype.getDirection = function () {
return Math.atan2(this.v.x, -this.v.y) * (180 / Math.PI);
};
this.lifespan -= this.game.time.elapsed;
Particle.prototype.reset = function (init) {
this.life = Infinity;
this.age = 0;
this.energy = 1;
this.dead = false;
this.sleep = false;
this.target = null;
this.sprite = null;
this.parent = null;
this.mass = 1;
this.radius = 10;
this.alpha = 1;
this.scale = 1;
this.rotation = 0;
this.color = null;
this.easing = Phaser.Easing.Linear.None;
if (init) {
this.transform = {};
this.p = new Phaser.Vec2();
this.v = new Phaser.Vec2();
this.a = new Phaser.Vec2();
this.old = {
p: new Phaser.Vec2(),
v: new Phaser.Vec2(),
a: new Phaser.Vec2()
};
this.behaviours = [];
} else {
Particles.ParticleUtils.destroyObject(this.transform);
this.p.setTo(0, 0);
this.v.setTo(0, 0);
this.a.setTo(0, 0);
this.old.p.setTo(0, 0);
this.old.v.setTo(0, 0);
this.old.a.setTo(0, 0);
this.removeAllBehaviours();
}
if (this.lifespan <= 0) {
this.kill();
}
};
this.transform.rgb = {
r: 255,
g: 255,
b: 255
};
return this;
};
/**
* Triggered whenever this object is launched by a <code>Emitter</code>.
* You can override this to add custom behavior like a sound or AI or something.
*/
ArcadeParticle.prototype.onEmit = function () {
};
return ArcadeParticle;
})(Phaser.Sprite);
Phaser.ArcadeParticle = ArcadeParticle;
Particle.prototype.update = function (time, index) {
if (!this.sleep) {
this.age += time;
var length = this.behaviours.length, i;
for (i = 0; i < length; i++) {
if (this.behaviours[i])
this.behaviours[i].applyBehaviour(this, time, index);
}
}
if (this.age >= this.life) {
this.destroy();
} else {
var scale = this.easing(this.age / this.life);
this.energy = Math.max(1 - scale, 0);
}
};
Particle.prototype.addBehaviour = function (behaviour) {
this.behaviours.push(behaviour);
if (behaviour.hasOwnProperty('parents'))
behaviour.parents.push(this);
behaviour.initialize(this);
};
Particle.prototype.addBehaviours = function (behaviours) {
var length = behaviours.length, i;
for (i = 0; i < length; i++) {
this.addBehaviour(behaviours[i]);
}
};
Particle.prototype.removeBehaviour = function (behaviour) {
var index = this.behaviours.indexOf(behaviour);
if (index > -1) {
var behaviour = this.behaviours.splice(index, 1);
behaviour.parents = null;
}
};
Particle.prototype.removeAllBehaviours = function () {
Particles.ParticleUtils.destroyArray(this.behaviours);
};
/**
* Destory this particle
* @method destory
*/
Particle.prototype.destroy = function () {
this.removeAllBehaviours();
this.energy = 0;
this.dead = true;
this.parent = null;
};
Particle.ID = 0;
return Particle;
})();
Particles.Particle = Particle;
})(Phaser.Particles || (Phaser.Particles = {}));
var Particles = Phaser.Particles;
})(Phaser || (Phaser = {}));

View file

@ -1,63 +1,171 @@
/// <reference path="../_definitions.ts" />
/**
* Phaser - ArcadeParticle
*
* This is a simple particle class that extends a Sprite to have a slightly more
* specialised behaviour. It is used exclusively by the Emitter class and can be extended as required.
*/
module Phaser.Particles {
module Phaser {
export class ArcadeParticle extends Phaser.Sprite {
export class Particle {
/**
* Instantiate a new particle. Like <code>Sprite</code>, all meaningful creation
* happens during <code>loadGraphic()</code> or <code>makeGraphic()</code> or whatever.
* the Particle class
*
* @class Proton.Particle
* @constructor
* @param {Object} pObj the parameters object;
* for example {life:3,dead:false}
*/
constructor(game: Phaser.Game) {
super(game);
this.body.type = Phaser.Types.BODY_DYNAMIC;
this.lifespan = 0;
constructor() {
/**
* The particle's id;
* @property id
* @type {String} id
*/
this.id = 'particle_' + Particle.ID++;
this.reset(true);
}
/**
* How long this particle lives before it disappears.
* NOTE: this is a maximum, not a minimum; the object
* could get recycled before its lifespan is up.
*/
public lifespan: number;
static ID = 0;
/**
* The particle's main update logic. Basically it checks to see if it should be dead yet.
*/
public update() {
id;
life = Infinity;
age = 0;
energy = 1;
dead = false;
sleep = false;
target = null;
sprite = null;
parent = null;
mass = 1;
radius = 10;
alpha = 1;
scale = 1;
rotation = 0;
color = null;
easing = Phaser.Easing.Linear.None;
transform;
p = new Phaser.Vec2();
v = new Phaser.Vec2();
a = new Phaser.Vec2();
old = {
p: new Phaser.Vec2(),
v: new Phaser.Vec2(),
a: new Phaser.Vec2()
};
behaviours = [];
// Lifespan behavior
if (this.lifespan <= 0)
getDirection() {
return Math.atan2(this.v.x, -this.v.y) * (180 / Math.PI);
}
reset(init) {
this.life = Infinity;
this.age = 0;
this.energy = 1;
this.dead = false;
this.sleep = false;
this.target = null;
this.sprite = null;
this.parent = null;
this.mass = 1;
this.radius = 10;
this.alpha = 1;
this.scale = 1;
this.rotation = 0;
this.color = null;
this.easing = Phaser.Easing.Linear.None;
if (init)
{
return;
this.transform = {}
this.p = new Phaser.Vec2();
this.v = new Phaser.Vec2();
this.a = new Phaser.Vec2();
this.old = {
p: new Phaser.Vec2(),
v: new Phaser.Vec2(),
a: new Phaser.Vec2()
};
this.behaviours = [];
} else
{
ParticleUtils.destroyObject(this.transform);
this.p.setTo(0, 0);
this.v.setTo(0, 0);
this.a.setTo(0, 0);
this.old.p.setTo(0, 0);
this.old.v.setTo(0, 0);
this.old.a.setTo(0, 0);
this.removeAllBehaviours();
}
this.lifespan -= this.game.time.elapsed;
this.transform.rgb = {
r: 255,
g: 255,
b: 255
}
return this;
}
if (this.lifespan <= 0)
update(time, index) {
if (!this.sleep)
{
this.kill();
this.age += time;
var length = this.behaviours.length, i;
for (i = 0; i < length; i++)
{
if (this.behaviours[i])
this.behaviours[i].applyBehaviour(this, time, index)
}
}
if (this.age >= this.life)
{
this.destroy();
} else
{
var scale = this.easing(this.age / this.life);
this.energy = Math.max(1 - scale, 0);
}
}
/**
* Triggered whenever this object is launched by a <code>Emitter</code>.
* You can override this to add custom behavior like a sound or AI or something.
*/
public onEmit() {
addBehaviour(behaviour) {
this.behaviours.push(behaviour);
if (behaviour.hasOwnProperty('parents'))
behaviour.parents.push(this);
behaviour.initialize(this);
}
addBehaviours(behaviours) {
var length = behaviours.length, i;
for (i = 0; i < length; i++)
{
this.addBehaviour(behaviours[i]);
}
}
removeBehaviour(behaviour) {
var index = this.behaviours.indexOf(behaviour);
if (index > -1)
{
var behaviour = this.behaviours.splice(index, 1);
behaviour.parents = null;
}
}
removeAllBehaviours() {
ParticleUtils.destroyArray(this.behaviours);
}
/**
* Destory this particle
* @method destory
*/
destroy() {
this.removeAllBehaviours();
this.energy = 0;
this.dead = true;
this.parent = null;
}
}
}

View file

@ -0,0 +1,127 @@
var Phaser;
(function (Phaser) {
/// <reference path="../_definitions.ts" />
(function (Particles) {
var ParticleManager = (function () {
function ParticleManager(proParticleCount, integrationType) {
this.PARTICLE_CREATED = 'partilcleCreated';
this.PARTICLE_UPDATE = 'partilcleUpdate';
this.PARTICLE_SLEEP = 'particleSleep';
this.PARTICLE_DEAD = 'partilcleDead';
this.PROTON_UPDATE = 'protonUpdate';
this.PROTON_UPDATE_AFTER = 'protonUpdateAfter';
this.EMITTER_ADDED = 'emitterAdded';
this.EMITTER_REMOVED = 'emitterRemoved';
this.emitters = [];
this.renderers = [];
this.time = 0;
this.oldTime = 0;
this.amendChangeTabsBug = true;
this.TextureBuffer = {};
this.TextureCanvasBuffer = {};
this.proParticleCount = Particles.ParticleUtils.initValue(proParticleCount, ParticleManager.POOL_MAX);
this.integrationType = Particles.ParticleUtils.initValue(integrationType, ParticleManager.EULER);
this.emitters = [];
this.renderers = [];
this.time = 0;
this.oldTime = 0;
ParticleManager.pool = new Phaser.Particles.ParticlePool(proParticleCount);
ParticleManager.integrator = new Phaser.Particles.NumericalIntegration(this.integrationType);
}
/**
* add a type of Renderer
*
* @method addRender
* @param {Renderer} render
*/
ParticleManager.prototype.addRender = function (render) {
render.proton = this;
this.renderers.push(render.proton);
};
/**
* add the Emitter
*
* @method addEmitter
* @param {Emitter} emitter
*/
ParticleManager.prototype.addEmitter = function (emitter) {
this.emitters.push(emitter);
emitter.parent = this;
//this.dispatchEvent(new Proton.Event({
// type: Proton.EMITTER_ADDED,
// emitter: emitter
//}));
};
ParticleManager.prototype.removeEmitter = function (emitter) {
var index = this.emitters.indexOf(emitter);
this.emitters.splice(index, 1);
emitter.parent = null;
//this.dispatchEvent(new Proton.Event({
// type: Proton.EMITTER_REMOVED,
// emitter: emitter
//}));
};
ParticleManager.prototype.update = function () {
if (!this.oldTime)
this.oldTime = new Date().getTime();
var time = new Date().getTime();
this.elapsed = (time - this.oldTime) / 1000;
//if (ParticleUtils.amendChangeTabsBug)
// this.amendChangeTabsBugHandler();
this.oldTime = time;
if (this.elapsed > 0) {
for (var i = 0; i < this.emitters.length; i++) {
this.emitters[i].update(this.elapsed);
}
}
//this.dispatchEvent(new Proton.Event({
// type: Proton.PROTON_UPDATE_AFTER
//}));
};
ParticleManager.prototype.amendChangeTabsBugHandler = function () {
if (this.elapsed > .5) {
this.oldTime = new Date().getTime();
this.elapsed = 0;
}
};
ParticleManager.prototype.getParticleNumber = function () {
var total = 0;
for (var i = 0; i < this.emitters.length; i++) {
total += this.emitters[i].particles.length;
}
return total;
};
ParticleManager.prototype.destroy = function () {
for (var i = 0; i < this.emitters.length; i++) {
this.emitters[i].destory();
delete this.emitters[i];
}
this.emitters = [];
this.time = 0;
this.oldTime = 0;
ParticleManager.pool.release();
};
ParticleManager.POOL_MAX = 1000;
ParticleManager.TIME_STEP = 60;
ParticleManager.MEASURE = 100;
ParticleManager.EULER = 'euler';
ParticleManager.RK2 = 'runge-kutta2';
ParticleManager.RK4 = 'runge-kutta4';
ParticleManager.VERLET = 'verlet';
return ParticleManager;
})();
Particles.ParticleManager = ParticleManager;
})(Phaser.Particles || (Phaser.Particles = {}));
var Particles = Phaser.Particles;
})(Phaser || (Phaser = {}));

View file

@ -0,0 +1,151 @@
/// <reference path="../_definitions.ts" />
module Phaser.Particles {
export class ParticleManager {
constructor(proParticleCount, integrationType) {
this.proParticleCount = ParticleUtils.initValue(proParticleCount, ParticleManager.POOL_MAX);
this.integrationType = ParticleUtils.initValue(integrationType, ParticleManager.EULER);
this.emitters = [];
this.renderers = [];
this.time = 0;
this.oldTime = 0;
ParticleManager.pool = new Phaser.Particles.ParticlePool(proParticleCount);
ParticleManager.integrator = new Phaser.Particles.NumericalIntegration(this.integrationType);
}
//the max particle number in pool
static POOL_MAX = 1000;
static TIME_STEP = 60;
//1:100
static MEASURE = 100;
static EULER = 'euler';
static RK2 = 'runge-kutta2';
static RK4 = 'runge-kutta4';
static VERLET = 'verlet';
PARTICLE_CREATED = 'partilcleCreated';
PARTICLE_UPDATE = 'partilcleUpdate';
PARTICLE_SLEEP = 'particleSleep';
PARTICLE_DEAD = 'partilcleDead';
PROTON_UPDATE = 'protonUpdate';
PROTON_UPDATE_AFTER = 'protonUpdateAfter';
EMITTER_ADDED = 'emitterAdded';
EMITTER_REMOVED = 'emitterRemoved';
proParticleCount;
integrationType;
emitters = [];
renderers = [];
time = 0;
oldTime = 0;
static pool;
static integrator;
amendChangeTabsBug = true;
TextureBuffer = {};
TextureCanvasBuffer = {};
elapsed;
/**
* add a type of Renderer
*
* @method addRender
* @param {Renderer} render
*/
addRender(render) {
render.proton = this;
this.renderers.push(render.proton);
}
/**
* add the Emitter
*
* @method addEmitter
* @param {Emitter} emitter
*/
addEmitter(emitter) {
this.emitters.push(emitter);
emitter.parent = this;
//this.dispatchEvent(new Proton.Event({
// type: Proton.EMITTER_ADDED,
// emitter: emitter
//}));
}
removeEmitter(emitter) {
var index = this.emitters.indexOf(emitter);
this.emitters.splice(index, 1);
emitter.parent = null;
//this.dispatchEvent(new Proton.Event({
// type: Proton.EMITTER_REMOVED,
// emitter: emitter
//}));
}
update() {
//this.dispatchEvent(new Proton.Event({
// type: Proton.PROTON_UPDATE
//}));
if (!this.oldTime)
this.oldTime = new Date().getTime();
var time = new Date().getTime();
this.elapsed = (time - this.oldTime) / 1000;
//if (ParticleUtils.amendChangeTabsBug)
// this.amendChangeTabsBugHandler();
this.oldTime = time;
if (this.elapsed > 0)
{
for (var i = 0; i < this.emitters.length; i++)
{
this.emitters[i].update(this.elapsed);
}
}
//this.dispatchEvent(new Proton.Event({
// type: Proton.PROTON_UPDATE_AFTER
//}));
}
amendChangeTabsBugHandler() {
if (this.elapsed > .5)
{
this.oldTime = new Date().getTime();
this.elapsed = 0;
}
}
getParticleNumber() {
var total = 0;
for (var i = 0; i < this.emitters.length; i++)
{
total += this.emitters[i].particles.length;
}
return total;
}
destroy() {
for (var i = 0; i < this.emitters.length; i++)
{
this.emitters[i].destory();
delete this.emitters[i];
}
this.emitters = [];
this.time = 0;
this.oldTime = 0;
ParticleManager.pool.release();
}
}
}

View file

@ -0,0 +1,71 @@
var Phaser;
(function (Phaser) {
/// <reference path="../_definitions.ts" />
(function (Particles) {
var ParticlePool = (function () {
function ParticlePool(num, releaseTime) {
if (typeof releaseTime === "undefined") { releaseTime = 0; }
this.poolList = [];
this.timeoutID = 0;
this.proParticleCount = Particles.ParticleUtils.initValue(num, 0);
this.releaseTime = Particles.ParticleUtils.initValue(releaseTime, -1);
this.poolList = [];
this.timeoutID = 0;
for (var i = 0; i < this.proParticleCount; i++) {
this.add();
}
if (this.releaseTime > 0) {
// TODO - Hook to game clock so Pause works
this.timeoutID = setTimeout(this.release, this.releaseTime / 1000);
}
}
ParticlePool.prototype.create = function (newTypeParticleClass) {
if (typeof newTypeParticleClass === "undefined") { newTypeParticleClass = null; }
if (newTypeParticleClass) {
return new newTypeParticleClass();
} else {
return new Phaser.Particles.Particle();
}
};
ParticlePool.prototype.getCount = function () {
return this.poolList.length;
};
ParticlePool.prototype.add = function () {
return this.poolList.push(this.create());
};
ParticlePool.prototype.get = function () {
if (this.poolList.length === 0) {
return this.create();
} else {
return this.poolList.pop().reset();
}
};
ParticlePool.prototype.set = function (particle) {
if (this.poolList.length < Particles.ParticleManager.POOL_MAX) {
return this.poolList.push(particle);
}
};
ParticlePool.prototype.release = function () {
for (var i = 0; i < this.poolList.length; i++) {
if (this.poolList[i]['destroy']) {
this.poolList[i].destroy();
}
delete this.poolList[i];
}
this.poolList = [];
};
return ParticlePool;
})();
Particles.ParticlePool = ParticlePool;
})(Phaser.Particles || (Phaser.Particles = {}));
var Particles = Phaser.Particles;
})(Phaser || (Phaser = {}));

View file

@ -0,0 +1,92 @@
/// <reference path="../_definitions.ts" />
module Phaser.Particles {
export class ParticlePool {
constructor(num, releaseTime = 0) {
this.proParticleCount = ParticleUtils.initValue(num, 0);
this.releaseTime = ParticleUtils.initValue(releaseTime, -1);
this.poolList = [];
this.timeoutID = 0;
for (var i = 0; i < this.proParticleCount; i++)
{
this.add();
}
if (this.releaseTime > 0)
{
// TODO - Hook to game clock so Pause works
this.timeoutID = setTimeout(this.release, this.releaseTime / 1000);
}
}
proParticleCount: number;
releaseTime: number;
poolList = [];
timeoutID: number = 0;
create(newTypeParticleClass = null) {
if (newTypeParticleClass)
{
return new newTypeParticleClass;
}
else
{
return new Phaser.Particles.Particle();
}
}
getCount() {
return this.poolList.length;
}
add() {
return this.poolList.push(this.create());
}
get() {
if (this.poolList.length === 0)
{
return this.create();
}
else
{
return this.poolList.pop().reset();
}
}
set(particle) {
if (this.poolList.length < ParticleManager.POOL_MAX)
{
return this.poolList.push(particle);
}
}
release() {
for (var i = 0; i < this.poolList.length; i++)
{
if (this.poolList[i]['destroy'])
{
this.poolList[i].destroy();
}
delete this.poolList[i];
}
this.poolList = [];
}
}
}

View file

@ -0,0 +1,180 @@
var Phaser;
(function (Phaser) {
/// <reference path="../_definitions.ts" />
(function (Particles) {
var ParticleUtils = (function () {
function ParticleUtils() {
}
ParticleUtils.initValue = function (value, defaults) {
var value = (value != null && value != undefined) ? value : defaults;
return value;
};
ParticleUtils.isArray = function (value) {
return typeof value === 'object' && value.hasOwnProperty('length');
};
ParticleUtils.destroyArray = function (array) {
array.length = 0;
};
ParticleUtils.destroyObject = function (obj) {
for (var o in obj) {
delete obj[o];
}
};
ParticleUtils.setSpanValue = function (a, b, c) {
if (typeof b === "undefined") { b = null; }
if (typeof c === "undefined") { c = null; }
if (a instanceof Phaser.Particles.Span) {
return a;
} else {
if (!b) {
return new Phaser.Particles.Span(a);
} else {
if (!c) {
return new Phaser.Particles.Span(a, b);
} else {
return new Phaser.Particles.Span(a, b, c);
}
}
}
};
ParticleUtils.getSpanValue = function (pan) {
if (pan instanceof Phaser.Particles.Span) {
return pan.getValue();
} else {
return pan;
}
};
ParticleUtils.randomAToB = function (a, b, INT) {
if (typeof INT === "undefined") { INT = null; }
if (!INT) {
return a + Math.random() * (b - a);
} else {
return Math.floor(Math.random() * (b - a)) + a;
}
};
ParticleUtils.randomFloating = function (center, f, INT) {
return ParticleUtils.randomAToB(center - f, center + f, INT);
};
ParticleUtils.randomZone = function (display) {
};
ParticleUtils.degreeTransform = function (a) {
return a * Math.PI / 180;
};
ParticleUtils.randomColor = //static toColor16 getRGB(num) {
// return "#" + num.toString(16);
//}
function () {
return '#' + ('00000' + (Math.random() * 0x1000000 << 0).toString(16)).slice(-6);
};
ParticleUtils.setEasingByName = function (name) {
switch (name) {
case 'easeLinear':
return Phaser.Easing.Linear.None;
break;
case 'easeInQuad':
return Phaser.Easing.Quadratic.In;
break;
case 'easeOutQuad':
return Phaser.Easing.Quadratic.Out;
break;
case 'easeInOutQuad':
return Phaser.Easing.Quadratic.InOut;
break;
case 'easeInCubic':
return Phaser.Easing.Cubic.In;
break;
case 'easeOutCubic':
return Phaser.Easing.Cubic.Out;
break;
case 'easeInOutCubic':
return Phaser.Easing.Cubic.InOut;
break;
case 'easeInQuart':
return Phaser.Easing.Quartic.In;
break;
case 'easeOutQuart':
return Phaser.Easing.Quartic.Out;
break;
case 'easeInOutQuart':
return Phaser.Easing.Quartic.InOut;
break;
case 'easeInSine':
return Phaser.Easing.Sinusoidal.In;
break;
case 'easeOutSine':
return Phaser.Easing.Sinusoidal.Out;
break;
case 'easeInOutSine':
return Phaser.Easing.Sinusoidal.InOut;
break;
case 'easeInExpo':
return Phaser.Easing.Exponential.In;
break;
case 'easeOutExpo':
return Phaser.Easing.Exponential.Out;
break;
case 'easeInOutExpo':
return Phaser.Easing.Exponential.InOut;
break;
case 'easeInCirc':
return Phaser.Easing.Circular.In;
break;
case 'easeOutCirc':
return Phaser.Easing.Circular.Out;
break;
case 'easeInOutCirc':
return Phaser.Easing.Circular.InOut;
break;
case 'easeInBack':
return Phaser.Easing.Back.In;
break;
case 'easeOutBack':
return Phaser.Easing.Back.Out;
break;
case 'easeInOutBack':
return Phaser.Easing.Back.InOut;
break;
default:
return Phaser.Easing.Linear.None;
break;
}
};
return ParticleUtils;
})();
Particles.ParticleUtils = ParticleUtils;
})(Phaser.Particles || (Phaser.Particles = {}));
var Particles = Phaser.Particles;
})(Phaser || (Phaser = {}));

View file

@ -0,0 +1,201 @@
/// <reference path="../_definitions.ts" />
module Phaser.Particles {
export class ParticleUtils {
static initValue(value, defaults) {
var value = (value != null && value != undefined) ? value : defaults;
return value;
}
static isArray(value) {
return typeof value === 'object' && value.hasOwnProperty('length');
}
static destroyArray(array) {
array.length = 0;
}
static destroyObject(obj) {
for (var o in obj)
{
delete obj[o];
}
}
static setSpanValue(a, b= null, c= null) {
if (a instanceof Phaser.Particles.Span)
{
return a;
}
else
{
if (!b)
{
return new Phaser.Particles.Span(a);
}
else
{
if (!c)
{
return new Phaser.Particles.Span(a, b);
}
else
{
return new Phaser.Particles.Span(a, b, c);
}
}
}
}
static getSpanValue(pan) {
if (pan instanceof Phaser.Particles.Span)
{
return pan.getValue();
}
else
{
return pan;
}
}
static randomAToB(a, b, INT = null) {
if (!INT)
{
return a + Math.random() * (b - a);
}
else
{
return Math.floor(Math.random() * (b - a)) + a;
}
}
static randomFloating(center, f, INT) {
return ParticleUtils.randomAToB(center - f, center + f, INT);
}
static randomZone(display) {
}
static degreeTransform(a) {
return a * Math.PI / 180;
}
//static toColor16 getRGB(num) {
// return "#" + num.toString(16);
//}
static randomColor() {
return '#' + ('00000' + (Math.random() * 0x1000000 << 0).toString(16)).slice(-6);
}
static setEasingByName(name) {
switch (name)
{
case 'easeLinear':
return Phaser.Easing.Linear.None;
break;
case 'easeInQuad':
return Phaser.Easing.Quadratic.In;
break;
case 'easeOutQuad':
return Phaser.Easing.Quadratic.Out;
break;
case 'easeInOutQuad':
return Phaser.Easing.Quadratic.InOut;
break;
case 'easeInCubic':
return Phaser.Easing.Cubic.In;
break;
case 'easeOutCubic':
return Phaser.Easing.Cubic.Out;
break;
case 'easeInOutCubic':
return Phaser.Easing.Cubic.InOut;
break;
case 'easeInQuart':
return Phaser.Easing.Quartic.In;
break;
case 'easeOutQuart':
return Phaser.Easing.Quartic.Out;
break;
case 'easeInOutQuart':
return Phaser.Easing.Quartic.InOut;
break;
case 'easeInSine':
return Phaser.Easing.Sinusoidal.In;
break;
case 'easeOutSine':
return Phaser.Easing.Sinusoidal.Out;
break;
case 'easeInOutSine':
return Phaser.Easing.Sinusoidal.InOut;
break;
case 'easeInExpo':
return Phaser.Easing.Exponential.In;
break;
case 'easeOutExpo':
return Phaser.Easing.Exponential.Out;
break;
case 'easeInOutExpo':
return Phaser.Easing.Exponential.InOut;
break;
case 'easeInCirc':
return Phaser.Easing.Circular.In;
break;
case 'easeOutCirc':
return Phaser.Easing.Circular.Out;
break;
case 'easeInOutCirc':
return Phaser.Easing.Circular.InOut;
break;
case 'easeInBack':
return Phaser.Easing.Back.In;
break;
case 'easeOutBack':
return Phaser.Easing.Back.Out;
break;
case 'easeInOutBack':
return Phaser.Easing.Back.InOut;
break;
default:
return Phaser.Easing.Linear.None;
break;
}
}
}
}

View file

@ -0,0 +1,71 @@
var Phaser;
(function (Phaser) {
/// <reference path="../_definitions.ts" />
(function (Particles) {
var Polar2D = (function () {
function Polar2D(r, tha) {
this.r = Math.abs(r) || 0;
this.tha = tha || 0;
}
Polar2D.prototype.set = function (r, tha) {
this.r = r;
this.tha = tha;
return this;
};
Polar2D.prototype.setR = function (r) {
this.r = r;
return this;
};
Polar2D.prototype.setTha = function (tha) {
this.tha = tha;
return this;
};
Polar2D.prototype.copy = function (p) {
this.r = p.r;
this.tha = p.tha;
return this;
};
Polar2D.prototype.toVector = function () {
return new Phaser.Vec2(this.getX(), this.getY());
};
Polar2D.prototype.getX = function () {
return this.r * Math.sin(this.tha);
};
Polar2D.prototype.getY = function () {
return -this.r * Math.cos(this.tha);
};
Polar2D.prototype.normalize = function () {
this.r = 1;
return this;
};
Polar2D.prototype.equals = function (v) {
return ((v.r === this.r) && (v.tha === this.tha));
};
Polar2D.prototype.toArray = function () {
return [this.r, this.tha];
};
Polar2D.prototype.clear = function () {
this.r = 0.0;
this.tha = 0.0;
return this;
};
Polar2D.prototype.clone = function () {
return new Polar2D(this.r, this.tha);
};
return Polar2D;
})();
Particles.Polar2D = Polar2D;
})(Phaser.Particles || (Phaser.Particles = {}));
var Particles = Phaser.Particles;
})(Phaser || (Phaser = {}));

View file

@ -0,0 +1,82 @@
/// <reference path="../_definitions.ts" />
module Phaser.Particles {
export class Polar2D {
constructor(r, tha) {
this.r = Math.abs(r) || 0;
this.tha = tha || 0;
}
r;
tha;
set(r, tha) {
this.r = r;
this.tha = tha;
return this;
}
setR(r) {
this.r = r;
return this;
}
setTha(tha) {
this.tha = tha;
return this;
}
copy(p) {
this.r = p.r;
this.tha = p.tha;
return this;
}
toVector() {
return new Phaser.Vec2(this.getX(), this.getY());
}
getX() {
return this.r * Math.sin(this.tha);
}
getY() {
return -this.r * Math.cos(this.tha);
}
normalize() {
this.r = 1;
return this;
}
equals(v) {
return ((v.r === this.r) && (v.tha === this.tha));
}
toArray() {
return [this.r, this.tha];
}
clear() {
this.r = 0.0;
this.tha = 0.0;
return this;
}
clone() {
return new Polar2D(this.r, this.tha);
}
}
}

41
Phaser/particles/Span.js Normal file
View file

@ -0,0 +1,41 @@
var Phaser;
(function (Phaser) {
/// <reference path="../_definitions.ts" />
(function (Particles) {
var Span = (function () {
function Span(a, b, center) {
if (typeof b === "undefined") { b = null; }
if (typeof center === "undefined") { center = null; }
this.isArray = false;
if (Particles.ParticleUtils.isArray(a)) {
this.isArray = true;
this.a = a;
} else {
this.a = Particles.ParticleUtils.initValue(a, 1);
this.b = Particles.ParticleUtils.initValue(b, this.a);
this.center = Particles.ParticleUtils.initValue(center, false);
}
}
Span.prototype.getValue = function (INT) {
if (typeof INT === "undefined") { INT = null; }
if (this.isArray) {
return this.a[Math.floor(this.a.length * Math.random())];
} else {
if (!this.center) {
return Particles.ParticleUtils.randomAToB(this.a, this.b, INT);
} else {
return Particles.ParticleUtils.randomFloating(this.a, this.b, INT);
}
}
};
Span.getSpan = function (a, b, center) {
return new Span(a, b, center);
};
return Span;
})();
Particles.Span = Span;
})(Phaser.Particles || (Phaser.Particles = {}));
var Particles = Phaser.Particles;
})(Phaser || (Phaser = {}));

57
Phaser/particles/Span.ts Normal file
View file

@ -0,0 +1,57 @@
/// <reference path="../_definitions.ts" />
module Phaser.Particles {
export class Span {
constructor(a, b = null, center = null) {
this.isArray = false;
if (ParticleUtils.isArray(a))
{
this.isArray = true;
this.a = a;
}
else
{
this.a = ParticleUtils.initValue(a, 1);
this.b = ParticleUtils.initValue(b, this.a);
this.center = ParticleUtils.initValue(center, false);
}
}
a;
b;
c;
center;
isArray;
getValue(INT = null) {
if (this.isArray)
{
return this.a[Math.floor(this.a.length * Math.random())];
}
else
{
if (!this.center)
{
return ParticleUtils.randomAToB(this.a, this.b, INT);
}
else
{
return ParticleUtils.randomFloating(this.a, this.b, INT);
}
}
}
static getSpan(a, b, center) {
return new Span(a, b, center);
}
}
}

View file

@ -0,0 +1,129 @@
var Phaser;
(function (Phaser) {
(function (Particles) {
/// <reference path="../../_definitions.ts" />
(function (Behaviours) {
var Behaviour = (function () {
function Behaviour(life, easing) {
/**
* The behaviour's id;
* @property id
* @type {String} id
*/
this.id = 'Behaviour_' + Behaviour.ID++;
this.life = Particles.ParticleUtils.initValue(life, Infinity);
/**
* The behaviour's decaying trend, for example Proton.easeOutQuart;
* @property easing
* @type {String}
* @default Proton.easeLinear
*/
this.easing = Particles.ParticleUtils.setEasingByName(easing);
this.age = 0;
this.energy = 1;
/**
* The behaviour is Dead;
* @property dead
* @type {Boolean}
*/
this.dead = false;
/**
* The behaviour's parents array;
* @property parents
* @type {Array}
*/
this.parents = [];
/**
* The behaviour name;
* @property name
* @type {string}
*/
this.name = 'Behaviour';
}
/**
* Reset this behaviour's parameters
*
* @method reset
* @param {Number} this behaviour's life
* @param {String} this behaviour's easing
*/
//reset (life, easing) {
// this.life = ParticleUtils.initValue(life, Infinity);
// //this.easing = ParticleUtils.initValue(easing, Proton.ease.setEasingByName(Proton.easeLinear));
//}
/**
* Normalize a force by 1:100;
*
* @method normalizeForce
* @param {Proton.Vector2D} force
*/
Behaviour.prototype.normalizeForce = function (force) {
return force.multiplyScalar(Particles.ParticleManager.MEASURE);
};
/**
* Normalize a value by 1:100;
*
* @method normalizeValue
* @param {Number} value
*/
Behaviour.prototype.normalizeValue = function (value) {
return value * Particles.ParticleManager.MEASURE;
};
/**
* Initialize the behaviour's parameters for all particles
*
* @method initialize
* @param {Proton.Particle} particle
*/
Behaviour.prototype.initialize = function (particle) {
};
/**
* Apply this behaviour for all particles every time
*
* @method applyBehaviour
* @param {Proton.Particle} particle
* @param {Number} the integrate time 1/ms
* @param {Int} the particle index
*/
Behaviour.prototype.applyBehaviour = function (particle, time, index) {
this.age += time;
if (this.age >= this.life || this.dead) {
this.energy = 0;
this.dead = true;
this.destroy();
} else {
var scale = this.easing(particle.age / particle.life);
this.energy = Math.max(1 - scale, 0);
}
};
/**
* Destory this behaviour
* @method destory
*/
Behaviour.prototype.destroy = function () {
var index;
var length = this.parents.length, i;
for (i = 0; i < length; i++) {
this.parents[i].removeBehaviour(this);
}
this.parents = [];
};
return Behaviour;
})();
Behaviours.Behaviour = Behaviour;
})(Particles.Behaviours || (Particles.Behaviours = {}));
var Behaviours = Particles.Behaviours;
})(Phaser.Particles || (Phaser.Particles = {}));
var Particles = Phaser.Particles;
})(Phaser || (Phaser = {}));

View file

@ -0,0 +1,140 @@
/// <reference path="../../_definitions.ts" />
module Phaser.Particles.Behaviours {
export class Behaviour {
constructor(life, easing) {
/**
* The behaviour's id;
* @property id
* @type {String} id
*/
this.id = 'Behaviour_' + Behaviour.ID++;
this.life = ParticleUtils.initValue(life, Infinity);
/**
* The behaviour's decaying trend, for example Proton.easeOutQuart;
* @property easing
* @type {String}
* @default Proton.easeLinear
*/
this.easing = ParticleUtils.setEasingByName(easing);
this.age = 0;
this.energy = 1;
/**
* The behaviour is Dead;
* @property dead
* @type {Boolean}
*/
this.dead = false;
/**
* The behaviour's parents array;
* @property parents
* @type {Array}
*/
this.parents = [];
/**
* The behaviour name;
* @property name
* @type {string}
*/
this.name = 'Behaviour';
}
static ID;
id;
life;
easing;
age;
energy;
dead;
parents;
name;
/**
* Reset this behaviour's parameters
*
* @method reset
* @param {Number} this behaviour's life
* @param {String} this behaviour's easing
*/
//reset (life, easing) {
// this.life = ParticleUtils.initValue(life, Infinity);
// //this.easing = ParticleUtils.initValue(easing, Proton.ease.setEasingByName(Proton.easeLinear));
//}
/**
* Normalize a force by 1:100;
*
* @method normalizeForce
* @param {Proton.Vector2D} force
*/
normalizeForce (force) {
return force.multiplyScalar(ParticleManager.MEASURE);
}
/**
* Normalize a value by 1:100;
*
* @method normalizeValue
* @param {Number} value
*/
normalizeValue (value) {
return value * ParticleManager.MEASURE;
}
/**
* Initialize the behaviour's parameters for all particles
*
* @method initialize
* @param {Proton.Particle} particle
*/
initialize (particle) {
}
/**
* Apply this behaviour for all particles every time
*
* @method applyBehaviour
* @param {Proton.Particle} particle
* @param {Number} the integrate time 1/ms
* @param {Int} the particle index
*/
applyBehaviour (particle, time, index) {
this.age += time;
if (this.age >= this.life || this.dead)
{
this.energy = 0;
this.dead = true;
this.destroy();
}
else
{
var scale = this.easing(particle.age / particle.life);
this.energy = Math.max(1 - scale, 0);
}
}
/**
* Destory this behaviour
* @method destory
*/
destroy () {
var index;
var length = this.parents.length, i;
for (i = 0; i < length; i++)
{
this.parents[i].removeBehaviour(this);
}
this.parents = [];
}
}
}

View file

@ -0,0 +1,50 @@
var __extends = this.__extends || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
__.prototype = b.prototype;
d.prototype = new __();
};
var Phaser;
(function (Phaser) {
(function (Particles) {
/// <reference path="../../_definitions.ts" />
(function (Behaviours) {
var RandomDrift = (function (_super) {
__extends(RandomDrift, _super);
function RandomDrift(driftX, driftY, delay, life, easing) {
_super.call(this, life, easing);
this.reset(driftX, driftY, delay);
this.time = 0;
this.name = "RandomDrift";
}
RandomDrift.prototype.reset = function (driftX, driftY, delay, life, easing) {
if (typeof life === "undefined") { life = null; }
if (typeof easing === "undefined") { easing = null; }
this.panFoce = new Phaser.Vec2(driftX, driftY);
this.panFoce = this.normalizeForce(this.panFoce);
this.delay = delay;
if (life) {
this.life = Particles.ParticleUtils.initValue(life, Infinity);
this.easing = Particles.ParticleUtils.initValue(easing, Phaser.Easing.Linear.None);
}
};
RandomDrift.prototype.applyBehaviour = function (particle, time, index) {
_super.prototype.applyBehaviour.call(this, particle, time, index);
this.time += time;
if (this.time >= this.delay) {
particle.a.addXY(Particles.ParticleUtils.randomAToB(-this.panFoce.x, this.panFoce.x), Particles.ParticleUtils.randomAToB(-this.panFoce.y, this.panFoce.y));
this.time = 0;
}
};
return RandomDrift;
})(Behaviours.Behaviour);
Behaviours.RandomDrift = RandomDrift;
})(Particles.Behaviours || (Particles.Behaviours = {}));
var Behaviours = Particles.Behaviours;
})(Phaser.Particles || (Phaser.Particles = {}));
var Particles = Phaser.Particles;
})(Phaser || (Phaser = {}));

View file

@ -0,0 +1,49 @@
/// <reference path="../../_definitions.ts" />
module Phaser.Particles.Behaviours {
export class RandomDrift extends Behaviour {
constructor(driftX, driftY, delay, life, easing) {
super(life, easing);
this.reset(driftX, driftY, delay);
this.time = 0;
this.name = "RandomDrift";
}
panFoce;
delay;
time;
reset(driftX, driftY, delay, life= null, easing= null) {
this.panFoce = new Phaser.Vec2(driftX, driftY);
this.panFoce = this.normalizeForce(this.panFoce);
this.delay = delay;
if (life)
{
this.life = ParticleUtils.initValue(life, Infinity);
this.easing = ParticleUtils.initValue(easing, Phaser.Easing.Linear.None);
}
}
applyBehaviour(particle, time, index) {
super.applyBehaviour(particle, time, index);
this.time += time;
if (this.time >= this.delay)
{
particle.a.addXY(ParticleUtils.randomAToB(-this.panFoce.x, this.panFoce.x), ParticleUtils.randomAToB(-this.panFoce.y, this.panFoce.y));
this.time = 0;
}
}
}
}

View file

@ -0,0 +1,30 @@
var Phaser;
(function (Phaser) {
(function (Particles) {
/// <reference path="../../_definitions.ts" />
(function (Initializers) {
var Initialize = (function () {
function Initialize() {
}
Initialize.prototype.initialize = function (target) {
};
Initialize.prototype.reset = function (a, b, c) {
};
Initialize.prototype.init = function (emitter, particle) {
if (typeof particle === "undefined") { particle = null; }
if (particle) {
this.initialize(particle);
} else {
this.initialize(emitter);
}
};
return Initialize;
})();
Initializers.Initialize = Initialize;
})(Particles.Initializers || (Particles.Initializers = {}));
var Initializers = Particles.Initializers;
})(Phaser.Particles || (Phaser.Particles = {}));
var Particles = Phaser.Particles;
})(Phaser || (Phaser = {}));

View file

@ -0,0 +1,28 @@
/// <reference path="../../_definitions.ts" />
module Phaser.Particles.Initializers {
export class Initialize {
initialize(target) {
}
reset(a,b,c) { }
init(emitter, particle= null) {
if (particle)
{
this.initialize(particle);
}
else
{
this.initialize(emitter);
}
}
}
}

View file

@ -0,0 +1,33 @@
var __extends = this.__extends || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
__.prototype = b.prototype;
d.prototype = new __();
};
var Phaser;
(function (Phaser) {
(function (Particles) {
/// <reference path="../../_definitions.ts" />
(function (Initializers) {
var Life = (function (_super) {
__extends(Life, _super);
function Life(a, b, c) {
_super.call(this);
this.lifePan = Particles.ParticleUtils.setSpanValue(a, b, c);
}
Life.prototype.initialize = function (target) {
if (this.lifePan.a == Infinity) {
target.life = Infinity;
} else {
target.life = this.lifePan.getValue();
}
};
return Life;
})(Initializers.Initialize);
Initializers.Life = Life;
})(Particles.Initializers || (Particles.Initializers = {}));
var Initializers = Particles.Initializers;
})(Phaser.Particles || (Phaser.Particles = {}));
var Particles = Phaser.Particles;
})(Phaser || (Phaser = {}));

View file

@ -0,0 +1,32 @@
/// <reference path="../../_definitions.ts" />
module Phaser.Particles.Initializers {
export class Life extends Initialize {
constructor(a,b,c) {
super();
this.lifePan = ParticleUtils.setSpanValue(a, b, c);
}
lifePan: Phaser.Particles.Span;
initialize(target) {
if (this.lifePan.a == Infinity)
{
target.life = Infinity;
}
else
{
target.life = this.lifePan.getValue();
}
}
}
}

View file

@ -0,0 +1,28 @@
var __extends = this.__extends || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
__.prototype = b.prototype;
d.prototype = new __();
};
var Phaser;
(function (Phaser) {
(function (Particles) {
/// <reference path="../../_definitions.ts" />
(function (Initializers) {
var Mass = (function (_super) {
__extends(Mass, _super);
function Mass(a, b, c) {
_super.call(this);
this.massPan = Particles.ParticleUtils.setSpanValue(a, b, c);
}
Mass.prototype.initialize = function (target) {
target.mass = this.massPan.getValue();
};
return Mass;
})(Initializers.Initialize);
Initializers.Mass = Mass;
})(Particles.Initializers || (Particles.Initializers = {}));
var Initializers = Particles.Initializers;
})(Phaser.Particles || (Phaser.Particles = {}));
var Particles = Phaser.Particles;
})(Phaser || (Phaser = {}));

View file

@ -0,0 +1,21 @@
/// <reference path="../../_definitions.ts" />
module Phaser.Particles.Initializers {
export class Mass extends Initialize {
constructor(a,b,c) {
super();
this.massPan = ParticleUtils.setSpanValue(a, b, c);
}
massPan: Phaser.Particles.Span;
initialize(target) {
target.mass = this.massPan.getValue();
}
}
}

View file

@ -0,0 +1,44 @@
var __extends = this.__extends || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
__.prototype = b.prototype;
d.prototype = new __();
};
var Phaser;
(function (Phaser) {
(function (Particles) {
/// <reference path="../../_definitions.ts" />
(function (Initializers) {
var Position = (function (_super) {
__extends(Position, _super);
function Position(zone) {
_super.call(this);
if (zone != null && zone != undefined) {
this.zone = zone;
} else {
this.zone = new Phaser.Particles.Zones.PointZone();
}
}
Position.prototype.reset = function (zone) {
if (zone != null && zone != undefined) {
this.zone = zone;
} else {
this.zone = new Phaser.Particles.Zones.PointZone();
}
};
Position.prototype.initialize = function (target) {
this.zone.getPosition();
target.p.x = this.zone.vector.x;
target.p.y = this.zone.vector.y;
};
return Position;
})(Initializers.Initialize);
Initializers.Position = Position;
})(Particles.Initializers || (Particles.Initializers = {}));
var Initializers = Particles.Initializers;
})(Phaser.Particles || (Phaser.Particles = {}));
var Particles = Phaser.Particles;
})(Phaser || (Phaser = {}));

View file

@ -0,0 +1,45 @@
/// <reference path="../../_definitions.ts" />
module Phaser.Particles.Initializers {
export class Position extends Initialize {
constructor(zone) {
super();
if (zone != null && zone != undefined)
{
this.zone = zone;
}
else
{
this.zone = new Phaser.Particles.Zones.PointZone();
}
}
zone;
reset(zone) {
if (zone != null && zone != undefined)
{
this.zone = zone;
}
else
{
this.zone = new Phaser.Particles.Zones.PointZone();
}
}
initialize(target) {
this.zone.getPosition();
target.p.x = this.zone.vector.x;
target.p.y = this.zone.vector.y;
}
}
}

View file

@ -0,0 +1,19 @@
var Shapes;
(function (Shapes) {
var Point = Shapes.Point = (function () {
function Point(x, y) {
this.x = x;
this.y = y;
}
Point.prototype.getDist = function () {
return Math.sqrt((this.x * this.x) + (this.y * this.y));
};
Point.origin = new Point(0, 0);
return Point;
})();
})(Shapes || (Shapes = {}));
var p = new Shapes.Point(3, 4);
var dist = p.getDist();

View file

@ -0,0 +1,33 @@
/// <reference path="../../_definitions.ts" />
module Phaser.Particles.Initializers {
export class Radius extends Initialize {
constructor(a,b,c) {
super();
this.radius = ParticleUtils.setSpanValue(a, b, c);
}
radius: Phaser.Particles.Span;
reset(a, b, c) {
this.radius = ParticleUtils.setSpanValue(a, b, c);
}
initialize(particle) {
particle.radius = this.radius.getValue();
particle.transform.oldRadius = particle.radius;
}
}
}

View file

@ -0,0 +1,57 @@
var __extends = this.__extends || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
__.prototype = b.prototype;
d.prototype = new __();
};
var Phaser;
(function (Phaser) {
(function (Particles) {
/// <reference path="../../_definitions.ts" />
(function (Initializers) {
var Rate = (function (_super) {
__extends(Rate, _super);
function Rate(numpan, timepan) {
_super.call(this);
numpan = Particles.ParticleUtils.initValue(numpan, 1);
timepan = Particles.ParticleUtils.initValue(timepan, 1);
this.numPan = new Phaser.Particles.Span(numpan);
this.timePan = new Phaser.Particles.Span(timepan);
this.startTime = 0;
this.nextTime = 0;
this.init();
}
Rate.prototype.init = function () {
this.startTime = 0;
this.nextTime = this.timePan.getValue();
};
Rate.prototype.getValue = function (time) {
this.startTime += time;
if (this.startTime >= this.nextTime) {
this.startTime = 0;
this.nextTime = this.timePan.getValue();
if (this.numPan.b == 1) {
if (this.numPan.getValue(false) > 0.5) {
return 1;
} else {
return 0;
}
} else {
return this.numPan.getValue(true);
}
}
return 0;
};
return Rate;
})(Initializers.Initialize);
Initializers.Rate = Rate;
})(Particles.Initializers || (Particles.Initializers = {}));
var Initializers = Particles.Initializers;
})(Phaser.Particles || (Phaser.Particles = {}));
var Particles = Phaser.Particles;
})(Phaser || (Phaser = {}));

View file

@ -0,0 +1,60 @@
/// <reference path="../../_definitions.ts" />
module Phaser.Particles.Initializers {
export class Rate extends Initialize {
constructor(numpan, timepan) {
super();
numpan = ParticleUtils.initValue(numpan, 1);
timepan = ParticleUtils.initValue(timepan, 1);
this.numPan = new Phaser.Particles.Span(numpan);
this.timePan = new Phaser.Particles.Span(timepan);
this.startTime = 0;
this.nextTime = 0;
this.init();
}
numPan: Phaser.Particles.Span;
timePan: Phaser.Particles.Span;
startTime;
nextTime;
init() {
this.startTime = 0;
this.nextTime = this.timePan.getValue();
}
getValue (time) {
this.startTime += time;
if (this.startTime >= this.nextTime)
{
this.startTime = 0;
this.nextTime = this.timePan.getValue();
if (this.numPan.b == 1)
{
if (this.numPan.getValue(false) > 0.5)
{
return 1;
}
else
{
return 0;
}
}
else
{
return this.numPan.getValue(true);
}
}
return 0;
}
}
}

View file

@ -0,0 +1,48 @@
var __extends = this.__extends || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
__.prototype = b.prototype;
d.prototype = new __();
};
var Phaser;
(function (Phaser) {
(function (Particles) {
/// <reference path="../../_definitions.ts" />
(function (Initializers) {
var Velocity = (function (_super) {
__extends(Velocity, _super);
function Velocity(rpan, thapan, type) {
_super.call(this);
this.rPan = Particles.ParticleUtils.setSpanValue(rpan);
this.thaPan = Particles.ParticleUtils.setSpanValue(thapan);
this.type = Particles.ParticleUtils.initValue(type, 'vector');
}
Velocity.prototype.reset = function (rpan, thapan, type) {
this.rPan = Particles.ParticleUtils.setSpanValue(rpan);
this.thaPan = Particles.ParticleUtils.setSpanValue(thapan);
this.type = Particles.ParticleUtils.initValue(type, 'vector');
};
Velocity.prototype.normalizeVelocity = function (vr) {
return vr * Particles.ParticleManager.MEASURE;
};
Velocity.prototype.initialize = function (target) {
if (this.type == 'p' || this.type == 'P' || this.type == 'polar') {
var polar2d = new Particles.Polar2D(this.normalizeVelocity(this.rPan.getValue()), this.thaPan.getValue() * Math.PI / 180);
target.v.x = polar2d.getX();
target.v.y = polar2d.getY();
} else {
target.v.x = this.normalizeVelocity(this.rPan.getValue());
target.v.y = this.normalizeVelocity(this.thaPan.getValue());
}
};
return Velocity;
})(Initializers.Initialize);
Initializers.Velocity = Velocity;
})(Particles.Initializers || (Particles.Initializers = {}));
var Initializers = Particles.Initializers;
})(Phaser.Particles || (Phaser.Particles = {}));
var Particles = Phaser.Particles;
})(Phaser || (Phaser = {}));

View file

@ -0,0 +1,46 @@
/// <reference path="../../_definitions.ts" />
module Phaser.Particles.Initializers {
export class Velocity extends Initialize {
constructor(rpan, thapan, type) {
super();
this.rPan = ParticleUtils.setSpanValue(rpan);
this.thaPan = ParticleUtils.setSpanValue(thapan);
this.type = ParticleUtils.initValue(type, 'vector');
}
rPan: Phaser.Particles.Span;
thaPan: Phaser.Particles.Span;
type;
reset(rpan, thapan, type) {
this.rPan = ParticleUtils.setSpanValue(rpan);
this.thaPan = ParticleUtils.setSpanValue(thapan);
this.type = ParticleUtils.initValue(type, 'vector');
}
normalizeVelocity(vr) {
return vr * ParticleManager.MEASURE;
}
initialize(target) {
if (this.type == 'p' || this.type == 'P' || this.type == 'polar')
{
var polar2d = new Polar2D(this.normalizeVelocity(this.rPan.getValue()), this.thaPan.getValue() * Math.PI / 180);
target.v.x = polar2d.getX();
target.v.y = polar2d.getY();
}
else
{
target.v.x = this.normalizeVelocity(this.rPan.getValue());
target.v.y = this.normalizeVelocity(this.thaPan.getValue());
}
}
}
}

View file

@ -0,0 +1,38 @@
var __extends = this.__extends || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
__.prototype = b.prototype;
d.prototype = new __();
};
var Phaser;
(function (Phaser) {
(function (Particles) {
/// <reference path="../../_definitions.ts" />
(function (Zones) {
var PointZone = (function (_super) {
__extends(PointZone, _super);
function PointZone(x, y) {
if (typeof x === "undefined") { x = 0; }
if (typeof y === "undefined") { y = 0; }
_super.call(this);
this.x = x;
this.y = y;
}
PointZone.prototype.getPosition = function () {
return this.vector.setTo(this.x, this.y);
};
PointZone.prototype.crossing = function (particle) {
if (this.alert) {
alert('Sorry PointZone does not support crossing method');
this.alert = false;
}
};
return PointZone;
})(Zones.Zone);
Zones.PointZone = PointZone;
})(Particles.Zones || (Particles.Zones = {}));
var Zones = Particles.Zones;
})(Phaser.Particles || (Phaser.Particles = {}));
var Particles = Phaser.Particles;
})(Phaser || (Phaser = {}));

View file

@ -0,0 +1,31 @@
/// <reference path="../../_definitions.ts" />
module Phaser.Particles.Zones {
export class PointZone extends Zone {
constructor(x=0,y=0) {
super();
this.x = x;
this.y = y;
}
x;
y;
getPosition() {
return this.vector.setTo(this.x, this.y);
}
crossing(particle) {
if (this.alert)
{
alert('Sorry PointZone does not support crossing method');
this.alert = false;
}
}
}
}

View file

@ -0,0 +1,20 @@
var Phaser;
(function (Phaser) {
(function (Particles) {
/// <reference path="../../_definitions.ts" />
(function (Zones) {
var Zone = (function () {
function Zone() {
this.vector = new Phaser.Vec2();
this.random = 0;
this.crossType = "dead";
this.alert = true;
}
return Zone;
})();
Zones.Zone = Zone;
})(Particles.Zones || (Particles.Zones = {}));
var Zones = Particles.Zones;
})(Phaser.Particles || (Phaser.Particles = {}));
var Particles = Phaser.Particles;
})(Phaser || (Phaser = {}));

View file

@ -0,0 +1,20 @@
/// <reference path="../../_definitions.ts" />
module Phaser.Particles.Zones {
export class Zone {
constructor() {
this.vector = new Phaser.Vec2;
this.random = 0;
this.crossType = "dead";
this.alert = true;
}
vector: Phaser.Vec2;
random: number;
crossType: string;
alert: boolean;
}
}

196
Phaser/physics/AABB.js Normal file
View file

@ -0,0 +1,196 @@
var Phaser;
(function (Phaser) {
/// <reference path="../_definitions.ts" />
/**
* Phaser - Physics - AABB
*/
(function (Physics) {
var AABB = (function () {
function AABB(game, x, y, xw, yw) {
this.type = 0;
this.game = game;
this.pos = new Phaser.Vec2(x, y);
this.oldpos = new Phaser.Vec2(x, y);
this.xw = Math.abs(xw);
this.yw = Math.abs(yw);
this.aabbTileProjections = {};
this.aabbTileProjections[Phaser.Physics.TileMapCell.CTYPE_FULL] = Phaser.Physics.Projection.AABBFull.Collide;
this.aabbTileProjections[Phaser.Physics.TileMapCell.CTYPE_CONCAVE] = Phaser.Physics.Projection.AABBConcave.Collide;
this.aabbTileProjections[Phaser.Physics.TileMapCell.CTYPE_CONVEX] = Phaser.Physics.Projection.AABBConvex.Collide;
}
AABB.prototype.IntegrateVerlet = function () {
var d = 1;
var g = 0.2;
var p = this.pos;
var o = this.oldpos;
var px;
var py;
//o = oldposition
var ox = o.x;
var oy = o.y;
o.x = px = p.x;
o.y = py = p.y;
//integrate
p.x += (d * px) - (d * ox);
p.y += (d * py) - (d * oy) + g;
};
AABB.prototype.ReportCollisionVsWorld = function (px, py, dx, dy, obj) {
var p = this.pos;
var o = this.oldpos;
//calc velocity
var vx = p.x - o.x;
var vy = p.y - o.y;
//find component of velocity parallel to collision normal
var dp = (vx * dx + vy * dy);
var nx = dp * dx;
var ny = dp * dy;
var tx = vx - nx;
var ty = vy - ny;
//we only want to apply collision response forces if the object is travelling into, and not out of, the collision
var b, bx, by, f, fx, fy;
if (dp < 0) {
//f = FRICTION;
f = 0.05;
fx = tx * f;
fy = ty * f;
//b = 1 + BOUNCE;//this bounce constant should be elsewhere, i.e inside the object/tile/etc..
b = 1 + 0.3;
bx = (nx * b);
by = (ny * b);
} else {
//moving out of collision, do not apply forces
bx = by = fx = fy = 0;
}
p.x += px;
p.y += py;
o.x += px + bx + fx;
o.y += py + by + fy;
};
AABB.prototype.CollideAABBVsTile = function (tile) {
var pos = this.pos;
var c = tile;
var tx = c.pos.x;
var ty = c.pos.y;
var txw = c.xw;
var tyw = c.yw;
var dx = pos.x - tx;
var px = (txw + this.xw) - Math.abs(dx);
if (0 < px) {
var dy = pos.y - ty;
var py = (tyw + this.yw) - Math.abs(dy);
if (0 < py) {
if (px < py) {
if (dx < 0) {
//project to the left
px *= -1;
py = 0;
} else {
//proj to right
py = 0;
}
} else {
if (dy < 0) {
//project up
px = 0;
py *= -1;
} else {
//project down
px = 0;
}
}
this.ResolveBoxTile(px, py, this, c);
}
}
};
AABB.prototype.CollideAABBVsWorldBounds = function () {
var p = this.pos;
var xw = this.xw;
var yw = this.yw;
var XMIN = 0;
var XMAX = 800;
var YMIN = 0;
var YMAX = 600;
//collide vs. x-bounds
//test XMIN
var dx = XMIN - (p.x - xw);
if (0 < dx) {
//object is colliding with XMIN
this.ReportCollisionVsWorld(dx, 0, 1, 0, null);
} else {
//test XMAX
dx = (p.x + xw) - XMAX;
if (0 < dx) {
//object is colliding with XMAX
this.ReportCollisionVsWorld(-dx, 0, -1, 0, null);
}
}
//collide vs. y-bounds
//test YMIN
var dy = YMIN - (p.y - yw);
if (0 < dy) {
//object is colliding with YMIN
this.ReportCollisionVsWorld(0, dy, 0, 1, null);
} else {
//test YMAX
dy = (p.y + yw) - YMAX;
if (0 < dy) {
//object is colliding with YMAX
this.ReportCollisionVsWorld(0, -dy, 0, -1, null);
}
}
};
AABB.prototype.render = function (context) {
context.beginPath();
context.strokeStyle = 'rgb(0,255,0)';
context.strokeRect(this.pos.x - this.xw, this.pos.y - this.yw, this.xw * 2, this.yw * 2);
context.stroke();
context.closePath();
context.fillStyle = 'rgb(0,255,0)';
context.fillRect(this.pos.x, this.pos.y, 2, 2);
};
AABB.prototype.ResolveBoxTile = function (x, y, box, t) {
if (0 < t.ID) {
return this.aabbTileProjections[t.CTYPE](x, y, box, t);
} else {
//trace("ResolveBoxTile() was called with an empty (or unknown) tile!: ID=" + t.ID + " ("+ t.i + "," + t.j + ")");
return false;
}
};
AABB.COL_NONE = 0;
AABB.COL_AXIS = 1;
AABB.COL_OTHER = 2;
return AABB;
})();
Physics.AABB = AABB;
})(Phaser.Physics || (Phaser.Physics = {}));
var Physics = Phaser.Physics;
})(Phaser || (Phaser = {}));

253
Phaser/physics/AABB.ts Normal file
View file

@ -0,0 +1,253 @@
/// <reference path="../_definitions.ts" />
/**
* Phaser - Physics - AABB
*/
module Phaser.Physics {
export class AABB {
constructor(game: Phaser.Game, x: number, y: number, xw: number, yw: number) {
this.game = game;
this.pos = new Phaser.Vec2(x, y);
this.oldpos = new Phaser.Vec2(x, y);
this.xw = Math.abs(xw);
this.yw = Math.abs(yw);
this.aabbTileProjections = {};
this.aabbTileProjections[Phaser.Physics.TileMapCell.CTYPE_FULL] = Phaser.Physics.Projection.AABBFull.Collide;
this.aabbTileProjections[Phaser.Physics.TileMapCell.CTYPE_CONCAVE] = Phaser.Physics.Projection.AABBConcave.Collide;
this.aabbTileProjections[Phaser.Physics.TileMapCell.CTYPE_CONVEX] = Phaser.Physics.Projection.AABBConvex.Collide;
}
public game: Phaser.Game;
public static COL_NONE = 0;
public static COL_AXIS = 1;
public static COL_OTHER = 2;
public type: number = 0;
public pos: Phaser.Vec2;
public oldpos: Phaser.Vec2;
public xw: number;
public yw: number;
public oH: number;
public oV: number;
private aabbTileProjections;
public IntegrateVerlet() {
var d = 1; // global drag
var g = 0.2; // global gravity
var p = this.pos;
var o = this.oldpos;
var px;
var py;
//o = oldposition
var ox = o.x;
var oy = o.y;
o.x = px = p.x; //get vector values
o.y = py = p.y; //p = position
//integrate
p.x += (d * px) - (d * ox);
p.y += (d * py) - (d * oy) + g;
}
public ReportCollisionVsWorld(px: number, py: number, dx: number, dy: number, obj: TileMapCell) {
var p = this.pos;
var o = this.oldpos;
//calc velocity
var vx = p.x - o.x;
var vy = p.y - o.y;
//find component of velocity parallel to collision normal
var dp = (vx * dx + vy * dy);
var nx = dp * dx;//project velocity onto collision normal
var ny = dp * dy;//nx,ny is normal velocity
var tx = vx - nx;//px,py is tangent velocity
var ty = vy - ny;
//we only want to apply collision response forces if the object is travelling into, and not out of, the collision
var b, bx, by, f, fx, fy;
if (dp < 0)
{
//f = FRICTION;
f = 0.05;
fx = tx * f;
fy = ty * f;
//b = 1 + BOUNCE;//this bounce constant should be elsewhere, i.e inside the object/tile/etc..
b = 1 + 0.3;//this bounce constant should be elsewhere, i.e inside the object/tile/etc..
bx = (nx * b);
by = (ny * b);
}
else
{
//moving out of collision, do not apply forces
bx = by = fx = fy = 0;
}
p.x += px;//project object out of collision
p.y += py;
o.x += px + bx + fx;//apply bounce+friction impulses which alter velocity
o.y += py + by + fy;
}
public CollideAABBVsTile(tile:Phaser.Physics.TileMapCell) {
var pos = this.pos;
var c = tile;
var tx = c.pos.x;
var ty = c.pos.y;
var txw = c.xw;
var tyw = c.yw;
var dx = pos.x - tx;//tile->obj delta
var px = (txw + this.xw) - Math.abs(dx);//penetration depth in x
if (0 < px)
{
var dy = pos.y - ty;//tile->obj delta
var py = (tyw + this.yw) - Math.abs(dy);//pen depth in y
if (0 < py)
{
//object may be colliding with tile; call tile-specific collision function
//calculate projection vectors
if (px < py)
{
//project in x
if (dx < 0)
{
//project to the left
px *= -1;
py = 0;
}
else
{
//proj to right
py = 0;
}
}
else
{
//project in y
if (dy < 0)
{
//project up
px = 0;
py *= -1;
}
else
{
//project down
px = 0;
}
}
this.ResolveBoxTile(px, py, this, c);
}
}
}
public CollideAABBVsWorldBounds() {
var p = this.pos;
var xw = this.xw;
var yw = this.yw;
var XMIN = 0;
var XMAX = 800;
var YMIN = 0;
var YMAX = 600;
//collide vs. x-bounds
//test XMIN
var dx = XMIN - (p.x - xw);
if (0 < dx)
{
//object is colliding with XMIN
this.ReportCollisionVsWorld(dx, 0, 1, 0, null);
}
else
{
//test XMAX
dx = (p.x + xw) - XMAX;
if (0 < dx)
{
//object is colliding with XMAX
this.ReportCollisionVsWorld(-dx, 0, -1, 0, null);
}
}
//collide vs. y-bounds
//test YMIN
var dy = YMIN - (p.y - yw);
if (0 < dy)
{
//object is colliding with YMIN
this.ReportCollisionVsWorld(0, dy, 0, 1, null);
}
else
{
//test YMAX
dy = (p.y + yw) - YMAX;
if (0 < dy)
{
//object is colliding with YMAX
this.ReportCollisionVsWorld(0, -dy, 0, -1, null);
}
}
}
public render(context: CanvasRenderingContext2D) {
context.beginPath();
context.strokeStyle = 'rgb(0,255,0)';
context.strokeRect(this.pos.x - this.xw, this.pos.y - this.yw, this.xw * 2, this.yw * 2);
context.stroke();
context.closePath();
context.fillStyle = 'rgb(0,255,0)';
context.fillRect(this.pos.x, this.pos.y, 2, 2);
}
public ResolveBoxTile(x, y, box, t) {
if (0 < t.ID)
{
return this.aabbTileProjections[t.CTYPE](x, y, box, t);
}
else
{
//trace("ResolveBoxTile() was called with an empty (or unknown) tile!: ID=" + t.ID + " ("+ t.i + "," + t.j + ")");
return false;
}
}
}
}

View file

@ -1,8 +1,9 @@
var Phaser;
(function (Phaser) {
/// <reference path="../../_definitions.ts" />
/// <reference path="../_definitions.ts" />
/**
* Phaser - ArcadePhysics - Body
* Phaser - Physics - Body
* A binding between a Sprite and a physics object (AABB or Circle)
*/
(function (Physics) {
var Body = (function () {

View file

@ -1,7 +1,8 @@
/// <reference path="../../_definitions.ts" />
/// <reference path="../_definitions.ts" />
/**
* Phaser - ArcadePhysics - Body
* Phaser - Physics - Body
* A binding between a Sprite and a physics object (AABB or Circle)
*/
module Phaser.Physics {

227
Phaser/physics/Circle.js Normal file
View file

@ -0,0 +1,227 @@
var Phaser;
(function (Phaser) {
/// <reference path="../_definitions.ts" />
/**
* Phaser - Physics - Circle
*/
(function (Physics) {
var Circle = (function () {
function Circle(game, x, y, radius) {
this.type = 1;
this.game = game;
this.pos = new Phaser.Vec2(x, y);
this.oldpos = new Phaser.Vec2(x, y);
this.radius = radius;
this.circleTileProjections = {};
this.circleTileProjections[Phaser.Physics.TileMapCell.CTYPE_FULL] = Phaser.Physics.Projection.CircleFull.Collide;
this.circleTileProjections[Phaser.Physics.TileMapCell.CTYPE_45DEG] = Phaser.Physics.Projection.Circle45Deg.Collide;
this.circleTileProjections[Phaser.Physics.TileMapCell.CTYPE_CONCAVE] = Phaser.Physics.Projection.CircleConcave.Collide;
this.circleTileProjections[Phaser.Physics.TileMapCell.CTYPE_CONVEX] = Phaser.Physics.Projection.CircleConvex.Collide;
}
Circle.prototype.IntegrateVerlet = function () {
var d = 1;
var g = 0.2;
var p = this.pos;
var o = this.oldpos;
var px;
var py;
var ox = o.x;
var oy = o.y;
//o = oldposition
o.x = px = p.x;
o.y = py = p.y;
//integrate
p.x += (d * px) - (d * ox);
p.y += (d * py) - (d * oy) + g;
};
Circle.prototype.ReportCollisionVsWorld = function (px, py, dx, dy, obj) {
var p = this.pos;
var o = this.oldpos;
//calc velocity
var vx = p.x - o.x;
var vy = p.y - o.y;
//find component of velocity parallel to collision normal
var dp = (vx * dx + vy * dy);
var nx = dp * dx;
var ny = dp * dy;
var tx = vx - nx;
var ty = vy - ny;
//we only want to apply collision response forces if the object is travelling into, and not out of, the collision
var b, bx, by, f, fx, fy;
if (dp < 0) {
//f = FRICTION;
f = 0.05;
fx = tx * f;
fy = ty * f;
//b = 1 + BOUNCE;//this bounce constant should be elsewhere, i.e inside the object/tile/etc..
b = 1 + 0.3;
bx = (nx * b);
by = (ny * b);
} else {
//moving out of collision, do not apply forces
bx = by = fx = fy = 0;
}
p.x += px;
p.y += py;
o.x += px + bx + fx;
o.y += py + by + fy;
};
Circle.prototype.CollideCircleVsWorldBounds = function () {
var p = this.pos;
var r = this.radius;
var XMIN = 0;
var XMAX = 800;
var YMIN = 0;
var YMAX = 600;
//collide vs. x-bounds
//test XMIN
var dx = XMIN - (p.x - r);
if (0 < dx) {
//object is colliding with XMIN
this.ReportCollisionVsWorld(dx, 0, 1, 0, null);
} else {
//test XMAX
dx = (p.x + r) - XMAX;
if (0 < dx) {
//object is colliding with XMAX
this.ReportCollisionVsWorld(-dx, 0, -1, 0, null);
}
}
//collide vs. y-bounds
//test YMIN
var dy = YMIN - (p.y - r);
if (0 < dy) {
//object is colliding with YMIN
this.ReportCollisionVsWorld(0, dy, 0, 1, null);
} else {
//test YMAX
dy = (p.y + r) - YMAX;
if (0 < dy) {
//object is colliding with YMAX
this.ReportCollisionVsWorld(0, -dy, 0, -1, null);
}
}
};
Circle.prototype.render = function (context) {
context.beginPath();
context.strokeStyle = 'rgb(0,255,0)';
context.arc(this.pos.x, this.pos.y, this.radius, 0, Math.PI * 2);
context.stroke();
context.closePath();
if (this.oH == 1) {
context.beginPath();
context.strokeStyle = 'rgb(255,0,0)';
context.moveTo(this.pos.x - this.radius, this.pos.y - this.radius);
context.lineTo(this.pos.x - this.radius, this.pos.y + this.radius);
context.stroke();
context.closePath();
} else if (this.oH == -1) {
context.beginPath();
context.strokeStyle = 'rgb(255,0,0)';
context.moveTo(this.pos.x + this.radius, this.pos.y - this.radius);
context.lineTo(this.pos.x + this.radius, this.pos.y + this.radius);
context.stroke();
context.closePath();
}
if (this.oV == 1) {
context.beginPath();
context.strokeStyle = 'rgb(255,0,0)';
context.moveTo(this.pos.x - this.radius, this.pos.y - this.radius);
context.lineTo(this.pos.x + this.radius, this.pos.y - this.radius);
context.stroke();
context.closePath();
} else if (this.oV == -1) {
context.beginPath();
context.strokeStyle = 'rgb(255,0,0)';
context.moveTo(this.pos.x - this.radius, this.pos.y + this.radius);
context.lineTo(this.pos.x + this.radius, this.pos.y + this.radius);
context.stroke();
context.closePath();
}
};
Circle.prototype.CollideCircleVsTile = function (tile) {
var pos = this.pos;
var r = this.radius;
var c = tile;
var tx = c.pos.x;
var ty = c.pos.y;
var txw = c.xw;
var tyw = c.yw;
var dx = pos.x - tx;
var px = (txw + r) - Math.abs(dx);
if (0 < px) {
var dy = pos.y - ty;
var py = (tyw + r) - Math.abs(dy);
if (0 < py) {
//object may be colliding with tile
//determine grid/voronoi region of circle center
this.oH = 0;
this.oV = 0;
if (dx < -txw) {
//circle is on left side of tile
this.oH = -1;
} else if (txw < dx) {
//circle is on right side of tile
this.oH = 1;
}
if (dy < -tyw) {
//circle is on top side of tile
this.oV = -1;
} else if (tyw < dy) {
//circle is on bottom side of tile
this.oV = 1;
}
this.ResolveCircleTile(px, py, this.oH, this.oV, this, c);
}
}
};
Circle.prototype.ResolveCircleTile = function (x, y, oH, oV, obj, t) {
if (0 < t.ID) {
return this.circleTileProjections[t.CTYPE](x, y, oH, oV, obj, t);
} else {
console.log("ResolveCircleTile() was called with an empty (or unknown) tile!: ID=" + t.ID + " (" + t.i + "," + t.j + ")");
return false;
}
};
Circle.COL_NONE = 0;
Circle.COL_AXIS = 1;
Circle.COL_OTHER = 2;
return Circle;
})();
Physics.Circle = Circle;
})(Phaser.Physics || (Phaser.Physics = {}));
var Physics = Phaser.Physics;
})(Phaser || (Phaser = {}));

279
Phaser/physics/Circle.ts Normal file
View file

@ -0,0 +1,279 @@
/// <reference path="../_definitions.ts" />
/**
* Phaser - Physics - Circle
*/
module Phaser.Physics {
export class Circle {
constructor(game: Phaser.Game, x: number, y: number, radius:number) {
this.game = game;
this.pos = new Phaser.Vec2(x, y);
this.oldpos = new Phaser.Vec2(x, y);
this.radius = radius;
this.circleTileProjections = {};
this.circleTileProjections[Phaser.Physics.TileMapCell.CTYPE_FULL] = Phaser.Physics.Projection.CircleFull.Collide;
this.circleTileProjections[Phaser.Physics.TileMapCell.CTYPE_45DEG] = Phaser.Physics.Projection.Circle45Deg.Collide;
this.circleTileProjections[Phaser.Physics.TileMapCell.CTYPE_CONCAVE] = Phaser.Physics.Projection.CircleConcave.Collide;
this.circleTileProjections[Phaser.Physics.TileMapCell.CTYPE_CONVEX] = Phaser.Physics.Projection.CircleConvex.Collide;
}
public game: Phaser.Game;
public static COL_NONE = 0;
public static COL_AXIS = 1;
public static COL_OTHER = 2;
public type: number = 1;
public pos: Phaser.Vec2;
public oldpos: Phaser.Vec2;
public radius: number;
public oH: number; // horizontal collision
public oV: number;
private circleTileProjections;
public IntegrateVerlet() {
var d = 1; // drag
var g = 0.2; // gravity
var p = this.pos;
var o = this.oldpos;
var px;
var py;
var ox = o.x;
var oy = o.y;
//o = oldposition
o.x = px = p.x; //get vector values
o.y = py = p.y; //p = position
//integrate
p.x += (d * px) - (d * ox);
p.y += (d * py) - (d * oy) + g;
}
public ReportCollisionVsWorld(px: number, py: number, dx: number, dy: number, obj: Phaser.Physics.TileMapCell) {
var p = this.pos;
var o = this.oldpos;
//calc velocity
var vx = p.x - o.x;
var vy = p.y - o.y;
//find component of velocity parallel to collision normal
var dp = (vx * dx + vy * dy);
var nx = dp * dx;//project velocity onto collision normal
var ny = dp * dy;//nx,ny is normal velocity
var tx = vx - nx;//px,py is tangent velocity
var ty = vy - ny;
//we only want to apply collision response forces if the object is travelling into, and not out of, the collision
var b, bx, by, f, fx, fy;
if (dp < 0)
{
//f = FRICTION;
f = 0.05;
fx = tx * f;
fy = ty * f;
//b = 1 + BOUNCE;//this bounce constant should be elsewhere, i.e inside the object/tile/etc..
b = 1 + 0.9;//this bounce constant should be elsewhere, i.e inside the object/tile/etc..
bx = (nx * b);
by = (ny * b);
}
else
{
//moving out of collision, do not apply forces
bx = by = fx = fy = 0;
}
p.x += px;//project object out of collision
p.y += py;
o.x += px + bx + fx;//apply bounce+friction impulses which alter velocity
o.y += py + by + fy;
}
public CollideCircleVsWorldBounds() {
var p = this.pos;
var r = this.radius;
var XMIN = 0;
var XMAX = 800;
var YMIN = 0;
var YMAX = 600;
//collide vs. x-bounds
//test XMIN
var dx = XMIN - (p.x - r);
if (0 < dx)
{
//object is colliding with XMIN
this.ReportCollisionVsWorld(dx, 0, 1, 0, null);
}
else
{
//test XMAX
dx = (p.x + r) - XMAX;
if (0 < dx)
{
//object is colliding with XMAX
this.ReportCollisionVsWorld(-dx, 0, -1, 0, null);
}
}
//collide vs. y-bounds
//test YMIN
var dy = YMIN - (p.y - r);
if (0 < dy)
{
//object is colliding with YMIN
this.ReportCollisionVsWorld(0, dy, 0, 1, null);
}
else
{
//test YMAX
dy = (p.y + r) - YMAX;
if (0 < dy)
{
//object is colliding with YMAX
this.ReportCollisionVsWorld(0, -dy, 0, -1, null);
}
}
}
public render(context: CanvasRenderingContext2D) {
context.beginPath();
context.strokeStyle = 'rgb(0,255,0)';
context.arc(this.pos.x, this.pos.y, this.radius, 0, Math.PI * 2);
context.stroke();
context.closePath();
if (this.oH == 1)
{
context.beginPath();
context.strokeStyle = 'rgb(255,0,0)';
context.moveTo(this.pos.x - this.radius, this.pos.y - this.radius);
context.lineTo(this.pos.x - this.radius, this.pos.y + this.radius);
context.stroke();
context.closePath();
}
else if (this.oH == -1)
{
context.beginPath();
context.strokeStyle = 'rgb(255,0,0)';
context.moveTo(this.pos.x + this.radius, this.pos.y - this.radius);
context.lineTo(this.pos.x + this.radius, this.pos.y + this.radius);
context.stroke();
context.closePath();
}
if (this.oV == 1)
{
context.beginPath();
context.strokeStyle = 'rgb(255,0,0)';
context.moveTo(this.pos.x - this.radius, this.pos.y - this.radius);
context.lineTo(this.pos.x + this.radius, this.pos.y - this.radius);
context.stroke();
context.closePath();
}
else if (this.oV == -1)
{
context.beginPath();
context.strokeStyle = 'rgb(255,0,0)';
context.moveTo(this.pos.x - this.radius, this.pos.y + this.radius);
context.lineTo(this.pos.x + this.radius, this.pos.y + this.radius);
context.stroke();
context.closePath();
}
}
public CollideCircleVsTile(tile) {
var pos = this.pos;
var r = this.radius;
var c = tile;
var tx = c.pos.x;
var ty = c.pos.y;
var txw = c.xw;
var tyw = c.yw;
var dx = pos.x - tx;//tile->obj delta
var px = (txw + r) - Math.abs(dx);//penetration depth in x
if (0 < px)
{
var dy = pos.y - ty;//tile->obj delta
var py = (tyw + r) - Math.abs(dy);//pen depth in y
if (0 < py)
{
//object may be colliding with tile
//determine grid/voronoi region of circle center
this.oH = 0;
this.oV = 0;
if (dx < -txw)
{
//circle is on left side of tile
this.oH = -1;
}
else if (txw < dx)
{
//circle is on right side of tile
this.oH = 1;
}
if (dy < -tyw)
{
//circle is on top side of tile
this.oV = -1;
}
else if (tyw < dy)
{
//circle is on bottom side of tile
this.oV = 1;
}
this.ResolveCircleTile(px, py, this.oH, this.oV, this, c);
}
}
}
public ResolveCircleTile(x, y, oH, oV, obj, t) {
if (0 < t.ID)
{
return this.circleTileProjections[t.CTYPE](x, y, oH, oV, obj, t);
}
else
{
console.log("ResolveCircleTile() was called with an empty (or unknown) tile!: ID=" + t.ID + " (" + t.i + "," + t.j + ")");
return false;
}
}
}
}

View file

@ -0,0 +1,38 @@
var Phaser;
(function (Phaser) {
/// <reference path="../_definitions.ts" />
/**
* Phaser - Physics - PhysicsManager
*/
(function (Physics) {
var PhysicsManager = (function () {
function PhysicsManager(game) {
this.grav = 0.2;
this.drag = 1;
this.bounce = 0.3;
this.friction = 0.05;
this.min_f = 0;
this.max_f = 1;
this.min_b = 0;
this.max_b = 1;
this.min_g = 0;
this.max_g = 1;
this.xmin = 0;
this.xmax = 800;
this.ymin = 0;
this.ymax = 600;
this.objrad = 24;
this.tilerad = 24 * 2;
this.objspeed = 0.2;
this.maxspeed = 20;
this.game = game;
}
PhysicsManager.prototype.update = function () {
// Booyah!
};
return PhysicsManager;
})();
Physics.PhysicsManager = PhysicsManager;
})(Phaser.Physics || (Phaser.Physics = {}));
var Physics = Phaser.Physics;
})(Phaser || (Phaser = {}));

View file

@ -0,0 +1,51 @@
/// <reference path="../_definitions.ts" />
/**
* Phaser - Physics - PhysicsManager
*/
module Phaser.Physics {
export class PhysicsManager {
constructor(game: Phaser.Game) {
this.game = game;
}
public game: Phaser.Game;
grav: number = 0.2;
drag: number = 1;
bounce: number = 0.3;
friction: number = 0.05;
min_f: number = 0;
max_f: number = 1;
min_b: number = 0;
max_b: number = 1;
min_g: number = 0;
max_g = 1;
xmin: number = 0;
xmax: number = 800;
ymin: number = 0;
ymax: number = 600;
objrad: number = 24;
tilerad: number = 24 * 2;
objspeed: number = 0.2;
maxspeed: number = 20;
public update() {
// Booyah!
}
}
}

View file

@ -0,0 +1,361 @@
var Phaser;
(function (Phaser) {
/// <reference path="../_definitions.ts" />
/**
* Phaser - Physics - TileMapCell
*/
(function (Physics) {
var TileMapCell = (function () {
function TileMapCell(game, x, y, xw, yw) {
this.game = game;
this.ID = TileMapCell.TID_EMPTY;
this.CTYPE = TileMapCell.CTYPE_EMPTY;
this.pos = new Phaser.Vec2(x, y);
this.xw = xw;
this.yw = yw;
this.minx = this.pos.x - this.xw;
this.maxx = this.pos.x + this.xw;
this.miny = this.pos.y - this.yw;
this.maxy = this.pos.y + this.yw;
//this stores tile-specific collision information
this.signx = 0;
this.signy = 0;
this.sx = 0;
this.sy = 0;
}
//these functions are used to update the cell
//note: ID is assumed to NOT be "empty" state..
//if it IS the empty state, the tile clears itself
TileMapCell.prototype.SetState = function (ID) {
if (ID == TileMapCell.TID_EMPTY) {
this.Clear();
} else {
//set tile state to a non-emtpy value, and update it's edges and those of the neighbors
this.ID = ID;
this.UpdateType();
//this.Draw();
}
return this;
};
TileMapCell.prototype.Clear = function () {
//tile was on, turn it off
this.ID = TileMapCell.TID_EMPTY;
this.UpdateType();
//this.Draw();
};
TileMapCell.prototype.render = function (context) {
context.beginPath();
context.strokeStyle = 'rgb(255,255,0)';
context.strokeRect(this.minx, this.miny, this.xw * 2, this.yw * 2);
context.strokeRect(this.pos.x, this.pos.y, 2, 2);
context.closePath();
};
//this converts a tile from implicitly-defined (via ID), to explicit (via properties)
TileMapCell.prototype.UpdateType = function () {
if (0 < this.ID) {
if (this.ID < TileMapCell.CTYPE_45DEG) {
//TID_FULL
this.CTYPE = TileMapCell.CTYPE_FULL;
this.signx = 0;
this.signy = 0;
this.sx = 0;
this.sy = 0;
} else if (this.ID < TileMapCell.CTYPE_CONCAVE) {
//45deg
this.CTYPE = TileMapCell.CTYPE_45DEG;
if (this.ID == TileMapCell.TID_45DEGpn) {
console.log('set tile as 45deg pn');
this.signx = 1;
this.signy = -1;
this.sx = this.signx / Math.SQRT2;
this.sy = this.signy / Math.SQRT2;
} else if (this.ID == TileMapCell.TID_45DEGnn) {
this.signx = -1;
this.signy = -1;
this.sx = this.signx / Math.SQRT2;
this.sy = this.signy / Math.SQRT2;
} else if (this.ID == TileMapCell.TID_45DEGnp) {
this.signx = -1;
this.signy = 1;
this.sx = this.signx / Math.SQRT2;
this.sy = this.signy / Math.SQRT2;
} else if (this.ID == TileMapCell.TID_45DEGpp) {
this.signx = 1;
this.signy = 1;
this.sx = this.signx / Math.SQRT2;
this.sy = this.signy / Math.SQRT2;
} else {
//trace("BAAAD TILE!!!!!: ID=" + this.ID + " ("+ t.i + "," + t.j + ")");
return false;
}
} else if (this.ID < TileMapCell.CTYPE_CONVEX) {
//concave
this.CTYPE = TileMapCell.CTYPE_CONCAVE;
if (this.ID == TileMapCell.TID_CONCAVEpn) {
this.signx = 1;
this.signy = -1;
this.sx = 0;
this.sy = 0;
} else if (this.ID == TileMapCell.TID_CONCAVEnn) {
this.signx = -1;
this.signy = -1;
this.sx = 0;
this.sy = 0;
} else if (this.ID == TileMapCell.TID_CONCAVEnp) {
this.signx = -1;
this.signy = 1;
this.sx = 0;
this.sy = 0;
} else if (this.ID == TileMapCell.TID_CONCAVEpp) {
this.signx = 1;
this.signy = 1;
this.sx = 0;
this.sy = 0;
} else {
//trace("BAAAD TILE!!!!!: ID=" + this.ID + " ("+ t.i + "," + t.j + ")");
return false;
}
} else if (this.ID < TileMapCell.CTYPE_22DEGs) {
//convex
this.CTYPE = TileMapCell.CTYPE_CONVEX;
if (this.ID == TileMapCell.TID_CONVEXpn) {
this.signx = 1;
this.signy = -1;
this.sx = 0;
this.sy = 0;
} else if (this.ID == TileMapCell.TID_CONVEXnn) {
this.signx = -1;
this.signy = -1;
this.sx = 0;
this.sy = 0;
} else if (this.ID == TileMapCell.TID_CONVEXnp) {
this.signx = -1;
this.signy = 1;
this.sx = 0;
this.sy = 0;
} else if (this.ID == TileMapCell.TID_CONVEXpp) {
this.signx = 1;
this.signy = 1;
this.sx = 0;
this.sy = 0;
} else {
//trace("BAAAD TILE!!!!!: ID=" + this.ID + " ("+ t.i + "," + t.j + ")");
return false;
}
} else if (this.ID < TileMapCell.CTYPE_22DEGb) {
//22deg small
this.CTYPE = TileMapCell.CTYPE_22DEGs;
if (this.ID == TileMapCell.TID_22DEGpnS) {
this.signx = 1;
this.signy = -1;
var slen = Math.sqrt(2 * 2 + 1 * 1);
this.sx = (this.signx * 1) / slen;
this.sy = (this.signy * 2) / slen;
} else if (this.ID == TileMapCell.TID_22DEGnnS) {
this.signx = -1;
this.signy = -1;
var slen = Math.sqrt(2 * 2 + 1 * 1);
this.sx = (this.signx * 1) / slen;
this.sy = (this.signy * 2) / slen;
} else if (this.ID == TileMapCell.TID_22DEGnpS) {
this.signx = -1;
this.signy = 1;
var slen = Math.sqrt(2 * 2 + 1 * 1);
this.sx = (this.signx * 1) / slen;
this.sy = (this.signy * 2) / slen;
} else if (this.ID == TileMapCell.TID_22DEGppS) {
this.signx = 1;
this.signy = 1;
var slen = Math.sqrt(2 * 2 + 1 * 1);
this.sx = (this.signx * 1) / slen;
this.sy = (this.signy * 2) / slen;
} else {
//trace("BAAAD TILE!!!!!: ID=" + this.ID + " ("+ t.i + "," + t.j + ")");
return false;
}
} else if (this.ID < TileMapCell.CTYPE_67DEGs) {
//22deg big
this.CTYPE = TileMapCell.CTYPE_22DEGb;
if (this.ID == TileMapCell.TID_22DEGpnB) {
this.signx = 1;
this.signy = -1;
var slen = Math.sqrt(2 * 2 + 1 * 1);
this.sx = (this.signx * 1) / slen;
this.sy = (this.signy * 2) / slen;
} else if (this.ID == TileMapCell.TID_22DEGnnB) {
this.signx = -1;
this.signy = -1;
var slen = Math.sqrt(2 * 2 + 1 * 1);
this.sx = (this.signx * 1) / slen;
this.sy = (this.signy * 2) / slen;
} else if (this.ID == TileMapCell.TID_22DEGnpB) {
this.signx = -1;
this.signy = 1;
var slen = Math.sqrt(2 * 2 + 1 * 1);
this.sx = (this.signx * 1) / slen;
this.sy = (this.signy * 2) / slen;
} else if (this.ID == TileMapCell.TID_22DEGppB) {
this.signx = 1;
this.signy = 1;
var slen = Math.sqrt(2 * 2 + 1 * 1);
this.sx = (this.signx * 1) / slen;
this.sy = (this.signy * 2) / slen;
} else {
//trace("BAAAD TILE!!!!!: ID=" + this.ID + " ("+ t.i + "," + t.j + ")");
return false;
}
} else if (this.ID < TileMapCell.CTYPE_67DEGb) {
//67deg small
this.CTYPE = TileMapCell.CTYPE_67DEGs;
if (this.ID == TileMapCell.TID_67DEGpnS) {
this.signx = 1;
this.signy = -1;
var slen = Math.sqrt(2 * 2 + 1 * 1);
this.sx = (this.signx * 2) / slen;
this.sy = (this.signy * 1) / slen;
} else if (this.ID == TileMapCell.TID_67DEGnnS) {
this.signx = -1;
this.signy = -1;
var slen = Math.sqrt(2 * 2 + 1 * 1);
this.sx = (this.signx * 2) / slen;
this.sy = (this.signy * 1) / slen;
} else if (this.ID == TileMapCell.TID_67DEGnpS) {
this.signx = -1;
this.signy = 1;
var slen = Math.sqrt(2 * 2 + 1 * 1);
this.sx = (this.signx * 2) / slen;
this.sy = (this.signy * 1) / slen;
} else if (this.ID == TileMapCell.TID_67DEGppS) {
this.signx = 1;
this.signy = 1;
var slen = Math.sqrt(2 * 2 + 1 * 1);
this.sx = (this.signx * 2) / slen;
this.sy = (this.signy * 1) / slen;
} else {
//trace("BAAAD TILE!!!!!: ID=" + this.ID + " ("+ t.i + "," + t.j + ")");
return false;
}
} else if (this.ID < TileMapCell.CTYPE_HALF) {
//67deg big
this.CTYPE = TileMapCell.CTYPE_67DEGb;
if (this.ID == TileMapCell.TID_67DEGpnB) {
this.signx = 1;
this.signy = -1;
var slen = Math.sqrt(2 * 2 + 1 * 1);
this.sx = (this.signx * 2) / slen;
this.sy = (this.signy * 1) / slen;
} else if (this.ID == TileMapCell.TID_67DEGnnB) {
this.signx = -1;
this.signy = -1;
var slen = Math.sqrt(2 * 2 + 1 * 1);
this.sx = (this.signx * 2) / slen;
this.sy = (this.signy * 1) / slen;
} else if (this.ID == TileMapCell.TID_67DEGnpB) {
this.signx = -1;
this.signy = 1;
var slen = Math.sqrt(2 * 2 + 1 * 1);
this.sx = (this.signx * 2) / slen;
this.sy = (this.signy * 1) / slen;
} else if (this.ID == TileMapCell.TID_67DEGppB) {
this.signx = 1;
this.signy = 1;
var slen = Math.sqrt(2 * 2 + 1 * 1);
this.sx = (this.signx * 2) / slen;
this.sy = (this.signy * 1) / slen;
} else {
//trace("BAAAD TILE!!!!!: ID=" + this.ID + " ("+ t.i + "," + t.j + ")");
return false;
}
} else {
//half-full tile
this.CTYPE = TileMapCell.CTYPE_HALF;
if (this.ID == TileMapCell.TID_HALFd) {
this.signx = 0;
this.signy = -1;
this.sx = this.signx;
this.sy = this.signy;
} else if (this.ID == TileMapCell.TID_HALFu) {
this.signx = 0;
this.signy = 1;
this.sx = this.signx;
this.sy = this.signy;
} else if (this.ID == TileMapCell.TID_HALFl) {
this.signx = 1;
this.signy = 0;
this.sx = this.signx;
this.sy = this.signy;
} else if (this.ID == TileMapCell.TID_HALFr) {
this.signx = -1;
this.signy = 0;
this.sx = this.signx;
this.sy = this.signy;
} else {
//trace("BAAD TILE!!!: ID=" + this.ID + " ("+ t.i + "," + t.j + ")");
return false;
}
}
} else {
//TID_EMPTY
this.CTYPE = TileMapCell.CTYPE_EMPTY;
this.signx = 0;
this.signy = 0;
this.sx = 0;
this.sy = 0;
}
};
TileMapCell.TID_EMPTY = 0;
TileMapCell.TID_FULL = 1;
TileMapCell.TID_45DEGpn = 2;
TileMapCell.TID_45DEGnn = 3;
TileMapCell.TID_45DEGnp = 4;
TileMapCell.TID_45DEGpp = 5;
TileMapCell.TID_CONCAVEpn = 6;
TileMapCell.TID_CONCAVEnn = 7;
TileMapCell.TID_CONCAVEnp = 8;
TileMapCell.TID_CONCAVEpp = 9;
TileMapCell.TID_CONVEXpn = 10;
TileMapCell.TID_CONVEXnn = 11;
TileMapCell.TID_CONVEXnp = 12;
TileMapCell.TID_CONVEXpp = 13;
TileMapCell.TID_22DEGpnS = 14;
TileMapCell.TID_22DEGnnS = 15;
TileMapCell.TID_22DEGnpS = 16;
TileMapCell.TID_22DEGppS = 17;
TileMapCell.TID_22DEGpnB = 18;
TileMapCell.TID_22DEGnnB = 19;
TileMapCell.TID_22DEGnpB = 20;
TileMapCell.TID_22DEGppB = 21;
TileMapCell.TID_67DEGpnS = 22;
TileMapCell.TID_67DEGnnS = 23;
TileMapCell.TID_67DEGnpS = 24;
TileMapCell.TID_67DEGppS = 25;
TileMapCell.TID_67DEGpnB = 26;
TileMapCell.TID_67DEGnnB = 27;
TileMapCell.TID_67DEGnpB = 28;
TileMapCell.TID_67DEGppB = 29;
TileMapCell.TID_HALFd = 30;
TileMapCell.TID_HALFr = 31;
TileMapCell.TID_HALFu = 32;
TileMapCell.TID_HALFl = 33;
TileMapCell.CTYPE_EMPTY = 0;
TileMapCell.CTYPE_FULL = 1;
TileMapCell.CTYPE_45DEG = 2;
TileMapCell.CTYPE_CONCAVE = 6;
TileMapCell.CTYPE_CONVEX = 10;
TileMapCell.CTYPE_22DEGs = 14;
TileMapCell.CTYPE_22DEGb = 18;
TileMapCell.CTYPE_67DEGs = 22;
TileMapCell.CTYPE_67DEGb = 26;
TileMapCell.CTYPE_HALF = 30;
return TileMapCell;
})();
Physics.TileMapCell = TileMapCell;
})(Phaser.Physics || (Phaser.Physics = {}));
var Physics = Phaser.Physics;
})(Phaser || (Phaser = {}));

View file

@ -0,0 +1,492 @@
/// <reference path="../_definitions.ts" />
/**
* Phaser - Physics - TileMapCell
*/
module Phaser.Physics {
export class TileMapCell {
constructor(game: Phaser.Game, x: number, y: number, xw: number, yw: number) {
this.game = game;
this.ID = TileMapCell.TID_EMPTY; //all tiles start empty
this.CTYPE = TileMapCell.CTYPE_EMPTY;
this.pos = new Phaser.Vec2(x, y); //setup collision properties
this.xw = xw;
this.yw = yw;
this.minx = this.pos.x - this.xw;
this.maxx = this.pos.x + this.xw;
this.miny = this.pos.y - this.yw;
this.maxy = this.pos.y + this.yw;
//this stores tile-specific collision information
this.signx = 0;
this.signy = 0;
this.sx = 0;
this.sy = 0;
}
public game: Phaser.Game;
static TID_EMPTY = 0;
static TID_FULL = 1;//fullAABB tile
static TID_45DEGpn = 2;//45-degree triangle, whose normal is (+ve,-ve)
static TID_45DEGnn = 3;//(+ve,+ve)
static TID_45DEGnp = 4;//(-ve,+ve)
static TID_45DEGpp = 5;//(-ve,-ve)
static TID_CONCAVEpn = 6;//1/4-circle cutout
static TID_CONCAVEnn = 7;
static TID_CONCAVEnp = 8;
static TID_CONCAVEpp = 9;
static TID_CONVEXpn = 10;//1/4/circle
static TID_CONVEXnn = 11;
static TID_CONVEXnp = 12;
static TID_CONVEXpp = 13;
static TID_22DEGpnS = 14;//22.5 degree slope
static TID_22DEGnnS = 15;
static TID_22DEGnpS = 16;
static TID_22DEGppS = 17;
static TID_22DEGpnB = 18;
static TID_22DEGnnB = 19;
static TID_22DEGnpB = 20;
static TID_22DEGppB = 21;
static TID_67DEGpnS = 22;//67.5 degree slope
static TID_67DEGnnS = 23;
static TID_67DEGnpS = 24;
static TID_67DEGppS = 25;
static TID_67DEGpnB = 26;
static TID_67DEGnnB = 27;
static TID_67DEGnpB = 28;
static TID_67DEGppB = 29;
static TID_HALFd = 30;//half-full tiles
static TID_HALFr = 31;
static TID_HALFu = 32;
static TID_HALFl = 33;
//collision shape "types"
static CTYPE_EMPTY = 0;
static CTYPE_FULL = 1;
static CTYPE_45DEG = 2;
static CTYPE_CONCAVE = 6;
static CTYPE_CONVEX = 10;
static CTYPE_22DEGs = 14;
static CTYPE_22DEGb = 18;
static CTYPE_67DEGs = 22;
static CTYPE_67DEGb = 26;
static CTYPE_HALF = 30;
ID;
CTYPE;
pos: Phaser.Vec2;
xw;
yw;
minx;
maxx;
miny;
maxy;
signx;
signy;
sx;
sy;
//these functions are used to update the cell
//note: ID is assumed to NOT be "empty" state..
//if it IS the empty state, the tile clears itself
SetState(ID) {
if (ID == TileMapCell.TID_EMPTY)
{
this.Clear();
}
else
{
//set tile state to a non-emtpy value, and update it's edges and those of the neighbors
this.ID = ID;
this.UpdateType();
//this.Draw();
}
return this;
}
Clear() {
//tile was on, turn it off
this.ID = TileMapCell.TID_EMPTY
this.UpdateType();
//this.Draw();
}
public render(context: CanvasRenderingContext2D) {
context.beginPath();
context.strokeStyle = 'rgb(255,255,0)';
context.strokeRect(this.minx, this.miny, this.xw * 2, this.yw * 2);
context.strokeRect(this.pos.x, this.pos.y, 2, 2);
context.closePath();
}
//this converts a tile from implicitly-defined (via ID), to explicit (via properties)
UpdateType() {
if (0 < this.ID)
{
//tile is non-empty; collide
if (this.ID < TileMapCell.CTYPE_45DEG)
{
//TID_FULL
this.CTYPE = TileMapCell.CTYPE_FULL;
this.signx = 0;
this.signy = 0;
this.sx = 0;
this.sy = 0;
}
else if (this.ID < TileMapCell.CTYPE_CONCAVE)
{
//45deg
this.CTYPE = TileMapCell.CTYPE_45DEG;
if (this.ID == TileMapCell.TID_45DEGpn)
{
console.log('set tile as 45deg pn');
this.signx = 1;
this.signy = -1;
this.sx = this.signx / Math.SQRT2;//get slope _unit_ normal
this.sy = this.signy / Math.SQRT2;//since normal is (1,-1), length is sqrt(1*1 + -1*-1) = sqrt(2)
}
else if (this.ID == TileMapCell.TID_45DEGnn)
{
this.signx = -1;
this.signy = -1;
this.sx = this.signx / Math.SQRT2;//get slope _unit_ normal
this.sy = this.signy / Math.SQRT2;//since normal is (1,-1), length is sqrt(1*1 + -1*-1) = sqrt(2)
}
else if (this.ID == TileMapCell.TID_45DEGnp)
{
this.signx = -1;
this.signy = 1;
this.sx = this.signx / Math.SQRT2;//get slope _unit_ normal
this.sy = this.signy / Math.SQRT2;//since normal is (1,-1), length is sqrt(1*1 + -1*-1) = sqrt(2)
}
else if (this.ID == TileMapCell.TID_45DEGpp)
{
this.signx = 1;
this.signy = 1;
this.sx = this.signx / Math.SQRT2;//get slope _unit_ normal
this.sy = this.signy / Math.SQRT2;//since normal is (1,-1), length is sqrt(1*1 + -1*-1) = sqrt(2)
}
else
{
//trace("BAAAD TILE!!!!!: ID=" + this.ID + " ("+ t.i + "," + t.j + ")");
return false;
}
}
else if (this.ID < TileMapCell.CTYPE_CONVEX)
{
//concave
this.CTYPE = TileMapCell.CTYPE_CONCAVE;
if (this.ID == TileMapCell.TID_CONCAVEpn)
{
this.signx = 1;
this.signy = -1;
this.sx = 0;
this.sy = 0;
}
else if (this.ID == TileMapCell.TID_CONCAVEnn)
{
this.signx = -1;
this.signy = -1;
this.sx = 0;
this.sy = 0;
}
else if (this.ID == TileMapCell.TID_CONCAVEnp)
{
this.signx = -1;
this.signy = 1;
this.sx = 0;
this.sy = 0;
}
else if (this.ID == TileMapCell.TID_CONCAVEpp)
{
this.signx = 1;
this.signy = 1;
this.sx = 0;
this.sy = 0;
}
else
{
//trace("BAAAD TILE!!!!!: ID=" + this.ID + " ("+ t.i + "," + t.j + ")");
return false;
}
}
else if (this.ID < TileMapCell.CTYPE_22DEGs)
{
//convex
this.CTYPE = TileMapCell.CTYPE_CONVEX;
if (this.ID == TileMapCell.TID_CONVEXpn)
{
this.signx = 1;
this.signy = -1;
this.sx = 0;
this.sy = 0;
}
else if (this.ID == TileMapCell.TID_CONVEXnn)
{
this.signx = -1;
this.signy = -1;
this.sx = 0;
this.sy = 0;
}
else if (this.ID == TileMapCell.TID_CONVEXnp)
{
this.signx = -1;
this.signy = 1;
this.sx = 0;
this.sy = 0;
}
else if (this.ID == TileMapCell.TID_CONVEXpp)
{
this.signx = 1;
this.signy = 1;
this.sx = 0;
this.sy = 0;
}
else
{
//trace("BAAAD TILE!!!!!: ID=" + this.ID + " ("+ t.i + "," + t.j + ")");
return false;
}
}
else if (this.ID < TileMapCell.CTYPE_22DEGb)
{
//22deg small
this.CTYPE = TileMapCell.CTYPE_22DEGs;
if (this.ID == TileMapCell.TID_22DEGpnS)
{
this.signx = 1;
this.signy = -1;
var slen = Math.sqrt(2 * 2 + 1 * 1);
this.sx = (this.signx * 1) / slen;
this.sy = (this.signy * 2) / slen;
}
else if (this.ID == TileMapCell.TID_22DEGnnS)
{
this.signx = -1;
this.signy = -1;
var slen = Math.sqrt(2 * 2 + 1 * 1);
this.sx = (this.signx * 1) / slen;
this.sy = (this.signy * 2) / slen;
}
else if (this.ID == TileMapCell.TID_22DEGnpS)
{
this.signx = -1;
this.signy = 1;
var slen = Math.sqrt(2 * 2 + 1 * 1);
this.sx = (this.signx * 1) / slen;
this.sy = (this.signy * 2) / slen;
}
else if (this.ID == TileMapCell.TID_22DEGppS)
{
this.signx = 1;
this.signy = 1;
var slen = Math.sqrt(2 * 2 + 1 * 1);
this.sx = (this.signx * 1) / slen;
this.sy = (this.signy * 2) / slen;
}
else
{
//trace("BAAAD TILE!!!!!: ID=" + this.ID + " ("+ t.i + "," + t.j + ")");
return false;
}
}
else if (this.ID < TileMapCell.CTYPE_67DEGs)
{
//22deg big
this.CTYPE = TileMapCell.CTYPE_22DEGb;
if (this.ID == TileMapCell.TID_22DEGpnB)
{
this.signx = 1;
this.signy = -1;
var slen = Math.sqrt(2 * 2 + 1 * 1);
this.sx = (this.signx * 1) / slen;
this.sy = (this.signy * 2) / slen;
}
else if (this.ID == TileMapCell.TID_22DEGnnB)
{
this.signx = -1;
this.signy = -1;
var slen = Math.sqrt(2 * 2 + 1 * 1);
this.sx = (this.signx * 1) / slen;
this.sy = (this.signy * 2) / slen;
}
else if (this.ID == TileMapCell.TID_22DEGnpB)
{
this.signx = -1;
this.signy = 1;
var slen = Math.sqrt(2 * 2 + 1 * 1);
this.sx = (this.signx * 1) / slen;
this.sy = (this.signy * 2) / slen;
}
else if (this.ID == TileMapCell.TID_22DEGppB)
{
this.signx = 1;
this.signy = 1;
var slen = Math.sqrt(2 * 2 + 1 * 1);
this.sx = (this.signx * 1) / slen;
this.sy = (this.signy * 2) / slen;
}
else
{
//trace("BAAAD TILE!!!!!: ID=" + this.ID + " ("+ t.i + "," + t.j + ")");
return false;
}
}
else if (this.ID < TileMapCell.CTYPE_67DEGb)
{
//67deg small
this.CTYPE = TileMapCell.CTYPE_67DEGs;
if (this.ID == TileMapCell.TID_67DEGpnS)
{
this.signx = 1;
this.signy = -1;
var slen = Math.sqrt(2 * 2 + 1 * 1);
this.sx = (this.signx * 2) / slen;
this.sy = (this.signy * 1) / slen;
}
else if (this.ID == TileMapCell.TID_67DEGnnS)
{
this.signx = -1;
this.signy = -1;
var slen = Math.sqrt(2 * 2 + 1 * 1);
this.sx = (this.signx * 2) / slen;
this.sy = (this.signy * 1) / slen;
}
else if (this.ID == TileMapCell.TID_67DEGnpS)
{
this.signx = -1;
this.signy = 1;
var slen = Math.sqrt(2 * 2 + 1 * 1);
this.sx = (this.signx * 2) / slen;
this.sy = (this.signy * 1) / slen;
}
else if (this.ID == TileMapCell.TID_67DEGppS)
{
this.signx = 1;
this.signy = 1;
var slen = Math.sqrt(2 * 2 + 1 * 1);
this.sx = (this.signx * 2) / slen;
this.sy = (this.signy * 1) / slen;
}
else
{
//trace("BAAAD TILE!!!!!: ID=" + this.ID + " ("+ t.i + "," + t.j + ")");
return false;
}
}
else if (this.ID < TileMapCell.CTYPE_HALF)
{
//67deg big
this.CTYPE = TileMapCell.CTYPE_67DEGb;
if (this.ID == TileMapCell.TID_67DEGpnB)
{
this.signx = 1;
this.signy = -1;
var slen = Math.sqrt(2 * 2 + 1 * 1);
this.sx = (this.signx * 2) / slen;
this.sy = (this.signy * 1) / slen;
}
else if (this.ID == TileMapCell.TID_67DEGnnB)
{
this.signx = -1;
this.signy = -1;
var slen = Math.sqrt(2 * 2 + 1 * 1);
this.sx = (this.signx * 2) / slen;
this.sy = (this.signy * 1) / slen;
}
else if (this.ID == TileMapCell.TID_67DEGnpB)
{
this.signx = -1;
this.signy = 1;
var slen = Math.sqrt(2 * 2 + 1 * 1);
this.sx = (this.signx * 2) / slen;
this.sy = (this.signy * 1) / slen;
}
else if (this.ID == TileMapCell.TID_67DEGppB)
{
this.signx = 1;
this.signy = 1;
var slen = Math.sqrt(2 * 2 + 1 * 1);
this.sx = (this.signx * 2) / slen;
this.sy = (this.signy * 1) / slen;
}
else
{
//trace("BAAAD TILE!!!!!: ID=" + this.ID + " ("+ t.i + "," + t.j + ")");
return false;
}
}
else
{
//half-full tile
this.CTYPE = TileMapCell.CTYPE_HALF;
if (this.ID == TileMapCell.TID_HALFd)
{
this.signx = 0;
this.signy = -1;
this.sx = this.signx;
this.sy = this.signy;
}
else if (this.ID == TileMapCell.TID_HALFu)
{
this.signx = 0;
this.signy = 1;
this.sx = this.signx;
this.sy = this.signy;
}
else if (this.ID == TileMapCell.TID_HALFl)
{
this.signx = 1;
this.signy = 0;
this.sx = this.signx;
this.sy = this.signy;
}
else if (this.ID == TileMapCell.TID_HALFr)
{
this.signx = -1;
this.signy = 0;
this.sx = this.signx;
this.sy = this.signy;
}
else
{
//trace("BAAD TILE!!!: ID=" + this.ID + " ("+ t.i + "," + t.j + ")");
return false;
}
}
}
else
{
//TID_EMPTY
this.CTYPE = TileMapCell.CTYPE_EMPTY;
this.signx = 0;
this.signy = 0;
this.sx = 0;
this.sy = 0;
}
}
}
}

View file

@ -0,0 +1,56 @@
var Phaser;
(function (Phaser) {
(function (Physics) {
/// <reference path="../../_definitions.ts" />
/**
* Phaser - Physics - Projection
*/
(function (Projection) {
var AABBConcave = (function () {
function AABBConcave() {
}
AABBConcave.Collide = function (x, y, obj, t) {
//if distance from "innermost" corner of AABB is further than tile radius,
//collision is occuring and we need to project
var signx = t.signx;
var signy = t.signy;
var ox = (t.pos.x + (signx * t.xw)) - (obj.pos.x - (signx * obj.xw));
var oy = (t.pos.y + (signy * t.yw)) - (obj.pos.y - (signy * obj.yw));
var twid = t.xw * 2;
var rad = Math.sqrt(twid * twid + 0);
//note that this should be precomputed at compile-time since it's constant
var len = Math.sqrt(ox * ox + oy * oy);
var pen = len - rad;
if (0 < pen) {
//collision; we need to either project along the axes, or project along corner->circlecenter vector
var lenP = Math.sqrt(x * x + y * y);
if (lenP < pen) {
//it's shorter to move along axis directions
obj.ReportCollisionVsWorld(x, y, x / lenP, y / lenP, t);
return Phaser.Physics.AABB.COL_AXIS;
} else {
//project along corner->circle vector
ox /= len;
oy /= len;
obj.ReportCollisionVsWorld(ox * pen, oy * pen, ox, oy, t);
return Phaser.Physics.AABB.COL_OTHER;
}
}
return Phaser.Physics.AABB.COL_NONE;
};
return AABBConcave;
})();
Projection.AABBConcave = AABBConcave;
})(Physics.Projection || (Physics.Projection = {}));
var Projection = Physics.Projection;
})(Phaser.Physics || (Phaser.Physics = {}));
var Physics = Phaser.Physics;
})(Phaser || (Phaser = {}));

View file

@ -0,0 +1,60 @@
/// <reference path="../../_definitions.ts" />
/**
* Phaser - Physics - Projection
*/
module Phaser.Physics.Projection {
export class AABBConcave {
public static Collide(x: number, y: number, obj: Phaser.Physics.AABB, t: Phaser.Physics.TileMapCell) {
//if distance from "innermost" corner of AABB is further than tile radius,
//collision is occuring and we need to project
var signx = t.signx;
var signy = t.signy;
var ox = (t.pos.x + (signx * t.xw)) - (obj.pos.x - (signx * obj.xw));//(ox,oy) is the vector form the innermost AABB corner to the
var oy = (t.pos.y + (signy * t.yw)) - (obj.pos.y - (signy * obj.yw));//circle's center
var twid = t.xw * 2;
var rad = Math.sqrt(twid * twid + 0);//this gives us the radius of a circle centered on the tile's corner and extending to the opposite edge of the tile;
//note that this should be precomputed at compile-time since it's constant
var len = Math.sqrt(ox * ox + oy * oy);
var pen = len - rad;
if (0 < pen)
{
//collision; we need to either project along the axes, or project along corner->circlecenter vector
var lenP = Math.sqrt(x * x + y * y);
if (lenP < pen)
{
//it's shorter to move along axis directions
obj.ReportCollisionVsWorld(x, y, x / lenP, y / lenP, t);
return Phaser.Physics.AABB.COL_AXIS;
}
else
{
//project along corner->circle vector
ox /= len;//len should never be 0, since if it IS 0, rad should be > than len
oy /= len;//and we should never reach here
obj.ReportCollisionVsWorld(ox * pen, oy * pen, ox, oy, t);
return Phaser.Physics.AABB.COL_OTHER;
}
}
return Phaser.Physics.AABB.COL_NONE;
}
}
}

View file

@ -0,0 +1,51 @@
var Phaser;
(function (Phaser) {
(function (Physics) {
/// <reference path="../../_definitions.ts" />
/**
* Phaser - Physics - Projection
*/
(function (Projection) {
var AABBConvex = (function () {
function AABBConvex() {
}
AABBConvex.Collide = function (x, y, obj, t) {
//if distance from "innermost" corner of AABB is less than than tile radius,
//collision is occuring and we need to project
var signx = t.signx;
var signy = t.signy;
var ox = (obj.pos.x - (signx * obj.xw)) - (t.pos.x - (signx * t.xw));
var oy = (obj.pos.y - (signy * obj.yw)) - (t.pos.y - (signy * t.yw));
var len = Math.sqrt(ox * ox + oy * oy);
var twid = t.xw * 2;
var rad = Math.sqrt(twid * twid + 0);
//note that this should be precomputed at compile-time since it's constant
var pen = rad - len;
if (((signx * ox) < 0) || ((signy * oy) < 0)) {
//the test corner is "outside" the 1/4 of the circle we're interested in
var lenP = Math.sqrt(x * x + y * y);
obj.ReportCollisionVsWorld(x, y, x / lenP, y / lenP, t);
return Phaser.Physics.AABB.COL_AXIS;
} else if (0 < pen) {
//project along corner->circle vector
ox /= len;
oy /= len;
obj.ReportCollisionVsWorld(ox * pen, oy * pen, ox, oy, t);
return Phaser.Physics.AABB.COL_OTHER;
}
return Phaser.Physics.AABB.COL_NONE;
};
return AABBConvex;
})();
Projection.AABBConvex = AABBConvex;
})(Physics.Projection || (Physics.Projection = {}));
var Projection = Physics.Projection;
})(Phaser.Physics || (Phaser.Physics = {}));
var Physics = Phaser.Physics;
})(Phaser || (Phaser = {}));

View file

@ -0,0 +1,50 @@
/// <reference path="../../_definitions.ts" />
/**
* Phaser - Physics - Projection
*/
module Phaser.Physics.Projection {
export class AABBConvex {
public static Collide(x: number, y: number, obj: Phaser.Physics.AABB, t: Phaser.Physics.TileMapCell) {
//if distance from "innermost" corner of AABB is less than than tile radius,
//collision is occuring and we need to project
var signx = t.signx;
var signy = t.signy;
var ox = (obj.pos.x - (signx * obj.xw)) - (t.pos.x - (signx * t.xw));//(ox,oy) is the vector from the circle center to
var oy = (obj.pos.y - (signy * obj.yw)) - (t.pos.y - (signy * t.yw));//the AABB
var len = Math.sqrt(ox * ox + oy * oy);
var twid = t.xw * 2;
var rad = Math.sqrt(twid * twid + 0);//this gives us the radius of a circle centered on the tile's corner and extending to the opposite edge of the tile;
//note that this should be precomputed at compile-time since it's constant
var pen = rad - len;
if (((signx * ox) < 0) || ((signy * oy) < 0))
{
//the test corner is "outside" the 1/4 of the circle we're interested in
var lenP = Math.sqrt(x * x + y * y);
obj.ReportCollisionVsWorld(x, y, x / lenP, y / lenP, t);
return Phaser.Physics.AABB.COL_AXIS;//we need to report
}
else if (0 < pen)
{
//project along corner->circle vector
ox /= len;
oy /= len;
obj.ReportCollisionVsWorld(ox * pen, oy * pen, ox, oy, t);
return Phaser.Physics.AABB.COL_OTHER;
}
return Phaser.Physics.AABB.COL_NONE;
}
}
}

View file

@ -0,0 +1,26 @@
var Phaser;
(function (Phaser) {
(function (Physics) {
/// <reference path="../../_definitions.ts" />
/**
* Phaser - Physics - Projection
*/
(function (Projection) {
var AABBFull = (function () {
function AABBFull() {
}
AABBFull.Collide = function (x, y, obj, t) {
var l = Math.sqrt(x * x + y * y);
obj.ReportCollisionVsWorld(x, y, x / l, y / l, t);
return Phaser.Physics.AABB.COL_AXIS;
};
return AABBFull;
})();
Projection.AABBFull = AABBFull;
})(Physics.Projection || (Physics.Projection = {}));
var Projection = Physics.Projection;
})(Phaser.Physics || (Phaser.Physics = {}));
var Physics = Phaser.Physics;
})(Phaser || (Phaser = {}));

View file

@ -0,0 +1,23 @@
/// <reference path="../../_definitions.ts" />
/**
* Phaser - Physics - Projection
*/
module Phaser.Physics.Projection {
export class AABBFull {
public static Collide(x: number, y: number, obj: Phaser.Physics.AABB, t: Phaser.Physics.TileMapCell) {
var l = Math.sqrt(x * x + y * y);
obj.ReportCollisionVsWorld(x, y, x / l, y / l, t);
return Phaser.Physics.AABB.COL_AXIS;
}
}
}

View file

@ -0,0 +1,218 @@
var Phaser;
(function (Phaser) {
(function (Physics) {
/// <reference path="../../_definitions.ts" />
/**
* Phaser - Physics - Projection
*/
(function (Projection) {
var Circle45Deg = (function () {
function Circle45Deg() {
}
Circle45Deg.Collide = function (x, y, oH, oV, obj, t) {
//if we're colliding diagonally:
// -if obj is in the diagonal pointed to by the slope normal: we can't collide, do nothing
// -else, collide vs. the appropriate vertex
//if obj is in this tile: perform collision as for aabb-ve-45deg
//if obj is horiz OR very neighb in direction of slope: collide only vs. slope
//if obj is horiz or vert neigh against direction of slope: collide vs. face
var signx = t.signx;
var signy = t.signy;
var lenP;
if (oH == 0) {
if (oV == 0) {
//colliding with current tile
var sx = t.sx;
var sy = t.sy;
var ox = (obj.pos.x - (sx * obj.radius)) - t.pos.x;
var oy = (obj.pos.y - (sy * obj.radius)) - t.pos.y;
//if the dotprod of (ox,oy) and (sx,sy) is negative, the innermost point is in the slope
//and we need toproject it out by the magnitude of the projection of (ox,oy) onto (sx,sy)
var dp = (ox * sx) + (oy * sy);
if (dp < 0) {
//collision; project delta onto slope and use this as the slope penetration vector
sx *= -dp;
sy *= -dp;
if (x < y) {
//penetration in x is smaller
lenP = x;
y = 0;
if ((obj.pos.x - t.pos.x) < 0) {
x *= -1;
}
} else {
//penetration in y is smaller
lenP = y;
x = 0;
if ((obj.pos.y - t.pos.y) < 0) {
y *= -1;
}
}
var lenN = Math.sqrt(sx * sx + sy * sy);
if (lenP < lenN) {
obj.ReportCollisionVsWorld(x, y, x / lenP, y / lenP, t);
return Phaser.Physics.Circle.COL_AXIS;
} else {
obj.ReportCollisionVsWorld(sx, sy, t.sx, t.sy, t);
return Phaser.Physics.Circle.COL_OTHER;
}
}
} else {
if ((signy * oV) < 0) {
//colliding with face/edge
obj.ReportCollisionVsWorld(0, y * oV, 0, oV, t);
return Phaser.Physics.Circle.COL_AXIS;
} else {
//we could only be colliding vs the slope OR a vertex
//look at the vector form the closest vert to the circle to decide
var sx = t.sx;
var sy = t.sy;
var ox = obj.pos.x - (t.pos.x - (signx * t.xw));
var oy = obj.pos.y - (t.pos.y + (oV * t.yw));
//if the component of (ox,oy) parallel to the normal's righthand normal
//has the same sign as the slope of the slope (the sign of the slope's slope is signx*signy)
//then we project by the vertex, otherwise by the normal.
//note that this is simply a VERY tricky/weird method of determining
//if the circle is in side the slope/face's voronoi region, or that of the vertex.
var perp = (ox * -sy) + (oy * sx);
if (0 < (perp * signx * signy)) {
//collide vs. vertex
var len = Math.sqrt(ox * ox + oy * oy);
var pen = obj.radius - len;
if (0 < pen) {
//note: if len=0, then perp=0 and we'll never reach here, so don't worry about div-by-0
ox /= len;
oy /= len;
obj.ReportCollisionVsWorld(ox * pen, oy * pen, ox, oy, t);
return Phaser.Physics.Circle.COL_OTHER;
}
} else {
//collide vs. slope
//if the component of (ox,oy) parallel to the normal is less than the circle radius, we're
//penetrating the slope. note that this method of penetration calculation doesn't hold
//in general (i.e it won't work if the circle is in the slope), but works in this case
//because we know the circle is in a neighboring cell
var dp = (ox * sx) + (oy * sy);
var pen = obj.radius - Math.abs(dp);
if (0 < pen) {
//collision; circle out along normal by penetration amount
obj.ReportCollisionVsWorld(sx * pen, sy * pen, sx, sy, t);
return Phaser.Physics.Circle.COL_OTHER;
}
}
}
}
} else if (oV == 0) {
if ((signx * oH) < 0) {
//colliding with face/edge
obj.ReportCollisionVsWorld(x * oH, 0, oH, 0, t);
return Phaser.Physics.Circle.COL_AXIS;
} else {
//we could only be colliding vs the slope OR a vertex
//look at the vector form the closest vert to the circle to decide
var sx = t.sx;
var sy = t.sy;
var ox = obj.pos.x - (t.pos.x + (oH * t.xw));
var oy = obj.pos.y - (t.pos.y - (signy * t.yw));
//if the component of (ox,oy) parallel to the normal's righthand normal
//has the same sign as the slope of the slope (the sign of the slope's slope is signx*signy)
//then we project by the normal, otherwise by the vertex.
//(NOTE: this is the opposite logic of the vertical case;
// for vertical, if the perp prod and the slope's slope agree, it's outside.
// for horizontal, if the perp prod and the slope's slope agree, circle is inside.
// ..but this is only a property of flahs' coord system (i.e the rules might swap
// in righthanded systems))
//note that this is simply a VERY tricky/weird method of determining
//if the circle is in side the slope/face's voronio region, or that of the vertex.
var perp = (ox * -sy) + (oy * sx);
if ((perp * signx * signy) < 0) {
//collide vs. vertex
var len = Math.sqrt(ox * ox + oy * oy);
var pen = obj.radius - len;
if (0 < pen) {
//note: if len=0, then perp=0 and we'll never reach here, so don't worry about div-by-0
ox /= len;
oy /= len;
obj.ReportCollisionVsWorld(ox * pen, oy * pen, ox, oy, t);
return Phaser.Physics.Circle.COL_OTHER;
}
} else {
//collide vs. slope
//if the component of (ox,oy) parallel to the normal is less than the circle radius, we're
//penetrating the slope. note that this method of penetration calculation doesn't hold
//in general (i.e it won't work if the circle is in the slope), but works in this case
//because we know the circle is in a neighboring cell
var dp = (ox * sx) + (oy * sy);
var pen = obj.radius - Math.abs(dp);
if (0 < pen) {
//collision; circle out along normal by penetration amount
obj.ReportCollisionVsWorld(sx * pen, sy * pen, sx, sy, t);
return Phaser.Physics.Circle.COL_OTHER;
}
}
}
} else {
if (0 < ((signx * oH) + (signy * oV))) {
//the dotprod of slope normal and cell offset is strictly positive,
//therefore obj is in the diagonal neighb pointed at by the normal, and
//it cannot possibly reach/touch/penetrate the slope
return Phaser.Physics.Circle.COL_NONE;
} else {
//collide vs. vertex
//get diag vertex position
var vx = t.pos.x + (oH * t.xw);
var vy = t.pos.y + (oV * t.yw);
var dx = obj.pos.x - vx;
var dy = obj.pos.y - vy;
var len = Math.sqrt(dx * dx + dy * dy);
var pen = obj.radius - len;
if (0 < pen) {
if (len == 0) {
//project out by 45deg
dx = oH / Math.SQRT2;
dy = oV / Math.SQRT2;
} else {
dx /= len;
dy /= len;
}
obj.ReportCollisionVsWorld(dx * pen, dy * pen, dx, dy, t);
return Phaser.Physics.Circle.COL_OTHER;
}
}
}
return Phaser.Physics.Circle.COL_NONE;
};
return Circle45Deg;
})();
Projection.Circle45Deg = Circle45Deg;
})(Physics.Projection || (Physics.Projection = {}));
var Projection = Physics.Projection;
})(Phaser.Physics || (Phaser.Physics = {}));
var Physics = Phaser.Physics;
})(Phaser || (Phaser = {}));

View file

@ -0,0 +1,271 @@
/// <reference path="../../_definitions.ts" />
/**
* Phaser - Physics - Projection
*/
module Phaser.Physics.Projection {
export class Circle45Deg {
public static Collide(x, y, oH, oV, obj: Phaser.Physics.Circle, t: Phaser.Physics.TileMapCell) {
//if we're colliding diagonally:
// -if obj is in the diagonal pointed to by the slope normal: we can't collide, do nothing
// -else, collide vs. the appropriate vertex
//if obj is in this tile: perform collision as for aabb-ve-45deg
//if obj is horiz OR very neighb in direction of slope: collide only vs. slope
//if obj is horiz or vert neigh against direction of slope: collide vs. face
var signx = t.signx;
var signy = t.signy;
var lenP;
if (oH == 0)
{
if (oV == 0)
{
//colliding with current tile
var sx = t.sx;
var sy = t.sy;
var ox = (obj.pos.x - (sx * obj.radius)) - t.pos.x;//this gives is the coordinates of the innermost
var oy = (obj.pos.y - (sy * obj.radius)) - t.pos.y;//point on the circle, relative to the tile center
//if the dotprod of (ox,oy) and (sx,sy) is negative, the innermost point is in the slope
//and we need toproject it out by the magnitude of the projection of (ox,oy) onto (sx,sy)
var dp = (ox * sx) + (oy * sy);
if (dp < 0)
{
//collision; project delta onto slope and use this as the slope penetration vector
sx *= -dp;//(sx,sy) is now the penetration vector
sy *= -dp;
//find the smallest axial projection vector
if (x < y)
{
//penetration in x is smaller
lenP = x;
y = 0;
//get sign for projection along x-axis
if ((obj.pos.x - t.pos.x) < 0)
{
x *= -1;
}
}
else
{
//penetration in y is smaller
lenP = y;
x = 0;
//get sign for projection along y-axis
if ((obj.pos.y - t.pos.y) < 0)
{
y *= -1;
}
}
var lenN = Math.sqrt(sx * sx + sy * sy);
if (lenP < lenN)
{
obj.ReportCollisionVsWorld(x, y, x / lenP, y / lenP, t);
return Phaser.Physics.Circle.COL_AXIS;
}
else
{
obj.ReportCollisionVsWorld(sx, sy, t.sx, t.sy, t);
return Phaser.Physics.Circle.COL_OTHER;
}
}
}
else
{
//colliding vertically
if ((signy * oV) < 0)
{
//colliding with face/edge
obj.ReportCollisionVsWorld(0, y * oV, 0, oV, t);
return Phaser.Physics.Circle.COL_AXIS;
}
else
{
//we could only be colliding vs the slope OR a vertex
//look at the vector form the closest vert to the circle to decide
var sx = t.sx;
var sy = t.sy;
var ox = obj.pos.x - (t.pos.x - (signx * t.xw));//this gives is the coordinates of the innermost
var oy = obj.pos.y - (t.pos.y + (oV * t.yw));//point on the circle, relative to the closest tile vert
//if the component of (ox,oy) parallel to the normal's righthand normal
//has the same sign as the slope of the slope (the sign of the slope's slope is signx*signy)
//then we project by the vertex, otherwise by the normal.
//note that this is simply a VERY tricky/weird method of determining
//if the circle is in side the slope/face's voronoi region, or that of the vertex.
var perp = (ox * -sy) + (oy * sx);
if (0 < (perp * signx * signy))
{
//collide vs. vertex
var len = Math.sqrt(ox * ox + oy * oy);
var pen = obj.radius - len;
if (0 < pen)
{
//note: if len=0, then perp=0 and we'll never reach here, so don't worry about div-by-0
ox /= len;
oy /= len;
obj.ReportCollisionVsWorld(ox * pen, oy * pen, ox, oy, t);
return Phaser.Physics.Circle.COL_OTHER;
}
}
else
{
//collide vs. slope
//if the component of (ox,oy) parallel to the normal is less than the circle radius, we're
//penetrating the slope. note that this method of penetration calculation doesn't hold
//in general (i.e it won't work if the circle is in the slope), but works in this case
//because we know the circle is in a neighboring cell
var dp = (ox * sx) + (oy * sy);
var pen = obj.radius - Math.abs(dp);//note: we don't need the abs because we know the dp will be positive, but just in case..
if (0 < pen)
{
//collision; circle out along normal by penetration amount
obj.ReportCollisionVsWorld(sx * pen, sy * pen, sx, sy, t);
return Phaser.Physics.Circle.COL_OTHER;
}
}
}
}
}
else if (oV == 0)
{
//colliding horizontally
if ((signx * oH) < 0)
{
//colliding with face/edge
obj.ReportCollisionVsWorld(x * oH, 0, oH, 0, t);
return Phaser.Physics.Circle.COL_AXIS;
}
else
{
//we could only be colliding vs the slope OR a vertex
//look at the vector form the closest vert to the circle to decide
var sx = t.sx;
var sy = t.sy;
var ox = obj.pos.x - (t.pos.x + (oH * t.xw));//this gives is the coordinates of the innermost
var oy = obj.pos.y - (t.pos.y - (signy * t.yw));//point on the circle, relative to the closest tile vert
//if the component of (ox,oy) parallel to the normal's righthand normal
//has the same sign as the slope of the slope (the sign of the slope's slope is signx*signy)
//then we project by the normal, otherwise by the vertex.
//(NOTE: this is the opposite logic of the vertical case;
// for vertical, if the perp prod and the slope's slope agree, it's outside.
// for horizontal, if the perp prod and the slope's slope agree, circle is inside.
// ..but this is only a property of flahs' coord system (i.e the rules might swap
// in righthanded systems))
//note that this is simply a VERY tricky/weird method of determining
//if the circle is in side the slope/face's voronio region, or that of the vertex.
var perp = (ox * -sy) + (oy * sx);
if ((perp * signx * signy) < 0)
{
//collide vs. vertex
var len = Math.sqrt(ox * ox + oy * oy);
var pen = obj.radius - len;
if (0 < pen)
{
//note: if len=0, then perp=0 and we'll never reach here, so don't worry about div-by-0
ox /= len;
oy /= len;
obj.ReportCollisionVsWorld(ox * pen, oy * pen, ox, oy, t);
return Phaser.Physics.Circle.COL_OTHER;
}
}
else
{
//collide vs. slope
//if the component of (ox,oy) parallel to the normal is less than the circle radius, we're
//penetrating the slope. note that this method of penetration calculation doesn't hold
//in general (i.e it won't work if the circle is in the slope), but works in this case
//because we know the circle is in a neighboring cell
var dp = (ox * sx) + (oy * sy);
var pen = obj.radius - Math.abs(dp);//note: we don't need the abs because we know the dp will be positive, but just in case..
if (0 < pen)
{
//collision; circle out along normal by penetration amount
obj.ReportCollisionVsWorld(sx * pen, sy * pen, sx, sy, t);
return Phaser.Physics.Circle.COL_OTHER;
}
}
}
}
else
{
//colliding diagonally
if (0 < ((signx * oH) + (signy * oV)))
{
//the dotprod of slope normal and cell offset is strictly positive,
//therefore obj is in the diagonal neighb pointed at by the normal, and
//it cannot possibly reach/touch/penetrate the slope
return Phaser.Physics.Circle.COL_NONE;
}
else
{
//collide vs. vertex
//get diag vertex position
var vx = t.pos.x + (oH * t.xw);
var vy = t.pos.y + (oV * t.yw);
var dx = obj.pos.x - vx;//calc vert->circle vector
var dy = obj.pos.y - vy;
var len = Math.sqrt(dx * dx + dy * dy);
var pen = obj.radius - len;
if (0 < pen)
{
//vertex is in the circle; project outward
if (len == 0)
{
//project out by 45deg
dx = oH / Math.SQRT2;
dy = oV / Math.SQRT2;
}
else
{
dx /= len;
dy /= len;
}
obj.ReportCollisionVsWorld(dx * pen, dy * pen, dx, dy, t);
return Phaser.Physics.Circle.COL_OTHER;
}
}
}
return Phaser.Physics.Circle.COL_NONE;
}
}
}

View file

@ -0,0 +1,181 @@
var Phaser;
(function (Phaser) {
(function (Physics) {
/// <reference path="../../_definitions.ts" />
/**
* Phaser - Physics - Projection
*/
(function (Projection) {
var CircleConcave = (function () {
function CircleConcave() {
}
CircleConcave.Collide = function (x, y, oH, oV, obj, t) {
//if we're colliding diagonally:
// -if obj is in the diagonal pointed to by the slope normal: we can't collide, do nothing
// -else, collide vs. the appropriate vertex
//if obj is in this tile: perform collision as for aabb
//if obj is horiz OR very neighb in direction of slope: collide vs vert
//if obj is horiz or vert neigh against direction of slope: collide vs. face
var signx = t.signx;
var signy = t.signy;
var lenP;
if (oH == 0) {
if (oV == 0) {
//colliding with current tile
var ox = (t.pos.x + (signx * t.xw)) - obj.pos.x;
var oy = (t.pos.y + (signy * t.yw)) - obj.pos.y;
var twid = t.xw * 2;
var trad = Math.sqrt(twid * twid + 0);
//note that this should be precomputed at compile-time since it's constant
var len = Math.sqrt(ox * ox + oy * oy);
var pen = (len + obj.radius) - trad;
if (0 < pen) {
if (x < y) {
//penetration in x is smaller
lenP = x;
y = 0;
if ((obj.pos.x - t.pos.x) < 0) {
x *= -1;
}
} else {
//penetration in y is smaller
lenP = y;
x = 0;
if ((obj.pos.y - t.pos.y) < 0) {
y *= -1;
}
}
if (lenP < pen) {
obj.ReportCollisionVsWorld(x, y, x / lenP, y / lenP, t);
return Phaser.Physics.Circle.COL_AXIS;
} else {
//we can assume that len >0, because if we're here then
//(len + obj.radius) > trad, and since obj.radius <= trad
//len MUST be > 0
ox /= len;
oy /= len;
obj.ReportCollisionVsWorld(ox * pen, oy * pen, ox, oy, t);
return Phaser.Physics.Circle.COL_OTHER;
}
} else {
return Phaser.Physics.Circle.COL_NONE;
}
} else {
if ((signy * oV) < 0) {
//colliding with face/edge
obj.ReportCollisionVsWorld(0, y * oV, 0, oV, t);
return Phaser.Physics.Circle.COL_AXIS;
} else {
//we could only be colliding vs the vertical tip
//get diag vertex position
var vx = t.pos.x - (signx * t.xw);
var vy = t.pos.y + (oV * t.yw);
var dx = obj.pos.x - vx;
var dy = obj.pos.y - vy;
var len = Math.sqrt(dx * dx + dy * dy);
var pen = obj.radius - len;
if (0 < pen) {
if (len == 0) {
//project out vertically
dx = 0;
dy = oV;
} else {
dx /= len;
dy /= len;
}
obj.ReportCollisionVsWorld(dx * pen, dy * pen, dx, dy, t);
return Phaser.Physics.Circle.COL_OTHER;
}
}
}
} else if (oV == 0) {
if ((signx * oH) < 0) {
//colliding with face/edge
obj.ReportCollisionVsWorld(x * oH, 0, oH, 0, t);
return Phaser.Physics.Circle.COL_AXIS;
} else {
//we could only be colliding vs the horizontal tip
//get diag vertex position
var vx = t.pos.x + (oH * t.xw);
var vy = t.pos.y - (signy * t.yw);
var dx = obj.pos.x - vx;
var dy = obj.pos.y - vy;
var len = Math.sqrt(dx * dx + dy * dy);
var pen = obj.radius - len;
if (0 < pen) {
if (len == 0) {
//project out horizontally
dx = oH;
dy = 0;
} else {
dx /= len;
dy /= len;
}
obj.ReportCollisionVsWorld(dx * pen, dy * pen, dx, dy, t);
return Phaser.Physics.Circle.COL_OTHER;
}
}
} else {
if (0 < ((signx * oH) + (signy * oV))) {
//the dotprod of slope normal and cell offset is strictly positive,
//therefore obj is in the diagonal neighb pointed at by the normal, and
//it cannot possibly reach/touch/penetrate the slope
return Phaser.Physics.Circle.COL_NONE;
} else {
//collide vs. vertex
//get diag vertex position
var vx = t.pos.x + (oH * t.xw);
var vy = t.pos.y + (oV * t.yw);
var dx = obj.pos.x - vx;
var dy = obj.pos.y - vy;
var len = Math.sqrt(dx * dx + dy * dy);
var pen = obj.radius - len;
if (0 < pen) {
if (len == 0) {
//project out by 45deg
dx = oH / Math.SQRT2;
dy = oV / Math.SQRT2;
} else {
dx /= len;
dy /= len;
}
obj.ReportCollisionVsWorld(dx * pen, dy * pen, dx, dy, t);
return Phaser.Physics.Circle.COL_OTHER;
}
}
}
return Phaser.Physics.Circle.COL_NONE;
};
return CircleConcave;
})();
Projection.CircleConcave = CircleConcave;
})(Physics.Projection || (Physics.Projection = {}));
var Projection = Physics.Projection;
})(Phaser.Physics || (Phaser.Physics = {}));
var Physics = Phaser.Physics;
})(Phaser || (Phaser = {}));

View file

@ -0,0 +1,235 @@
/// <reference path="../../_definitions.ts" />
/**
* Phaser - Physics - Projection
*/
module Phaser.Physics.Projection {
export class CircleConcave {
public static Collide(x, y, oH, oV, obj: Phaser.Physics.Circle, t: Phaser.Physics.TileMapCell) {
//if we're colliding diagonally:
// -if obj is in the diagonal pointed to by the slope normal: we can't collide, do nothing
// -else, collide vs. the appropriate vertex
//if obj is in this tile: perform collision as for aabb
//if obj is horiz OR very neighb in direction of slope: collide vs vert
//if obj is horiz or vert neigh against direction of slope: collide vs. face
var signx = t.signx;
var signy = t.signy;
var lenP;
if (oH == 0)
{
if (oV == 0)
{
//colliding with current tile
var ox = (t.pos.x + (signx * t.xw)) - obj.pos.x;//(ox,oy) is the vector from the circle to
var oy = (t.pos.y + (signy * t.yw)) - obj.pos.y;//tile-circle's center
var twid = t.xw * 2;
var trad = Math.sqrt(twid * twid + 0);//this gives us the radius of a circle centered on the tile's corner and extending to the opposite edge of the tile;
//note that this should be precomputed at compile-time since it's constant
var len = Math.sqrt(ox * ox + oy * oy);
var pen = (len + obj.radius) - trad;
if (0 < pen)
{
//find the smallest axial projection vector
if (x < y)
{
//penetration in x is smaller
lenP = x;
y = 0;
//get sign for projection along x-axis
if ((obj.pos.x - t.pos.x) < 0)
{
x *= -1;
}
}
else
{
//penetration in y is smaller
lenP = y;
x = 0;
//get sign for projection along y-axis
if ((obj.pos.y - t.pos.y) < 0)
{
y *= -1;
}
}
if (lenP < pen)
{
obj.ReportCollisionVsWorld(x, y, x / lenP, y / lenP, t);
return Phaser.Physics.Circle.COL_AXIS;
}
else
{
//we can assume that len >0, because if we're here then
//(len + obj.radius) > trad, and since obj.radius <= trad
//len MUST be > 0
ox /= len;
oy /= len;
obj.ReportCollisionVsWorld(ox * pen, oy * pen, ox, oy, t);
return Phaser.Physics.Circle.COL_OTHER;
}
}
else
{
return Phaser.Physics.Circle.COL_NONE;
}
}
else
{
//colliding vertically
if ((signy * oV) < 0)
{
//colliding with face/edge
obj.ReportCollisionVsWorld(0, y * oV, 0, oV, t);
return Phaser.Physics.Circle.COL_AXIS;
}
else
{
//we could only be colliding vs the vertical tip
//get diag vertex position
var vx = t.pos.x - (signx * t.xw);
var vy = t.pos.y + (oV * t.yw);
var dx = obj.pos.x - vx;//calc vert->circle vector
var dy = obj.pos.y - vy;
var len = Math.sqrt(dx * dx + dy * dy);
var pen = obj.radius - len;
if (0 < pen)
{
//vertex is in the circle; project outward
if (len == 0)
{
//project out vertically
dx = 0;
dy = oV;
}
else
{
dx /= len;
dy /= len;
}
obj.ReportCollisionVsWorld(dx * pen, dy * pen, dx, dy, t);
return Phaser.Physics.Circle.COL_OTHER;
}
}
}
}
else if (oV == 0)
{
//colliding horizontally
if ((signx * oH) < 0)
{
//colliding with face/edge
obj.ReportCollisionVsWorld(x * oH, 0, oH, 0, t);
return Phaser.Physics.Circle.COL_AXIS;
}
else
{
//we could only be colliding vs the horizontal tip
//get diag vertex position
var vx = t.pos.x + (oH * t.xw);
var vy = t.pos.y - (signy * t.yw);
var dx = obj.pos.x - vx;//calc vert->circle vector
var dy = obj.pos.y - vy;
var len = Math.sqrt(dx * dx + dy * dy);
var pen = obj.radius - len;
if (0 < pen)
{
//vertex is in the circle; project outward
if (len == 0)
{
//project out horizontally
dx = oH;
dy = 0;
}
else
{
dx /= len;
dy /= len;
}
obj.ReportCollisionVsWorld(dx * pen, dy * pen, dx, dy, t);
return Phaser.Physics.Circle.COL_OTHER;
}
}
}
else
{
//colliding diagonally
if (0 < ((signx * oH) + (signy * oV)))
{
//the dotprod of slope normal and cell offset is strictly positive,
//therefore obj is in the diagonal neighb pointed at by the normal, and
//it cannot possibly reach/touch/penetrate the slope
return Phaser.Physics.Circle.COL_NONE;
}
else
{
//collide vs. vertex
//get diag vertex position
var vx = t.pos.x + (oH * t.xw);
var vy = t.pos.y + (oV * t.yw);
var dx = obj.pos.x - vx;//calc vert->circle vector
var dy = obj.pos.y - vy;
var len = Math.sqrt(dx * dx + dy * dy);
var pen = obj.radius - len;
if (0 < pen)
{
//vertex is in the circle; project outward
if (len == 0)
{
//project out by 45deg
dx = oH / Math.SQRT2;
dy = oV / Math.SQRT2;
}
else
{
dx /= len;
dy /= len;
}
obj.ReportCollisionVsWorld(dx * pen, dy * pen, dx, dy, t);
return Phaser.Physics.Circle.COL_OTHER;
}
}
}
return Phaser.Physics.Circle.COL_NONE;
}
}
}

View file

@ -0,0 +1,193 @@
var Phaser;
(function (Phaser) {
(function (Physics) {
/// <reference path="../../_definitions.ts" />
/**
* Phaser - Physics - Projection
*/
(function (Projection) {
var CircleConvex = (function () {
function CircleConvex() {
}
CircleConvex.Collide = function (x, y, oH, oV, obj, t) {
//if the object is horiz AND/OR vertical neighbor in the normal (signx,signy)
//direction, collide vs. tile-circle only.
//if we're colliding diagonally:
// -else, collide vs. the appropriate vertex
//if obj is in this tile: perform collision as for aabb
//if obj is horiz or vert neigh against direction of slope: collide vs. face
var signx = t.signx;
var signy = t.signy;
var lenP;
if (oH == 0) {
if (oV == 0) {
//colliding with current tile
var ox = obj.pos.x - (t.pos.x - (signx * t.xw));
var oy = obj.pos.y - (t.pos.y - (signy * t.yw));
var twid = t.xw * 2;
var trad = Math.sqrt(twid * twid + 0);
//note that this should be precomputed at compile-time since it's constant
var len = Math.sqrt(ox * ox + oy * oy);
var pen = (trad + obj.radius) - len;
if (0 < pen) {
if (x < y) {
//penetration in x is smaller
lenP = x;
y = 0;
if ((obj.pos.x - t.pos.x) < 0) {
x *= -1;
}
} else {
//penetration in y is smaller
lenP = y;
x = 0;
if ((obj.pos.y - t.pos.y) < 0) {
y *= -1;
}
}
if (lenP < pen) {
obj.ReportCollisionVsWorld(x, y, x / lenP, y / lenP, t);
return Phaser.Physics.Circle.COL_AXIS;
} else {
//note: len should NEVER be == 0, because if it is,
//projeciton by an axis shoudl always be shorter, and we should
//never arrive here
ox /= len;
oy /= len;
obj.ReportCollisionVsWorld(ox * pen, oy * pen, ox, oy, t);
return Phaser.Physics.Circle.COL_OTHER;
}
}
} else {
if ((signy * oV) < 0) {
//colliding with face/edge
obj.ReportCollisionVsWorld(0, y * oV, 0, oV, t);
return Phaser.Physics.Circle.COL_AXIS;
} else {
//obj in neighboring cell pointed at by tile normal;
//we could only be colliding vs the tile-circle surface
var ox = obj.pos.x - (t.pos.x - (signx * t.xw));
var oy = obj.pos.y - (t.pos.y - (signy * t.yw));
var twid = t.xw * 2;
var trad = Math.sqrt(twid * twid + 0);
//note that this should be precomputed at compile-time since it's constant
var len = Math.sqrt(ox * ox + oy * oy);
var pen = (trad + obj.radius) - len;
if (0 < pen) {
//note: len should NEVER be == 0, because if it is,
//obj is not in a neighboring cell!
ox /= len;
oy /= len;
obj.ReportCollisionVsWorld(ox * pen, oy * pen, ox, oy, t);
return Phaser.Physics.Circle.COL_OTHER;
}
}
}
} else if (oV == 0) {
if ((signx * oH) < 0) {
//colliding with face/edge
obj.ReportCollisionVsWorld(x * oH, 0, oH, 0, t);
return Phaser.Physics.Circle.COL_AXIS;
} else {
//obj in neighboring cell pointed at by tile normal;
//we could only be colliding vs the tile-circle surface
var ox = obj.pos.x - (t.pos.x - (signx * t.xw));
var oy = obj.pos.y - (t.pos.y - (signy * t.yw));
var twid = t.xw * 2;
var trad = Math.sqrt(twid * twid + 0);
//note that this should be precomputed at compile-time since it's constant
var len = Math.sqrt(ox * ox + oy * oy);
var pen = (trad + obj.radius) - len;
if (0 < pen) {
//note: len should NEVER be == 0, because if it is,
//obj is not in a neighboring cell!
ox /= len;
oy /= len;
obj.ReportCollisionVsWorld(ox * pen, oy * pen, ox, oy, t);
return Phaser.Physics.Circle.COL_OTHER;
}
}
} else {
if (0 < ((signx * oH) + (signy * oV))) {
//obj in diag neighb cell pointed at by tile normal;
//we could only be colliding vs the tile-circle surface
var ox = obj.pos.x - (t.pos.x - (signx * t.xw));
var oy = obj.pos.y - (t.pos.y - (signy * t.yw));
var twid = t.xw * 2;
var trad = Math.sqrt(twid * twid + 0);
//note that this should be precomputed at compile-time since it's constant
var len = Math.sqrt(ox * ox + oy * oy);
var pen = (trad + obj.radius) - len;
if (0 < pen) {
//note: len should NEVER be == 0, because if it is,
//obj is not in a neighboring cell!
ox /= len;
oy /= len;
obj.ReportCollisionVsWorld(ox * pen, oy * pen, ox, oy, t);
return Phaser.Physics.Circle.COL_OTHER;
}
} else {
//collide vs. vertex
//get diag vertex position
var vx = t.pos.x + (oH * t.xw);
var vy = t.pos.y + (oV * t.yw);
var dx = obj.pos.x - vx;
var dy = obj.pos.y - vy;
var len = Math.sqrt(dx * dx + dy * dy);
var pen = obj.radius - len;
if (0 < pen) {
if (len == 0) {
//project out by 45deg
dx = oH / Math.SQRT2;
dy = oV / Math.SQRT2;
} else {
dx /= len;
dy /= len;
}
obj.ReportCollisionVsWorld(dx * pen, dy * pen, dx, dy, t);
return Phaser.Physics.Circle.COL_OTHER;
}
}
}
return Phaser.Physics.Circle.COL_NONE;
};
return CircleConvex;
})();
Projection.CircleConvex = CircleConvex;
})(Physics.Projection || (Physics.Projection = {}));
var Projection = Physics.Projection;
})(Phaser.Physics || (Phaser.Physics = {}));
var Physics = Phaser.Physics;
})(Phaser || (Phaser = {}));

View file

@ -0,0 +1,242 @@
/// <reference path="../../_definitions.ts" />
/**
* Phaser - Physics - Projection
*/
module Phaser.Physics.Projection {
export class CircleConvex {
public static Collide(x, y, oH, oV, obj: Phaser.Physics.Circle, t: Phaser.Physics.TileMapCell) {
//if the object is horiz AND/OR vertical neighbor in the normal (signx,signy)
//direction, collide vs. tile-circle only.
//if we're colliding diagonally:
// -else, collide vs. the appropriate vertex
//if obj is in this tile: perform collision as for aabb
//if obj is horiz or vert neigh against direction of slope: collide vs. face
var signx = t.signx;
var signy = t.signy;
var lenP;
if (oH == 0)
{
if (oV == 0)
{
//colliding with current tile
var ox = obj.pos.x - (t.pos.x - (signx * t.xw));//(ox,oy) is the vector from the tile-circle to
var oy = obj.pos.y - (t.pos.y - (signy * t.yw));//the circle's center
var twid = t.xw * 2;
var trad = Math.sqrt(twid * twid + 0);//this gives us the radius of a circle centered on the tile's corner and extending to the opposite edge of the tile;
//note that this should be precomputed at compile-time since it's constant
var len = Math.sqrt(ox * ox + oy * oy);
var pen = (trad + obj.radius) - len;
if (0 < pen)
{
//find the smallest axial projection vector
if (x < y)
{
//penetration in x is smaller
lenP = x;
y = 0;
//get sign for projection along x-axis
if ((obj.pos.x - t.pos.x) < 0)
{
x *= -1;
}
}
else
{
//penetration in y is smaller
lenP = y;
x = 0;
//get sign for projection along y-axis
if ((obj.pos.y - t.pos.y) < 0)
{
y *= -1;
}
}
if (lenP < pen)
{
obj.ReportCollisionVsWorld(x, y, x / lenP, y / lenP, t);
return Phaser.Physics.Circle.COL_AXIS;
}
else
{
//note: len should NEVER be == 0, because if it is,
//projeciton by an axis shoudl always be shorter, and we should
//never arrive here
ox /= len;
oy /= len;
obj.ReportCollisionVsWorld(ox * pen, oy * pen, ox, oy, t);
return Phaser.Physics.Circle.COL_OTHER;
}
}
}
else
{
//colliding vertically
if ((signy * oV) < 0)
{
//colliding with face/edge
obj.ReportCollisionVsWorld(0, y * oV, 0, oV, t);
return Phaser.Physics.Circle.COL_AXIS;
}
else
{
//obj in neighboring cell pointed at by tile normal;
//we could only be colliding vs the tile-circle surface
var ox = obj.pos.x - (t.pos.x - (signx * t.xw));//(ox,oy) is the vector from the tile-circle to
var oy = obj.pos.y - (t.pos.y - (signy * t.yw));//the circle's center
var twid = t.xw * 2;
var trad = Math.sqrt(twid * twid + 0);//this gives us the radius of a circle centered on the tile's corner and extending to the opposite edge of the tile;
//note that this should be precomputed at compile-time since it's constant
var len = Math.sqrt(ox * ox + oy * oy);
var pen = (trad + obj.radius) - len;
if (0 < pen)
{
//note: len should NEVER be == 0, because if it is,
//obj is not in a neighboring cell!
ox /= len;
oy /= len;
obj.ReportCollisionVsWorld(ox * pen, oy * pen, ox, oy, t);
return Phaser.Physics.Circle.COL_OTHER;
}
}
}
}
else if (oV == 0)
{
//colliding horizontally
if ((signx * oH) < 0)
{
//colliding with face/edge
obj.ReportCollisionVsWorld(x * oH, 0, oH, 0, t);
return Phaser.Physics.Circle.COL_AXIS;
}
else
{
//obj in neighboring cell pointed at by tile normal;
//we could only be colliding vs the tile-circle surface
var ox = obj.pos.x - (t.pos.x - (signx * t.xw));//(ox,oy) is the vector from the tile-circle to
var oy = obj.pos.y - (t.pos.y - (signy * t.yw));//the circle's center
var twid = t.xw * 2;
var trad = Math.sqrt(twid * twid + 0);//this gives us the radius of a circle centered on the tile's corner and extending to the opposite edge of the tile;
//note that this should be precomputed at compile-time since it's constant
var len = Math.sqrt(ox * ox + oy * oy);
var pen = (trad + obj.radius) - len;
if (0 < pen)
{
//note: len should NEVER be == 0, because if it is,
//obj is not in a neighboring cell!
ox /= len;
oy /= len;
obj.ReportCollisionVsWorld(ox * pen, oy * pen, ox, oy, t);
return Phaser.Physics.Circle.COL_OTHER;
}
}
}
else
{
//colliding diagonally
if (0 < ((signx * oH) + (signy * oV)))
{
//obj in diag neighb cell pointed at by tile normal;
//we could only be colliding vs the tile-circle surface
var ox = obj.pos.x - (t.pos.x - (signx * t.xw));//(ox,oy) is the vector from the tile-circle to
var oy = obj.pos.y - (t.pos.y - (signy * t.yw));//the circle's center
var twid = t.xw * 2;
var trad = Math.sqrt(twid * twid + 0);//this gives us the radius of a circle centered on the tile's corner and extending to the opposite edge of the tile;
//note that this should be precomputed at compile-time since it's constant
var len = Math.sqrt(ox * ox + oy * oy);
var pen = (trad + obj.radius) - len;
if (0 < pen)
{
//note: len should NEVER be == 0, because if it is,
//obj is not in a neighboring cell!
ox /= len;
oy /= len;
obj.ReportCollisionVsWorld(ox * pen, oy * pen, ox, oy, t);
return Phaser.Physics.Circle.COL_OTHER;
}
}
else
{
//collide vs. vertex
//get diag vertex position
var vx = t.pos.x + (oH * t.xw);
var vy = t.pos.y + (oV * t.yw);
var dx = obj.pos.x - vx;//calc vert->circle vector
var dy = obj.pos.y - vy;
var len = Math.sqrt(dx * dx + dy * dy);
var pen = obj.radius - len;
if (0 < pen)
{
//vertex is in the circle; project outward
if (len == 0)
{
//project out by 45deg
dx = oH / Math.SQRT2;
dy = oV / Math.SQRT2;
}
else
{
dx /= len;
dy /= len;
}
obj.ReportCollisionVsWorld(dx * pen, dy * pen, dx, dy, t);
return Phaser.Physics.Circle.COL_OTHER;
}
}
}
return Phaser.Physics.Circle.COL_NONE;
}
}
}

View file

@ -0,0 +1,84 @@
var Phaser;
(function (Phaser) {
(function (Physics) {
/// <reference path="../../_definitions.ts" />
/**
* Phaser - Physics - Projection
*/
(function (Projection) {
var CircleFull = (function () {
function CircleFull() {
}
CircleFull.Collide = function (x, y, oH, oV, obj, t) {
if (oH == 0) {
if (oV == 0) {
if (x < y) {
//penetration in x is smaller; project in x
var dx = obj.pos.x - t.pos.x;
if (dx < 0) {
obj.ReportCollisionVsWorld(-x, 0, -1, 0, t);
return Phaser.Physics.Circle.COL_AXIS;
} else {
obj.ReportCollisionVsWorld(x, 0, 1, 0, t);
return Phaser.Physics.Circle.COL_AXIS;
}
} else {
//penetration in y is smaller; project in y
var dy = obj.pos.y - t.pos.y;
if (dy < 0) {
obj.ReportCollisionVsWorld(0, -y, 0, -1, t);
return Phaser.Physics.Circle.COL_AXIS;
} else {
obj.ReportCollisionVsWorld(0, y, 0, 1, t);
return Phaser.Physics.Circle.COL_AXIS;
}
}
} else {
//collision with vertical neighbor
obj.ReportCollisionVsWorld(0, y * oV, 0, oV, t);
return Phaser.Physics.Circle.COL_AXIS;
}
} else if (oV == 0) {
//collision with horizontal neighbor
obj.ReportCollisionVsWorld(x * oH, 0, oH, 0, t);
return Phaser.Physics.Circle.COL_AXIS;
} else {
//diagonal collision
//get diag vertex position
var vx = t.pos.x + (oH * t.xw);
var vy = t.pos.y + (oV * t.yw);
var dx = obj.pos.x - vx;
var dy = obj.pos.y - vy;
var len = Math.sqrt(dx * dx + dy * dy);
var pen = obj.radius - len;
if (0 < pen) {
if (len == 0) {
//project out by 45deg
dx = oH / Math.SQRT2;
dy = oV / Math.SQRT2;
} else {
dx /= len;
dy /= len;
}
obj.ReportCollisionVsWorld(dx * pen, dy * pen, dx, dy, t);
return Phaser.Physics.Circle.COL_OTHER;
}
}
return Phaser.Physics.Circle.COL_NONE;
};
return CircleFull;
})();
Projection.CircleFull = CircleFull;
})(Physics.Projection || (Physics.Projection = {}));
var Projection = Physics.Projection;
})(Phaser.Physics || (Phaser.Physics = {}));
var Physics = Phaser.Physics;
})(Phaser || (Phaser = {}));

View file

@ -0,0 +1,112 @@
/// <reference path="../../_definitions.ts" />
/**
* Phaser - Physics - Projection
*/
module Phaser.Physics.Projection {
export class CircleFull {
public static Collide(x, y, oH, oV, obj: Phaser.Physics.Circle, t: Phaser.Physics.TileMapCell) {
//if we're colliding vs. the current cell, we need to project along the
//smallest penetration vector.
//if we're colliding vs. horiz. or vert. neighb, we simply project horiz/vert
//if we're colliding diagonally, we need to collide vs. tile corner
if (oH == 0)
{
if (oV == 0)
{
//collision with current cell
if (x < y)
{
//penetration in x is smaller; project in x
var dx = obj.pos.x - t.pos.x;//get sign for projection along x-axis
//NOTE: should we handle the delta == 0 case?! and how? (project towards oldpos?)
if (dx < 0)
{
obj.ReportCollisionVsWorld(-x, 0, -1, 0, t);
return Phaser.Physics.Circle.COL_AXIS;
}
else
{
obj.ReportCollisionVsWorld(x, 0, 1, 0, t);
return Phaser.Physics.Circle.COL_AXIS;
}
}
else
{
//penetration in y is smaller; project in y
var dy = obj.pos.y - t.pos.y;//get sign for projection along y-axis
//NOTE: should we handle the delta == 0 case?! and how? (project towards oldpos?)
if (dy < 0)
{
obj.ReportCollisionVsWorld(0, -y, 0, -1, t);
return Phaser.Physics.Circle.COL_AXIS;
}
else
{
obj.ReportCollisionVsWorld(0, y, 0, 1, t);
return Phaser.Physics.Circle.COL_AXIS;
}
}
}
else
{
//collision with vertical neighbor
obj.ReportCollisionVsWorld(0, y * oV, 0, oV, t);
return Phaser.Physics.Circle.COL_AXIS;
}
}
else if (oV == 0)
{
//collision with horizontal neighbor
obj.ReportCollisionVsWorld(x * oH, 0, oH, 0, t);
return Phaser.Physics.Circle.COL_AXIS;
}
else
{
//diagonal collision
//get diag vertex position
var vx = t.pos.x + (oH * t.xw);
var vy = t.pos.y + (oV * t.yw);
var dx = obj.pos.x - vx;//calc vert->circle vector
var dy = obj.pos.y - vy;
var len = Math.sqrt(dx * dx + dy * dy);
var pen = obj.radius - len;
if (0 < pen)
{
//vertex is in the circle; project outward
if (len == 0)
{
//project out by 45deg
dx = oH / Math.SQRT2;
dy = oV / Math.SQRT2;
}
else
{
dx /= len;
dy /= len;
}
obj.ReportCollisionVsWorld(dx * pen, dy * pen, dx, dy, t);
return Phaser.Physics.Circle.COL_OTHER;
}
}
return Phaser.Physics.Circle.COL_NONE;
}
}
}

View file

@ -54,6 +54,19 @@ var Phaser;
return colors;
};
ColorUtils.hexToRGB = function (h) {
var hex16 = (h.charAt(0) == "#") ? h.substring(1, 7) : h;
var r = parseInt(hex16.substring(0, 2), 16);
var g = parseInt(hex16.substring(2, 4), 16);
var b = parseInt(hex16.substring(4, 6), 16);
return {
r: r,
g: g,
b: b
};
};
ColorUtils.getComplementHarmony = /**
* Returns a Complementary Color Harmony for the given color.
* <p>A complementary hue is one directly opposite the color given on the color wheel</p>

View file

@ -59,6 +59,21 @@ module Phaser {
}
public static hexToRGB(h: string) {
var hex16 = (h.charAt(0) == "#") ? h.substring(1, 7) : h;
var r = parseInt(hex16.substring(0, 2), 16);
var g = parseInt(hex16.substring(2, 4), 16);
var b = parseInt(hex16.substring(4, 6), 16);
return {
r: r,
g: g,
b: b
}
}
/**
* Returns a Complementary Color Harmony for the given color.
* <p>A complementary hue is one directly opposite the color given on the color wheel</p>

View file

@ -183,6 +183,11 @@ var Phaser;
Phaser.DebugUtils.line('bottom: ' + sprite.worldView.bottom + ' right: ' + sprite.worldView.right.toFixed(1));
};
DebugUtils.renderSpriteWorldViewBounds = function (sprite, color) {
if (typeof color === "undefined") { color = 'rgba(0,255,0,0.3)'; }
Phaser.DebugUtils.renderRectangle(sprite.worldView, color);
};
DebugUtils.renderSpriteInfo = /**
* Render debug infos. (including name, bounds info, position and some other properties)
* @param x {number} X position of the debug info to be rendered.

View file

@ -231,7 +231,6 @@
<Content Include="input\world drag.js">
<DependentUpon>world drag.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="mobile\sprite test 1.ts" />
<TypeScriptCompile Include="misc\point1.ts" />
<Content Include="misc\color utils 1.ts" />
<Content Include="misc\color utils 2.ts" />
@ -252,21 +251,23 @@
</Content>
<Content Include="misc\rectangle utils 1.ts" />
<Content Include="misc\rectangle utils 2.ts" />
<Content Include="mobile\sprite test 1.js">
<DependentUpon>sprite test 1.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="scrollzones\simple scrollzone.ts" />
<TypeScriptCompile Include="scrollzones\scroll window.ts" />
<TypeScriptCompile Include="scrollzones\region demo.ts" />
<TypeScriptCompile Include="scrollzones\parallax.ts" />
<TypeScriptCompile Include="scrollzones\ballscroller.ts" />
<TypeScriptCompile Include="physics\sprite bounds.ts" />
<TypeScriptCompile Include="physics\circle 1.ts" />
<Content Include="physics\circle 1.js">
<DependentUpon>circle 1.ts</DependentUpon>
</Content>
<Content Include="physics\sprite bounds.js">
<DependentUpon>sprite bounds.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="physics\temp2.ts" />
<Content Include="scrollzones\ballscroller.js">
<DependentUpon>ballscroller.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="scrollzones\blasteroids.ts" />
<Content Include="scrollzones\blasteroids.js">
<DependentUpon>blasteroids.ts</DependentUpon>
</Content>
<Content Include="scrollzones\parallax.js">
<DependentUpon>parallax.ts</DependentUpon>
</Content>
@ -359,10 +360,6 @@
</Content>
<TypeScriptCompile Include="tilemaps\tiled tilemap.ts" />
<TypeScriptCompile Include="tilemaps\tiled layers.ts" />
<TypeScriptCompile Include="tilemaps\map draw.ts" />
<Content Include="tilemaps\map draw.js">
<DependentUpon>map draw.ts</DependentUpon>
</Content>
<Content Include="tilemaps\tiled layers.js">
<DependentUpon>tiled layers.ts</DependentUpon>
</Content>
@ -446,8 +443,8 @@
</ItemGroup>
<ItemGroup>
<Folder Include="animation\" />
<Folder Include="mobile\" />
<Folder Include="particles\" />
<Folder Include="physics\" />
</ItemGroup>
<Import Project="$(VSToolsPath)\TypeScript\Microsoft.TypeScript.targets" />
</Project>

View file

@ -31,10 +31,8 @@
function clickedIt() {
if (this.image.visible == true) {
game.stage.backgroundColor = '';
this.image.visible = false;
} else {
game.stage.backgroundColor = 'rgb(0,0,0)';
this.image.visible = true;
}
}

File diff suppressed because it is too large Load diff

90
Tests/physics/circle 1.js Normal file
View file

@ -0,0 +1,90 @@
/// <reference path="../../Phaser/_definitions.ts" />
(function () {
var game = new Phaser.Game(this, 'game', 800, 600, preload, create, update, render);
function preload() {
game.load.image('ball', 'assets/sprites/shinyball.png');
game.load.image('card', 'assets/sprites/mana_card.png');
}
var cells;
var b;
var c;
var t;
var ball;
var card;
function create() {
this.ball = game.add.sprite(0, 0, 'ball');
this.card = game.add.sprite(0, 0, 'card');
this.card.rotation = 30;
this.c = game.add.circle(200, 200, 16);
this.b = game.add.aabb(400, 200, 74, 128);
// pos is center, not upper-left
this.cells = [];
var tid;
for (var i = 0; i < 10; i++) {
if (i % 2 == 0) {
tid = Phaser.Physics.TileMapCell.TID_CONCAVEpn;
} else {
tid = Phaser.Physics.TileMapCell.TID_CONCAVEnn;
}
this.cells.push(game.add.cell(100 + (i * 100), 400, 50, 50, tid));
//this.cells.push(new TileMapCell(100 + (i * 100), 500, 50, 50).SetState(TileMapCell.TID_FULL));
//this.cells.push(new TileMapCell(100 + (i * 100), 500, 50, 50).SetState(TileMapCell.TID_CONCAVEpn));
}
}
function update() {
var fx = 0;
var fy = 0;
if (game.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
fx -= 0.2;
} else if (game.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
fx += 0.2;
}
if (game.input.keyboard.isDown(Phaser.Keyboard.UP)) {
fy -= 0.2 + 0.2;
} else if (game.input.keyboard.isDown(Phaser.Keyboard.DOWN)) {
fy += 0.2;
}
// update circle
this.c.pos.x = this.c.oldpos.x + Math.min(20, Math.max(-20, this.c.pos.x - this.c.oldpos.x + fx));
this.c.pos.y = this.c.oldpos.y + Math.min(20, Math.max(-20, this.c.pos.y - this.c.oldpos.y + fy));
this.c.IntegrateVerlet();
// update box
this.b.pos.x = this.b.oldpos.x + Math.min(40, Math.max(-40, this.b.pos.x - this.b.oldpos.x + fx));
this.b.pos.y = this.b.oldpos.y + Math.min(40, Math.max(-40, this.b.pos.y - this.b.oldpos.y + fy));
this.b.IntegrateVerlet();
for (var i = 0; i < this.cells.length; i++) {
this.c.CollideCircleVsTile(this.cells[i]);
this.b.CollideAABBVsTile(this.cells[i]);
}
this.c.CollideCircleVsWorldBounds();
this.b.CollideAABBVsWorldBounds();
this.ball.transform.centerOn(this.c.pos.x, this.c.pos.y);
this.card.transform.centerOn(this.b.pos.x, this.b.pos.y);
}
function render() {
this.c.render(game.stage.context);
this.b.render(game.stage.context);
for (var i = 0; i < this.cells.length; i++) {
this.cells[i].render(game.stage.context);
}
}
})();

113
Tests/physics/circle 1.ts Normal file
View file

@ -0,0 +1,113 @@
/// <reference path="../../Phaser/_definitions.ts" />
(function () {
var game = new Phaser.Game(this, 'game', 800, 600, preload, create, update, render);
function preload() {
game.load.image('ball', 'assets/sprites/shinyball.png');
game.load.image('card', 'assets/sprites/mana_card.png');
}
var cells;
var b: Phaser.Physics.AABB;
var c: Phaser.Physics.Circle;
var t: Phaser.Physics.TileMapCell;
var ball: Phaser.Sprite;
var card: Phaser.Sprite;
function create() {
this.ball = game.add.sprite(0, 0, 'ball');
this.card = game.add.sprite(0, 0, 'card');
this.card.rotation = 30;
this.c = game.add.circle(200, 200, 16);
this.b = game.add.aabb(400, 200, 74, 128);
// pos is center, not upper-left
this.cells = [];
var tid;
for (var i = 0; i < 10; i++)
{
if (i % 2 == 0)
{
tid = Phaser.Physics.TileMapCell.TID_CONCAVEpn;
}
else
{
tid = Phaser.Physics.TileMapCell.TID_CONCAVEnn;
}
this.cells.push(game.add.cell(100 + (i * 100), 400, 50, 50, tid));
//this.cells.push(new TileMapCell(100 + (i * 100), 500, 50, 50).SetState(TileMapCell.TID_FULL));
//this.cells.push(new TileMapCell(100 + (i * 100), 500, 50, 50).SetState(TileMapCell.TID_CONCAVEpn));
}
}
function update() {
var fx = 0;
var fy = 0;
if (game.input.keyboard.isDown(Phaser.Keyboard.LEFT))
{
fx -= 0.2;
}
else if (game.input.keyboard.isDown(Phaser.Keyboard.RIGHT))
{
fx += 0.2;
}
if (game.input.keyboard.isDown(Phaser.Keyboard.UP))
{
fy -= 0.2 + 0.2;
}
else if (game.input.keyboard.isDown(Phaser.Keyboard.DOWN))
{
fy += 0.2;
}
// update circle
this.c.pos.x = this.c.oldpos.x + Math.min(20, Math.max(-20, this.c.pos.x - this.c.oldpos.x + fx));
this.c.pos.y = this.c.oldpos.y + Math.min(20, Math.max(-20, this.c.pos.y - this.c.oldpos.y + fy));
this.c.IntegrateVerlet();
// update box
this.b.pos.x = this.b.oldpos.x + Math.min(40, Math.max(-40, this.b.pos.x - this.b.oldpos.x + fx));
this.b.pos.y = this.b.oldpos.y + Math.min(40, Math.max(-40, this.b.pos.y - this.b.oldpos.y + fy));
this.b.IntegrateVerlet();
for (var i = 0; i < this.cells.length; i++)
{
this.c.CollideCircleVsTile(this.cells[i]);
this.b.CollideAABBVsTile(this.cells[i]);
}
this.c.CollideCircleVsWorldBounds();
this.b.CollideAABBVsWorldBounds();
this.ball.transform.centerOn(this.c.pos.x, this.c.pos.y);
this.card.transform.centerOn(this.b.pos.x, this.b.pos.y);
}
function render() {
this.c.render(game.stage.context);
this.b.render(game.stage.context);
for (var i = 0; i < this.cells.length; i++)
{
this.cells[i].render(game.stage.context);
}
}
})();

View file

@ -0,0 +1,43 @@
/// <reference path="../../Phaser/_definitions.ts" />
(function () {
var game = new Phaser.Game(this, 'game', 800, 600, preload, create, update, render);
function preload() {
game.load.image('fuji', 'assets/pics/atari_fujilogo.png');
}
var fuji;
var tween;
var b;
function create() {
game.stage.backgroundColor = 'rgb(0,0,100)';
fuji = game.add.sprite(game.stage.centerX, game.stage.centerY, 'fuji');
fuji.origin.setTo(0, 0.5);
fuji.rotation = 34;
b = new Phaser.Rectangle(fuji.transform.center.x, fuji.transform.center.y, fuji.width, fuji.height);
//game.add.tween(fuji).to({ rotation: 360 }, 20000, Phaser.Easing.Linear.None, true, 0, true);
}
function update() {
if (game.input.activePointer.justPressed()) {
//fuji.transform.centerOn(game.input.x, game.input.y);
fuji.x = game.input.x;
fuji.y = game.input.y;
}
b.x = fuji.transform.center.x - fuji.transform.halfWidth;
b.y = fuji.transform.center.y - fuji.transform.halfHeight;
}
function render() {
//Phaser.DebugUtils.renderSpriteWorldViewBounds(fuji);
//Phaser.DebugUtils.renderSpriteBounds(fuji);
Phaser.DebugUtils.renderSpriteCorners(fuji);
//Phaser.DebugUtils.renderSpriteWorldView(fuji, 32, 32);
Phaser.DebugUtils.renderRectangle(b, 'rgba(237,20,91,0.3)');
}
})();

View file

@ -0,0 +1,53 @@
/// <reference path="../../Phaser/_definitions.ts" />
(function () {
var game = new Phaser.Game(this, 'game', 800, 600, preload, create, update, render);
function preload() {
game.load.image('fuji', 'assets/pics/atari_fujilogo.png');
}
var fuji: Phaser.Sprite;
var tween: Phaser.Tween;
var b: Phaser.Rectangle;
function create() {
game.stage.backgroundColor = 'rgb(0,0,100)';
fuji = game.add.sprite(game.stage.centerX, game.stage.centerY, 'fuji');
fuji.origin.setTo(0, 0.5);
fuji.rotation = 34;
b = new Phaser.Rectangle(fuji.transform.center.x, fuji.transform.center.y, fuji.width, fuji.height);
//game.add.tween(fuji).to({ rotation: 360 }, 20000, Phaser.Easing.Linear.None, true, 0, true);
}
function update() {
if (game.input.activePointer.justPressed())
{
//fuji.transform.centerOn(game.input.x, game.input.y);
fuji.x = game.input.x;
fuji.y = game.input.y;
}
b.x = fuji.transform.center.x - fuji.transform.halfWidth;
b.y = fuji.transform.center.y - fuji.transform.halfHeight;
}
function render() {
//Phaser.DebugUtils.renderSpriteWorldViewBounds(fuji);
//Phaser.DebugUtils.renderSpriteBounds(fuji);
Phaser.DebugUtils.renderSpriteCorners(fuji);
//Phaser.DebugUtils.renderSpriteWorldView(fuji, 32, 32);
Phaser.DebugUtils.renderRectangle(b, 'rgba(237,20,91,0.3)');
}
})();

File diff suppressed because it is too large Load diff

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