mirror of
https://github.com/photonstorm/phaser
synced 2024-11-10 15:14:47 +00:00
Merge branch 'photonstorm/097'
This commit is contained in:
commit
80f5c0a67d
34 changed files with 13614 additions and 52 deletions
|
@ -56,7 +56,9 @@
|
|||
<TypeScriptOutFile>../build/phaser.js</TypeScriptOutFile>
|
||||
<TypeScriptGeneratesDeclarations>true</TypeScriptGeneratesDeclarations>
|
||||
</PropertyGroup>
|
||||
<ItemGroup />
|
||||
<ItemGroup>
|
||||
<Folder Include="physics\arcade\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="components\animation\AnimationManager.js">
|
||||
<DependentUpon>AnimationManager.ts</DependentUpon>
|
||||
|
@ -161,12 +163,88 @@
|
|||
</Content>
|
||||
<TypeScriptCompile Include="Motion.ts" />
|
||||
<TypeScriptCompile Include="math\Vec2.ts" />
|
||||
<TypeScriptCompile Include="math\Transform.ts" />
|
||||
<Content Include="math\Transform.js">
|
||||
<DependentUpon>Transform.ts</DependentUpon>
|
||||
</Content>
|
||||
<TypeScriptCompile Include="math\TransformUtils.ts" />
|
||||
<Content Include="math\TransformUtils.js">
|
||||
<DependentUpon>TransformUtils.ts</DependentUpon>
|
||||
</Content>
|
||||
<Content Include="math\Vec2.js">
|
||||
<DependentUpon>Vec2.ts</DependentUpon>
|
||||
</Content>
|
||||
<Content Include="Motion.js">
|
||||
<DependentUpon>Motion.ts</DependentUpon>
|
||||
</Content>
|
||||
<TypeScriptCompile Include="physics\ArcadePhysics.ts" />
|
||||
<TypeScriptCompile Include="physics\advanced\Body.ts" />
|
||||
<Content Include="physics\advanced\Body.js">
|
||||
<DependentUpon>Body.ts</DependentUpon>
|
||||
</Content>
|
||||
<TypeScriptCompile Include="physics\advanced\Bounds.ts" />
|
||||
<Content Include="physics\advanced\Bounds.js">
|
||||
<DependentUpon>Bounds.ts</DependentUpon>
|
||||
</Content>
|
||||
<TypeScriptCompile Include="physics\advanced\Contact.ts" />
|
||||
<TypeScriptCompile Include="physics\advanced\Collision.ts" />
|
||||
<Content Include="physics\advanced\Collision.js">
|
||||
<DependentUpon>Collision.ts</DependentUpon>
|
||||
</Content>
|
||||
<Content Include="physics\advanced\Contact.js">
|
||||
<DependentUpon>Contact.ts</DependentUpon>
|
||||
</Content>
|
||||
<TypeScriptCompile Include="physics\advanced\ContactSolver.ts" />
|
||||
<Content Include="physics\advanced\ContactSolver.js">
|
||||
<DependentUpon>ContactSolver.ts</DependentUpon>
|
||||
</Content>
|
||||
<TypeScriptCompile Include="physics\advanced\Manager.ts" />
|
||||
<TypeScriptCompile Include="physics\advanced\joints\IJoint.ts" />
|
||||
<Content Include="physics\advanced\joints\IJoint.js">
|
||||
<DependentUpon>IJoint.ts</DependentUpon>
|
||||
</Content>
|
||||
<TypeScriptCompile Include="physics\advanced\joints\Joint.ts" />
|
||||
<Content Include="physics\advanced\joints\Joint.js">
|
||||
<DependentUpon>Joint.ts</DependentUpon>
|
||||
</Content>
|
||||
<Content Include="physics\advanced\Manager.js">
|
||||
<DependentUpon>Manager.ts</DependentUpon>
|
||||
</Content>
|
||||
<TypeScriptCompile Include="physics\advanced\shapes\Shape.ts" />
|
||||
<TypeScriptCompile Include="physics\advanced\shapes\IShape.ts" />
|
||||
<TypeScriptCompile Include="physics\advanced\shapes\Box.ts" />
|
||||
<Content Include="physics\advanced\shapes\Box.js">
|
||||
<DependentUpon>Box.ts</DependentUpon>
|
||||
</Content>
|
||||
<TypeScriptCompile Include="physics\advanced\shapes\Circle.ts" />
|
||||
<Content Include="physics\advanced\shapes\Circle.js">
|
||||
<DependentUpon>Circle.ts</DependentUpon>
|
||||
</Content>
|
||||
<Content Include="physics\advanced\shapes\IShape.js">
|
||||
<DependentUpon>IShape.ts</DependentUpon>
|
||||
</Content>
|
||||
<TypeScriptCompile Include="physics\advanced\shapes\Poly.ts" />
|
||||
<Content Include="physics\advanced\shapes\Poly.js">
|
||||
<DependentUpon>Poly.ts</DependentUpon>
|
||||
</Content>
|
||||
<TypeScriptCompile Include="physics\advanced\shapes\Segment.ts" />
|
||||
<Content Include="physics\advanced\shapes\Segment.js">
|
||||
<DependentUpon>Segment.ts</DependentUpon>
|
||||
</Content>
|
||||
<Content Include="physics\advanced\shapes\Shape.js">
|
||||
<DependentUpon>Shape.ts</DependentUpon>
|
||||
</Content>
|
||||
<TypeScriptCompile Include="physics\advanced\shapes\Triangle.ts" />
|
||||
<Content Include="physics\advanced\shapes\Triangle.js">
|
||||
<DependentUpon>Triangle.ts</DependentUpon>
|
||||
</Content>
|
||||
<TypeScriptCompile Include="physics\advanced\Space.ts" />
|
||||
<Content Include="physics\advanced\Space.js">
|
||||
<DependentUpon>Space.ts</DependentUpon>
|
||||
</Content>
|
||||
<Content Include="physics\ArcadePhysics.js">
|
||||
<DependentUpon>ArcadePhysics.ts</DependentUpon>
|
||||
</Content>
|
||||
<Content Include="physics\Body.js">
|
||||
<DependentUpon>Body.ts</DependentUpon>
|
||||
</Content>
|
||||
|
|
|
@ -25,9 +25,9 @@ module Phaser {
|
|||
static GEOM_POLYGON: number = 4;
|
||||
|
||||
static BODY_DISABLED: number = 0;
|
||||
static BODY_DYNAMIC: number = 1;
|
||||
static BODY_STATIC: number = 2;
|
||||
static BODY_KINEMATIC: number = 3;
|
||||
static BODY_STATIC: number = 1;
|
||||
static BODY_KINETIC: number = 2;
|
||||
static BODY_DYNAMIC: number = 3;
|
||||
|
||||
/**
|
||||
* Flag used to allow GameObjects to collide on their left side
|
||||
|
|
|
@ -75,7 +75,7 @@ module Phaser {
|
|||
}
|
||||
|
||||
/**
|
||||
* Called one by Game during the boot process.
|
||||
* Called once by Game during the boot process.
|
||||
*/
|
||||
public boot() {
|
||||
|
||||
|
|
|
@ -623,7 +623,6 @@ module Phaser {
|
|||
this.sort();
|
||||
|
||||
// What's the z index of the top most child?
|
||||
var tempZ: number = child.z;
|
||||
var childIndex: number = this._zCounter;
|
||||
|
||||
this._i = 0;
|
||||
|
@ -632,17 +631,21 @@ module Phaser {
|
|||
{
|
||||
this._member = this.members[this._i++];
|
||||
|
||||
if (this._i > childIndex)
|
||||
if (this._member)
|
||||
{
|
||||
this._member.z--;
|
||||
}
|
||||
else if (this._member.z == child.z)
|
||||
{
|
||||
childIndex = this._i;
|
||||
this._member.z = this._zCounter;
|
||||
if (this._i > childIndex)
|
||||
{
|
||||
this._member.z--;
|
||||
}
|
||||
else if (this._member.z == child.z)
|
||||
{
|
||||
childIndex = this._i;
|
||||
this._member.z = this._zCounter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Maybe redundant?
|
||||
this.sort();
|
||||
|
||||
return true;
|
||||
|
|
69
Phaser/math/Transform.ts
Normal file
69
Phaser/math/Transform.ts
Normal file
|
@ -0,0 +1,69 @@
|
|||
/// <reference path="../Game.ts" />
|
||||
/// <reference path="Vec2Utils.ts" />
|
||||
|
||||
/**
|
||||
* Phaser - 2D Transform
|
||||
*
|
||||
* A 2D Transform
|
||||
*/
|
||||
|
||||
module Phaser {
|
||||
|
||||
export class Transform {
|
||||
|
||||
/**
|
||||
* Creates a new 2D Transform object.
|
||||
* @class Transform
|
||||
* @constructor
|
||||
* @return {Transform} This object
|
||||
**/
|
||||
constructor(pos: Phaser.Vec2, angle: number) {
|
||||
|
||||
this.t = Phaser.Vec2Utils.clone(pos);
|
||||
this.c = Math.cos(angle);
|
||||
this.s = Math.sin(angle);
|
||||
|
||||
}
|
||||
|
||||
public t: Phaser.Vec2;
|
||||
public c: number;
|
||||
public s: number;
|
||||
|
||||
public setTo(pos:Phaser.Vec2, angle:number) {
|
||||
|
||||
this.t.copyFrom(pos);
|
||||
this.c = Math.cos(angle);
|
||||
this.s = Math.sin(angle);
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
public setRotation(angle:number) {
|
||||
|
||||
this.c = Math.cos(angle);
|
||||
this.s = Math.sin(angle);
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
public setPosition(p:Phaser.Vec2) {
|
||||
|
||||
this.t.copyFrom(p);
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
public identity() {
|
||||
|
||||
this.t.setTo(0, 0);
|
||||
this.c = 1;
|
||||
this.s = 0;
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
39
Phaser/math/TransformUtils.ts
Normal file
39
Phaser/math/TransformUtils.ts
Normal file
|
@ -0,0 +1,39 @@
|
|||
/// <reference path="../Game.ts" />
|
||||
/// <reference path="Vec2.ts" />
|
||||
/// <reference path="Transform.ts" />
|
||||
|
||||
/**
|
||||
* Phaser - TransformUtils
|
||||
*
|
||||
* A collection of methods useful for manipulating and performing operations on 2D Transforms.
|
||||
*
|
||||
*/
|
||||
|
||||
module Phaser {
|
||||
|
||||
export class TransformUtils {
|
||||
|
||||
public static rotate(t: Transform, v:Phaser.Vec2, out?: Vec2 = new Vec2):Phaser.Vec2 {
|
||||
return out.setTo(v.x * t.c - v.y * t.s, v.x * t.s + v.y * t.c);
|
||||
}
|
||||
|
||||
public static unrotate(t: Transform, v:Phaser.Vec2, out?: Vec2 = new Vec2):Phaser.Vec2 {
|
||||
return out.setTo(v.x * t.c + v.y * t.s, -v.x * t.s + v.y * t.c);
|
||||
}
|
||||
|
||||
public static transform(t: Transform, v:Phaser.Vec2, out?: Vec2 = new Vec2):Phaser.Vec2 {
|
||||
return out.setTo(v.x * t.c - v.y * t.s + t.t.x, v.x * t.s + v.y * t.c + t.t.y);
|
||||
}
|
||||
|
||||
public static untransform(t: Transform, v:Phaser.Vec2, out?: Vec2 = new Vec2):Phaser.Vec2 {
|
||||
|
||||
var px = v.x - t.t.x;
|
||||
var py = v.y - t.t.y;
|
||||
|
||||
return out.setTo(px * t.c + py * t.s, -px * t.s + py * t.c);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -137,6 +137,20 @@ module Phaser {
|
|||
return (this.x * this.x) + (this.y * this.y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize this vector.
|
||||
*
|
||||
* @return {Vec2} This for chaining.
|
||||
*/
|
||||
public normalize(): Vec2 {
|
||||
|
||||
var inv = (this.x != 0 || this.y != 0) ? 1 / Math.sqrt(this.x * this.x + this.y * this.y) : 0;
|
||||
this.x *= inv;
|
||||
this.y *= inv;
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The dot product of two 2D vectors.
|
||||
*
|
||||
|
@ -217,6 +231,21 @@ module Phaser {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given vector to this vector then multiplies by the given scalar.
|
||||
*
|
||||
* @param {Vec2} a Reference to a source Vec2 object.
|
||||
* @param {number} scalar
|
||||
* @return {Vec2} This for chaining.
|
||||
*/
|
||||
public multiplyAddByScalar(a: Vec2, scalar: number): Vec2 {
|
||||
|
||||
this.x += a.x * scalar;
|
||||
this.y += a.y * scalar;
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Divide this vector by the given scalar.
|
||||
*
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/// <reference path="../Game.ts" />
|
||||
/// <reference path="../math/Vec2.ts" />
|
||||
/// <reference path="Vec2.ts" />
|
||||
|
||||
/**
|
||||
* Phaser - Vec2Utils
|
||||
|
@ -73,13 +73,48 @@ module Phaser {
|
|||
}
|
||||
|
||||
/**
|
||||
* Rotate a 2D vector by 90 degrees.
|
||||
* Adds two 2D vectors together and multiplies the result by the given scalar.
|
||||
*
|
||||
* @param {Vec2} a Reference to a source Vec2 object.
|
||||
* @param {Vec2} b Reference to a source Vec2 object.
|
||||
* @param {number} s Scaling value.
|
||||
* @param {Vec2} out The output Vec2 that is the result of the operation.
|
||||
* @return {Vec2} A Vec2 that is the sum of the two vectors added and multiplied.
|
||||
*/
|
||||
static multiplyAdd(a: Vec2, b: Vec2, s: number, out?: Vec2 = new Vec2): Vec2 {
|
||||
return out.setTo(a.x + b.x * s, a.y + b.y * s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a negative vector.
|
||||
*
|
||||
* @param {Vec2} a Reference to a source Vec2 object.
|
||||
* @param {Vec2} out The output Vec2 that is the result of the operation.
|
||||
* @return {Vec2} A Vec2 that is the negative vector.
|
||||
*/
|
||||
static negative(a: Vec2, out?: Vec2 = new Vec2): Vec2 {
|
||||
return out.setTo(-a.x, -a.y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a perpendicular vector (90 degrees rotation)
|
||||
*
|
||||
* @param {Vec2} a Reference to a source Vec2 object.
|
||||
* @param {Vec2} out The output Vec2 that is the result of the operation.
|
||||
* @return {Vec2} A Vec2 that is the scaled vector.
|
||||
*/
|
||||
static perp(a: Vec2, out?: Vec2 = new Vec2): Vec2 {
|
||||
return out.setTo(-a.y, a.x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a perpendicular vector (-90 degrees rotation)
|
||||
*
|
||||
* @param {Vec2} a Reference to a source Vec2 object.
|
||||
* @param {Vec2} out The output Vec2 that is the result of the operation.
|
||||
* @return {Vec2} A Vec2 that is the scaled vector.
|
||||
*/
|
||||
static rperp(a: Vec2, out?: Vec2 = new Vec2): Vec2 {
|
||||
return out.setTo(a.y, -a.x);
|
||||
}
|
||||
|
||||
|
@ -253,12 +288,30 @@ module Phaser {
|
|||
* @param {Vec2} out The output Vec2 that is the result of the operation.
|
||||
* @return {Vec2} A Vec2.
|
||||
*/
|
||||
static rotate(a: Vec2, b: Vec2, theta: number, out?: Vec2 = new Vec2): Vec2 {
|
||||
static rotateAroundOrigin(a: Vec2, b: Vec2, theta: number, out?: Vec2 = new Vec2): Vec2 {
|
||||
var x = a.x - b.x;
|
||||
var y = a.y - b.y;
|
||||
return out.setTo(x * Math.cos(theta) - y * Math.sin(theta) + b.x, x * Math.sin(theta) + y * Math.cos(theta) + b.y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotate a 2D vector to the given angle (theta).
|
||||
*
|
||||
* @param {Vec2} a Reference to a source Vec2 object.
|
||||
* @param {Vec2} b Reference to a source Vec2 object.
|
||||
* @param {Number} theta The angle of rotation in radians.
|
||||
* @param {Vec2} out The output Vec2 that is the result of the operation.
|
||||
* @return {Vec2} A Vec2.
|
||||
*/
|
||||
static rotate(a: Vec2, theta: number, out?: Vec2 = new Vec2): Vec2 {
|
||||
|
||||
var c = Math.cos(theta);
|
||||
var s = Math.sin(theta);
|
||||
|
||||
return out.setTo(a.x * c - a.y * s, a.x * s + a.y * c);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone a 2D vector.
|
||||
*
|
||||
|
|
1121
Phaser/physics/ArcadePhysics.ts
Normal file
1121
Phaser/physics/ArcadePhysics.ts
Normal file
File diff suppressed because it is too large
Load diff
589
Phaser/physics/advanced/Body.ts
Normal file
589
Phaser/physics/advanced/Body.ts
Normal file
|
@ -0,0 +1,589 @@
|
|||
/// <reference path="../../math/Vec2.ts" />
|
||||
/// <reference path="../../geom/Point.ts" />
|
||||
/// <reference path="../../math/Vec2Utils.ts" />
|
||||
/// <reference path="../../math/Transform.ts" />
|
||||
/// <reference path="../../math/TransformUtils.ts" />
|
||||
/// <reference path="Manager.ts" />
|
||||
/// <reference path="joints/Joint.ts" />
|
||||
/// <reference path="Bounds.ts" />
|
||||
/// <reference path="Space.ts" />
|
||||
/// <reference path="shapes/IShape.ts" />
|
||||
|
||||
/**
|
||||
* Phaser - Advanced Physics - Body
|
||||
*
|
||||
* Based on the work Ju Hyung Lee started in JS PhyRus.
|
||||
*/
|
||||
|
||||
module Phaser.Physics.Advanced {
|
||||
|
||||
export class Body {
|
||||
|
||||
constructor(sprite: Phaser.Sprite, type: number, x?: number = 0, y?: number = 0) {
|
||||
|
||||
this.id = Phaser.Physics.Advanced.Manager.bodyCounter++;
|
||||
this.name = 'body' + this.id;
|
||||
this.type = type;
|
||||
|
||||
if (sprite)
|
||||
{
|
||||
this.sprite = sprite;
|
||||
this.game = sprite.game;
|
||||
this.position = new Phaser.Vec2(sprite.x, sprite.y);
|
||||
this.angle = sprite.rotation;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.position = new Phaser.Vec2(x, y);
|
||||
this.angle = 0;
|
||||
}
|
||||
|
||||
this.transform = new Phaser.Transform(this.position, this.angle);
|
||||
this.centroid = new Phaser.Vec2;
|
||||
this.velocity = new Phaser.Vec2;
|
||||
this.force = new Phaser.Vec2;
|
||||
this.angularVelocity = 0;
|
||||
this.torque = 0;
|
||||
this.linearDamping = 0;
|
||||
this.angularDamping = 0;
|
||||
this.sleepTime = 0;
|
||||
this.awaked = false;
|
||||
|
||||
this.shapes = [];
|
||||
this.joints = [];
|
||||
this.jointHash = {};
|
||||
|
||||
this.bounds = new Bounds;
|
||||
|
||||
this.fixedRotation = false;
|
||||
|
||||
this.categoryBits = 0x0001;
|
||||
this.maskBits = 0xFFFF;
|
||||
|
||||
this.stepCount = 0;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Reference to Phaser.Game
|
||||
*/
|
||||
public game: Game;
|
||||
|
||||
/**
|
||||
* Reference to the parent Sprite
|
||||
*/
|
||||
public sprite: Phaser.Sprite;
|
||||
|
||||
/**
|
||||
* The Body ID
|
||||
*/
|
||||
public id: number;
|
||||
|
||||
/**
|
||||
* The Body name
|
||||
*/
|
||||
public name: string;
|
||||
|
||||
/**
|
||||
* The type of Body (disabled, dynamic, static or kinematic)
|
||||
* Disabled = skips all physics operations / tests (default)
|
||||
* Dynamic = gives and receives impacts
|
||||
* Static = gives but doesn't receive impacts, cannot be moved by physics
|
||||
* Kinematic = gives impacts, but never receives, can be moved by physics
|
||||
* @type {number}
|
||||
*/
|
||||
public type: number;
|
||||
|
||||
public angle: number;
|
||||
|
||||
// Local to world transform
|
||||
public transform: Phaser.Transform;
|
||||
|
||||
// Local center of mass
|
||||
public centroid: Phaser.Vec2;
|
||||
|
||||
// World position of centroid
|
||||
public position: Phaser.Vec2;
|
||||
|
||||
// Velocity
|
||||
public velocity: Phaser.Vec2;
|
||||
|
||||
// Force
|
||||
public force: Phaser.Vec2;
|
||||
|
||||
// Angular velocity
|
||||
public angularVelocity: number;
|
||||
|
||||
// Torque
|
||||
public torque: number;
|
||||
|
||||
// Linear damping
|
||||
public linearDamping: number;
|
||||
|
||||
// Angular damping
|
||||
public angularDamping: number;
|
||||
|
||||
// Sleep time
|
||||
public sleepTime: number;
|
||||
|
||||
// Awaked
|
||||
public awaked: bool;
|
||||
|
||||
// Shapes
|
||||
public shapes: IShape[] = [];
|
||||
|
||||
// Joints
|
||||
public joints: IJoint[] = [];
|
||||
public jointHash = {};
|
||||
|
||||
// Bounds of all shapes
|
||||
public bounds: Bounds;
|
||||
|
||||
public fixedRotation = false;
|
||||
public categoryBits = 0x0001;
|
||||
public maskBits = 0xFFFF;
|
||||
public stepCount = 0;
|
||||
public space: Space;
|
||||
|
||||
public duplicate() {
|
||||
|
||||
//console.log('body duplicate called');
|
||||
|
||||
//var body = new Body(this.type, this.transform.t, this.angle);
|
||||
|
||||
//for (var i = 0; i < this.shapes.length; i++)
|
||||
//{
|
||||
// body.addShape(this.shapes[i].duplicate());
|
||||
//}
|
||||
|
||||
//body.resetMassData();
|
||||
|
||||
//return body;
|
||||
|
||||
}
|
||||
|
||||
public get isDisabled(): bool {
|
||||
return this.type == Phaser.Types.BODY_DISABLED ? true : false;
|
||||
}
|
||||
|
||||
public get isStatic(): bool {
|
||||
return this.type == Phaser.Types.BODY_STATIC ? true : false;
|
||||
}
|
||||
|
||||
public get isKinetic(): bool {
|
||||
return this.type == Phaser.Types.BODY_KINETIC ? true : false;
|
||||
}
|
||||
|
||||
public get isDynamic(): bool {
|
||||
return this.type == Phaser.Types.BODY_DYNAMIC ? true : false;
|
||||
}
|
||||
|
||||
public setType(type: number) {
|
||||
|
||||
if (type == this.type)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.force.setTo(0, 0);
|
||||
this.velocity.setTo(0, 0);
|
||||
this.torque = 0;
|
||||
this.angularVelocity = 0;
|
||||
this.type = type;
|
||||
|
||||
this.awake(true);
|
||||
|
||||
}
|
||||
|
||||
public addShape(shape) {
|
||||
|
||||
// Check not already part of this body
|
||||
shape.body = this;
|
||||
|
||||
this.shapes.push(shape);
|
||||
|
||||
return shape;
|
||||
|
||||
}
|
||||
|
||||
public removeShape(shape) {
|
||||
|
||||
var index = this.shapes.indexOf(shape);
|
||||
|
||||
if (index != -1)
|
||||
{
|
||||
this.shapes.splice(index, 1);
|
||||
shape.body = undefined;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public mass: number;
|
||||
public massInverted: number;
|
||||
public inertia: number;
|
||||
public inertiaInverted: number;
|
||||
|
||||
private setMass(mass) {
|
||||
|
||||
this.mass = mass;
|
||||
this.massInverted = mass > 0 ? 1 / mass : 0;
|
||||
|
||||
}
|
||||
|
||||
private setInertia(inertia) {
|
||||
|
||||
this.inertia = inertia;
|
||||
this.inertiaInverted = inertia > 0 ? 1 / inertia : 0;
|
||||
|
||||
}
|
||||
|
||||
public setTransform(pos, angle) {
|
||||
|
||||
this.transform.setTo(pos, angle);
|
||||
// inject the transform into this.position
|
||||
Phaser.TransformUtils.transform(this.transform, this.centroid, this.position);
|
||||
//this.position.copyFrom(this.transform.transform(this.centroid));
|
||||
this.angle = angle;
|
||||
|
||||
}
|
||||
|
||||
public syncTransform() {
|
||||
|
||||
this.transform.setRotation(this.angle);
|
||||
|
||||
//var rotc: Phaser.Vec2 = this.transform.rotate(this.centroid);
|
||||
//var sub: Phaser.Vec2 = Phaser.Vec2Utils.subtract(this.position, rotc);
|
||||
//this.transform.setPosition(sub);
|
||||
|
||||
// this.transform.setPosition(vec2.sub(this.position, this.transform.rotate(this.centroid)));
|
||||
//Phaser.Vec2Utils.subtract(this.position, this.transform.rotate(this.centroid), this.transform.t);
|
||||
|
||||
// OPTIMISE: Creating new vector
|
||||
Phaser.Vec2Utils.subtract(this.position, Phaser.TransformUtils.rotate(this.transform, this.centroid), this.transform.t);
|
||||
|
||||
}
|
||||
|
||||
public getWorldPoint(p:Phaser.Vec2) {
|
||||
// OPTIMISE: Creating new vector
|
||||
return Phaser.TransformUtils.transform(this.transform, p);
|
||||
}
|
||||
|
||||
public getWorldVector(v) {
|
||||
// OPTIMISE: Creating new vector
|
||||
return Phaser.TransformUtils.rotate(this.transform, v);
|
||||
}
|
||||
|
||||
public getLocalPoint(p) {
|
||||
// OPTIMISE: Creating new vector
|
||||
return Phaser.TransformUtils.untransform(this.transform, p);
|
||||
}
|
||||
|
||||
public getLocalVector(v) {
|
||||
// OPTIMISE: Creating new vector
|
||||
return Phaser.TransformUtils.unrotate(this.transform, v);
|
||||
}
|
||||
|
||||
public setFixedRotation(flag) {
|
||||
this.fixedRotation = flag;
|
||||
this.resetMassData();
|
||||
}
|
||||
|
||||
public resetMassData() {
|
||||
|
||||
this.centroid.setTo(0, 0);
|
||||
this.mass = 0;
|
||||
this.massInverted = 0;
|
||||
this.inertia = 0;
|
||||
this.inertiaInverted = 0;
|
||||
|
||||
if (this.isDynamic == false)
|
||||
{
|
||||
Phaser.TransformUtils.transform(this.transform, this.centroid, this.position);
|
||||
//this.position.copyFrom(this.transform.transform(this.centroid));
|
||||
return;
|
||||
}
|
||||
|
||||
var totalMassCentroid = new Phaser.Vec2(0, 0);
|
||||
var totalMass = 0;
|
||||
var totalInertia = 0;
|
||||
|
||||
for (var i = 0; i < this.shapes.length; i++)
|
||||
{
|
||||
var shape = this.shapes[i];
|
||||
var centroid = shape.centroid();
|
||||
var mass = shape.area() * shape.density;
|
||||
var inertia = shape.inertia(mass);
|
||||
|
||||
//console.log('rmd', centroid, shape);
|
||||
|
||||
totalMassCentroid.multiplyAddByScalar(centroid, mass);
|
||||
totalMass += mass;
|
||||
totalInertia += inertia;
|
||||
}
|
||||
|
||||
//this.centroid.copy(vec2.scale(totalMassCentroid, 1 / totalMass));
|
||||
Phaser.Vec2Utils.scale(totalMassCentroid, 1 / totalMass, this.centroid);
|
||||
|
||||
this.setMass(totalMass);
|
||||
|
||||
if (!this.fixedRotation)
|
||||
{
|
||||
//this.setInertia(totalInertia - totalMass * vec2.dot(this.centroid, this.centroid));
|
||||
this.setInertia(totalInertia - totalMass * Phaser.Vec2Utils.dot(this.centroid, this.centroid));
|
||||
}
|
||||
|
||||
//console.log("mass = " + this.m + " inertia = " + this.i);
|
||||
|
||||
// Move center of mass
|
||||
var oldPosition: Phaser.Vec2 = Phaser.Vec2Utils.clone(this.position);
|
||||
//this.position.copyFrom(this.transform.transform(this.centroid));
|
||||
Phaser.TransformUtils.transform(this.transform, this.centroid, this.position);
|
||||
|
||||
// Update center of mass velocity
|
||||
|
||||
//this.velocity.mad(vec2.perp(vec2.sub(this.position, old_p)), this.angularVelocity);
|
||||
oldPosition.subtract(this.position);
|
||||
this.velocity.multiplyAddByScalar(Phaser.Vec2Utils.perp(oldPosition, oldPosition), this.angularVelocity);
|
||||
|
||||
}
|
||||
|
||||
public resetJointAnchors() {
|
||||
|
||||
for (var i = 0; i < this.joints.length; i++)
|
||||
{
|
||||
var joint = this.joints[i];
|
||||
|
||||
if (!joint)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var anchor1 = joint.getWorldAnchor1();
|
||||
var anchor2 = joint.getWorldAnchor2();
|
||||
|
||||
joint.setWorldAnchor1(anchor1);
|
||||
joint.setWorldAnchor2(anchor2);
|
||||
}
|
||||
}
|
||||
|
||||
public cacheData() {
|
||||
|
||||
//console.log('Body cacheData', this.name, 'len', this.shapes.length);
|
||||
|
||||
this.bounds.clear();
|
||||
|
||||
for (var i = 0; i < this.shapes.length; i++)
|
||||
{
|
||||
var shape = this.shapes[i];
|
||||
shape.cacheData(this.transform);
|
||||
this.bounds.addBounds(shape.bounds);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private _tempVec2: Phaser.Vec2 = new Phaser.Vec2;
|
||||
|
||||
public updateVelocity(gravity, dt, damping) {
|
||||
|
||||
// this.velocity = vec2.mad(this.velocity, vec2.mad(gravity, this.force, this.massInverted), dt);
|
||||
Phaser.Vec2Utils.multiplyAdd(gravity, this.force, this.massInverted, this._tempVec2);
|
||||
Phaser.Vec2Utils.multiplyAdd(this.velocity, this._tempVec2, dt, this.velocity);
|
||||
|
||||
this.angularVelocity = this.angularVelocity + this.torque * this.inertiaInverted * dt;
|
||||
|
||||
// Apply damping.
|
||||
// ODE: dv/dt + c * v = 0
|
||||
// Solution: v(t) = v0 * exp(-c * t)
|
||||
// Time step: v(t + dt) = v0 * exp(-c * (t + dt)) = v0 * exp(-c * t) * exp(-c * dt) = v * exp(-c * dt)
|
||||
// v2 = exp(-c * dt) * v1
|
||||
// Taylor expansion:
|
||||
// v2 = (1.0f - c * dt) * v1
|
||||
this.velocity.scale(this.game.math.clamp(1 - dt * (damping + this.linearDamping), 0, 1));
|
||||
this.angularVelocity *= this.game.math.clamp(1 - dt * (damping + this.angularDamping), 0, 1);
|
||||
|
||||
this.force.setTo(0, 0);
|
||||
this.torque = 0;
|
||||
|
||||
}
|
||||
|
||||
public updatePosition(dt) {
|
||||
|
||||
//console.log('body update pos', this.position.y);
|
||||
//console.log('pre add temp', this._tempVec2.y);
|
||||
|
||||
//this.position.addself(vec2.scale(this.velocity, dt));
|
||||
this.position.add(Phaser.Vec2Utils.scale(this.velocity, dt, this._tempVec2));
|
||||
|
||||
//console.log('post add temp', this._tempVec2.y);
|
||||
//console.log('post add', this.position.y);
|
||||
|
||||
this.angle += this.angularVelocity * dt;
|
||||
|
||||
}
|
||||
|
||||
public resetForce() {
|
||||
this.force.setTo(0, 0);
|
||||
this.torque = 0;
|
||||
}
|
||||
|
||||
public applyForce(force, p) {
|
||||
|
||||
if (this.isDynamic == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.isAwake == false)
|
||||
{
|
||||
this.awake(true);
|
||||
}
|
||||
|
||||
this.force.add(force);
|
||||
|
||||
// this.f.addself(force);
|
||||
// this.torque += vec2.cross(vec2.sub(p, this.p), force);
|
||||
|
||||
Phaser.Vec2Utils.subtract(p, this.position, this._tempVec2);
|
||||
this.torque += Phaser.Vec2Utils.cross(this._tempVec2, force);
|
||||
|
||||
}
|
||||
|
||||
public applyForceToCenter(force) {
|
||||
|
||||
if (this.isDynamic == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.isAwake == false)
|
||||
{
|
||||
this.awake(true);
|
||||
}
|
||||
|
||||
this.force.add(force);
|
||||
|
||||
}
|
||||
|
||||
public applyTorque(torque) {
|
||||
|
||||
if (this.isDynamic == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.isAwake == false)
|
||||
{
|
||||
this.awake(true);
|
||||
}
|
||||
|
||||
this.torque += torque;
|
||||
|
||||
}
|
||||
|
||||
public applyLinearImpulse(impulse, p) {
|
||||
|
||||
if (this.isDynamic == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.isAwake == false)
|
||||
{
|
||||
this.awake(true);
|
||||
}
|
||||
|
||||
this.velocity.multiplyAddByScalar(impulse, this.massInverted);
|
||||
|
||||
// this.angularVelocity += vec2.cross(vec2.sub(p, this.position), impulse) * this.inertiaInverted;
|
||||
|
||||
Phaser.Vec2Utils.subtract(p, this.position, this._tempVec2);
|
||||
this.angularVelocity += Phaser.Vec2Utils.cross(this._tempVec2, impulse) * this.inertiaInverted;
|
||||
|
||||
}
|
||||
|
||||
public applyAngularImpulse(impulse: number) {
|
||||
|
||||
if (this.isDynamic == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.isAwake == false)
|
||||
{
|
||||
this.awake(true);
|
||||
}
|
||||
|
||||
this.angularVelocity += impulse * this.inertiaInverted;
|
||||
|
||||
}
|
||||
|
||||
public kineticEnergy() {
|
||||
|
||||
var vsq = this.velocity.dot(this.velocity);
|
||||
var wsq = this.angularVelocity * this.angularVelocity;
|
||||
|
||||
return 0.5 * (this.mass * vsq + this.inertia * wsq);
|
||||
|
||||
}
|
||||
|
||||
public get isAwake(): bool {
|
||||
return this.awaked;
|
||||
}
|
||||
|
||||
public awake(flag) {
|
||||
|
||||
this.awaked = flag;
|
||||
|
||||
if (flag)
|
||||
{
|
||||
this.sleepTime = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.velocity.setTo(0, 0);
|
||||
this.angularVelocity = 0;
|
||||
this.force.setTo(0, 0);
|
||||
this.torque = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public isCollidable(other) {
|
||||
|
||||
if (this == other)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.isDynamic == false && other.isDynamic == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(this.maskBits & other.categoryBits) || !(other.maskBits & this.categoryBits))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (var i = 0; i < this.joints.length; i++)
|
||||
{
|
||||
var joint = this.joints[i];
|
||||
|
||||
if (!joint)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!joint.collideConnected && other.jointHash[joint.id] != undefined)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
173
Phaser/physics/advanced/Bounds.ts
Normal file
173
Phaser/physics/advanced/Bounds.ts
Normal file
|
@ -0,0 +1,173 @@
|
|||
/// <reference path="../../Game.ts" />
|
||||
/// <reference path="../../math/Vec2.ts" />
|
||||
/// <reference path="../../math/Vec2Utils.ts" />
|
||||
|
||||
/**
|
||||
* Phaser - 2D AABB
|
||||
*
|
||||
* A 2D AABB object
|
||||
*/
|
||||
|
||||
module Phaser.Physics.Advanced {
|
||||
|
||||
export class Bounds {
|
||||
|
||||
/**
|
||||
* Creates a new 2D AABB object.
|
||||
* @class Bounds
|
||||
* @constructor
|
||||
* @return {Bounds} This object
|
||||
**/
|
||||
constructor(mins?: Phaser.Vec2 = null, maxs?: Phaser.Vec2 = null) {
|
||||
|
||||
if (mins)
|
||||
{
|
||||
this.mins = Phaser.Vec2Utils.clone(mins);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.mins = new Phaser.Vec2(999999, 999999);
|
||||
}
|
||||
|
||||
if (maxs)
|
||||
{
|
||||
this.maxs = Phaser.Vec2Utils.clone(maxs);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.maxs = new Phaser.Vec2(999999, 999999);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public mins: Phaser.Vec2;
|
||||
public maxs: Phaser.Vec2;
|
||||
|
||||
public toString() {
|
||||
return ["mins:", this.mins.toString(), "maxs:", this.maxs.toString()].join(" ");
|
||||
}
|
||||
|
||||
public setTo(mins: Phaser.Vec2, maxs: Phaser.Vec2) {
|
||||
|
||||
this.mins.setTo(mins.x, mins.y);
|
||||
this.maxs.setTo(maxs.x, maxs.y);
|
||||
|
||||
}
|
||||
|
||||
public copy(b: Bounds): Bounds {
|
||||
|
||||
this.mins.copyFrom(b.mins);
|
||||
this.maxs.copyFrom(b.maxs);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public clear(): Bounds {
|
||||
|
||||
this.mins.setTo(999999, 999999);
|
||||
this.maxs.setTo(-999999, -999999);
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
public isEmpty(): bool {
|
||||
return (this.mins.x > this.maxs.x || this.mins.y > this.maxs.y);
|
||||
}
|
||||
|
||||
/*
|
||||
public getCenter() {
|
||||
return vec2.scale(vec2.add(this.mins, this.maxs), 0.5);
|
||||
}
|
||||
|
||||
public getExtent() {
|
||||
return vec2.scale(vec2.sub(this.maxs, this.mins), 0.5);
|
||||
}
|
||||
*/
|
||||
|
||||
public getPerimeter(): number {
|
||||
return (this.maxs.x - this.mins.x + this.maxs.y - this.mins.y) * 2;
|
||||
}
|
||||
|
||||
public addPoint(p: Phaser.Vec2): Bounds {
|
||||
|
||||
if (this.mins.x > p.x) this.mins.x = p.x;
|
||||
if (this.maxs.x < p.x) this.maxs.x = p.x;
|
||||
if (this.mins.y > p.y) this.mins.y = p.y;
|
||||
if (this.maxs.y < p.y) this.maxs.y = p.y;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public addBounds(b: Bounds): Bounds {
|
||||
|
||||
if (this.mins.x > b.mins.x) this.mins.x = b.mins.x;
|
||||
if (this.maxs.x < b.maxs.x) this.maxs.x = b.maxs.x;
|
||||
if (this.mins.y > b.mins.y) this.mins.y = b.mins.y;
|
||||
if (this.maxs.y < b.maxs.y) this.maxs.y = b.maxs.y;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public addBounds2(mins, maxs) {
|
||||
if (this.mins.x > mins.x) this.mins.x = mins.x;
|
||||
if (this.maxs.x < maxs.x) this.maxs.x = maxs.x;
|
||||
if (this.mins.y > mins.y) this.mins.y = mins.y;
|
||||
if (this.maxs.y < maxs.y) this.maxs.y = maxs.y;
|
||||
return this;
|
||||
}
|
||||
|
||||
public addExtents(center: Phaser.Vec2, extent_x: number, extent_y: number): Bounds {
|
||||
|
||||
if (this.mins.x > center.x - extent_x) this.mins.x = center.x - extent_x;
|
||||
if (this.maxs.x < center.x + extent_x) this.maxs.x = center.x + extent_x;
|
||||
if (this.mins.y > center.y - extent_y) this.mins.y = center.y - extent_y;
|
||||
if (this.maxs.y < center.y + extent_y) this.maxs.y = center.y + extent_y;
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
public expand(ax: number, ay: number): Bounds {
|
||||
|
||||
this.mins.x -= ax;
|
||||
this.mins.y -= ay;
|
||||
this.maxs.x += ax;
|
||||
this.maxs.y += ay;
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
public containPoint(p: Phaser.Vec2): bool {
|
||||
|
||||
if (p.x < this.mins.x || p.x > this.maxs.x || p.y < this.mins.y || p.y > this.maxs.y)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
public intersectsBounds(b: Bounds): bool {
|
||||
|
||||
if (this.mins.x > b.maxs.x || this.maxs.x < b.mins.x || this.mins.y > b.maxs.y || this.maxs.y < b.mins.y)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static expand(b: Bounds, ax, ay) {
|
||||
|
||||
var b = new Bounds(b.mins, b.maxs);
|
||||
b.expand(ax, ay);
|
||||
return b;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
558
Phaser/physics/advanced/Collision.ts
Normal file
558
Phaser/physics/advanced/Collision.ts
Normal file
|
@ -0,0 +1,558 @@
|
|||
/// <reference path="../../math/Vec2.ts" />
|
||||
/// <reference path="../../geom/Point.ts" />
|
||||
/// <reference path="../../math/Vec2Utils.ts" />
|
||||
/// <reference path="shapes/Shape.ts" />
|
||||
/// <reference path="shapes/Circle.ts" />
|
||||
/// <reference path="shapes/Poly.ts" />
|
||||
/// <reference path="shapes/Segment.ts" />
|
||||
/// <reference path="Manager.ts" />
|
||||
/// <reference path="Body.ts" />
|
||||
/// <reference path="Contact.ts" />
|
||||
|
||||
/**
|
||||
* Phaser - Advanced Physics - Collision Handlers
|
||||
*
|
||||
* Based on the work Ju Hyung Lee started in JS PhyRus.
|
||||
*/
|
||||
|
||||
module Phaser.Physics.Advanced {
|
||||
|
||||
export class Collision {
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
public collide(a, b, contacts: Contact[]) {
|
||||
|
||||
// Circle (a is the circle)
|
||||
if (a.type == Manager.SHAPE_TYPE_CIRCLE)
|
||||
{
|
||||
if (b.type == Manager.SHAPE_TYPE_CIRCLE)
|
||||
{
|
||||
return this.circle2Circle(a, b, contacts);
|
||||
}
|
||||
else if (b.type == Manager.SHAPE_TYPE_SEGMENT)
|
||||
{
|
||||
return this.circle2Segment(a, b, contacts);
|
||||
}
|
||||
else if (b.type == Manager.SHAPE_TYPE_POLY)
|
||||
{
|
||||
return this.circle2Poly(a, b, contacts);
|
||||
}
|
||||
}
|
||||
|
||||
// Segment (a is the segment)
|
||||
if (a.type == Manager.SHAPE_TYPE_SEGMENT)
|
||||
{
|
||||
if (b.type == Manager.SHAPE_TYPE_CIRCLE)
|
||||
{
|
||||
return this.circle2Segment(b, a, contacts);
|
||||
}
|
||||
else if (b.type == Manager.SHAPE_TYPE_SEGMENT)
|
||||
{
|
||||
return this.segment2Segment(a, b, contacts);
|
||||
}
|
||||
else if (b.type == Manager.SHAPE_TYPE_POLY)
|
||||
{
|
||||
return this.segment2Poly(a, b, contacts);
|
||||
}
|
||||
}
|
||||
|
||||
// Poly (a is the poly)
|
||||
if (a.type == Manager.SHAPE_TYPE_POLY)
|
||||
{
|
||||
if (b.type == Manager.SHAPE_TYPE_CIRCLE)
|
||||
{
|
||||
return this.circle2Poly(b, a, contacts);
|
||||
}
|
||||
else if (b.type == Manager.SHAPE_TYPE_SEGMENT)
|
||||
{
|
||||
return this.segment2Poly(b, a, contacts);
|
||||
}
|
||||
else if (b.type == Manager.SHAPE_TYPE_POLY)
|
||||
{
|
||||
return this.poly2Poly(a, b, contacts);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private _circle2Circle(c1, r1, c2, r2, contactArr) {
|
||||
|
||||
var rmax = r1 + r2;
|
||||
|
||||
var t: Phaser.Vec2 = new Phaser.Vec2;
|
||||
//var t = vec2.sub(c2, c1);
|
||||
Phaser.Vec2Utils.subtract(c2, c1, t);
|
||||
|
||||
var distsq = t.lengthSq();
|
||||
|
||||
if (distsq > rmax * rmax)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
var dist = Math.sqrt(distsq);
|
||||
|
||||
var p: Phaser.Vec2 = new Phaser.Vec2;
|
||||
Phaser.Vec2Utils.multiplyAdd(c1, t, 0.5 + (r1 - r2) * 0.5 / dist, p);
|
||||
//var p = vec2.mad(c1, t, 0.5 + (r1 - r2) * 0.5 / dist);
|
||||
|
||||
var n: Phaser.Vec2 = new Phaser.Vec2;
|
||||
//var n = (dist != 0) ? vec2.scale(t, 1 / dist) : vec2.zero;
|
||||
|
||||
if (dist != 0)
|
||||
{
|
||||
Phaser.Vec2Utils.scale(t, 1 / dist, n);
|
||||
}
|
||||
|
||||
var d = dist - rmax;
|
||||
|
||||
contactArr.push(new Contact(p, n, d, 0));
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
public circle2Circle(circ1: Phaser.Physics.Advanced.Shapes.Circle, circ2: Phaser.Physics.Advanced.Shapes.Circle, contactArr: Contact[]) {
|
||||
return this._circle2Circle(circ1.tc, circ1.radius, circ2.tc, circ2.radius, contactArr);
|
||||
}
|
||||
|
||||
public circle2Segment(circ: Phaser.Physics.Advanced.Shapes.Circle, seg: Phaser.Physics.Advanced.Shapes.Segment, contactArr: Contact[]) {
|
||||
|
||||
var rsum = circ.radius + seg.radius;
|
||||
|
||||
// Normal distance from segment
|
||||
var dn = Phaser.Vec2Utils.dot(circ.tc, seg.tn) - Phaser.Vec2Utils.dot(seg.ta, seg.tn);
|
||||
var dist = (dn < 0 ? dn * -1 : dn) - rsum;
|
||||
if (dist > 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Tangential distance along segment
|
||||
var dt = Phaser.Vec2Utils.cross(circ.tc, seg.tn);
|
||||
var dtMin = Phaser.Vec2Utils.cross(seg.ta, seg.tn);
|
||||
var dtMax = Phaser.Vec2Utils.cross(seg.tb, seg.tn);
|
||||
|
||||
if (dt < dtMin)
|
||||
{
|
||||
if (dt < dtMin - rsum)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return this._circle2Circle(circ.tc, circ.radius, seg.ta, seg.radius, contactArr);
|
||||
}
|
||||
else if (dt > dtMax)
|
||||
{
|
||||
if (dt > dtMax + rsum)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return this._circle2Circle(circ.tc, circ.radius, seg.tb, seg.radius, contactArr);
|
||||
}
|
||||
|
||||
var n: Phaser.Vec2 = new Phaser.Vec2;
|
||||
|
||||
if (dn > 0)
|
||||
{
|
||||
n.copyFrom(seg.tn);
|
||||
}
|
||||
else
|
||||
{
|
||||
Phaser.Vec2Utils.negative(seg.tn, n);
|
||||
}
|
||||
//var n = (dn > 0) ? seg.tn : vec2.neg(seg.tn);
|
||||
|
||||
var c1: Phaser.Vec2 = new Phaser.Vec2;
|
||||
Phaser.Vec2Utils.multiplyAdd(circ.tc, n, -(circ.radius + dist * 0.5), c1);
|
||||
|
||||
var c2: Phaser.Vec2 = new Phaser.Vec2;
|
||||
Phaser.Vec2Utils.negative(n, c2);
|
||||
|
||||
contactArr.push(new Contact(c1, c2, dist, 0));
|
||||
//contactArr.push(new Contact(vec2.mad(circ.tc, n, -(circ.r + dist * 0.5)), vec2.neg(n), dist, 0));
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
public circle2Poly(circ: Phaser.Physics.Advanced.Shapes.Circle, poly: Phaser.Physics.Advanced.Shapes.Poly, contactArr: Contact[]) {
|
||||
|
||||
var minDist = -999999;
|
||||
var minIdx = -1;
|
||||
|
||||
for (var i = 0; i < poly.verts.length; i++)
|
||||
{
|
||||
var plane = poly.tplanes[i];
|
||||
var dist = Phaser.Vec2Utils.dot(circ.tc, plane.n) - plane.d - circ.radius;
|
||||
|
||||
if (dist > 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (dist > minDist)
|
||||
{
|
||||
minDist = dist;
|
||||
minIdx = i;
|
||||
}
|
||||
}
|
||||
|
||||
var n = poly.tplanes[minIdx].n;
|
||||
var a = poly.tverts[minIdx];
|
||||
var b = poly.tverts[(minIdx + 1) % poly.verts.length];
|
||||
var dta = Phaser.Vec2Utils.cross(a, n);
|
||||
var dtb = Phaser.Vec2Utils.cross(b, n);
|
||||
var dt = Phaser.Vec2Utils.cross(circ.tc, n);
|
||||
|
||||
if (dt > dta)
|
||||
{
|
||||
return this._circle2Circle(circ.tc, circ.radius, a, 0, contactArr);
|
||||
}
|
||||
else if (dt < dtb)
|
||||
{
|
||||
return this._circle2Circle(circ.tc, circ.radius, b, 0, contactArr);
|
||||
}
|
||||
|
||||
var c1: Phaser.Vec2 = new Phaser.Vec2;
|
||||
Phaser.Vec2Utils.multiplyAdd(circ.tc, n, -(circ.radius + minDist * 0.5), c1);
|
||||
|
||||
var c2: Phaser.Vec2 = new Phaser.Vec2;
|
||||
Phaser.Vec2Utils.negative(n, c2);
|
||||
|
||||
contactArr.push(new Contact(c1, c2, minDist, 0));
|
||||
|
||||
//contactArr.push(new Contact(vec2.mad(circ.tc, n, -(circ.r + minDist * 0.5)), vec2.neg(n), minDist, 0));
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
public segmentPointDistanceSq(seg: Phaser.Physics.Advanced.Shapes.Segment, p) {
|
||||
|
||||
var w: Phaser.Vec2 = new Phaser.Vec2;
|
||||
var d: Phaser.Vec2 = new Phaser.Vec2;
|
||||
Phaser.Vec2Utils.subtract(p, seg.ta, w);
|
||||
Phaser.Vec2Utils.subtract(seg.tb, seg.ta, d);
|
||||
|
||||
//var w = vec2.sub(p, seg.ta);
|
||||
//var d = vec2.sub(seg.tb, seg.ta);
|
||||
|
||||
var proj = w.dot(d);
|
||||
|
||||
if (proj <= 0)
|
||||
{
|
||||
return w.dot(w);
|
||||
}
|
||||
|
||||
var vsq = d.dot(d);
|
||||
|
||||
if (proj >= vsq)
|
||||
{
|
||||
return w.dot(w) - 2 * proj + vsq;
|
||||
}
|
||||
|
||||
return w.dot(w) - proj * proj / vsq;
|
||||
|
||||
}
|
||||
|
||||
// FIXME and optimise me lots!!!
|
||||
public segment2Segment(seg1: Phaser.Physics.Advanced.Shapes.Segment, seg2: Phaser.Physics.Advanced.Shapes.Segment, contactArr: Contact[]) {
|
||||
|
||||
var d = [];
|
||||
d[0] = this.segmentPointDistanceSq(seg1, seg2.ta);
|
||||
d[1] = this.segmentPointDistanceSq(seg1, seg2.tb);
|
||||
d[2] = this.segmentPointDistanceSq(seg2, seg1.ta);
|
||||
d[3] = this.segmentPointDistanceSq(seg2, seg1.tb);
|
||||
|
||||
var idx1 = d[0] < d[1] ? 0 : 1;
|
||||
var idx2 = d[2] < d[3] ? 2 : 3;
|
||||
var idxm = d[idx1] < d[idx2] ? idx1 : idx2;
|
||||
var s, t;
|
||||
|
||||
var u = Phaser.Vec2Utils.subtract(seg1.tb, seg1.ta);
|
||||
var v = Phaser.Vec2Utils.subtract(seg2.tb, seg2.ta);
|
||||
|
||||
switch (idxm)
|
||||
{
|
||||
case 0:
|
||||
s = Phaser.Vec2Utils.dot(Phaser.Vec2Utils.subtract(seg2.ta, seg1.ta), u) / Phaser.Vec2Utils.dot(u, u);
|
||||
s = s < 0 ? 0 : (s > 1 ? 1 : s);
|
||||
t = 0;
|
||||
break;
|
||||
case 1:
|
||||
s = Phaser.Vec2Utils.dot(Phaser.Vec2Utils.subtract(seg2.tb, seg1.ta), u) / Phaser.Vec2Utils.dot(u, u);
|
||||
s = s < 0 ? 0 : (s > 1 ? 1 : s);
|
||||
t = 1;
|
||||
break;
|
||||
case 2:
|
||||
s = 0;
|
||||
t = Phaser.Vec2Utils.dot(Phaser.Vec2Utils.subtract(seg1.ta, seg2.ta), v) / Phaser.Vec2Utils.dot(v, v);
|
||||
t = t < 0 ? 0 : (t > 1 ? 1 : t);
|
||||
break;
|
||||
case 3:
|
||||
s = 1;
|
||||
t = Phaser.Vec2Utils.dot(Phaser.Vec2Utils.subtract(seg1.tb, seg2.ta), v) / Phaser.Vec2Utils.dot(v, v);
|
||||
t = t < 0 ? 0 : (t > 1 ? 1 : t);
|
||||
break;
|
||||
}
|
||||
|
||||
var minp1 = Phaser.Vec2Utils.multiplyAdd(seg1.ta, u, s);
|
||||
var minp2 = Phaser.Vec2Utils.multiplyAdd(seg2.ta, v, t);
|
||||
|
||||
return this._circle2Circle(minp1, seg1.radius, minp2, seg2.radius, contactArr);
|
||||
|
||||
}
|
||||
|
||||
// Identify vertexes that have penetrated the segment.
|
||||
public findPointsBehindSeg(contactArr: Contact[], seg: Phaser.Physics.Advanced.Shapes.Segment, poly: Phaser.Physics.Advanced.Shapes.Poly, dist: number, coef: number) {
|
||||
|
||||
var dta = Phaser.Vec2Utils.cross(seg.tn, seg.ta);
|
||||
var dtb = Phaser.Vec2Utils.cross(seg.tn, seg.tb);
|
||||
|
||||
var n: Phaser.Vec2 = new Phaser.Vec2;
|
||||
Phaser.Vec2Utils.scale(seg.tn, coef, n);
|
||||
//var n = vec2.scale(seg.tn, coef);
|
||||
|
||||
for (var i = 0; i < poly.verts.length; i++)
|
||||
{
|
||||
var v = poly.tverts[i];
|
||||
|
||||
if (Phaser.Vec2Utils.dot(v, n) < Phaser.Vec2Utils.dot(seg.tn, seg.ta) * coef + seg.radius)
|
||||
{
|
||||
var dt = Phaser.Vec2Utils.cross(seg.tn, v);
|
||||
|
||||
if (dta >= dt && dt >= dtb)
|
||||
{
|
||||
contactArr.push(new Contact(v, n, dist, (poly.id << 16) | i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public segment2Poly(seg: Phaser.Physics.Advanced.Shapes.Segment, poly: Phaser.Physics.Advanced.Shapes.Poly, contactArr: Contact[]) {
|
||||
|
||||
var seg_td = Phaser.Vec2Utils.dot(seg.tn, seg.ta);
|
||||
var seg_d1 = poly.distanceOnPlane(seg.tn, seg_td) - seg.radius;
|
||||
|
||||
if (seg_d1 > 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
var n: Phaser.Vec2 = new Phaser.Vec2;
|
||||
Phaser.Vec2Utils.negative(seg.tn, n);
|
||||
var seg_d2 = poly.distanceOnPlane(n, -seg_td) - seg.radius;
|
||||
//var seg_d2 = poly.distanceOnPlane(vec2.neg(seg.tn), -seg_td) - seg.r;
|
||||
|
||||
if (seg_d2 > 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
var poly_d = -999999;
|
||||
var poly_i = -1;
|
||||
|
||||
for (var i = 0; i < poly.verts.length; i++)
|
||||
{
|
||||
var plane = poly.tplanes[i];
|
||||
var dist = seg.distanceOnPlane(plane.n, plane.d);
|
||||
|
||||
if (dist > 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dist > poly_d)
|
||||
{
|
||||
poly_d = dist;
|
||||
poly_i = i;
|
||||
}
|
||||
}
|
||||
|
||||
var poly_n: Phaser.Vec2 = new Phaser.Vec2;
|
||||
Phaser.Vec2Utils.negative(poly.tplanes[poly_i].n, poly_n);
|
||||
//var poly_n = vec2.neg(poly.tplanes[poly_i].n);
|
||||
|
||||
var va: Phaser.Vec2 = new Phaser.Vec2;
|
||||
Phaser.Vec2Utils.multiplyAdd(seg.ta, poly_n, seg.radius, va);
|
||||
//var va = vec2.mad(seg.ta, poly_n, seg.r);
|
||||
|
||||
var vb: Phaser.Vec2 = new Phaser.Vec2;
|
||||
Phaser.Vec2Utils.multiplyAdd(seg.tb, poly_n, seg.radius, vb);
|
||||
//var vb = vec2.mad(seg.tb, poly_n, seg.r);
|
||||
|
||||
if (poly.containPoint(va))
|
||||
{
|
||||
contactArr.push(new Contact(va, poly_n, poly_d, (seg.id << 16) | 0));
|
||||
}
|
||||
|
||||
if (poly.containPoint(vb))
|
||||
{
|
||||
contactArr.push(new Contact(vb, poly_n, poly_d, (seg.id << 16) | 1));
|
||||
}
|
||||
|
||||
// Floating point precision problems here.
|
||||
// This will have to do for now.
|
||||
poly_d -= 0.1
|
||||
if (seg_d1 >= poly_d || seg_d2 >= poly_d)
|
||||
{
|
||||
if (seg_d1 > seg_d2)
|
||||
{
|
||||
this.findPointsBehindSeg(contactArr, seg, poly, seg_d1, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.findPointsBehindSeg(contactArr, seg, poly, seg_d2, -1);
|
||||
}
|
||||
}
|
||||
|
||||
// If no other collision points are found, try colliding endpoints.
|
||||
if (contactArr.length == 0)
|
||||
{
|
||||
var poly_a = poly.tverts[poly_i];
|
||||
var poly_b = poly.tverts[(poly_i + 1) % poly.verts.length];
|
||||
|
||||
if (this._circle2Circle(seg.ta, seg.radius, poly_a, 0, contactArr))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (this._circle2Circle(seg.tb, seg.radius, poly_a, 0, contactArr))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (this._circle2Circle(seg.ta, seg.radius, poly_b, 0, contactArr))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (this._circle2Circle(seg.tb, seg.radius, poly_b, 0, contactArr))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return contactArr.length;
|
||||
|
||||
}
|
||||
|
||||
// Find the minimum separating axis for the given poly and plane list.
|
||||
public findMSA(poly: Phaser.Physics.Advanced.Shapes.Poly, planes, num: number) {
|
||||
|
||||
var min_dist = -999999;
|
||||
var min_index = -1;
|
||||
|
||||
for (var i = 0; i < num; i++)
|
||||
{
|
||||
var dist = poly.distanceOnPlane(planes[i].n, planes[i].d);
|
||||
|
||||
if (dist > 0)
|
||||
{
|
||||
// no collision
|
||||
return { dist: 0, index: -1 };
|
||||
}
|
||||
else if (dist > min_dist)
|
||||
{
|
||||
min_dist = dist;
|
||||
min_index = i;
|
||||
}
|
||||
}
|
||||
|
||||
// new object - see what we can do here
|
||||
return { dist: min_dist, index: min_index };
|
||||
|
||||
}
|
||||
|
||||
public findVertsFallback(contactArr: Contact[], poly1: Phaser.Physics.Advanced.Shapes.Poly, poly2: Phaser.Physics.Advanced.Shapes.Poly, n, dist: number) {
|
||||
|
||||
var num = 0;
|
||||
|
||||
for (var i = 0; i < poly1.verts.length; i++)
|
||||
{
|
||||
var v = poly1.tverts[i];
|
||||
|
||||
if (poly2.containPointPartial(v, n))
|
||||
{
|
||||
contactArr.push(new Contact(v, n, dist, (poly1.id << 16) | i));
|
||||
num++;
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < poly2.verts.length; i++)
|
||||
{
|
||||
var v = poly2.tverts[i];
|
||||
|
||||
if (poly1.containPointPartial(v, n))
|
||||
{
|
||||
contactArr.push(new Contact(v, n, dist, (poly2.id << 16) | i));
|
||||
num++;
|
||||
}
|
||||
}
|
||||
|
||||
return num;
|
||||
|
||||
}
|
||||
|
||||
// Find the overlapped vertices.
|
||||
public findVerts(contactArr: Contact[], poly1: Phaser.Physics.Advanced.Shapes.Poly, poly2: Phaser.Physics.Advanced.Shapes.Poly, n, dist: number) {
|
||||
|
||||
var num = 0;
|
||||
|
||||
for (var i = 0; i < poly1.verts.length; i++)
|
||||
{
|
||||
var v = poly1.tverts[i];
|
||||
|
||||
if (poly2.containPoint(v))
|
||||
{
|
||||
contactArr.push(new Contact(v, n, dist, (poly1.id << 16) | i));
|
||||
num++;
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < poly2.verts.length; i++)
|
||||
{
|
||||
var v = poly2.tverts[i];
|
||||
|
||||
if (poly1.containPoint(v))
|
||||
{
|
||||
contactArr.push(new Contact(v, n, dist, (poly2.id << 16) | i));
|
||||
num++;
|
||||
}
|
||||
}
|
||||
|
||||
return num > 0 ? num : this.findVertsFallback(contactArr, poly1, poly2, n, dist);
|
||||
|
||||
}
|
||||
|
||||
public poly2Poly(poly1: Phaser.Physics.Advanced.Shapes.Poly, poly2: Phaser.Physics.Advanced.Shapes.Poly, contactArr: Contact[]) {
|
||||
|
||||
var msa1 = this.findMSA(poly2, poly1.tplanes, poly1.verts.length);
|
||||
|
||||
if (msa1.index == -1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
var msa2 = this.findMSA(poly1, poly2.tplanes, poly2.verts.length);
|
||||
if (msa2.index == -1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Penetration normal direction shoud be from poly1 to poly2
|
||||
if (msa1.dist > msa2.dist)
|
||||
{
|
||||
return this.findVerts(contactArr, poly1, poly2, poly1.tplanes[msa1.index].n, msa1.dist);
|
||||
}
|
||||
|
||||
return this.findVerts(contactArr, poly1, poly2, Phaser.Vec2Utils.negative(poly2.tplanes[msa2.index].n), msa2.dist);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
62
Phaser/physics/advanced/Contact.ts
Normal file
62
Phaser/physics/advanced/Contact.ts
Normal file
|
@ -0,0 +1,62 @@
|
|||
/// <reference path="../../math/Vec2.ts" />
|
||||
/// <reference path="../../math/Vec2Utils.ts" />
|
||||
/// <reference path="Manager.ts" />
|
||||
/// <reference path="Body.ts" />
|
||||
/// <reference path="shapes/Shape.ts" />
|
||||
|
||||
/**
|
||||
* Phaser - Advanced Physics - Contact
|
||||
*
|
||||
* Based on the work Ju Hyung Lee started in JS PhyRus.
|
||||
*/
|
||||
|
||||
module Phaser.Physics.Advanced {
|
||||
|
||||
export class Contact {
|
||||
|
||||
constructor(p, n, d, hash) {
|
||||
|
||||
this.hash = hash;
|
||||
this.point = p;
|
||||
this.normal = n;
|
||||
this.depth = d;
|
||||
this.lambdaNormal = 0;
|
||||
this.lambdaTangential = 0;
|
||||
|
||||
this.r1 = new Phaser.Vec2;
|
||||
this.r2 = new Phaser.Vec2;
|
||||
this.r1_local = new Phaser.Vec2;
|
||||
this.r2_local = new Phaser.Vec2;
|
||||
|
||||
}
|
||||
|
||||
public hash;
|
||||
|
||||
// Linear velocities at contact point
|
||||
public r1: Phaser.Vec2;
|
||||
public r2: Phaser.Vec2;
|
||||
public r1_local: Phaser.Vec2;
|
||||
public r2_local: Phaser.Vec2;
|
||||
// Bounce velocity
|
||||
public bounce: number;
|
||||
public emn: number;
|
||||
public emt: number;
|
||||
|
||||
// Contact point
|
||||
public point;
|
||||
|
||||
// Contact normal (toward shape2)
|
||||
public normal: Phaser.Vec2;
|
||||
|
||||
// Penetration depth (d < 0)
|
||||
public depth;
|
||||
|
||||
// Accumulated normal constraint impulse
|
||||
public lambdaNormal;
|
||||
|
||||
// Accumulated tangential constraint impulse
|
||||
public lambdaTangential;
|
||||
|
||||
}
|
||||
|
||||
}
|
359
Phaser/physics/advanced/ContactSolver.ts
Normal file
359
Phaser/physics/advanced/ContactSolver.ts
Normal file
|
@ -0,0 +1,359 @@
|
|||
/// <reference path="../../math/Vec2.ts" />
|
||||
/// <reference path="../../geom/Point.ts" />
|
||||
/// <reference path="../../math/Vec2Utils.ts" />
|
||||
/// <reference path="Manager.ts" />
|
||||
/// <reference path="Body.ts" />
|
||||
/// <reference path="shapes/Shape.ts" />
|
||||
/// <reference path="Contact.ts" />
|
||||
|
||||
/**
|
||||
* Phaser - Advanced Physics - ContactSolver
|
||||
*
|
||||
* Based on the work Ju Hyung Lee started in JS PhyRus.
|
||||
*/
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
// Contact Constraint
|
||||
//
|
||||
// Non-penetration constraint:
|
||||
// C = dot(p2 - p1, n)
|
||||
// Cdot = dot(v2 - v1, n)
|
||||
// J = [ -n, -cross(r1, n), n, cross(r2, n) ]
|
||||
//
|
||||
// impulse = JT * lambda = [ -n * lambda, -cross(r1, n) * lambda, n * lambda, cross(r1, n) * lambda ]
|
||||
//
|
||||
// Friction constraint:
|
||||
// C = dot(p2 - p1, t)
|
||||
// Cdot = dot(v2 - v1, t)
|
||||
// J = [ -t, -cross(r1, t), t, cross(r2, t) ]
|
||||
//
|
||||
// impulse = JT * lambda = [ -t * lambda, -cross(r1, t) * lambda, t * lambda, cross(r1, t) * lambda ]
|
||||
//
|
||||
// NOTE: lambda is an impulse in constraint space.
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
|
||||
module Phaser.Physics.Advanced {
|
||||
|
||||
export class ContactSolver {
|
||||
|
||||
constructor(shape1, shape2) {
|
||||
|
||||
//console.log('ContactSolver super');
|
||||
|
||||
this.shape1 = shape1;
|
||||
this.shape2 = shape2;
|
||||
|
||||
this.contacts = [];
|
||||
this.elasticity = 1;
|
||||
this.friction = 1;
|
||||
|
||||
}
|
||||
|
||||
public shape1;
|
||||
public shape2;
|
||||
|
||||
// Contact list
|
||||
public contacts: Contact[];
|
||||
|
||||
// Coefficient of restitution (elasticity)
|
||||
public elasticity: number;
|
||||
|
||||
// Frictional coefficient
|
||||
public friction: number;
|
||||
|
||||
public update(newContactArr: Contact[]) {
|
||||
|
||||
for (var i = 0; i < newContactArr.length; i++)
|
||||
{
|
||||
var newContact = newContactArr[i];
|
||||
var k = -1;
|
||||
|
||||
for (var j = 0; j < this.contacts.length; j++)
|
||||
{
|
||||
if (newContact.hash == this.contacts[j].hash)
|
||||
{
|
||||
k = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (k > -1)
|
||||
{
|
||||
newContact.lambdaNormal = this.contacts[k].lambdaNormal;
|
||||
newContact.lambdaTangential = this.contacts[k].lambdaTangential;
|
||||
}
|
||||
}
|
||||
|
||||
this.contacts = newContactArr;
|
||||
|
||||
}
|
||||
|
||||
public initSolver(dt_inv) {
|
||||
|
||||
var body1: Body = this.shape1.body;
|
||||
var body2: Body = this.shape2.body;
|
||||
|
||||
var sum_m_inv = body1.massInverted + body2.massInverted;
|
||||
|
||||
for (var i = 0; i < this.contacts.length; i++)
|
||||
{
|
||||
var con: Contact = this.contacts[i];
|
||||
|
||||
//console.log('initSolver con');
|
||||
//console.log(con);
|
||||
|
||||
// Transformed r1, r2
|
||||
Phaser.Vec2Utils.subtract(con.point, body1.position, con.r1);
|
||||
Phaser.Vec2Utils.subtract(con.point, body2.position, con.r2);
|
||||
//con.r1 = vec2.sub(con.point, body1.p);
|
||||
//con.r2 = vec2.sub(con.point, body2.p);
|
||||
|
||||
// Local r1, r2
|
||||
Phaser.TransformUtils.unrotate(body1.transform, con.r1, con.r1_local);
|
||||
Phaser.TransformUtils.unrotate(body2.transform, con.r2, con.r2_local);
|
||||
//con.r1_local = body1.transform.unrotate(con.r1);
|
||||
//con.r2_local = body2.transform.unrotate(con.r2);
|
||||
|
||||
var n = con.normal;
|
||||
var t = Phaser.Vec2Utils.perp(con.normal);
|
||||
|
||||
// invEMn = J * invM * JT
|
||||
// J = [ -n, -cross(r1, n), n, cross(r2, n) ]
|
||||
var sn1 = Phaser.Vec2Utils.cross(con.r1, n);
|
||||
var sn2 = Phaser.Vec2Utils.cross(con.r2, n);
|
||||
var emn_inv = sum_m_inv + body1.inertiaInverted * sn1 * sn1 + body2.inertiaInverted * sn2 * sn2;
|
||||
con.emn = emn_inv == 0 ? 0 : 1 / emn_inv;
|
||||
|
||||
// invEMt = J * invM * JT
|
||||
// J = [ -t, -cross(r1, t), t, cross(r2, t) ]
|
||||
var st1 = Phaser.Vec2Utils.cross(con.r1, t);
|
||||
var st2 = Phaser.Vec2Utils.cross(con.r2, t);
|
||||
var emt_inv = sum_m_inv + body1.inertiaInverted * st1 * st1 + body2.inertiaInverted * st2 * st2;
|
||||
con.emt = emt_inv == 0 ? 0 : 1 / emt_inv;
|
||||
|
||||
// Linear velocities at contact point
|
||||
// in 2D: cross(w, r) = perp(r) * w
|
||||
|
||||
var v1 = new Phaser.Vec2;
|
||||
var v2 = new Phaser.Vec2;
|
||||
|
||||
Phaser.Vec2Utils.multiplyAdd(body1.velocity, Phaser.Vec2Utils.perp(con.r1), body1.angularVelocity, v1);
|
||||
Phaser.Vec2Utils.multiplyAdd(body2.velocity, Phaser.Vec2Utils.perp(con.r2), body2.angularVelocity, v2);
|
||||
//var v1 = vec2.mad(body1.v, vec2.perp(con.r1), body1.w);
|
||||
//var v2 = vec2.mad(body2.v, vec2.perp(con.r2), body2.w);
|
||||
|
||||
// relative velocity at contact point
|
||||
var rv = new Phaser.Vec2;
|
||||
Phaser.Vec2Utils.subtract(v2, v1, rv);
|
||||
//var rv = vec2.sub(v2, v1);
|
||||
|
||||
// bounce velocity dot n
|
||||
con.bounce = Phaser.Vec2Utils.dot(rv, con.normal) * this.elasticity;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public warmStart() {
|
||||
|
||||
var body1: Body = this.shape1.body;
|
||||
var body2: Body = this.shape2.body;
|
||||
|
||||
for (var i = 0; i < this.contacts.length; i++)
|
||||
{
|
||||
var con = this.contacts[i];
|
||||
var n = con.normal;
|
||||
var lambda_n = con.lambdaNormal;
|
||||
var lambda_t = con.lambdaTangential;
|
||||
|
||||
// Apply accumulated impulses
|
||||
//var impulse = vec2.rotate_vec(new vec2(lambda_n, lambda_t), n);
|
||||
//var impulse = new vec2(lambda_n * n.x - lambda_t * n.y, lambda_t * n.x + lambda_n * n.y);
|
||||
var impulse = new Phaser.Vec2(lambda_n * n.x - lambda_t * n.y, lambda_t * n.x + lambda_n * n.y);
|
||||
|
||||
body1.velocity.multiplyAddByScalar(impulse, -body1.massInverted);
|
||||
//body1.v.mad(impulse, -body1.m_inv);
|
||||
|
||||
body1.angularVelocity -= Phaser.Vec2Utils.cross(con.r1, impulse) * body1.inertiaInverted;
|
||||
//body1.w -= vec2.cross(con.r1, impulse) * body1.i_inv;
|
||||
|
||||
body2.velocity.multiplyAddByScalar(impulse, -body2.massInverted);
|
||||
//body2.v.mad(impulse, body2.m_inv);
|
||||
|
||||
body2.angularVelocity -= Phaser.Vec2Utils.cross(con.r2, impulse) * body2.inertiaInverted;
|
||||
//body2.w += vec2.cross(con.r2, impulse) * body2.i_inv;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public solveVelocityConstraints() {
|
||||
|
||||
var body1: Body = this.shape1.body;
|
||||
var body2: Body = this.shape2.body;
|
||||
|
||||
var m1_inv = body1.massInverted;
|
||||
var i1_inv = body1.inertiaInverted;
|
||||
var m2_inv = body2.massInverted;
|
||||
var i2_inv = body2.inertiaInverted;
|
||||
|
||||
for (var i = 0; i < this.contacts.length; i++)
|
||||
{
|
||||
var con = this.contacts[i];
|
||||
var n = con.normal;
|
||||
var t = Phaser.Vec2Utils.perp(n);
|
||||
var r1 = con.r1;
|
||||
var r2 = con.r2;
|
||||
|
||||
// Linear velocities at contact point
|
||||
// in 2D: cross(w, r) = perp(r) * w
|
||||
|
||||
var v1 = new Phaser.Vec2;
|
||||
var v2 = new Phaser.Vec2;
|
||||
|
||||
Phaser.Vec2Utils.multiplyAdd(body1.velocity, Phaser.Vec2Utils.perp(r1), body1.angularVelocity, v1);
|
||||
//var v1 = vec2.mad(body1.v, vec2.perp(r1), body1.w);
|
||||
|
||||
Phaser.Vec2Utils.multiplyAdd(body2.velocity, Phaser.Vec2Utils.perp(r2), body2.angularVelocity, v2);
|
||||
//var v2 = vec2.mad(body2.v, vec2.perp(r2), body2.w);
|
||||
|
||||
// Relative velocity at contact point
|
||||
var rv = new Phaser.Vec2;
|
||||
Phaser.Vec2Utils.subtract(v2, v1, rv);
|
||||
//var rv = vec2.sub(v2, v1);
|
||||
|
||||
// Compute normal constraint impulse + adding bounce as a velocity bias
|
||||
// lambda_n = -EMn * J * V
|
||||
var lambda_n = -con.emn * (Phaser.Vec2Utils.dot(n, rv) + con.bounce);
|
||||
|
||||
// Accumulate and clamp
|
||||
var lambda_n_old = con.lambdaNormal;
|
||||
con.lambdaNormal = Math.max(lambda_n_old + lambda_n, 0);
|
||||
lambda_n = con.lambdaNormal - lambda_n_old;
|
||||
|
||||
// Compute frictional constraint impulse
|
||||
// lambda_t = -EMt * J * V
|
||||
var lambda_t = -con.emt * Phaser.Vec2Utils.dot(t, rv);
|
||||
|
||||
// Max friction constraint impulse (Coulomb's Law)
|
||||
var lambda_t_max = con.lambdaNormal * this.friction;
|
||||
|
||||
// Accumulate and clamp
|
||||
var lambda_t_old = con.lambdaTangential;
|
||||
con.lambdaTangential = this.clamp(lambda_t_old + lambda_t, -lambda_t_max, lambda_t_max);
|
||||
lambda_t = con.lambdaTangential - lambda_t_old;
|
||||
|
||||
// Apply the final impulses
|
||||
//var impulse = vec2.rotate_vec(new vec2(lambda_n, lambda_t), n);
|
||||
var impulse = new Phaser.Vec2(lambda_n * n.x - lambda_t * n.y, lambda_t * n.x + lambda_n * n.y);
|
||||
|
||||
|
||||
body1.velocity.multiplyAddByScalar(impulse, -m1_inv);
|
||||
//body1.v.mad(impulse, -m1_inv);
|
||||
|
||||
body1.angularVelocity -= Phaser.Vec2Utils.cross(r1, impulse) * i1_inv;
|
||||
//body1.w -= vec2.cross(r1, impulse) * i1_inv;
|
||||
|
||||
body2.velocity.multiplyAddByScalar(impulse, m2_inv);
|
||||
//body2.v.mad(impulse, m2_inv);
|
||||
|
||||
body1.angularVelocity += Phaser.Vec2Utils.cross(r2, impulse) * i2_inv;
|
||||
//body2.w += vec2.cross(r2, impulse) * i2_inv;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public solvePositionConstraints() {
|
||||
|
||||
var body1: Body = this.shape1.body;
|
||||
var body2: Body = this.shape2.body;
|
||||
|
||||
var m1_inv = body1.massInverted;
|
||||
var i1_inv = body1.inertiaInverted;
|
||||
var m2_inv = body2.massInverted;
|
||||
var i2_inv = body2.inertiaInverted;
|
||||
var sum_m_inv = m1_inv + m2_inv;
|
||||
|
||||
var max_penetration = 0;
|
||||
|
||||
for (var i = 0; i < this.contacts.length; i++)
|
||||
{
|
||||
var con = this.contacts[i];
|
||||
var n = con.normal;
|
||||
|
||||
var r1 = new Phaser.Vec2;
|
||||
var r2 = new Phaser.Vec2;
|
||||
|
||||
// Transformed r1, r2
|
||||
|
||||
Phaser.Vec2Utils.rotate(con.r1_local, body1.angle, r1);
|
||||
//var r1 = vec2.rotate(con.r1_local, body1.a);
|
||||
|
||||
|
||||
Phaser.Vec2Utils.rotate(con.r2_local, body2.angle, r2);
|
||||
//var r2 = vec2.rotate(con.r2_local, body2.a);
|
||||
|
||||
// Contact points (corrected)
|
||||
var p1 = new Phaser.Vec2;
|
||||
var p2 = new Phaser.Vec2;
|
||||
|
||||
Phaser.Vec2Utils.add(body1.position, r1, p1);
|
||||
//var p1 = vec2.add(body1.p, r1);
|
||||
|
||||
Phaser.Vec2Utils.add(body2.position, r2, p2);
|
||||
//var p2 = vec2.add(body2.p, r2);
|
||||
|
||||
// Corrected delta vector
|
||||
var dp = new Phaser.Vec2;
|
||||
Phaser.Vec2Utils.subtract(p2, p1);
|
||||
//var dp = vec2.sub(p2, p1);
|
||||
|
||||
// Position constraint
|
||||
var c = Phaser.Vec2Utils.dot(dp, n) + con.depth;
|
||||
|
||||
var correction = this.clamp(Manager.CONTACT_SOLVER_BAUMGARTE * (c + Manager.CONTACT_SOLVER_COLLISION_SLOP), -Manager.CONTACT_SOLVER_MAX_LINEAR_CORRECTION, 0);
|
||||
|
||||
if (correction == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// We don't need max_penetration less than or equal slop
|
||||
max_penetration = Math.max(max_penetration, -c);
|
||||
|
||||
// Compute lambda for position constraint
|
||||
// Solve (J * invM * JT) * lambda = -C / dt
|
||||
var sn1 = Phaser.Vec2Utils.cross(r1, n);
|
||||
var sn2 = Phaser.Vec2Utils.cross(r2, n);
|
||||
|
||||
var em_inv = sum_m_inv + body1.inertiaInverted * sn1 * sn1 + body2.inertiaInverted * sn2 * sn2;
|
||||
|
||||
var lambda_dt = em_inv == 0 ? 0 : -correction / em_inv;
|
||||
|
||||
// Apply correction impulses
|
||||
var impulse_dt = new Phaser.Vec2;
|
||||
Phaser.Vec2Utils.scale(n, lambda_dt, impulse_dt);
|
||||
//var impulse_dt = vec2.scale(n, lambda_dt);
|
||||
|
||||
body1.position.multiplyAddByScalar(impulse_dt, -m1_inv);
|
||||
//body1.p.mad(impulse_dt, -m1_inv);
|
||||
|
||||
body1.angle -= sn1 * lambda_dt * i1_inv;
|
||||
|
||||
body2.position.multiplyAddByScalar(impulse_dt, m2_inv);
|
||||
//body2.p.mad(impulse_dt, m2_inv);
|
||||
|
||||
body2.angle += sn2 * lambda_dt * i2_inv;
|
||||
}
|
||||
|
||||
return max_penetration <= Manager.CONTACT_SOLVER_COLLISION_SLOP * 3;
|
||||
|
||||
}
|
||||
|
||||
public clamp(v, min, max) {
|
||||
return v < min ? min : (v > max ? max : v);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
328
Phaser/physics/advanced/Manager.ts
Normal file
328
Phaser/physics/advanced/Manager.ts
Normal file
|
@ -0,0 +1,328 @@
|
|||
/// <reference path="../../Game.ts" />
|
||||
/// <reference path="Body.ts" />
|
||||
/// <reference path="joints/Joint.ts" />
|
||||
|
||||
/**
|
||||
* Phaser - Advanced Physics Manager
|
||||
*
|
||||
* Your game only has one PhysicsManager instance and it's responsible for looking after, creating and colliding
|
||||
* all of the physics objects in the world.
|
||||
*/
|
||||
|
||||
module Phaser.Physics.Advanced {
|
||||
|
||||
export class Manager {
|
||||
|
||||
constructor(game: Game) {
|
||||
|
||||
this.game = game;
|
||||
|
||||
this.space = new Space();
|
||||
|
||||
Manager.collision = new Collision();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Local reference to Game.
|
||||
*/
|
||||
public game: Game;
|
||||
|
||||
public static collision: Collision;
|
||||
|
||||
public static SHAPE_TYPE_CIRCLE: number = 0;
|
||||
public static SHAPE_TYPE_SEGMENT: number = 1;
|
||||
public static SHAPE_TYPE_POLY: number = 2;
|
||||
public static SHAPE_NUM_TYPES: number = 3;
|
||||
|
||||
public static JOINT_TYPE_ANGLE: number = 0;
|
||||
public static JOINT_TYPE_REVOLUTE: number = 1;
|
||||
public static JOINT_TYPE_WELD: number = 2;
|
||||
public static JOINT_TYPE_WHEEL: number = 3;
|
||||
public static JOINT_TYPE_PRISMATIC: number = 4;
|
||||
public static JOINT_TYPE_DISTANCE: number = 5;
|
||||
public static JOINT_TYPE_ROPE: number = 6;
|
||||
public static JOINT_TYPE_MOUSE: number = 7;
|
||||
|
||||
public static JOINT_LINEAR_SLOP: number = 0.0008;
|
||||
public static JOINT_ANGULAR_SLOP: number = 2 * Phaser.GameMath.DEG_TO_RAD;
|
||||
public static JOINT_MAX_LINEAR_CORRECTION: number = 0.5;
|
||||
public static JOINT_MAX_ANGULAR_CORRECTION: number = 8 * Phaser.GameMath.DEG_TO_RAD;
|
||||
|
||||
public static JOINT_LIMIT_STATE_INACTIVE: number = 0;
|
||||
public static JOINT_LIMIT_STATE_AT_LOWER: number = 1;
|
||||
public static JOINT_LIMIT_STATE_AT_UPPER: number = 2;
|
||||
public static JOINT_LIMIT_STATE_EQUAL_LIMITS: number = 3;
|
||||
|
||||
public static CONTACT_SOLVER_COLLISION_SLOP: number = 0.0008;
|
||||
public static CONTACT_SOLVER_BAUMGARTE: number = 0.28;
|
||||
public static CONTACT_SOLVER_MAX_LINEAR_CORRECTION: number = 1;//Infinity;
|
||||
|
||||
public static bodyCounter: number = 0;
|
||||
public static jointCounter: number = 0;
|
||||
public static shapeCounter: number = 0;
|
||||
|
||||
public space: Space;
|
||||
public lastTime: number = Date.now();
|
||||
public frameRateHz: number = 60;
|
||||
public timeDelta: number = 0;
|
||||
public paused: bool = false;
|
||||
public step: bool = false; // step through the simulation (i.e. per click)
|
||||
public velocityIterations: number = 8;
|
||||
public positionIterations: number = 4;
|
||||
public allowSleep: bool = true;
|
||||
public warmStarting: bool = true;
|
||||
|
||||
public update() {
|
||||
|
||||
var time = Date.now();
|
||||
var frameTime = (time - this.lastTime) / 1000;
|
||||
this.lastTime = time;
|
||||
|
||||
// if rAf - why?
|
||||
frameTime = Math.floor(frameTime * 60 + 0.5) / 60;
|
||||
|
||||
//if (!mouseDown)
|
||||
//{
|
||||
// var p = canvasToWorld(mousePosition);
|
||||
// var body = space.findBodyByPoint(p);
|
||||
// //domCanvas.style.cursor = body ? "pointer" : "default";
|
||||
//}
|
||||
|
||||
if (!this.paused || this.step)
|
||||
{
|
||||
var h = 1 / this.frameRateHz;
|
||||
|
||||
this.timeDelta += frameTime;
|
||||
|
||||
if (this.step)
|
||||
{
|
||||
this.step = false;
|
||||
this.timeDelta = h;
|
||||
}
|
||||
|
||||
for (var maxSteps = 4; maxSteps > 0 && this.timeDelta >= h; maxSteps--)
|
||||
{
|
||||
this.space.step(h, this.velocityIterations, this.positionIterations, this.warmStarting, this.allowSleep);
|
||||
this.timeDelta -= h;
|
||||
}
|
||||
|
||||
if (this.timeDelta > h)
|
||||
{
|
||||
this.timeDelta = 0;
|
||||
}
|
||||
|
||||
//if (sceneIndex < demoArr.length)
|
||||
//{
|
||||
// demo = demoArr[sceneIndex];
|
||||
// demo.runFrame();
|
||||
//}
|
||||
}
|
||||
|
||||
//frameCount++;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public pixelsToMeters(value: number): number {
|
||||
return value * 0.02;
|
||||
}
|
||||
|
||||
public metersToPixels(value: number): number {
|
||||
return value * 50;
|
||||
}
|
||||
|
||||
public static pixelsToMeters(value: number): number {
|
||||
return value * 0.02;
|
||||
}
|
||||
|
||||
public static metersToPixels(value: number): number {
|
||||
return value * 50;
|
||||
}
|
||||
|
||||
public static p2m(value: number): number {
|
||||
return value * 0.02;
|
||||
}
|
||||
|
||||
public static m2p(value: number): number {
|
||||
return value * 50;
|
||||
}
|
||||
|
||||
public static areaForCircle(radius_outer, radius_inner): number {
|
||||
return Math.PI * (radius_outer * radius_outer - radius_inner * radius_inner);
|
||||
}
|
||||
|
||||
public static inertiaForCircle(mass, center, radius_outer, radius_inner): number {
|
||||
return mass * ((radius_outer * radius_outer + radius_inner * radius_inner) * 0.5 + center.lengthSq());
|
||||
}
|
||||
|
||||
public static areaForSegment(a, b, radius): number {
|
||||
return radius * (Math.PI * radius + 2 * Phaser.Vec2Utils.distance(a, b));
|
||||
}
|
||||
|
||||
public static centroidForSegment(a, b): Phaser.Vec2 {
|
||||
return Phaser.Vec2Utils.scale(Phaser.Vec2Utils.add(a, b), 0.5);
|
||||
}
|
||||
|
||||
public static inertiaForSegment(mass, a, b): number {
|
||||
|
||||
var distsq = Phaser.Vec2Utils.distanceSq(b, a);
|
||||
var offset: Phaser.Vec2 = Phaser.Vec2Utils.scale(Phaser.Vec2Utils.add(a, b), 0.5);
|
||||
|
||||
return mass * (distsq / 12 + offset.lengthSq());
|
||||
}
|
||||
|
||||
public static areaForPoly(verts): number {
|
||||
|
||||
var area = 0;
|
||||
|
||||
for (var i = 0; i < verts.length; i++)
|
||||
{
|
||||
area += Phaser.Vec2Utils.cross(verts[i], verts[(i + 1) % verts.length]);
|
||||
}
|
||||
|
||||
return area / 2;
|
||||
}
|
||||
|
||||
public static centroidForPoly(verts): Phaser.Vec2 {
|
||||
|
||||
var area = 0;
|
||||
var vsum = new Phaser.Vec2;
|
||||
|
||||
for (var i = 0; i < verts.length; i++)
|
||||
{
|
||||
var v1 = verts[i];
|
||||
var v2 = verts[(i + 1) % verts.length];
|
||||
var cross = Phaser.Vec2Utils.cross(v1, v2);
|
||||
|
||||
area += cross;
|
||||
|
||||
// SO many vecs created here - unroll these bad boys
|
||||
vsum.add(Phaser.Vec2Utils.scale(Phaser.Vec2Utils.add(v1, v2), cross));
|
||||
}
|
||||
|
||||
return Phaser.Vec2Utils.scale(vsum, 1 / (3 * area));
|
||||
}
|
||||
|
||||
public static inertiaForPoly(mass, verts, offset): number {
|
||||
|
||||
var sum1 = 0;
|
||||
var sum2 = 0;
|
||||
|
||||
for (var i = 0; i < verts.length; i++)
|
||||
{
|
||||
var v1 = Phaser.Vec2Utils.add(verts[i], offset);
|
||||
var v2 = Phaser.Vec2Utils.add(verts[(i + 1) % verts.length], offset);
|
||||
|
||||
var a = Phaser.Vec2Utils.cross(v2, v1);
|
||||
var b = Phaser.Vec2Utils.dot(v1, v1) + Phaser.Vec2Utils.dot(v1, v2) + Phaser.Vec2Utils.dot(v2, v2);
|
||||
|
||||
sum1 += a * b;
|
||||
sum2 += a;
|
||||
}
|
||||
|
||||
return (mass * sum1) / (6 * sum2);
|
||||
}
|
||||
|
||||
public static inertiaForBox(mass, w, h) {
|
||||
return mass * (w * w + h * h) / 12;
|
||||
}
|
||||
|
||||
// Create the convex hull using the Gift wrapping algorithm (http://en.wikipedia.org/wiki/Gift_wrapping_algorithm)
|
||||
public static createConvexHull(points) {
|
||||
|
||||
// Find the right most point on the hull
|
||||
var i0 = 0;
|
||||
var x0 = points[0].x;
|
||||
|
||||
for (var i = 1; i < points.length; i++)
|
||||
{
|
||||
var x = points[i].x;
|
||||
|
||||
if (x > x0 || (x == x0 && points[i].y < points[i0].y))
|
||||
{
|
||||
i0 = i;
|
||||
x0 = x;
|
||||
}
|
||||
}
|
||||
|
||||
var n = points.length;
|
||||
var hull = [];
|
||||
var m = 0;
|
||||
var ih = i0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
hull[m] = ih;
|
||||
|
||||
var ie = 0;
|
||||
|
||||
for (var j = 1; j < n; j++)
|
||||
{
|
||||
if (ie == ih)
|
||||
{
|
||||
ie = j;
|
||||
continue;
|
||||
}
|
||||
|
||||
var r = Phaser.Vec2Utils.subtract(points[ie], points[hull[m]]);
|
||||
var v = Phaser.Vec2Utils.subtract(points[j], points[hull[m]]);
|
||||
var c = Phaser.Vec2Utils.cross(r, v);
|
||||
|
||||
if (c < 0)
|
||||
{
|
||||
ie = j;
|
||||
}
|
||||
|
||||
// Collinearity check
|
||||
if (c == 0 && v.lengthSq() > r.lengthSq())
|
||||
{
|
||||
ie = j;
|
||||
}
|
||||
}
|
||||
|
||||
m++;
|
||||
ih = ie;
|
||||
|
||||
if (ie == i0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy vertices
|
||||
var newPoints = [];
|
||||
|
||||
for (var i = 0; i < m; ++i)
|
||||
{
|
||||
newPoints.push(points[hull[i]]);
|
||||
}
|
||||
|
||||
return newPoints;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
850
Phaser/physics/advanced/Space.ts
Normal file
850
Phaser/physics/advanced/Space.ts
Normal file
|
@ -0,0 +1,850 @@
|
|||
/// <reference path="../../math/Vec2.ts" />
|
||||
/// <reference path="../../math/Vec2Utils.ts" />
|
||||
/// <reference path="Manager.ts" />
|
||||
/// <reference path="Body.ts" />
|
||||
/// <reference path="shapes/Shape.ts" />
|
||||
/// <reference path="ContactSolver.ts" />
|
||||
/// <reference path="Contact.ts" />
|
||||
/// <reference path="Collision.ts" />
|
||||
/// <reference path="joints/IJoint.ts" />
|
||||
|
||||
/**
|
||||
* Phaser - Advanced Physics - Space
|
||||
*
|
||||
* Based on the work Ju Hyung Lee started in JS PhyRus.
|
||||
*/
|
||||
|
||||
module Phaser.Physics.Advanced {
|
||||
|
||||
export class Space {
|
||||
|
||||
constructor() {
|
||||
|
||||
this.bodyArr = [];
|
||||
this.bodyHash = {};
|
||||
|
||||
this.jointArr = [];
|
||||
this.jointHash = {};
|
||||
|
||||
this.numContacts = 0;
|
||||
this.contactSolvers = [];
|
||||
|
||||
//this.postSolve(arb) { };
|
||||
|
||||
this.gravity = new Phaser.Vec2(0, 10);
|
||||
this.damping = 0;
|
||||
|
||||
}
|
||||
|
||||
public static TIME_TO_SLEEP = 0.5;
|
||||
public static SLEEP_LINEAR_TOLERANCE = 0.5;
|
||||
public static SLEEP_ANGULAR_TOLERANCE = 2 * Phaser.GameMath.DEG_TO_RAD;
|
||||
|
||||
public bodyArr: Body[];
|
||||
public bodyHash;
|
||||
public jointArr: IJoint[];
|
||||
public jointHash;
|
||||
public numContacts: number;
|
||||
public contactSolvers: ContactSolver[];
|
||||
public postSolve;
|
||||
public gravity: Phaser.Vec2;
|
||||
public damping: number;
|
||||
public stepCount: number = 0;
|
||||
|
||||
public clear() {
|
||||
|
||||
Manager.shapeCounter = 0;
|
||||
Manager.bodyCounter = 0;
|
||||
Manager.jointCounter = 0;
|
||||
|
||||
for (var i = 0; i < this.bodyArr.length; i++)
|
||||
{
|
||||
if (this.bodyArr[i])
|
||||
{
|
||||
this.removeBody(this.bodyArr[i]);
|
||||
}
|
||||
}
|
||||
|
||||
this.bodyArr = [];
|
||||
this.bodyHash = {};
|
||||
|
||||
this.jointArr = [];
|
||||
this.jointHash = {};
|
||||
|
||||
this.contactSolvers = [];
|
||||
|
||||
this.stepCount = 0;
|
||||
|
||||
}
|
||||
|
||||
public addBody(body: Body) {
|
||||
|
||||
if (this.bodyHash[body.id] != undefined)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//console.log('Body added to space', body.name);
|
||||
|
||||
var index = this.bodyArr.push(body) - 1;
|
||||
this.bodyHash[body.id] = index;
|
||||
|
||||
body.awake(true);
|
||||
body.space = this;
|
||||
body.cacheData();
|
||||
|
||||
}
|
||||
|
||||
public removeBody(body: Body) {
|
||||
|
||||
if (this.bodyHash[body.id] == undefined)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove linked joint
|
||||
for (var i = 0; i < body.joints.length; i++)
|
||||
{
|
||||
if (body.joints[i])
|
||||
{
|
||||
this.removeJoint(body.joints[i]);
|
||||
}
|
||||
}
|
||||
|
||||
body.space = null;
|
||||
|
||||
var index = this.bodyHash[body.id];
|
||||
delete this.bodyHash[body.id];
|
||||
delete this.bodyArr[index];
|
||||
|
||||
}
|
||||
|
||||
public addJoint(joint: IJoint) {
|
||||
|
||||
if (this.jointHash[joint.id] != undefined)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
joint.body1.awake(true);
|
||||
joint.body2.awake(true);
|
||||
|
||||
var index = this.jointArr.push(joint) - 1;
|
||||
this.jointHash[joint.id] = index;
|
||||
|
||||
var index = joint.body1.joints.push(joint) - 1;
|
||||
joint.body1.jointHash[joint.id] = index;
|
||||
|
||||
var index = joint.body2.joints.push(joint) - 1;
|
||||
joint.body2.jointHash[joint.id] = index;
|
||||
|
||||
}
|
||||
|
||||
public removeJoint(joint: IJoint) {
|
||||
|
||||
if (this.jointHash[joint.id] == undefined)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
joint.body1.awake(true);
|
||||
joint.body2.awake(true);
|
||||
|
||||
var index = joint.body1.jointHash[joint.id];
|
||||
delete joint.body1.jointHash[joint.id];
|
||||
delete joint.body1.joints[index];
|
||||
|
||||
var index = joint.body2.jointHash[joint.id];
|
||||
delete joint.body2.jointHash[joint.id];
|
||||
delete joint.body2.joints[index];
|
||||
|
||||
var index = this.jointHash[joint.id];
|
||||
delete this.jointHash[joint.id];
|
||||
delete this.jointArr[index];
|
||||
|
||||
}
|
||||
|
||||
public findShapeByPoint(p, refShape) {
|
||||
|
||||
var firstShape;
|
||||
|
||||
for (var i = 0; i < this.bodyArr.length; i++)
|
||||
{
|
||||
var body = this.bodyArr[i];
|
||||
|
||||
if (!body)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var j = 0; j < body.shapes.length; j++)
|
||||
{
|
||||
var shape = body.shapes[j];
|
||||
|
||||
if (shape.pointQuery(p))
|
||||
{
|
||||
if (!refShape)
|
||||
{
|
||||
return shape;
|
||||
}
|
||||
|
||||
if (!firstShape)
|
||||
{
|
||||
firstShape = shape;
|
||||
}
|
||||
|
||||
if (shape == refShape)
|
||||
{
|
||||
refShape = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return firstShape;
|
||||
}
|
||||
|
||||
public findBodyByPoint(p, refBody: Body) {
|
||||
|
||||
var firstBody;
|
||||
|
||||
for (var i = 0; i < this.bodyArr.length; i++)
|
||||
{
|
||||
var body = this.bodyArr[i];
|
||||
|
||||
if (!body)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var j = 0; j < body.shapes.length; j++)
|
||||
{
|
||||
var shape = body.shapes[j];
|
||||
|
||||
if (shape.pointQuery(p))
|
||||
{
|
||||
if (!refBody)
|
||||
{
|
||||
return shape.body;
|
||||
}
|
||||
|
||||
if (!firstBody)
|
||||
{
|
||||
firstBody = shape.body;
|
||||
}
|
||||
|
||||
if (shape.body == refBody)
|
||||
{
|
||||
refBody = null;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return firstBody;
|
||||
|
||||
}
|
||||
|
||||
// TODO: Replace this function to shape hashing
|
||||
public shapeById(id) {
|
||||
|
||||
var shape;
|
||||
|
||||
for (var i = 0; i < this.bodyArr.length; i++)
|
||||
{
|
||||
var body = this.bodyArr[i];
|
||||
if (!body)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var j = 0; j < body.shapes.length; j++)
|
||||
{
|
||||
if (body.shapes[j].id == id)
|
||||
{
|
||||
return body.shapes[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public jointById(id) {
|
||||
|
||||
var index = this.jointHash[id];
|
||||
|
||||
if (index != undefined)
|
||||
{
|
||||
return this.jointArr[index];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public findVertexByPoint(p, minDist, refVertexId) {
|
||||
|
||||
var firstVertexId = -1;
|
||||
|
||||
refVertexId = refVertexId || -1;
|
||||
|
||||
for (var i = 0; i < this.bodyArr.length; i++)
|
||||
{
|
||||
var body = this.bodyArr[i];
|
||||
|
||||
if (!body)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var j = 0; j < body.shapes.length; j++)
|
||||
{
|
||||
var shape = body.shapes[j];
|
||||
var index = shape.findVertexByPoint(p, minDist);
|
||||
|
||||
if (index != -1)
|
||||
{
|
||||
var vertex = (shape.id << 16) | index;
|
||||
|
||||
if (refVertexId == -1)
|
||||
{
|
||||
return vertex;
|
||||
}
|
||||
|
||||
if (firstVertexId == -1)
|
||||
{
|
||||
firstVertexId = vertex;
|
||||
}
|
||||
|
||||
if (vertex == refVertexId)
|
||||
{
|
||||
refVertexId = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return firstVertexId;
|
||||
|
||||
}
|
||||
|
||||
public findEdgeByPoint(p, minDist, refEdgeId) {
|
||||
|
||||
var firstEdgeId = -1;
|
||||
|
||||
refEdgeId = refEdgeId || -1;
|
||||
|
||||
for (var i = 0; i < this.bodyArr.length; i++)
|
||||
{
|
||||
var body = this.bodyArr[i];
|
||||
|
||||
if (!body)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var j = 0; j < body.shapes.length; j++)
|
||||
{
|
||||
var shape = body.shapes[j];
|
||||
|
||||
if (shape.type != Manager.SHAPE_TYPE_POLY)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var index = shape.findEdgeByPoint(p, minDist);
|
||||
|
||||
if (index != -1)
|
||||
{
|
||||
var edge = (shape.id << 16) | index;
|
||||
|
||||
if (refEdgeId == -1)
|
||||
{
|
||||
return edge;
|
||||
}
|
||||
|
||||
if (firstEdgeId == -1)
|
||||
{
|
||||
firstEdgeId = edge;
|
||||
}
|
||||
|
||||
if (edge == refEdgeId)
|
||||
{
|
||||
refEdgeId = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return firstEdgeId;
|
||||
}
|
||||
|
||||
public findJointByPoint(p, minDist, refJointId) {
|
||||
|
||||
var firstJointId = -1;
|
||||
|
||||
var dsq = minDist * minDist;
|
||||
|
||||
refJointId = refJointId || -1;
|
||||
|
||||
for (var i = 0; i < this.jointArr.length; i++)
|
||||
{
|
||||
var joint = this.jointArr[i];
|
||||
|
||||
if (!joint)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var jointId = -1;
|
||||
|
||||
if (Phaser.Vec2Utils.distanceSq(p, joint.getWorldAnchor1()) < dsq)
|
||||
{
|
||||
jointId = (joint.id << 16 | 0);
|
||||
}
|
||||
else if (Phaser.Vec2Utils.distanceSq(p, joint.getWorldAnchor2()) < dsq)
|
||||
{
|
||||
jointId = (joint.id << 16 | 1);
|
||||
}
|
||||
|
||||
if (jointId != -1)
|
||||
{
|
||||
if (refJointId == -1)
|
||||
{
|
||||
return jointId;
|
||||
}
|
||||
|
||||
if (firstJointId == -1)
|
||||
{
|
||||
firstJointId = jointId;
|
||||
}
|
||||
|
||||
if (jointId == refJointId)
|
||||
{
|
||||
refJointId = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return firstJointId;
|
||||
}
|
||||
|
||||
public findContactSolver(shape1, shape2) {
|
||||
|
||||
for (var i = 0; i < this.contactSolvers.length; i++)
|
||||
{
|
||||
var contactSolver = this.contactSolvers[i];
|
||||
|
||||
if (shape1 == contactSolver.shape1 && shape2 == contactSolver.shape2)
|
||||
{
|
||||
return contactSolver;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public genTemporalContactSolvers() {
|
||||
|
||||
//console.log('genTemporalContactSolvers');
|
||||
|
||||
//var t0 = Date.now();
|
||||
|
||||
var newContactSolverArr = [];
|
||||
|
||||
this.numContacts = 0;
|
||||
|
||||
for (var body1_index = 0; body1_index < this.bodyArr.length; body1_index++)
|
||||
{
|
||||
var body1: Body = this.bodyArr[body1_index];
|
||||
|
||||
//console.log('body1', body1_index, body1.type);
|
||||
|
||||
if (!body1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
body1.stepCount = this.stepCount;
|
||||
|
||||
for (var body2_index = 0; body2_index < this.bodyArr.length; body2_index++)
|
||||
{
|
||||
var body2: Body = this.bodyArr[body2_index];
|
||||
|
||||
//console.log('body2', body2_index, body2.type);
|
||||
|
||||
if (!body2)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (body1.stepCount == body2.stepCount)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//console.log('step');
|
||||
|
||||
var active1 = body1.isAwake && !body1.isStatic;
|
||||
var active2 = body2.isAwake && !body2.isStatic;
|
||||
|
||||
if (!active1 && !active2)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//console.log('active');
|
||||
|
||||
if (!body1.isCollidable(body2))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//console.log('collideable');
|
||||
|
||||
if (!body1.bounds.intersectsBounds(body2.bounds))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//console.log('>>>>>>>>>> intersects');
|
||||
|
||||
for (var i = 0; i < body1.shapes.length; i++)
|
||||
{
|
||||
for (var j = 0; j < body2.shapes.length; j++)
|
||||
{
|
||||
var shape1 = body1.shapes[i];
|
||||
var shape2 = body2.shapes[j];
|
||||
|
||||
var contactArr = [];
|
||||
|
||||
if (!Manager.collision.collide(shape1, shape2, contactArr))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (shape1.type > shape2.type)
|
||||
{
|
||||
var temp = shape1;
|
||||
shape1 = shape2;
|
||||
shape2 = temp;
|
||||
}
|
||||
|
||||
this.numContacts += contactArr.length;
|
||||
|
||||
var contactSolver = this.findContactSolver(shape1, shape2);
|
||||
|
||||
if (contactSolver)
|
||||
{
|
||||
contactSolver.update(contactArr);
|
||||
newContactSolverArr.push(contactSolver);
|
||||
}
|
||||
else
|
||||
{
|
||||
body1.awake(true);
|
||||
body2.awake(true);
|
||||
|
||||
var newContactSolver = new ContactSolver(shape1, shape2);
|
||||
newContactSolver.contacts = contactArr;
|
||||
newContactSolver.elasticity = Math.max(shape1.elasticity, shape2.elasticity);
|
||||
newContactSolver.friction = Math.sqrt(shape1.friction * shape2.friction);
|
||||
newContactSolverArr.push(newContactSolver);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//stats.timeCollision = Date.now() - t0;
|
||||
|
||||
return newContactSolverArr;
|
||||
}
|
||||
|
||||
public initSolver(dt, dt_inv, warmStarting) {
|
||||
|
||||
//var t0 = Date.now();
|
||||
|
||||
// Initialize contact solvers
|
||||
for (var i = 0; i < this.contactSolvers.length; i++)
|
||||
{
|
||||
this.contactSolvers[i].initSolver(dt_inv);
|
||||
}
|
||||
|
||||
// Initialize joint solver
|
||||
for (var i = 0; i < this.jointArr.length; i++)
|
||||
{
|
||||
if (this.jointArr[i])
|
||||
{
|
||||
this.jointArr[i].initSolver(dt, warmStarting);
|
||||
}
|
||||
}
|
||||
|
||||
// Warm starting (apply cached impulse)
|
||||
if (warmStarting)
|
||||
{
|
||||
for (var i = 0; i < this.contactSolvers.length; i++)
|
||||
{
|
||||
this.contactSolvers[i].warmStart();
|
||||
}
|
||||
}
|
||||
|
||||
//stats.timeInitSolver = Date.now() - t0;
|
||||
}
|
||||
|
||||
public velocitySolver(iteration) {
|
||||
|
||||
//var t0 = Date.now();
|
||||
|
||||
for (var i = 0; i < iteration; i++)
|
||||
{
|
||||
for (var j = 0; j < this.jointArr.length; j++)
|
||||
{
|
||||
if (this.jointArr[j])
|
||||
{
|
||||
this.jointArr[j].solveVelocityConstraints();
|
||||
}
|
||||
}
|
||||
|
||||
for (var j = 0; j < this.contactSolvers.length; j++)
|
||||
{
|
||||
this.contactSolvers[j].solveVelocityConstraints();
|
||||
}
|
||||
}
|
||||
|
||||
//stats.timeVelocitySolver = Date.now() - t0;
|
||||
}
|
||||
|
||||
public positionSolver(iteration) {
|
||||
|
||||
//var t0 = Date.now();
|
||||
|
||||
var positionSolved = false;
|
||||
|
||||
//stats.positionIterations = 0;
|
||||
|
||||
for (var i = 0; i < iteration; i++)
|
||||
{
|
||||
var contactsOk = true;
|
||||
var jointsOk = true;
|
||||
|
||||
for (var j = 0; j < this.contactSolvers.length; j++)
|
||||
{
|
||||
var contactOk = this.contactSolvers[j].solvePositionConstraints();
|
||||
contactsOk = contactOk && contactsOk;
|
||||
}
|
||||
|
||||
for (var j = 0; j < this.jointArr.length; j++)
|
||||
{
|
||||
if (this.jointArr[j])
|
||||
{
|
||||
var jointOk = this.jointArr[j].solvePositionConstraints();
|
||||
jointsOk = jointOk && jointsOk;
|
||||
}
|
||||
}
|
||||
|
||||
if (contactsOk && jointsOk)
|
||||
{
|
||||
// exit early if the position errors are small
|
||||
positionSolved = true;
|
||||
break;
|
||||
}
|
||||
|
||||
//stats.positionIterations++;
|
||||
}
|
||||
|
||||
//stats.timePositionSolver = Date.now() - t0;
|
||||
|
||||
return positionSolved;
|
||||
|
||||
}
|
||||
|
||||
public step(dt, vel_iteration, pos_iteration, warmStarting, allowSleep) {
|
||||
|
||||
var dt_inv = 1 / dt;
|
||||
|
||||
this.stepCount++;
|
||||
|
||||
// Generate contact & contactSolver
|
||||
this.contactSolvers = this.genTemporalContactSolvers();
|
||||
|
||||
// Initialize contacts & joints solver
|
||||
this.initSolver(dt, dt_inv, warmStarting);
|
||||
|
||||
// Intergrate velocity
|
||||
for (var i = 0; i < this.bodyArr.length; i++)
|
||||
{
|
||||
var body = this.bodyArr[i];
|
||||
|
||||
if (!body)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (body.isDynamic && body.isAwake)
|
||||
{
|
||||
body.updateVelocity(this.gravity, dt, this.damping);
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < this.jointArr.length; i++)
|
||||
{
|
||||
var joint = this.jointArr[i];
|
||||
|
||||
if (!joint)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var body1 = joint.body1;
|
||||
var body2 = joint.body2;
|
||||
|
||||
var awake1 = body1.isAwake && !body1.isStatic;
|
||||
var awake2 = body2.isAwake && !body2.isStatic;
|
||||
|
||||
if (awake1 ^ awake2)
|
||||
{
|
||||
if (!awake1)
|
||||
{
|
||||
body1.awake(true);
|
||||
}
|
||||
|
||||
if (!awake2)
|
||||
{
|
||||
body2.awake(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Iterative velocity constraints solver
|
||||
this.velocitySolver(vel_iteration);
|
||||
|
||||
// Intergrate position
|
||||
for (var i = 0; i < this.bodyArr.length; i++)
|
||||
{
|
||||
var body = this.bodyArr[i];
|
||||
|
||||
if (!body)
|
||||
{
|
||||
continue
|
||||
}
|
||||
|
||||
if (body.isDynamic && body.isAwake)
|
||||
{
|
||||
body.updatePosition(dt);
|
||||
}
|
||||
}
|
||||
|
||||
// Process breakable joint
|
||||
for (var i = 0; i < this.jointArr.length; i++)
|
||||
{
|
||||
var joint = this.jointArr[i];
|
||||
|
||||
if (!joint)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (joint.breakable)
|
||||
{
|
||||
if (joint.getReactionForce(dt_inv).lengthsq() >= joint.maxForce * joint.maxForce)
|
||||
{
|
||||
this.removeJoint(joint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Iterative position constraints solver
|
||||
var positionSolved = this.positionSolver(pos_iteration);
|
||||
|
||||
for (var i = 0; i < this.bodyArr.length; i++)
|
||||
{
|
||||
var body = this.bodyArr[i];
|
||||
|
||||
if (!body)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
body.syncTransform();
|
||||
}
|
||||
|
||||
// Post solve collision callback
|
||||
for (var i = 0; i < this.contactSolvers.length; i++)
|
||||
{
|
||||
var arb = this.contactSolvers[i];
|
||||
|
||||
// Re-enable this
|
||||
//this.postSolve(arb);
|
||||
}
|
||||
|
||||
for (var i = 0; i < this.bodyArr.length; i++)
|
||||
{
|
||||
var body = this.bodyArr[i];
|
||||
|
||||
if (!body)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (body.isDynamic && body.isAwake)
|
||||
{
|
||||
body.cacheData();
|
||||
}
|
||||
}
|
||||
|
||||
// Process sleeping
|
||||
if (allowSleep)
|
||||
{
|
||||
var minSleepTime = 999999;
|
||||
|
||||
var linTolSqr = Space.SLEEP_LINEAR_TOLERANCE * Space.SLEEP_LINEAR_TOLERANCE;
|
||||
var angTolSqr = Space.SLEEP_ANGULAR_TOLERANCE * Space.SLEEP_ANGULAR_TOLERANCE;
|
||||
|
||||
for (var i = 0; i < this.bodyArr.length; i++)
|
||||
{
|
||||
var body = this.bodyArr[i];
|
||||
|
||||
if (!body)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!body.isDynamic)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (body.angularVelocity * body.angularVelocity > angTolSqr || body.velocity.dot(body.velocity) > linTolSqr)
|
||||
{
|
||||
body.sleepTime = 0;
|
||||
minSleepTime = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
body.sleepTime += dt;
|
||||
minSleepTime = Math.min(minSleepTime, body.sleepTime);
|
||||
}
|
||||
}
|
||||
|
||||
if (positionSolved && minSleepTime >= Space.TIME_TO_SLEEP)
|
||||
{
|
||||
for (var i = 0; i < this.bodyArr.length; i++)
|
||||
{
|
||||
var body = this.bodyArr[i];
|
||||
|
||||
if (!body)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
body.awake(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
43
Phaser/physics/advanced/joints/IJoint.ts
Normal file
43
Phaser/physics/advanced/joints/IJoint.ts
Normal file
|
@ -0,0 +1,43 @@
|
|||
/// <reference path="../../../math/Vec2.ts" />
|
||||
/// <reference path="../../../geom/Point.ts" />
|
||||
/// <reference path="../../../math/Vec2Utils.ts" />
|
||||
/// <reference path="../Manager.ts" />
|
||||
/// <reference path="../Body.ts" />
|
||||
|
||||
/**
|
||||
* Phaser - Advanced Physics - Joint
|
||||
*
|
||||
* Based on the work Ju Hyung Lee started in JS PhyRus.
|
||||
*/
|
||||
|
||||
module Phaser.Physics.Advanced {
|
||||
|
||||
export interface IJoint {
|
||||
|
||||
id: number;
|
||||
type: number;
|
||||
|
||||
body1: Phaser.Physics.Advanced.Body;
|
||||
body2: Phaser.Physics.Advanced.Body;
|
||||
|
||||
collideConnected; // bool?
|
||||
maxForce: number;
|
||||
breakable: bool;
|
||||
|
||||
anchor1: Phaser.Vec2;
|
||||
anchor2: Phaser.Vec2;
|
||||
|
||||
getWorldAnchor1();
|
||||
getWorldAnchor2();
|
||||
setWorldAnchor1(anchor1);
|
||||
setWorldAnchor2(anchor2);
|
||||
|
||||
initSolver(dt, warmStarting);
|
||||
solveVelocityConstraints();
|
||||
solvePositionConstraints();
|
||||
getReactionForce(dt_inv);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
64
Phaser/physics/advanced/joints/Joint.ts
Normal file
64
Phaser/physics/advanced/joints/Joint.ts
Normal file
|
@ -0,0 +1,64 @@
|
|||
/// <reference path="../../../math/Vec2.ts" />
|
||||
/// <reference path="../../../geom/Point.ts" />
|
||||
/// <reference path="../../../math/Vec2Utils.ts" />
|
||||
/// <reference path="../Manager.ts" />
|
||||
/// <reference path="../Body.ts" />
|
||||
|
||||
/**
|
||||
* Phaser - Advanced Physics - Joint
|
||||
*
|
||||
* Based on the work Ju Hyung Lee started in JS PhyRus.
|
||||
*/
|
||||
|
||||
module Phaser.Physics.Advanced {
|
||||
|
||||
export class Joint {
|
||||
|
||||
constructor(type: number, body1:Phaser.Physics.Advanced.Body, body2:Phaser.Physics.Advanced.Body, collideConnected) {
|
||||
|
||||
this.id = Phaser.Physics.Advanced.Manager.jointCounter++;
|
||||
this.type = type;
|
||||
|
||||
this.body1 = body1;
|
||||
this.body2 = body2;
|
||||
|
||||
this.collideConnected = collideConnected;
|
||||
|
||||
this.maxForce = 9999999999;
|
||||
this.breakable = false;
|
||||
|
||||
}
|
||||
|
||||
public id: number;
|
||||
public type: number;
|
||||
|
||||
public body1: Phaser.Physics.Advanced.Body;
|
||||
public body2: Phaser.Physics.Advanced.Body;
|
||||
|
||||
public collideConnected; // bool?
|
||||
public maxForce: number;
|
||||
public breakable: bool;
|
||||
|
||||
public anchor1: Phaser.Vec2;
|
||||
public anchor2: Phaser.Vec2;
|
||||
|
||||
public getWorldAnchor1() {
|
||||
return this.body1.getWorldPoint(this.anchor1);
|
||||
}
|
||||
|
||||
public getWorldAnchor2() {
|
||||
return this.body2.getWorldPoint(this.anchor2);
|
||||
}
|
||||
|
||||
public setWorldAnchor1(anchor1) {
|
||||
this.anchor1 = this.body1.getLocalPoint(anchor1);
|
||||
}
|
||||
|
||||
public setWorldAnchor2(anchor2) {
|
||||
this.anchor2 = this.body2.getLocalPoint(anchor2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
39
Phaser/physics/advanced/shapes/Box.ts
Normal file
39
Phaser/physics/advanced/shapes/Box.ts
Normal file
|
@ -0,0 +1,39 @@
|
|||
/// <reference path="../../../math/Vec2.ts" />
|
||||
/// <reference path="../Manager.ts" />
|
||||
/// <reference path="../Body.ts" />
|
||||
/// <reference path="Shape.ts" />
|
||||
/// <reference path="Poly.ts" />
|
||||
|
||||
/**
|
||||
* Phaser - Advanced Physics - Shapes - Box
|
||||
*
|
||||
* Based on the work Ju Hyung Lee started in JS PhyRus.
|
||||
*/
|
||||
|
||||
module Phaser.Physics.Advanced.Shapes {
|
||||
|
||||
export class Box extends Phaser.Physics.Advanced.Shapes.Poly {
|
||||
|
||||
// Give in pixels
|
||||
constructor(x, y, width, height) {
|
||||
|
||||
x = Manager.pixelsToMeters(x);
|
||||
y = Manager.pixelsToMeters(y);
|
||||
width = Manager.pixelsToMeters(width);
|
||||
height = Manager.pixelsToMeters(height);
|
||||
|
||||
var hw = width * 0.5;
|
||||
var hh = height * 0.5;
|
||||
|
||||
super([
|
||||
new Phaser.Vec2(-hw + x, +hh + y),
|
||||
new Phaser.Vec2(-hw + x, -hh + y),
|
||||
new Phaser.Vec2(+hw + x, -hh + y),
|
||||
new Phaser.Vec2(+hw + x, +hh + y)
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
101
Phaser/physics/advanced/shapes/Circle.ts
Normal file
101
Phaser/physics/advanced/shapes/Circle.ts
Normal file
|
@ -0,0 +1,101 @@
|
|||
/// <reference path="../../../math/Vec2.ts" />
|
||||
/// <reference path="../../../math/Vec2Utils.ts" />
|
||||
/// <reference path="../Manager.ts" />
|
||||
/// <reference path="../Body.ts" />
|
||||
/// <reference path="Shape.ts" />
|
||||
|
||||
/**
|
||||
* Phaser - Advanced Physics - Shape - Circle
|
||||
*
|
||||
* Based on the work Ju Hyung Lee started in JS PhyRus.
|
||||
*/
|
||||
|
||||
module Phaser.Physics.Advanced.Shapes {
|
||||
|
||||
export class Circle extends Phaser.Physics.Advanced.Shape implements IShape {
|
||||
|
||||
constructor(radius: number, x?: number = 0, y?: number = 0) {
|
||||
|
||||
super(Manager.SHAPE_TYPE_CIRCLE);
|
||||
|
||||
this.center = new Phaser.Vec2(x, y);
|
||||
this.radius = radius;
|
||||
this.tc = new Phaser.Vec2;
|
||||
|
||||
this.finishVerts();
|
||||
|
||||
}
|
||||
|
||||
public radius: number;
|
||||
public center: Phaser.Vec2;
|
||||
public tc: Phaser.Vec2;
|
||||
|
||||
public finishVerts() {
|
||||
this.radius = Math.abs(this.radius);
|
||||
}
|
||||
|
||||
public duplicate(): Circle {
|
||||
return new Circle(this.center.x, this.center.y, this.radius);
|
||||
}
|
||||
|
||||
public recenter(c:Phaser.Vec2) {
|
||||
this.center.subtract(c);
|
||||
}
|
||||
|
||||
public transform(xf: Transform) {
|
||||
|
||||
Phaser.TransformUtils.transform(xf, this.center, this.center);
|
||||
//this.center = xf.transform(this.center);
|
||||
}
|
||||
|
||||
public untransform(xf: Transform) {
|
||||
Phaser.TransformUtils.untransform(xf, this.center, this.center);
|
||||
//this.center = xf.untransform(this.center);
|
||||
}
|
||||
|
||||
public area(): number {
|
||||
return Manager.areaForCircle(this.radius, 0);
|
||||
}
|
||||
|
||||
public centroid(): Phaser.Vec2 {
|
||||
return Phaser.Vec2Utils.clone(this.center);
|
||||
}
|
||||
|
||||
public inertia(mass: number): number {
|
||||
return Manager.inertiaForCircle(mass, this.center, this.radius, 0);
|
||||
}
|
||||
|
||||
public cacheData(xf: Transform) {
|
||||
|
||||
Phaser.TransformUtils.transform(xf, this.center, this.tc);
|
||||
//this.tc = xf.transform(this.center);
|
||||
|
||||
this.bounds.mins.setTo(this.tc.x - this.radius, this.tc.y - this.radius);
|
||||
this.bounds.maxs.setTo(this.tc.x + this.radius, this.tc.y + this.radius);
|
||||
|
||||
}
|
||||
|
||||
public pointQuery(p:Phaser.Vec2): bool {
|
||||
//return vec2.distsq(this.tc, p) < (this.r * this.r);
|
||||
return Phaser.Vec2Utils.distanceSq(this.tc, p) < (this.radius * this.radius);
|
||||
}
|
||||
|
||||
public findVertexByPoint(p:Phaser.Vec2, minDist: number): number {
|
||||
|
||||
var dsq = minDist * minDist;
|
||||
|
||||
if (Phaser.Vec2Utils.distanceSq(this.tc, p) < dsq)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public distanceOnPlane(n, d) {
|
||||
Phaser.Vec2Utils.dot(n, this.tc) - this.radius - d;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
39
Phaser/physics/advanced/shapes/IShape.ts
Normal file
39
Phaser/physics/advanced/shapes/IShape.ts
Normal file
|
@ -0,0 +1,39 @@
|
|||
/// <reference path="../../../math/Vec2.ts" />
|
||||
/// <reference path="../../../geom/Point.ts" />
|
||||
/// <reference path="../../../math/Vec2Utils.ts" />
|
||||
/// <reference path="../Manager.ts" />
|
||||
/// <reference path="../Body.ts" />
|
||||
/// <reference path="Shape.ts" />
|
||||
|
||||
/**
|
||||
* Phaser - Advanced Physics - IShape
|
||||
*
|
||||
* Based on the work Ju Hyung Lee started in JS PhyRus.
|
||||
*/
|
||||
|
||||
module Phaser.Physics.Advanced {
|
||||
|
||||
export interface IShape {
|
||||
|
||||
id: number;
|
||||
type: number;
|
||||
|
||||
elasticity: number;
|
||||
friction: number;
|
||||
density: number;
|
||||
|
||||
body: Body;
|
||||
bounds: Bounds;
|
||||
|
||||
area(): number;
|
||||
centroid(): Phaser.Vec2;
|
||||
inertia(mass: number): number;
|
||||
cacheData(xf:Transform);
|
||||
pointQuery(p: Phaser.Vec2): bool;
|
||||
findEdgeByPoint(p: Phaser.Vec2, minDist: number): number;
|
||||
findVertexByPoint(p: Phaser.Vec2, minDist: number): number;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
295
Phaser/physics/advanced/shapes/Poly.ts
Normal file
295
Phaser/physics/advanced/shapes/Poly.ts
Normal file
|
@ -0,0 +1,295 @@
|
|||
/// <reference path="../../../math/Vec2.ts" />
|
||||
/// <reference path="../../../math/Vec2Utils.ts" />
|
||||
/// <reference path="../Manager.ts" />
|
||||
/// <reference path="../Body.ts" />
|
||||
/// <reference path="Shape.ts" />
|
||||
|
||||
/**
|
||||
* Phaser - Advanced Physics - Shapes - Convex Polygon
|
||||
*
|
||||
* Based on the work Ju Hyung Lee started in JS PhyRus.
|
||||
*/
|
||||
|
||||
module Phaser.Physics.Advanced.Shapes {
|
||||
|
||||
export class Poly extends Phaser.Physics.Advanced.Shape implements IShape {
|
||||
|
||||
constructor(verts?:Phaser.Vec2[]) {
|
||||
|
||||
super(Manager.SHAPE_TYPE_POLY);
|
||||
|
||||
this.verts = [];
|
||||
this.planes = [];
|
||||
|
||||
this.tverts = [];
|
||||
this.tplanes = [];
|
||||
|
||||
if (verts)
|
||||
{
|
||||
for (var i = 0; i < verts.length; i++)
|
||||
{
|
||||
this.verts[i] = Phaser.Vec2Utils.clone(verts[i]);
|
||||
this.tverts[i] = this.verts[i];
|
||||
|
||||
this.tplanes[i] = {};
|
||||
this.tplanes[i].n = new Phaser.Vec2;
|
||||
this.tplanes[i].d = 0;
|
||||
}
|
||||
}
|
||||
|
||||
this.finishVerts();
|
||||
|
||||
}
|
||||
|
||||
public verts: Phaser.Vec2[];
|
||||
public planes;
|
||||
|
||||
public tverts;
|
||||
public tplanes;
|
||||
|
||||
public convexity: bool;
|
||||
|
||||
public finishVerts() {
|
||||
|
||||
if (this.verts.length < 2)
|
||||
{
|
||||
this.convexity = false;
|
||||
this.planes = [];
|
||||
return;
|
||||
}
|
||||
|
||||
this.convexity = true;
|
||||
this.tverts = [];
|
||||
this.tplanes = [];
|
||||
|
||||
// Must be counter-clockwise verts
|
||||
for (var i = 0; i < this.verts.length; i++)
|
||||
{
|
||||
var a = this.verts[i];
|
||||
var b = this.verts[(i + 1) % this.verts.length];
|
||||
var n = Phaser.Vec2Utils.normalize(Phaser.Vec2Utils.perp(Phaser.Vec2Utils.subtract(a, b)));
|
||||
|
||||
this.planes[i] = {};
|
||||
this.planes[i].n = n;
|
||||
this.planes[i].d = Phaser.Vec2Utils.dot(n, a);
|
||||
|
||||
this.tverts[i] = this.verts[i];
|
||||
|
||||
this.tplanes[i] = {};
|
||||
this.tplanes[i].n = new Phaser.Vec2;
|
||||
this.tplanes[i].d = 0;
|
||||
}
|
||||
|
||||
for (var i = 0; i < this.verts.length; i++)
|
||||
{
|
||||
var b = this.verts[(i + 2) % this.verts.length];
|
||||
var n = this.planes[i].n;
|
||||
var d = this.planes[i].d;
|
||||
|
||||
if (Phaser.Vec2Utils.dot(n, b) - d > 0)
|
||||
{
|
||||
this.convexity = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public duplicate() {
|
||||
return new Phaser.Physics.Advanced.Shapes.Poly(this.verts);
|
||||
}
|
||||
|
||||
public recenter(c) {
|
||||
|
||||
for (var i = 0; i < this.verts.length; i++)
|
||||
{
|
||||
this.verts[i].subtract(c);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public transform(xf) {
|
||||
for (var i = 0; i < this.verts.length; i++)
|
||||
{
|
||||
this.verts[i] = xf.transform(this.verts[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public untransform(xf) {
|
||||
for (var i = 0; i < this.verts.length; i++)
|
||||
{
|
||||
this.verts[i] = xf.untransform(this.verts[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public area(): number {
|
||||
return Manager.areaForPoly(this.verts);
|
||||
}
|
||||
|
||||
public centroid(): Phaser.Vec2 {
|
||||
return Manager.centroidForPoly(this.verts);
|
||||
}
|
||||
|
||||
public inertia(mass: number): number {
|
||||
return Manager.inertiaForPoly(mass, this.verts, new Phaser.Vec2);
|
||||
}
|
||||
|
||||
public cacheData(xf:Transform) {
|
||||
|
||||
this.bounds.clear();
|
||||
|
||||
var numVerts = this.verts.length;
|
||||
|
||||
//console.log('shapePoly cacheData', numVerts);
|
||||
|
||||
if (numVerts == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (var i = 0; i < numVerts; i++)
|
||||
{
|
||||
Phaser.TransformUtils.transform(xf, this.tverts[i], this.tverts[i]);
|
||||
//this.tverts[i] = xf.transform(this.verts[i]);
|
||||
}
|
||||
|
||||
if (numVerts < 2)
|
||||
{
|
||||
this.bounds.addPoint(this.tverts[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
for (var i = 0; i < numVerts; i++)
|
||||
{
|
||||
var a = this.tverts[i];
|
||||
var b = this.tverts[(i + 1) % numVerts];
|
||||
|
||||
var n = Phaser.Vec2Utils.normalize(Phaser.Vec2Utils.perp(Phaser.Vec2Utils.subtract(a, b)));
|
||||
|
||||
this.tplanes[i].n = n;
|
||||
this.tplanes[i].d = Phaser.Vec2Utils.dot(n, a);
|
||||
|
||||
this.bounds.addPoint(a);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public pointQuery(p: Phaser.Vec2): bool {
|
||||
|
||||
if (!this.bounds.containPoint(p))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.containPoint(p);
|
||||
}
|
||||
|
||||
public findVertexByPoint(p:Phaser.Vec2, minDist: number): number {
|
||||
|
||||
var dsq = minDist * minDist;
|
||||
|
||||
for (var i = 0; i < this.tverts.length; i++)
|
||||
{
|
||||
if (Phaser.Vec2Utils.distanceSq(this.tverts[i], p) < dsq)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public findEdgeByPoint(p: Phaser.Vec2, minDist: number): number {
|
||||
|
||||
var dsq = minDist * minDist;
|
||||
var numVerts = this.tverts.length;
|
||||
|
||||
for (var i = 0; i < this.tverts.length; i++)
|
||||
{
|
||||
var v1 = this.tverts[i];
|
||||
var v2 = this.tverts[(i + 1) % numVerts];
|
||||
var n = this.tplanes[i].n;
|
||||
|
||||
var dtv1 = Phaser.Vec2Utils.cross(v1, n);
|
||||
var dtv2 = Phaser.Vec2Utils.cross(v2, n);
|
||||
var dt = Phaser.Vec2Utils.cross(p, n);
|
||||
|
||||
if (dt > dtv1)
|
||||
{
|
||||
if (Phaser.Vec2Utils.distanceSq(v1, p) < dsq)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
else if (dt < dtv2)
|
||||
{
|
||||
if (Phaser.Vec2Utils.distanceSq(v2, p) < dsq)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var dist = Phaser.Vec2Utils.dot(n, p) - Phaser.Vec2Utils.dot(n, v1);
|
||||
|
||||
if (dist * dist < dsq)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
public distanceOnPlane(n, d) {
|
||||
|
||||
var min = 999999;
|
||||
|
||||
for (var i = 0; i < this.verts.length; i++)
|
||||
{
|
||||
min = Math.min(min, Phaser.Vec2Utils.dot(n, this.tverts[i]));
|
||||
}
|
||||
|
||||
return min - d;
|
||||
|
||||
}
|
||||
|
||||
public containPoint(p) {
|
||||
|
||||
for (var i = 0; i < this.verts.length; i++)
|
||||
{
|
||||
var plane = this.tplanes[i];
|
||||
|
||||
if (Phaser.Vec2Utils.dot(plane.n, p) - plane.d > 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
public containPointPartial(p, n) {
|
||||
|
||||
for (var i = 0; i < this.verts.length; i++)
|
||||
{
|
||||
var plane = this.tplanes[i];
|
||||
|
||||
if (Phaser.Vec2Utils.dot(plane.n, n) < 0.0001)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Phaser.Vec2Utils.dot(plane.n, p) - plane.d > 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
204
Phaser/physics/advanced/shapes/Segment.ts
Normal file
204
Phaser/physics/advanced/shapes/Segment.ts
Normal file
|
@ -0,0 +1,204 @@
|
|||
/// <reference path="../../../math/Vec2.ts" />
|
||||
/// <reference path="../../../math/Vec2Utils.ts" />
|
||||
/// <reference path="../Manager.ts" />
|
||||
/// <reference path="../Body.ts" />
|
||||
/// <reference path="Shape.ts" />
|
||||
|
||||
/**
|
||||
* Phaser - Advanced Physics - Shapes - Segment
|
||||
*
|
||||
* Based on the work Ju Hyung Lee started in JS PhyRus.
|
||||
*/
|
||||
|
||||
module Phaser.Physics.Advanced.Shapes {
|
||||
|
||||
export class Segment extends Phaser.Physics.Advanced.Shape implements IShape {
|
||||
|
||||
constructor(a, b, radius: number) {
|
||||
|
||||
super(Manager.SHAPE_TYPE_SEGMENT);
|
||||
|
||||
this.a = a.duplicate();
|
||||
this.b = b.duplicate();
|
||||
this.radius = radius;
|
||||
|
||||
this.normal = Phaser.Vec2Utils.perp(Phaser.Vec2Utils.subtract(b, a));
|
||||
this.normal.normalize();
|
||||
|
||||
this.ta = new Phaser.Vec2;
|
||||
this.tb = new Phaser.Vec2;
|
||||
this.tn = new Phaser.Vec2;
|
||||
|
||||
this.finishVerts();
|
||||
|
||||
}
|
||||
|
||||
public a: Phaser.Vec2;
|
||||
public b: Phaser.Vec2;
|
||||
public radius: number;
|
||||
|
||||
public normal: Phaser.Vec2;
|
||||
public ta: Phaser.Vec2;
|
||||
public tb: Phaser.Vec2;
|
||||
public tn: Phaser.Vec2;
|
||||
|
||||
public finishVerts() {
|
||||
|
||||
this.normal = Phaser.Vec2Utils.perp(Phaser.Vec2Utils.subtract(this.b, this.a));
|
||||
this.normal.normalize();
|
||||
|
||||
this.radius = Math.abs(this.radius);
|
||||
|
||||
}
|
||||
|
||||
public duplicate() {
|
||||
return new Phaser.Physics.Advanced.Shapes.Segment(this.a, this.b, this.radius);
|
||||
}
|
||||
|
||||
public recenter(c) {
|
||||
this.a.subtract(c);
|
||||
this.b.subtract(c);
|
||||
}
|
||||
|
||||
public transform(xf:Transform) {
|
||||
|
||||
Phaser.TransformUtils.transform(xf, this.a, this.a);
|
||||
Phaser.TransformUtils.transform(xf, this.b, this.b);
|
||||
|
||||
//this.a = xf.transform(this.a);
|
||||
//this.b = xf.transform(this.b);
|
||||
|
||||
}
|
||||
|
||||
public untransform(xf:Transform) {
|
||||
|
||||
Phaser.TransformUtils.untransform(xf, this.a, this.a);
|
||||
Phaser.TransformUtils.untransform(xf, this.b, this.b);
|
||||
|
||||
//this.a = xf.untransform(this.a);
|
||||
//this.b = xf.untransform(this.b);
|
||||
|
||||
}
|
||||
|
||||
public area(): number {
|
||||
return Manager.areaForSegment(this.a, this.b, this.radius);
|
||||
}
|
||||
|
||||
public centroid(): Phaser.Vec2 {
|
||||
return Manager.centroidForSegment(this.a, this.b);
|
||||
}
|
||||
|
||||
public inertia(mass: number): number {
|
||||
return Manager.inertiaForSegment(mass, this.a, this.b);
|
||||
}
|
||||
|
||||
public cacheData(xf:Transform) {
|
||||
|
||||
Phaser.TransformUtils.transform(xf, this.a, this.ta);
|
||||
Phaser.TransformUtils.transform(xf, this.b, this.tb);
|
||||
|
||||
//this.ta = xf.transform(this.a);
|
||||
//this.tb = xf.transform(this.b);
|
||||
|
||||
this.tn = Phaser.Vec2Utils.perp(Phaser.Vec2Utils.subtract(this.tb, this.ta)).normalize();
|
||||
|
||||
var l;
|
||||
var r;
|
||||
var t;
|
||||
var b;
|
||||
|
||||
if (this.ta.x < this.tb.x)
|
||||
{
|
||||
l = this.ta.x;
|
||||
r = this.tb.x;
|
||||
}
|
||||
else
|
||||
{
|
||||
l = this.tb.x;
|
||||
r = this.ta.x;
|
||||
}
|
||||
|
||||
if (this.ta.y < this.tb.y)
|
||||
{
|
||||
b = this.ta.y;
|
||||
t = this.tb.y;
|
||||
} else
|
||||
{
|
||||
b = this.tb.y;
|
||||
t = this.ta.y;
|
||||
}
|
||||
|
||||
this.bounds.mins.setTo(l - this.radius, b - this.radius);
|
||||
this.bounds.maxs.setTo(r + this.radius, t + this.radius);
|
||||
|
||||
}
|
||||
|
||||
public pointQuery(p: Phaser.Vec2): bool {
|
||||
|
||||
if (!this.bounds.containPoint(p))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var dn = Phaser.Vec2Utils.dot(this.tn, p) - Phaser.Vec2Utils.dot(this.ta, this.tn);
|
||||
var dist = Math.abs(dn);
|
||||
|
||||
if (dist > this.radius)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var dt = Phaser.Vec2Utils.cross(p, this.tn);
|
||||
var dta = Phaser.Vec2Utils.cross(this.ta, this.tn);
|
||||
var dtb = Phaser.Vec2Utils.cross(this.tb, this.tn);
|
||||
|
||||
if (dt <= dta)
|
||||
{
|
||||
if (dt < dta - this.radius)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return Phaser.Vec2Utils.distanceSq(this.ta, p) < (this.radius * this.radius);
|
||||
}
|
||||
else if (dt > dtb)
|
||||
{
|
||||
if (dt > dtb + this.radius)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return Phaser.Vec2Utils.distanceSq(this.tb, p) < (this.radius * this.radius);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public findVertexByPoint(p:Phaser.Vec2, minDist: number): number {
|
||||
|
||||
var dsq = minDist * minDist;
|
||||
|
||||
if (Phaser.Vec2Utils.distanceSq(this.ta, p) < dsq)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (Phaser.Vec2Utils.distanceSq(this.tb, p) < dsq)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public distanceOnPlane(n, d) {
|
||||
|
||||
var a = Phaser.Vec2Utils.dot(n, this.ta) - this.radius;
|
||||
var b = Phaser.Vec2Utils.dot(n, this.tb) - this.radius;
|
||||
|
||||
return Math.min(a, b) - d;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
54
Phaser/physics/advanced/shapes/Shape.ts
Normal file
54
Phaser/physics/advanced/shapes/Shape.ts
Normal file
|
@ -0,0 +1,54 @@
|
|||
/// <reference path="../../../math/Vec2.ts" />
|
||||
/// <reference path="../../../math/Vec2Utils.ts" />
|
||||
/// <reference path="../Manager.ts" />
|
||||
/// <reference path="../Body.ts" />
|
||||
/// <reference path="../Bounds.ts" />
|
||||
/// <reference path="IShape.ts" />
|
||||
|
||||
/**
|
||||
* Phaser - Advanced Physics - Shape
|
||||
*
|
||||
* Based on the work Ju Hyung Lee started in JS PhyRus.
|
||||
*/
|
||||
|
||||
module Phaser.Physics.Advanced {
|
||||
|
||||
export class Shape {
|
||||
|
||||
constructor(type: number) {
|
||||
|
||||
this.id = Phaser.Physics.Advanced.Manager.shapeCounter++;
|
||||
this.type = type;
|
||||
|
||||
this.elasticity = 0.0;
|
||||
this.friction = 1.0;
|
||||
this.density = 1;
|
||||
|
||||
this.bounds = new Bounds;
|
||||
|
||||
}
|
||||
|
||||
public id: number;
|
||||
public type: number;
|
||||
public body: Body;
|
||||
|
||||
// Coefficient of restitution (elasticity)
|
||||
public elasticity: number;
|
||||
|
||||
// Frictional coefficient
|
||||
public friction: number;
|
||||
|
||||
// Mass density
|
||||
public density: number;
|
||||
|
||||
// Axis-aligned bounding box
|
||||
public bounds: Bounds;
|
||||
|
||||
// Over-ridden by ShapePoly
|
||||
public findEdgeByPoint(p: Phaser.Vec2, minDist: number): number {
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
25
Phaser/physics/advanced/shapes/Triangle.ts
Normal file
25
Phaser/physics/advanced/shapes/Triangle.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
/// <reference path="../../../math/Vec2.ts" />
|
||||
/// <reference path="../Manager.ts" />
|
||||
/// <reference path="../Body.ts" />
|
||||
/// <reference path="Shape.ts" />
|
||||
/// <reference path="Poly.ts" />
|
||||
|
||||
/**
|
||||
* Phaser - Advanced Physics - Shapes - Triangle
|
||||
*
|
||||
* Based on the work Ju Hyung Lee started in JS PhyRus.
|
||||
*/
|
||||
|
||||
module Phaser.Physics.Advanced.Shapes {
|
||||
|
||||
export class Triangle extends Phaser.Physics.Advanced.Shapes.Poly {
|
||||
|
||||
constructor(p1, p2, p3) {
|
||||
|
||||
super( [ new Phaser.Vec2(p1.x, p1.y), new Phaser.Vec2(p2.x, p2.y), new Phaser.Vec2(p3.x, p3.y) ] );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -45,6 +45,10 @@ TODO:
|
|||
* Sprite collision events
|
||||
* See which functions in the input component can move elsewhere (utils)
|
||||
* Move all of the renderDebugInfo methods to the DebugUtils class
|
||||
* Check bounds/edge points when sprite is only 1x1 sized :)
|
||||
|
||||
* See what I can move out of Body and into a BodyUtils class.
|
||||
* See about optimising Advanced Physics a lot more, so it doesn't create lots of Vec2s everywhere.
|
||||
|
||||
V1.0.0
|
||||
|
||||
|
@ -112,7 +116,7 @@ V1.0.0
|
|||
* Added SpriteUtils.overlapsXY and overlapsPoint to check if a point is within a sprite, taking scale and rotation into account.
|
||||
* Added Cache.getImageKeys (and similar) to return an array of all the keys for all currently cached objects.
|
||||
* Added Group.bringToTop feature. Will sort the Group, move the given sprites z-index to the top and shift the rest down by one.
|
||||
|
||||
* Brand new Advanced Physics system added and working! Woohoo :)
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -186,6 +186,14 @@
|
|||
<Content Include="physics\aabb vs aabb 1.js">
|
||||
<DependentUpon>aabb vs aabb 1.ts</DependentUpon>
|
||||
</Content>
|
||||
<TypeScriptCompile Include="physics\obb vs obb.ts" />
|
||||
<TypeScriptCompile Include="physics\body1.ts" />
|
||||
<Content Include="physics\body1.js">
|
||||
<DependentUpon>body1.ts</DependentUpon>
|
||||
</Content>
|
||||
<Content Include="physics\obb vs obb.js">
|
||||
<DependentUpon>obb vs obb.ts</DependentUpon>
|
||||
</Content>
|
||||
<Content Include="scrollzones\ballscroller.js">
|
||||
<DependentUpon>ballscroller.ts</DependentUpon>
|
||||
</Content>
|
||||
|
|
3691
Tests/phaser.js
3691
Tests/phaser.js
File diff suppressed because it is too large
Load diff
104
Tests/physics/body1.js
Normal file
104
Tests/physics/body1.js
Normal file
|
@ -0,0 +1,104 @@
|
|||
/// <reference path="../../Phaser/Game.ts" />
|
||||
/// <reference path="../../Phaser/physics/advanced/Manager.ts" />
|
||||
/// <reference path="../../Phaser/physics/advanced/shapes/Box.ts" />
|
||||
/// <reference path="../../Phaser/physics/advanced/shapes/Circle.ts" />
|
||||
(function () {
|
||||
var game = new Phaser.Game(this, 'game', 800, 600, init, create, update, render);
|
||||
function init() {
|
||||
game.load.image('xatari', 'assets/sprites/atari800xl.png');
|
||||
game.load.image('card', 'assets/sprites/mana_card.png');
|
||||
game.load.image('atari', 'assets/sprites/shinyball.png');
|
||||
game.load.start();
|
||||
}
|
||||
var atari;
|
||||
var card;
|
||||
var physics;
|
||||
var circle;
|
||||
var walls;
|
||||
var ground;
|
||||
function create() {
|
||||
atari = game.add.sprite(200, 100, 'atari');
|
||||
atari.transform.origin.setTo(0.5, 0.5);
|
||||
//card = game.add.sprite(500, 300, 'card');
|
||||
physics = new Phaser.Physics.Advanced.Manager(game);
|
||||
walls = new Phaser.Physics.Advanced.Body(null, Phaser.Types.BODY_STATIC);
|
||||
walls.game = game;
|
||||
// position is in relation to the containing body! don't forget this
|
||||
ground = walls.addShape(new Phaser.Physics.Advanced.Shapes.Box(400, 500, 500, 20));
|
||||
//walls.addShape(new Phaser.Physics.Advanced.ShapeBox(0, 0.2, 20.48, 0.4));
|
||||
//walls.addShape(new Phaser.Physics.Advanced.ShapeBox(0, 15.16, 20.48, 0.4));
|
||||
//walls.addShape(new Phaser.Physics.Advanced.ShapeBox(-10.04, 7.68, 0.4, 14.56));
|
||||
//walls.addShape(new Phaser.Physics.Advanced.ShapeBox(10.04, 7.68, 0.4, 14.56));
|
||||
walls.resetMassData();
|
||||
physics.space.addBody(walls);
|
||||
// Add a circle
|
||||
circle = new Phaser.Physics.Advanced.Body(null, Phaser.Types.BODY_DYNAMIC, physics.pixelsToMeters(300), physics.pixelsToMeters(200));
|
||||
circle.game = game;
|
||||
var shape = new Phaser.Physics.Advanced.Shapes.Circle(0.4, 0, 0);
|
||||
shape.elasticity = 0.8;
|
||||
shape.friction = 1;
|
||||
shape.density = 1;
|
||||
circle.addShape(shape);
|
||||
circle.resetMassData();
|
||||
physics.space.addBody(circle);
|
||||
}
|
||||
function update() {
|
||||
physics.update();
|
||||
atari.x = physics.metersToPixels(circle.position.x);
|
||||
atari.y = physics.metersToPixels(circle.position.y);
|
||||
atari.rotation = physics.metersToPixels(circle.angle);
|
||||
// force moves without rotating
|
||||
if(game.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
|
||||
circle.applyAngularImpulse(-0.02);
|
||||
} else if(game.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
|
||||
circle.applyAngularImpulse(0.02);
|
||||
}
|
||||
/*
|
||||
if (game.input.keyboard.isDown(Phaser.Keyboard.LEFT))
|
||||
{
|
||||
circle.applyForceToCenter(new Phaser.Vec2(-8, 0));
|
||||
}
|
||||
else if (game.input.keyboard.isDown(Phaser.Keyboard.RIGHT))
|
||||
{
|
||||
circle.applyForceToCenter(new Phaser.Vec2(8, 0));
|
||||
}
|
||||
*/
|
||||
if(game.input.keyboard.isDown(Phaser.Keyboard.UP)) {
|
||||
circle.applyForceToCenter(new Phaser.Vec2(0, -10));
|
||||
} else if(game.input.keyboard.isDown(Phaser.Keyboard.DOWN)) {
|
||||
circle.applyForceToCenter(new Phaser.Vec2(0, 5));
|
||||
}
|
||||
//console.log(circle.velocity.x, circle.velocity.y);
|
||||
//console.log('p', circle.position.x, circle.position.y);
|
||||
}
|
||||
function renderCircle(shape) {
|
||||
game.stage.context.beginPath();
|
||||
game.stage.context.arc(shape.tc.x * 50, shape.tc.y * 50, shape.radius * 50, 0, Math.PI * 2, false);
|
||||
if(shape.body.isAwake) {
|
||||
game.stage.context.fillStyle = 'rgba(0,255,0, 0.3)';
|
||||
} else {
|
||||
game.stage.context.fillStyle = 'rgba(100,100,100, 0.1)';
|
||||
}
|
||||
game.stage.context.fill();
|
||||
game.stage.context.closePath();
|
||||
}
|
||||
function drawPolygon(ctx, shape, lineWidth, fillStyle) {
|
||||
var verts = shape.verts;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(verts[0].x * 50, verts[0].y * 50);
|
||||
for(var i = 0; i < verts.length; i++) {
|
||||
ctx.lineTo(verts[i].x * 50, verts[i].y * 50);
|
||||
}
|
||||
ctx.lineTo(verts[verts.length - 1].x * 50, verts[verts.length - 1].y * 50);
|
||||
ctx.closePath();
|
||||
ctx.fillStyle = fillStyle;
|
||||
ctx.fill();
|
||||
}
|
||||
function render() {
|
||||
game.stage.context.fillStyle = 'rgb(255,255,0)';
|
||||
game.stage.context.fillText('x: ' + circle.position.x + ' y: ' + circle.position.y, 32, 32);
|
||||
game.stage.context.fillText('vx: ' + circle.velocity.x + ' vy: ' + circle.velocity.y, 32, 64);
|
||||
renderCircle(circle.shapes[0]);
|
||||
drawPolygon(game.stage.context, walls.shapes[0], 1, 'rgb(0,255,255)');
|
||||
}
|
||||
})();
|
160
Tests/physics/body1.ts
Normal file
160
Tests/physics/body1.ts
Normal file
|
@ -0,0 +1,160 @@
|
|||
/// <reference path="../../Phaser/Game.ts" />
|
||||
/// <reference path="../../Phaser/physics/advanced/Manager.ts" />
|
||||
/// <reference path="../../Phaser/physics/advanced/shapes/Box.ts" />
|
||||
/// <reference path="../../Phaser/physics/advanced/shapes/Circle.ts" />
|
||||
|
||||
(function () {
|
||||
|
||||
var game = new Phaser.Game(this, 'game', 800, 600, init, create, update, render);
|
||||
|
||||
function init() {
|
||||
|
||||
game.load.image('xatari', 'assets/sprites/atari800xl.png');
|
||||
game.load.image('card', 'assets/sprites/mana_card.png');
|
||||
game.load.image('atari', 'assets/sprites/shinyball.png');
|
||||
game.load.start();
|
||||
|
||||
}
|
||||
|
||||
var atari: Phaser.Sprite;
|
||||
var card: Phaser.Sprite;
|
||||
var physics: Phaser.Physics.Advanced.Manager;
|
||||
var circle: Phaser.Physics.Advanced.Body;
|
||||
var walls: Phaser.Physics.Advanced.Body;
|
||||
|
||||
var ground: Phaser.Physics.Advanced.Shapes.Box;
|
||||
|
||||
function create() {
|
||||
|
||||
atari = game.add.sprite(200, 100, 'atari');
|
||||
atari.transform.origin.setTo(0.5, 0.5);
|
||||
//card = game.add.sprite(500, 300, 'card');
|
||||
|
||||
physics = new Phaser.Physics.Advanced.Manager(game);
|
||||
|
||||
walls = new Phaser.Physics.Advanced.Body(null, Phaser.Types.BODY_STATIC);
|
||||
walls.game = game;
|
||||
|
||||
// position is in relation to the containing body! don't forget this
|
||||
ground = walls.addShape(new Phaser.Physics.Advanced.Shapes.Box(400, 500, 500, 20));
|
||||
|
||||
//walls.addShape(new Phaser.Physics.Advanced.ShapeBox(0, 0.2, 20.48, 0.4));
|
||||
//walls.addShape(new Phaser.Physics.Advanced.ShapeBox(0, 15.16, 20.48, 0.4));
|
||||
//walls.addShape(new Phaser.Physics.Advanced.ShapeBox(-10.04, 7.68, 0.4, 14.56));
|
||||
//walls.addShape(new Phaser.Physics.Advanced.ShapeBox(10.04, 7.68, 0.4, 14.56));
|
||||
walls.resetMassData();
|
||||
|
||||
physics.space.addBody(walls);
|
||||
|
||||
// Add a circle
|
||||
|
||||
circle = new Phaser.Physics.Advanced.Body(null, Phaser.Types.BODY_DYNAMIC, physics.pixelsToMeters(300), physics.pixelsToMeters(200));
|
||||
circle.game = game;
|
||||
|
||||
var shape = new Phaser.Physics.Advanced.Shapes.Circle(0.4, 0, 0);
|
||||
shape.elasticity = 0.8;
|
||||
shape.friction = 1;
|
||||
shape.density = 1;
|
||||
circle.addShape(shape);
|
||||
circle.resetMassData();
|
||||
|
||||
physics.space.addBody(circle);
|
||||
|
||||
}
|
||||
|
||||
function update() {
|
||||
|
||||
physics.update();
|
||||
|
||||
atari.x = physics.metersToPixels(circle.position.x);
|
||||
atari.y = physics.metersToPixels(circle.position.y);
|
||||
atari.rotation = physics.metersToPixels(circle.angle);
|
||||
|
||||
// force moves without rotating
|
||||
|
||||
if (game.input.keyboard.isDown(Phaser.Keyboard.LEFT))
|
||||
{
|
||||
circle.applyAngularImpulse(-0.02);
|
||||
}
|
||||
else if (game.input.keyboard.isDown(Phaser.Keyboard.RIGHT))
|
||||
{
|
||||
circle.applyAngularImpulse(0.02);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
if (game.input.keyboard.isDown(Phaser.Keyboard.LEFT))
|
||||
{
|
||||
circle.applyForceToCenter(new Phaser.Vec2(-8, 0));
|
||||
}
|
||||
else if (game.input.keyboard.isDown(Phaser.Keyboard.RIGHT))
|
||||
{
|
||||
circle.applyForceToCenter(new Phaser.Vec2(8, 0));
|
||||
}
|
||||
*/
|
||||
|
||||
if (game.input.keyboard.isDown(Phaser.Keyboard.UP))
|
||||
{
|
||||
circle.applyForceToCenter(new Phaser.Vec2(0, -10));
|
||||
}
|
||||
else if (game.input.keyboard.isDown(Phaser.Keyboard.DOWN))
|
||||
{
|
||||
circle.applyForceToCenter(new Phaser.Vec2(0, 5));
|
||||
}
|
||||
|
||||
//console.log(circle.velocity.x, circle.velocity.y);
|
||||
//console.log('p', circle.position.x, circle.position.y);
|
||||
}
|
||||
|
||||
function renderCircle(shape) {
|
||||
|
||||
game.stage.context.beginPath();
|
||||
game.stage.context.arc(shape.tc.x * 50, shape.tc.y * 50, shape.radius * 50, 0, Math.PI * 2, false);
|
||||
|
||||
if (shape.body.isAwake)
|
||||
{
|
||||
game.stage.context.fillStyle = 'rgba(0,255,0, 0.3)';
|
||||
}
|
||||
else
|
||||
{
|
||||
game.stage.context.fillStyle = 'rgba(100,100,100, 0.1)';
|
||||
}
|
||||
|
||||
game.stage.context.fill();
|
||||
game.stage.context.closePath();
|
||||
|
||||
}
|
||||
|
||||
function drawPolygon(ctx, shape, lineWidth, fillStyle) {
|
||||
|
||||
var verts = shape.verts;
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(verts[0].x * 50, verts[0].y * 50);
|
||||
|
||||
for (var i = 0; i < verts.length; i++) {
|
||||
ctx.lineTo(verts[i].x * 50, verts[i].y * 50);
|
||||
}
|
||||
|
||||
ctx.lineTo(verts[verts.length - 1].x * 50, verts[verts.length - 1].y * 50);
|
||||
|
||||
ctx.closePath();
|
||||
|
||||
ctx.fillStyle = fillStyle;
|
||||
ctx.fill();
|
||||
|
||||
}
|
||||
|
||||
function render() {
|
||||
|
||||
game.stage.context.fillStyle = 'rgb(255,255,0)';
|
||||
game.stage.context.fillText('x: ' + circle.position.x + ' y: ' + circle.position.y, 32, 32);
|
||||
game.stage.context.fillText('vx: ' + circle.velocity.x + ' vy: ' + circle.velocity.y, 32, 64);
|
||||
|
||||
renderCircle(circle.shapes[0]);
|
||||
|
||||
drawPolygon(game.stage.context, walls.shapes[0], 1, 'rgb(0,255,255)');
|
||||
|
||||
}
|
||||
|
||||
})();
|
33
Tests/physics/obb vs obb.js
Normal file
33
Tests/physics/obb vs obb.js
Normal file
|
@ -0,0 +1,33 @@
|
|||
/// <reference path="../../Phaser/Game.ts" />
|
||||
(function () {
|
||||
var game = new Phaser.Game(this, 'game', 800, 600, init, create, update, render);
|
||||
function init() {
|
||||
// Using Phasers asset loader we load up a PNG from the assets folder
|
||||
game.load.image('atari', 'assets/sprites/atari800xl.png');
|
||||
game.load.image('card', 'assets/sprites/mana_card.png');
|
||||
game.load.start();
|
||||
}
|
||||
var atari;
|
||||
var card;
|
||||
function create() {
|
||||
atari = game.add.sprite(200, 310, 'atari');
|
||||
card = game.add.sprite(500, 300, 'card');
|
||||
atari.input.start(0);
|
||||
atari.input.enableDrag();
|
||||
card.input.start(0);
|
||||
card.events.onInputDown.add(rotateIt, this);
|
||||
}
|
||||
function rotateIt() {
|
||||
card.rotation += 10;
|
||||
}
|
||||
function update() {
|
||||
}
|
||||
function render() {
|
||||
game.stage.context.save();
|
||||
game.stage.context.strokeStyle = 'rgb(255,255,0)';
|
||||
game.stage.context.strokeRect(atari.cameraView.x, atari.cameraView.y, atari.cameraView.width, atari.cameraView.height);
|
||||
game.stage.context.strokeStyle = 'rgb(255,0,255)';
|
||||
game.stage.context.strokeRect(card.cameraView.x, card.cameraView.y, card.cameraView.width, card.cameraView.height);
|
||||
game.stage.context.restore();
|
||||
}
|
||||
})();
|
54
Tests/physics/obb vs obb.ts
Normal file
54
Tests/physics/obb vs obb.ts
Normal file
|
@ -0,0 +1,54 @@
|
|||
/// <reference path="../../Phaser/Game.ts" />
|
||||
|
||||
(function () {
|
||||
|
||||
var game = new Phaser.Game(this, 'game', 800, 600, init, create, update, render);
|
||||
|
||||
function init() {
|
||||
|
||||
// Using Phasers asset loader we load up a PNG from the assets folder
|
||||
game.load.image('atari', 'assets/sprites/atari800xl.png');
|
||||
game.load.image('card', 'assets/sprites/mana_card.png');
|
||||
game.load.start();
|
||||
|
||||
}
|
||||
|
||||
var atari: Phaser.Sprite;
|
||||
var card: Phaser.Sprite;
|
||||
|
||||
function create() {
|
||||
|
||||
atari = game.add.sprite(200, 310, 'atari');
|
||||
|
||||
card = game.add.sprite(500, 300, 'card');
|
||||
|
||||
atari.input.start(0);
|
||||
atari.input.enableDrag();
|
||||
|
||||
card.input.start(0);
|
||||
card.events.onInputDown.add(rotateIt, this);
|
||||
|
||||
}
|
||||
|
||||
function rotateIt() {
|
||||
card.rotation += 10;
|
||||
}
|
||||
|
||||
function update() {
|
||||
}
|
||||
|
||||
function render() {
|
||||
|
||||
game.stage.context.save();
|
||||
|
||||
game.stage.context.strokeStyle = 'rgb(255,255,0)';
|
||||
game.stage.context.strokeRect(atari.cameraView.x, atari.cameraView.y, atari.cameraView.width, atari.cameraView.height);
|
||||
|
||||
game.stage.context.strokeStyle = 'rgb(255,0,255)';
|
||||
game.stage.context.strokeRect(card.cameraView.x, card.cameraView.y, card.cameraView.width, card.cameraView.height);
|
||||
|
||||
game.stage.context.restore();
|
||||
|
||||
}
|
||||
|
||||
})();
|
712
build/phaser.d.ts
vendored
712
build/phaser.d.ts
vendored
|
@ -572,6 +572,12 @@ module Phaser {
|
|||
*/
|
||||
public lengthSq(): number;
|
||||
/**
|
||||
* Normalize this vector.
|
||||
*
|
||||
* @return {Vec2} This for chaining.
|
||||
*/
|
||||
public normalize(): Vec2;
|
||||
/**
|
||||
* The dot product of two 2D vectors.
|
||||
*
|
||||
* @param {Vec2} a Reference to a source Vec2 object.
|
||||
|
@ -615,6 +621,14 @@ module Phaser {
|
|||
*/
|
||||
public multiplyByScalar(scalar: number): Vec2;
|
||||
/**
|
||||
* Adds the given vector to this vector then multiplies by the given scalar.
|
||||
*
|
||||
* @param {Vec2} a Reference to a source Vec2 object.
|
||||
* @param {number} scalar
|
||||
* @return {Vec2} This for chaining.
|
||||
*/
|
||||
public multiplyAddByScalar(a: Vec2, scalar: number): Vec2;
|
||||
/**
|
||||
* Divide this vector by the given scalar.
|
||||
*
|
||||
* @param {number} scalar
|
||||
|
@ -822,9 +836,9 @@ module Phaser {
|
|||
static GEOM_LINE: number;
|
||||
static GEOM_POLYGON: number;
|
||||
static BODY_DISABLED: number;
|
||||
static BODY_DYNAMIC: number;
|
||||
static BODY_STATIC: number;
|
||||
static BODY_KINEMATIC: number;
|
||||
static BODY_KINETIC: number;
|
||||
static BODY_DYNAMIC: number;
|
||||
/**
|
||||
* Flag used to allow GameObjects to collide on their left side
|
||||
* @type {number}
|
||||
|
@ -2378,7 +2392,25 @@ module Phaser {
|
|||
*/
|
||||
static scale(a: Vec2, s: number, out?: Vec2): Vec2;
|
||||
/**
|
||||
* Rotate a 2D vector by 90 degrees.
|
||||
* Adds two 2D vectors together and multiplies the result by the given scalar.
|
||||
*
|
||||
* @param {Vec2} a Reference to a source Vec2 object.
|
||||
* @param {Vec2} b Reference to a source Vec2 object.
|
||||
* @param {number} s Scaling value.
|
||||
* @param {Vec2} out The output Vec2 that is the result of the operation.
|
||||
* @return {Vec2} A Vec2 that is the sum of the two vectors added and multiplied.
|
||||
*/
|
||||
static multiplyAdd(a: Vec2, b: Vec2, s: number, out?: Vec2): Vec2;
|
||||
/**
|
||||
* Return a negative vector.
|
||||
*
|
||||
* @param {Vec2} a Reference to a source Vec2 object.
|
||||
* @param {Vec2} out The output Vec2 that is the result of the operation.
|
||||
* @return {Vec2} A Vec2 that is the negative vector.
|
||||
*/
|
||||
static negative(a: Vec2, out?: Vec2): Vec2;
|
||||
/**
|
||||
* Return a perpendicular vector (90 degrees rotation)
|
||||
*
|
||||
* @param {Vec2} a Reference to a source Vec2 object.
|
||||
* @param {Vec2} out The output Vec2 that is the result of the operation.
|
||||
|
@ -2386,6 +2418,14 @@ module Phaser {
|
|||
*/
|
||||
static perp(a: Vec2, out?: Vec2): Vec2;
|
||||
/**
|
||||
* Return a perpendicular vector (-90 degrees rotation)
|
||||
*
|
||||
* @param {Vec2} a Reference to a source Vec2 object.
|
||||
* @param {Vec2} out The output Vec2 that is the result of the operation.
|
||||
* @return {Vec2} A Vec2 that is the scaled vector.
|
||||
*/
|
||||
static rperp(a: Vec2, out?: Vec2): Vec2;
|
||||
/**
|
||||
* Checks if two 2D vectors are equal.
|
||||
*
|
||||
* @param {Vec2} a Reference to a source Vec2 object.
|
||||
|
@ -2493,7 +2533,17 @@ module Phaser {
|
|||
* @param {Vec2} out The output Vec2 that is the result of the operation.
|
||||
* @return {Vec2} A Vec2.
|
||||
*/
|
||||
static rotate(a: Vec2, b: Vec2, theta: number, out?: Vec2): Vec2;
|
||||
static rotateAroundOrigin(a: Vec2, b: Vec2, theta: number, out?: Vec2): Vec2;
|
||||
/**
|
||||
* Rotate a 2D vector to the given angle (theta).
|
||||
*
|
||||
* @param {Vec2} a Reference to a source Vec2 object.
|
||||
* @param {Vec2} b Reference to a source Vec2 object.
|
||||
* @param {Number} theta The angle of rotation in radians.
|
||||
* @param {Vec2} out The output Vec2 that is the result of the operation.
|
||||
* @return {Vec2} A Vec2.
|
||||
*/
|
||||
static rotate(a: Vec2, theta: number, out?: Vec2): Vec2;
|
||||
/**
|
||||
* Clone a 2D vector.
|
||||
*
|
||||
|
@ -3832,8 +3882,22 @@ module Phaser {
|
|||
* @return {object} The text data you want.
|
||||
*/
|
||||
public getText(key: string);
|
||||
/**
|
||||
* Returns an array containing all of the keys of Images in the Cache.
|
||||
* @return {Array} The string based keys in the Cache.
|
||||
*/
|
||||
public getImageKeys(): any[];
|
||||
/**
|
||||
* Returns an array containing all of the keys of Sounds in the Cache.
|
||||
* @return {Array} The string based keys in the Cache.
|
||||
*/
|
||||
public getSoundKeys(): any[];
|
||||
/**
|
||||
* Returns an array containing all of the keys of Text Files in the Cache.
|
||||
* @return {Array} The string based keys in the Cache.
|
||||
*/
|
||||
public getTextKeys(): any[];
|
||||
/**
|
||||
* Clean up cache memory.
|
||||
*/
|
||||
public destroy(): void;
|
||||
|
@ -7215,7 +7279,7 @@ module Phaser {
|
|||
private _groupCounter;
|
||||
public getNextGroupID(): number;
|
||||
/**
|
||||
* Called one by Game during the boot process.
|
||||
* Called once by Game during the boot process.
|
||||
*/
|
||||
public boot(): void;
|
||||
/**
|
||||
|
@ -9349,6 +9413,644 @@ module Phaser {
|
|||
}
|
||||
}
|
||||
/**
|
||||
* Phaser - 2D Transform
|
||||
*
|
||||
* A 2D Transform
|
||||
*/
|
||||
module Phaser {
|
||||
class Transform {
|
||||
/**
|
||||
* Creates a new 2D Transform object.
|
||||
* @class Transform
|
||||
* @constructor
|
||||
* @return {Transform} This object
|
||||
**/
|
||||
constructor(pos: Vec2, angle: number);
|
||||
public t: Vec2;
|
||||
public c: number;
|
||||
public s: number;
|
||||
public setTo(pos: Vec2, angle: number): Transform;
|
||||
public setRotation(angle: number): Transform;
|
||||
public setPosition(p: Vec2): Transform;
|
||||
public identity(): Transform;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Phaser - TransformUtils
|
||||
*
|
||||
* A collection of methods useful for manipulating and performing operations on 2D Transforms.
|
||||
*
|
||||
*/
|
||||
module Phaser {
|
||||
class TransformUtils {
|
||||
static rotate(t: Transform, v: Vec2, out?: Vec2): Vec2;
|
||||
static unrotate(t: Transform, v: Vec2, out?: Vec2): Vec2;
|
||||
static transform(t: Transform, v: Vec2, out?: Vec2): Vec2;
|
||||
static untransform(t: Transform, v: Vec2, out?: Vec2): Vec2;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Phaser - PhysicsManager
|
||||
*
|
||||
* Your game only has one PhysicsManager instance and it's responsible for looking after, creating and colliding
|
||||
* all of the physics objects in the world.
|
||||
*/
|
||||
module Phaser.Physics {
|
||||
class ArcadePhysics {
|
||||
constructor(game: Game, width: number, height: number);
|
||||
/**
|
||||
* Local private reference to Game.
|
||||
*/
|
||||
public game: Game;
|
||||
/**
|
||||
* Physics object pool
|
||||
*/
|
||||
public members: Group;
|
||||
private _drag;
|
||||
private _delta;
|
||||
private _velocityDelta;
|
||||
private _length;
|
||||
private _distance;
|
||||
private _tangent;
|
||||
private _separatedX;
|
||||
private _separatedY;
|
||||
private _overlap;
|
||||
private _maxOverlap;
|
||||
private _obj1Velocity;
|
||||
private _obj2Velocity;
|
||||
private _obj1NewVelocity;
|
||||
private _obj2NewVelocity;
|
||||
private _average;
|
||||
private _quadTree;
|
||||
private _quadTreeResult;
|
||||
public bounds: Rectangle;
|
||||
public gravity: Vec2;
|
||||
public drag: Vec2;
|
||||
public bounce: Vec2;
|
||||
public angularDrag: number;
|
||||
/**
|
||||
* The overlap bias is used when calculating hull overlap before separation - change it if you have especially small or large GameObjects
|
||||
* @type {number}
|
||||
*/
|
||||
static OVERLAP_BIAS: number;
|
||||
/**
|
||||
* The overlap bias is used when calculating hull overlap before separation - change it if you have especially small or large GameObjects
|
||||
* @type {number}
|
||||
*/
|
||||
static TILE_OVERLAP: bool;
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
public worldDivisions: number;
|
||||
public updateMotion(body: Body): void;
|
||||
/**
|
||||
* A tween-like function that takes a starting velocity and some other factors and returns an altered velocity.
|
||||
*
|
||||
* @param {number} Velocity Any component of velocity (e.g. 20).
|
||||
* @param {number} Acceleration Rate at which the velocity is changing.
|
||||
* @param {number} Drag Really kind of a deceleration, this is how much the velocity changes if Acceleration is not set.
|
||||
* @param {number} Max An absolute value cap for the velocity.
|
||||
*
|
||||
* @return {number} The altered Velocity value.
|
||||
*/
|
||||
public computeVelocity(velocity: number, gravity?: number, acceleration?: number, drag?: number, max?: number): number;
|
||||
/**
|
||||
* The core Collision separation method.
|
||||
* @param body1 The first Physics.Body to separate
|
||||
* @param body2 The second Physics.Body to separate
|
||||
* @returns {boolean} Returns true if the bodies were separated, otherwise false.
|
||||
*/
|
||||
public separate(body1: Body, body2: Body): bool;
|
||||
public checkHullIntersection(body1: Body, body2: Body): bool;
|
||||
/**
|
||||
* Separates the two objects on their x axis
|
||||
* @param object1 The first GameObject to separate
|
||||
* @param object2 The second GameObject to separate
|
||||
* @returns {boolean} Whether the objects in fact touched and were separated along the X axis.
|
||||
*/
|
||||
public separateBodyX(body1: Body, body2: Body): bool;
|
||||
/**
|
||||
* Separates the two objects on their y axis
|
||||
* @param object1 The first GameObject to separate
|
||||
* @param object2 The second GameObject to separate
|
||||
* @returns {boolean} Whether the objects in fact touched and were separated along the Y axis.
|
||||
*/
|
||||
public separateBodyY(body1: Body, body2: Body): bool;
|
||||
/**
|
||||
* Checks for overlaps between two objects using the world QuadTree. Can be Sprite vs. Sprite, Sprite vs. Group or Group vs. Group.
|
||||
* Note: Does not take the objects scrollFactor into account. All overlaps are check in world space.
|
||||
* @param object1 The first Sprite or Group to check. If null the world.group is used.
|
||||
* @param object2 The second Sprite or Group to check.
|
||||
* @param notifyCallback A callback function that is called if the objects overlap. The two objects will be passed to this function in the same order in which you passed them to Collision.overlap.
|
||||
* @param processCallback A callback function that lets you perform additional checks against the two objects if they overlap. If this is set then notifyCallback will only be called if processCallback returns true.
|
||||
* @param context The context in which the callbacks will be called
|
||||
* @returns {boolean} true if the objects overlap, otherwise false.
|
||||
*/
|
||||
public overlap(object1?, object2?, notifyCallback?, processCallback?, context?): bool;
|
||||
/**
|
||||
* Collision resolution specifically for GameObjects vs. Tiles.
|
||||
* @param object The GameObject to separate
|
||||
* @param tile The Tile to separate
|
||||
* @returns {boolean} Whether the objects in fact touched and were separated
|
||||
*/
|
||||
public separateTile(object: Sprite, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool, collideUp: bool, collideDown: bool, separateX: bool, separateY: bool): bool;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Phaser - Advanced Physics - Joint
|
||||
*
|
||||
* Based on the work Ju Hyung Lee started in JS PhyRus.
|
||||
*/
|
||||
module Phaser.Physics.Advanced {
|
||||
class Joint {
|
||||
constructor(type: number, body1: Body, body2: Body, collideConnected);
|
||||
public id: number;
|
||||
public type: number;
|
||||
public body1: Body;
|
||||
public body2: Body;
|
||||
public collideConnected;
|
||||
public maxForce: number;
|
||||
public breakable: bool;
|
||||
public anchor1: Vec2;
|
||||
public anchor2: Vec2;
|
||||
public getWorldAnchor1(): Vec2;
|
||||
public getWorldAnchor2(): Vec2;
|
||||
public setWorldAnchor1(anchor1): void;
|
||||
public setWorldAnchor2(anchor2): void;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Phaser - Advanced Physics Manager
|
||||
*
|
||||
* Your game only has one PhysicsManager instance and it's responsible for looking after, creating and colliding
|
||||
* all of the physics objects in the world.
|
||||
*/
|
||||
module Phaser.Physics.Advanced {
|
||||
class Manager {
|
||||
constructor(game: Game);
|
||||
/**
|
||||
* Local reference to Game.
|
||||
*/
|
||||
public game: Game;
|
||||
static collision: Collision;
|
||||
static SHAPE_TYPE_CIRCLE: number;
|
||||
static SHAPE_TYPE_SEGMENT: number;
|
||||
static SHAPE_TYPE_POLY: number;
|
||||
static SHAPE_NUM_TYPES: number;
|
||||
static JOINT_TYPE_ANGLE: number;
|
||||
static JOINT_TYPE_REVOLUTE: number;
|
||||
static JOINT_TYPE_WELD: number;
|
||||
static JOINT_TYPE_WHEEL: number;
|
||||
static JOINT_TYPE_PRISMATIC: number;
|
||||
static JOINT_TYPE_DISTANCE: number;
|
||||
static JOINT_TYPE_ROPE: number;
|
||||
static JOINT_TYPE_MOUSE: number;
|
||||
static JOINT_LINEAR_SLOP: number;
|
||||
static JOINT_ANGULAR_SLOP: number;
|
||||
static JOINT_MAX_LINEAR_CORRECTION: number;
|
||||
static JOINT_MAX_ANGULAR_CORRECTION: number;
|
||||
static JOINT_LIMIT_STATE_INACTIVE: number;
|
||||
static JOINT_LIMIT_STATE_AT_LOWER: number;
|
||||
static JOINT_LIMIT_STATE_AT_UPPER: number;
|
||||
static JOINT_LIMIT_STATE_EQUAL_LIMITS: number;
|
||||
static CONTACT_SOLVER_COLLISION_SLOP: number;
|
||||
static CONTACT_SOLVER_BAUMGARTE: number;
|
||||
static CONTACT_SOLVER_MAX_LINEAR_CORRECTION: number;
|
||||
static bodyCounter: number;
|
||||
static jointCounter: number;
|
||||
static shapeCounter: number;
|
||||
public space: Space;
|
||||
public lastTime: number;
|
||||
public frameRateHz: number;
|
||||
public timeDelta: number;
|
||||
public paused: bool;
|
||||
public step: bool;
|
||||
public velocityIterations: number;
|
||||
public positionIterations: number;
|
||||
public allowSleep: bool;
|
||||
public warmStarting: bool;
|
||||
public update(): void;
|
||||
public pixelsToMeters(value: number): number;
|
||||
public metersToPixels(value: number): number;
|
||||
static pixelsToMeters(value: number): number;
|
||||
static metersToPixels(value: number): number;
|
||||
static p2m(value: number): number;
|
||||
static m2p(value: number): number;
|
||||
static areaForCircle(radius_outer, radius_inner): number;
|
||||
static inertiaForCircle(mass, center, radius_outer, radius_inner): number;
|
||||
static areaForSegment(a, b, radius): number;
|
||||
static centroidForSegment(a, b): Vec2;
|
||||
static inertiaForSegment(mass, a, b): number;
|
||||
static areaForPoly(verts): number;
|
||||
static centroidForPoly(verts): Vec2;
|
||||
static inertiaForPoly(mass, verts, offset): number;
|
||||
static inertiaForBox(mass, w, h): number;
|
||||
static createConvexHull(points): any[];
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Phaser - 2D AABB
|
||||
*
|
||||
* A 2D AABB object
|
||||
*/
|
||||
module Phaser.Physics.Advanced {
|
||||
class Bounds {
|
||||
/**
|
||||
* Creates a new 2D AABB object.
|
||||
* @class Bounds
|
||||
* @constructor
|
||||
* @return {Bounds} This object
|
||||
**/
|
||||
constructor(mins?: Vec2, maxs?: Vec2);
|
||||
public mins: Vec2;
|
||||
public maxs: Vec2;
|
||||
public toString(): string;
|
||||
public setTo(mins: Vec2, maxs: Vec2): void;
|
||||
public copy(b: Bounds): Bounds;
|
||||
public clear(): Bounds;
|
||||
public isEmpty(): bool;
|
||||
public getPerimeter(): number;
|
||||
public addPoint(p: Vec2): Bounds;
|
||||
public addBounds(b: Bounds): Bounds;
|
||||
public addBounds2(mins, maxs): Bounds;
|
||||
public addExtents(center: Vec2, extent_x: number, extent_y: number): Bounds;
|
||||
public expand(ax: number, ay: number): Bounds;
|
||||
public containPoint(p: Vec2): bool;
|
||||
public intersectsBounds(b: Bounds): bool;
|
||||
static expand(b: Bounds, ax, ay);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Phaser - Advanced Physics - IShape
|
||||
*
|
||||
* Based on the work Ju Hyung Lee started in JS PhyRus.
|
||||
*/
|
||||
module Phaser.Physics.Advanced {
|
||||
interface IShape {
|
||||
id: number;
|
||||
type: number;
|
||||
elasticity: number;
|
||||
friction: number;
|
||||
density: number;
|
||||
body: Body;
|
||||
bounds: Bounds;
|
||||
area(): number;
|
||||
centroid(): Vec2;
|
||||
inertia(mass: number): number;
|
||||
cacheData(xf: Transform);
|
||||
pointQuery(p: Vec2): bool;
|
||||
findEdgeByPoint(p: Vec2, minDist: number): number;
|
||||
findVertexByPoint(p: Vec2, minDist: number): number;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Phaser - Advanced Physics - Shape
|
||||
*
|
||||
* Based on the work Ju Hyung Lee started in JS PhyRus.
|
||||
*/
|
||||
module Phaser.Physics.Advanced {
|
||||
class Shape {
|
||||
constructor(type: number);
|
||||
public id: number;
|
||||
public type: number;
|
||||
public body: Body;
|
||||
public elasticity: number;
|
||||
public friction: number;
|
||||
public density: number;
|
||||
public bounds: Bounds;
|
||||
public findEdgeByPoint(p: Vec2, minDist: number): number;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Phaser - Advanced Physics - Contact
|
||||
*
|
||||
* Based on the work Ju Hyung Lee started in JS PhyRus.
|
||||
*/
|
||||
module Phaser.Physics.Advanced {
|
||||
class Contact {
|
||||
constructor(p, n, d, hash);
|
||||
public hash;
|
||||
public r1: Vec2;
|
||||
public r2: Vec2;
|
||||
public r1_local: Vec2;
|
||||
public r2_local: Vec2;
|
||||
public bounce: number;
|
||||
public emn: number;
|
||||
public emt: number;
|
||||
public point;
|
||||
public normal: Vec2;
|
||||
public depth;
|
||||
public lambdaNormal;
|
||||
public lambdaTangential;
|
||||
}
|
||||
}
|
||||
module Phaser.Physics.Advanced {
|
||||
class ContactSolver {
|
||||
constructor(shape1, shape2);
|
||||
public shape1;
|
||||
public shape2;
|
||||
public contacts: Contact[];
|
||||
public elasticity: number;
|
||||
public friction: number;
|
||||
public update(newContactArr: Contact[]): void;
|
||||
public initSolver(dt_inv): void;
|
||||
public warmStart(): void;
|
||||
public solveVelocityConstraints(): void;
|
||||
public solvePositionConstraints(): bool;
|
||||
public clamp(v, min, max);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Phaser - Advanced Physics - Shape - Circle
|
||||
*
|
||||
* Based on the work Ju Hyung Lee started in JS PhyRus.
|
||||
*/
|
||||
module Phaser.Physics.Advanced.Shapes {
|
||||
class Circle extends Shape implements IShape {
|
||||
constructor(radius: number, x?: number, y?: number);
|
||||
public radius: number;
|
||||
public center: Vec2;
|
||||
public tc: Vec2;
|
||||
public finishVerts(): void;
|
||||
public duplicate(): Circle;
|
||||
public recenter(c: Vec2): void;
|
||||
public transform(xf: Transform): void;
|
||||
public untransform(xf: Transform): void;
|
||||
public area(): number;
|
||||
public centroid(): Vec2;
|
||||
public inertia(mass: number): number;
|
||||
public cacheData(xf: Transform): void;
|
||||
public pointQuery(p: Vec2): bool;
|
||||
public findVertexByPoint(p: Vec2, minDist: number): number;
|
||||
public distanceOnPlane(n, d): void;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Phaser - Advanced Physics - Shapes - Convex Polygon
|
||||
*
|
||||
* Based on the work Ju Hyung Lee started in JS PhyRus.
|
||||
*/
|
||||
module Phaser.Physics.Advanced.Shapes {
|
||||
class Poly extends Shape implements IShape {
|
||||
constructor(verts?: Vec2[]);
|
||||
public verts: Vec2[];
|
||||
public planes;
|
||||
public tverts;
|
||||
public tplanes;
|
||||
public convexity: bool;
|
||||
public finishVerts(): void;
|
||||
public duplicate(): Poly;
|
||||
public recenter(c): void;
|
||||
public transform(xf): void;
|
||||
public untransform(xf): void;
|
||||
public area(): number;
|
||||
public centroid(): Vec2;
|
||||
public inertia(mass: number): number;
|
||||
public cacheData(xf: Transform): void;
|
||||
public pointQuery(p: Vec2): bool;
|
||||
public findVertexByPoint(p: Vec2, minDist: number): number;
|
||||
public findEdgeByPoint(p: Vec2, minDist: number): number;
|
||||
public distanceOnPlane(n, d): number;
|
||||
public containPoint(p): bool;
|
||||
public containPointPartial(p, n): bool;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Phaser - Advanced Physics - Shapes - Segment
|
||||
*
|
||||
* Based on the work Ju Hyung Lee started in JS PhyRus.
|
||||
*/
|
||||
module Phaser.Physics.Advanced.Shapes {
|
||||
class Segment extends Shape implements IShape {
|
||||
constructor(a, b, radius: number);
|
||||
public a: Vec2;
|
||||
public b: Vec2;
|
||||
public radius: number;
|
||||
public normal: Vec2;
|
||||
public ta: Vec2;
|
||||
public tb: Vec2;
|
||||
public tn: Vec2;
|
||||
public finishVerts(): void;
|
||||
public duplicate(): Segment;
|
||||
public recenter(c): void;
|
||||
public transform(xf: Transform): void;
|
||||
public untransform(xf: Transform): void;
|
||||
public area(): number;
|
||||
public centroid(): Vec2;
|
||||
public inertia(mass: number): number;
|
||||
public cacheData(xf: Transform): void;
|
||||
public pointQuery(p: Vec2): bool;
|
||||
public findVertexByPoint(p: Vec2, minDist: number): number;
|
||||
public distanceOnPlane(n, d): number;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Phaser - Advanced Physics - Collision Handlers
|
||||
*
|
||||
* Based on the work Ju Hyung Lee started in JS PhyRus.
|
||||
*/
|
||||
module Phaser.Physics.Advanced {
|
||||
class Collision {
|
||||
constructor();
|
||||
public collide(a, b, contacts: Contact[]): number;
|
||||
private _circle2Circle(c1, r1, c2, r2, contactArr);
|
||||
public circle2Circle(circ1: Shapes.Circle, circ2: Shapes.Circle, contactArr: Contact[]): number;
|
||||
public circle2Segment(circ: Shapes.Circle, seg: Shapes.Segment, contactArr: Contact[]): number;
|
||||
public circle2Poly(circ: Shapes.Circle, poly: Shapes.Poly, contactArr: Contact[]): number;
|
||||
public segmentPointDistanceSq(seg: Shapes.Segment, p): number;
|
||||
public segment2Segment(seg1: Shapes.Segment, seg2: Shapes.Segment, contactArr: Contact[]): number;
|
||||
public findPointsBehindSeg(contactArr: Contact[], seg: Shapes.Segment, poly: Shapes.Poly, dist: number, coef: number): void;
|
||||
public segment2Poly(seg: Shapes.Segment, poly: Shapes.Poly, contactArr: Contact[]): number;
|
||||
public findMSA(poly: Shapes.Poly, planes, num: number): {
|
||||
dist: number;
|
||||
index: number;
|
||||
};
|
||||
public findVertsFallback(contactArr: Contact[], poly1: Shapes.Poly, poly2: Shapes.Poly, n, dist: number): number;
|
||||
public findVerts(contactArr: Contact[], poly1: Shapes.Poly, poly2: Shapes.Poly, n, dist: number): number;
|
||||
public poly2Poly(poly1: Shapes.Poly, poly2: Shapes.Poly, contactArr: Contact[]): number;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Phaser - Advanced Physics - Joint
|
||||
*
|
||||
* Based on the work Ju Hyung Lee started in JS PhyRus.
|
||||
*/
|
||||
module Phaser.Physics.Advanced {
|
||||
interface IJoint {
|
||||
id: number;
|
||||
type: number;
|
||||
body1: Body;
|
||||
body2: Body;
|
||||
collideConnected;
|
||||
maxForce: number;
|
||||
breakable: bool;
|
||||
anchor1: Vec2;
|
||||
anchor2: Vec2;
|
||||
getWorldAnchor1();
|
||||
getWorldAnchor2();
|
||||
setWorldAnchor1(anchor1);
|
||||
setWorldAnchor2(anchor2);
|
||||
initSolver(dt, warmStarting);
|
||||
solveVelocityConstraints();
|
||||
solvePositionConstraints();
|
||||
getReactionForce(dt_inv);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Phaser - Advanced Physics - Space
|
||||
*
|
||||
* Based on the work Ju Hyung Lee started in JS PhyRus.
|
||||
*/
|
||||
module Phaser.Physics.Advanced {
|
||||
class Space {
|
||||
constructor();
|
||||
static TIME_TO_SLEEP: number;
|
||||
static SLEEP_LINEAR_TOLERANCE: number;
|
||||
static SLEEP_ANGULAR_TOLERANCE: number;
|
||||
public bodyArr: Body[];
|
||||
public bodyHash;
|
||||
public jointArr: IJoint[];
|
||||
public jointHash;
|
||||
public numContacts: number;
|
||||
public contactSolvers: ContactSolver[];
|
||||
public postSolve;
|
||||
public gravity: Vec2;
|
||||
public damping: number;
|
||||
public stepCount: number;
|
||||
public clear(): void;
|
||||
public addBody(body: Body): void;
|
||||
public removeBody(body: Body): void;
|
||||
public addJoint(joint: IJoint): void;
|
||||
public removeJoint(joint: IJoint): void;
|
||||
public findShapeByPoint(p, refShape);
|
||||
public findBodyByPoint(p, refBody: Body);
|
||||
public shapeById(id): IShape;
|
||||
public jointById(id): IJoint;
|
||||
public findVertexByPoint(p, minDist, refVertexId): number;
|
||||
public findEdgeByPoint(p, minDist, refEdgeId): number;
|
||||
public findJointByPoint(p, minDist, refJointId): number;
|
||||
public findContactSolver(shape1, shape2): ContactSolver;
|
||||
public genTemporalContactSolvers(): any[];
|
||||
public initSolver(dt, dt_inv, warmStarting): void;
|
||||
public velocitySolver(iteration): void;
|
||||
public positionSolver(iteration): bool;
|
||||
public step(dt, vel_iteration, pos_iteration, warmStarting, allowSleep): void;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Phaser - Advanced Physics - Body
|
||||
*
|
||||
* Based on the work Ju Hyung Lee started in JS PhyRus.
|
||||
*/
|
||||
module Phaser.Physics.Advanced {
|
||||
class Body {
|
||||
constructor(sprite: Sprite, type: number, x?: number, y?: number);
|
||||
/**
|
||||
* Reference to Phaser.Game
|
||||
*/
|
||||
public game: Game;
|
||||
/**
|
||||
* Reference to the parent Sprite
|
||||
*/
|
||||
public sprite: Sprite;
|
||||
/**
|
||||
* The Body ID
|
||||
*/
|
||||
public id: number;
|
||||
/**
|
||||
* The Body name
|
||||
*/
|
||||
public name: string;
|
||||
/**
|
||||
* The type of Body (disabled, dynamic, static or kinematic)
|
||||
* Disabled = skips all physics operations / tests (default)
|
||||
* Dynamic = gives and receives impacts
|
||||
* Static = gives but doesn't receive impacts, cannot be moved by physics
|
||||
* Kinematic = gives impacts, but never receives, can be moved by physics
|
||||
* @type {number}
|
||||
*/
|
||||
public type: number;
|
||||
public angle: number;
|
||||
public transform: Transform;
|
||||
public centroid: Vec2;
|
||||
public position: Vec2;
|
||||
public velocity: Vec2;
|
||||
public force: Vec2;
|
||||
public angularVelocity: number;
|
||||
public torque: number;
|
||||
public linearDamping: number;
|
||||
public angularDamping: number;
|
||||
public sleepTime: number;
|
||||
public awaked: bool;
|
||||
public shapes: IShape[];
|
||||
public joints: IJoint[];
|
||||
public jointHash: {};
|
||||
public bounds: Bounds;
|
||||
public fixedRotation: bool;
|
||||
public categoryBits: number;
|
||||
public maskBits: number;
|
||||
public stepCount: number;
|
||||
public space: Space;
|
||||
public duplicate(): void;
|
||||
public isDisabled : bool;
|
||||
public isStatic : bool;
|
||||
public isKinetic : bool;
|
||||
public isDynamic : bool;
|
||||
public setType(type: number): void;
|
||||
public addShape(shape);
|
||||
public removeShape(shape): void;
|
||||
public mass: number;
|
||||
public massInverted: number;
|
||||
public inertia: number;
|
||||
public inertiaInverted: number;
|
||||
private setMass(mass);
|
||||
private setInertia(inertia);
|
||||
public setTransform(pos, angle): void;
|
||||
public syncTransform(): void;
|
||||
public getWorldPoint(p: Vec2): Vec2;
|
||||
public getWorldVector(v): Vec2;
|
||||
public getLocalPoint(p): Vec2;
|
||||
public getLocalVector(v): Vec2;
|
||||
public setFixedRotation(flag): void;
|
||||
public resetMassData(): void;
|
||||
public resetJointAnchors(): void;
|
||||
public cacheData(): void;
|
||||
private _tempVec2;
|
||||
public updateVelocity(gravity, dt, damping): void;
|
||||
public updatePosition(dt): void;
|
||||
public resetForce(): void;
|
||||
public applyForce(force, p): void;
|
||||
public applyForceToCenter(force): void;
|
||||
public applyTorque(torque): void;
|
||||
public applyLinearImpulse(impulse, p): void;
|
||||
public applyAngularImpulse(impulse: number): void;
|
||||
public kineticEnergy(): number;
|
||||
public isAwake : bool;
|
||||
public awake(flag): void;
|
||||
public isCollidable(other): bool;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Phaser - Advanced Physics - Shapes - Box
|
||||
*
|
||||
* Based on the work Ju Hyung Lee started in JS PhyRus.
|
||||
*/
|
||||
module Phaser.Physics.Advanced.Shapes {
|
||||
class Box extends Poly {
|
||||
constructor(x, y, width, height);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Phaser - Advanced Physics - Shapes - Triangle
|
||||
*
|
||||
* Based on the work Ju Hyung Lee started in JS PhyRus.
|
||||
*/
|
||||
module Phaser.Physics.Advanced.Shapes {
|
||||
class Triangle extends Poly {
|
||||
constructor(p1, p2, p3);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Phaser - PixelUtils
|
||||
*
|
||||
* A collection of methods useful for manipulating pixels.
|
||||
|
|
3691
build/phaser.js
3691
build/phaser.js
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue