From 4c9c50584e92e8d20260d8bf7b2f13488f00aa7f Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Fri, 2 Aug 2013 12:38:56 +0100 Subject: [PATCH] Tidying up the physics libraries --- Phaser/Game.ts | 8 - Phaser/Phaser.csproj | 85 +- Phaser/Phaser.ts | 4 +- Phaser/State.ts | 4 +- Phaser/gameobjects/Sprite.ts | 4 +- Phaser/phaser.js | 4 +- Phaser/physics/Manager.ts | 77 +- Phaser/physics/advanced/readme.txt | 15 + Phaser/physics/arcade/ArcadePhysics.ts | 1118 ++++ Phaser/physics/arcade/Body.ts | 311 + Phaser/{ => physics/arcade}/Motion.ts | 4 +- Phaser/renderers/CanvasRenderer.ts | 5 + Phaser/utils/DebugUtils.ts | 77 - Tests/groups/bring to top 1.ts | 92 + Tests/phaser.js | 5086 ++++++---------- build/phaser.d.ts | 1271 ++-- build/phaser.js | 6004 ++++++------------- todo/physics/AdvancedPhysics.js | 269 + {Phaser => todo}/physics/AdvancedPhysics.ts | 0 todo/physics/ArcadePhysics.js | 19 + {Phaser => todo}/physics/ArcadePhysics.ts | 0 todo/physics/Body.js | 416 ++ {Phaser => todo}/physics/Body.ts | 0 {Phaser/utils => todo/physics}/BodyUtils.ts | 0 todo/physics/Bounds.js | 201 + {Phaser => todo}/physics/Bounds.ts | 0 todo/physics/Collision.js | 373 ++ todo/physics/Collision.js.map | 1 + {Phaser => todo}/physics/Collision.ts | 0 todo/physics/Contact.js | 32 + todo/physics/Contact.js.map | 1 + {Phaser => todo}/physics/Contact.ts | 0 todo/physics/ContactSolver.js | 269 + todo/physics/ContactSolver.js.map | 1 + {Phaser => todo}/physics/ContactSolver.ts | 0 todo/physics/Manager.js | 67 + todo/physics/Manager.js.map | 1 + todo/physics/Manager.ts | 86 + todo/physics/Plane.js | 23 + todo/physics/Plane.js.map | 1 + {Phaser => todo}/physics/Plane.ts | 0 todo/physics/Space.js | 500 ++ todo/physics/Space.js.map | 1 + {Phaser => todo}/physics/Space.ts | 0 todo/physics/joints/IJoint.js | 3 + todo/physics/joints/IJoint.js.map | 1 + {Phaser => todo}/physics/joints/IJoint.ts | 0 todo/physics/joints/Joint.js | 41 + todo/physics/joints/Joint.js.map | 1 + {Phaser => todo}/physics/joints/Joint.ts | 0 todo/physics/shapes/Box.js | 59 + todo/physics/shapes/Box.js.map | 1 + {Phaser => todo}/physics/shapes/Box.ts | 0 todo/physics/shapes/Circle.js | 87 + todo/physics/shapes/Circle.js.map | 1 + {Phaser => todo}/physics/shapes/Circle.ts | 0 todo/physics/shapes/IShape.js | 3 + todo/physics/shapes/IShape.js.map | 1 + {Phaser => todo}/physics/shapes/IShape.ts | 0 todo/physics/shapes/Poly.js | 206 + todo/physics/shapes/Poly.js.map | 1 + {Phaser => todo}/physics/shapes/Poly.ts | 0 todo/physics/shapes/Segment.js | 141 + todo/physics/shapes/Segment.js.map | 1 + {Phaser => todo}/physics/shapes/Segment.ts | 0 todo/physics/shapes/Shape.js | 33 + todo/physics/shapes/Shape.js.map | 1 + {Phaser => todo}/physics/shapes/Shape.ts | 0 todo/physics/shapes/Triangle.js | 51 + todo/physics/shapes/Triangle.js.map | 1 + {Phaser => todo}/physics/shapes/Triangle.ts | 0 71 files changed, 8363 insertions(+), 8700 deletions(-) create mode 100644 Phaser/physics/advanced/readme.txt create mode 100644 Phaser/physics/arcade/ArcadePhysics.ts create mode 100644 Phaser/physics/arcade/Body.ts rename Phaser/{ => physics/arcade}/Motion.ts (99%) create mode 100644 Tests/groups/bring to top 1.ts create mode 100644 todo/physics/AdvancedPhysics.js rename {Phaser => todo}/physics/AdvancedPhysics.ts (100%) create mode 100644 todo/physics/ArcadePhysics.js rename {Phaser => todo}/physics/ArcadePhysics.ts (100%) create mode 100644 todo/physics/Body.js rename {Phaser => todo}/physics/Body.ts (100%) rename {Phaser/utils => todo/physics}/BodyUtils.ts (100%) create mode 100644 todo/physics/Bounds.js rename {Phaser => todo}/physics/Bounds.ts (100%) create mode 100644 todo/physics/Collision.js create mode 100644 todo/physics/Collision.js.map rename {Phaser => todo}/physics/Collision.ts (100%) create mode 100644 todo/physics/Contact.js create mode 100644 todo/physics/Contact.js.map rename {Phaser => todo}/physics/Contact.ts (100%) create mode 100644 todo/physics/ContactSolver.js create mode 100644 todo/physics/ContactSolver.js.map rename {Phaser => todo}/physics/ContactSolver.ts (100%) create mode 100644 todo/physics/Manager.js create mode 100644 todo/physics/Manager.js.map create mode 100644 todo/physics/Manager.ts create mode 100644 todo/physics/Plane.js create mode 100644 todo/physics/Plane.js.map rename {Phaser => todo}/physics/Plane.ts (100%) create mode 100644 todo/physics/Space.js create mode 100644 todo/physics/Space.js.map rename {Phaser => todo}/physics/Space.ts (100%) create mode 100644 todo/physics/joints/IJoint.js create mode 100644 todo/physics/joints/IJoint.js.map rename {Phaser => todo}/physics/joints/IJoint.ts (100%) create mode 100644 todo/physics/joints/Joint.js create mode 100644 todo/physics/joints/Joint.js.map rename {Phaser => todo}/physics/joints/Joint.ts (100%) create mode 100644 todo/physics/shapes/Box.js create mode 100644 todo/physics/shapes/Box.js.map rename {Phaser => todo}/physics/shapes/Box.ts (100%) create mode 100644 todo/physics/shapes/Circle.js create mode 100644 todo/physics/shapes/Circle.js.map rename {Phaser => todo}/physics/shapes/Circle.ts (100%) create mode 100644 todo/physics/shapes/IShape.js create mode 100644 todo/physics/shapes/IShape.js.map rename {Phaser => todo}/physics/shapes/IShape.ts (100%) create mode 100644 todo/physics/shapes/Poly.js create mode 100644 todo/physics/shapes/Poly.js.map rename {Phaser => todo}/physics/shapes/Poly.ts (100%) create mode 100644 todo/physics/shapes/Segment.js create mode 100644 todo/physics/shapes/Segment.js.map rename {Phaser => todo}/physics/shapes/Segment.ts (100%) create mode 100644 todo/physics/shapes/Shape.js create mode 100644 todo/physics/shapes/Shape.js.map rename {Phaser => todo}/physics/shapes/Shape.ts (100%) create mode 100644 todo/physics/shapes/Triangle.js create mode 100644 todo/physics/shapes/Triangle.js.map rename {Phaser => todo}/physics/shapes/Triangle.ts (100%) diff --git a/Phaser/Game.ts b/Phaser/Game.ts index e53a1409..09ce4d6f 100644 --- a/Phaser/Game.ts +++ b/Phaser/Game.ts @@ -20,7 +20,6 @@ /// /// /// -/// /// /// /// @@ -203,12 +202,6 @@ module Phaser { */ public math: GameMath; - /** - * Reference to the motion helper. - * @type {Motion} - */ - public motion: Motion; - /** * Reference to the network class. * @type {Net} @@ -302,7 +295,6 @@ module Phaser { { this.device = new Device(); this.net = new Net(this); - this.motion = new Motion(this); this.math = new GameMath(this); this.stage = new Stage(this, parent, width, height); this.world = new World(this, width, height); diff --git a/Phaser/Phaser.csproj b/Phaser/Phaser.csproj index 28a242aa..3136b66f 100644 --- a/Phaser/Phaser.csproj +++ b/Phaser/Phaser.csproj @@ -149,7 +149,6 @@ - @@ -166,7 +165,6 @@ LinkedList.ts - @@ -179,88 +177,27 @@ Vec2.ts - - Motion.ts - Net.ts - - - - AdvancedPhysics.ts - - + + + ArcadePhysics.ts - + + + Body.ts - - - Bounds.ts - - - - Collision.ts - - - - Contact.ts - - - - ContactSolver.ts - - - - - IJoint.ts - - - - Joint.ts + + + Motion.ts Manager.ts - - - Plane.ts - - - - - Box.ts - - - - Circle.ts - - - - IShape.ts - - - - Poly.ts - - - - Segment.ts - - - - Shape.ts - - - - Triangle.ts - - - Space.ts - HeadlessRenderer.ts @@ -278,10 +215,6 @@ OrientationScreen.ts - - - BodyUtils.ts - CircleUtils.ts diff --git a/Phaser/Phaser.ts b/Phaser/Phaser.ts index 11d83616..5f1b6f47 100644 --- a/Phaser/Phaser.ts +++ b/Phaser/Phaser.ts @@ -1,9 +1,9 @@ /** * Phaser * -* v1.0.0 - June XX 2013 +* v1.0.0 - August 12th 2013 * -* A small and feature-packed 2D canvas game framework born from the firey pits of Flixel and Kiwi. +* A feature-packed 2D canvas game framework born from the firey pits of Flixel and Kiwi. * * Richard Davey (@photonstorm) * diff --git a/Phaser/State.ts b/Phaser/State.ts index 99679557..6c22b4c4 100644 --- a/Phaser/State.ts +++ b/Phaser/State.ts @@ -24,7 +24,7 @@ module Phaser { this.input = game.input; this.load = game.load; this.math = game.math; - this.motion = game.motion; + //this.motion = game.motion; this.sound = game.sound; this.stage = game.stage; this.time = game.time; @@ -78,7 +78,7 @@ module Phaser { * Reference to the motion helper. * @type {Motion} */ - public motion: Motion; + //public motion: Motion; /** * Reference to the sound manager. diff --git a/Phaser/gameobjects/Sprite.ts b/Phaser/gameobjects/Sprite.ts index 77303a38..7c5d2e37 100644 --- a/Phaser/gameobjects/Sprite.ts +++ b/Phaser/gameobjects/Sprite.ts @@ -6,7 +6,7 @@ /// /// /// -/// +/// /** * Phaser - Sprite @@ -233,7 +233,7 @@ module Phaser { if (this.body) { - this.body.angle = this.game.math.degreesToRadians(this.game.math.wrap(value, 360, 0)); + //this.body.angle = this.game.math.degreesToRadians(this.game.math.wrap(value, 360, 0)); } } diff --git a/Phaser/phaser.js b/Phaser/phaser.js index 7b20a194..21b27d3f 100644 --- a/Phaser/phaser.js +++ b/Phaser/phaser.js @@ -1,9 +1,9 @@ /** * Phaser * -* v1.0.0 - June XX 2013 +* v1.0.0 - August 12th 2013 * -* A small and feature-packed 2D canvas game framework born from the firey pits of Flixel and Kiwi. +* A feature-packed 2D canvas game framework born from the firey pits of Flixel and Kiwi. * * Richard Davey (@photonstorm) * diff --git a/Phaser/physics/Manager.ts b/Phaser/physics/Manager.ts index 519e3cd8..8077069a 100644 --- a/Phaser/physics/Manager.ts +++ b/Phaser/physics/Manager.ts @@ -1,12 +1,10 @@ /// -/// -/// /** * Phaser - Physics Manager * -* The Physics Manager is responsible for looking after, creating and colliding -* all of the physics bodies and joints in the world. +* Eventually this will handle switching between the default ArcadePhysics manager or the new AdvancedPhysics manager. +* For now we direct everything through ArcadePhysics. */ module Phaser.Physics { @@ -14,7 +12,14 @@ module Phaser.Physics { export class Manager { constructor(game: Game) { + this.game = game; + + this.arcade = new Phaser.Physics.ArcadePhysics(this.game, this.game.stage.width, this.game.stage.height); + + this.gravity = this.arcade.gravity; + this.bounds = this.arcade.bounds; + } /** @@ -22,63 +27,21 @@ module Phaser.Physics { */ public game: Game; - public static debug: HTMLTextAreaElement; + /** + * Instance of the ArcadePhysics manager. + */ + public arcade: Phaser.Physics.ArcadePhysics; - public static clear() { - //Manager.debug.textContent = ""; - Manager.log = []; - } - - public static write(s: string) { - //Manager.debug.textContent += s + "\n"; - } - - public static writeAll() { - - for (var i = 0; i < Manager.log.length; i++) - { - //Manager.debug.textContent += Manager.log[i]; - } - - } - - public static log = []; - - public static dump(phase: string, body: Body) { - - /* - var s = "\n\nPhase: " + phase + "\n"; - s += "Position: " + body.position.toString() + "\n"; - s += "Velocity: " + body.velocity.toString() + "\n"; - s += "Angle: " + body.angle + "\n"; - s += "Force: " + body.force.toString() + "\n"; - s += "Torque: " + body.torque + "\n"; - s += "Bounds: " + body.bounds.toString() + "\n"; - s += "Shape ***\n"; - s += "Vert 0: " + body.shapes[0].verts[0].toString() + "\n"; - s += "Vert 1: " + body.shapes[0].verts[1].toString() + "\n"; - s += "Vert 2: " + body.shapes[0].verts[2].toString() + "\n"; - s += "Vert 3: " + body.shapes[0].verts[3].toString() + "\n"; - s += "TVert 0: " + body.shapes[0].tverts[0].toString() + "\n"; - s += "TVert 1: " + body.shapes[0].tverts[1].toString() + "\n"; - s += "TVert 2: " + body.shapes[0].tverts[2].toString() + "\n"; - s += "TVert 3: " + body.shapes[0].tverts[3].toString() + "\n"; - s += "Plane 0: " + body.shapes[0].planes[0].normal.toString() + "\n"; - s += "Plane 1: " + body.shapes[0].planes[1].normal.toString() + "\n"; - s += "Plane 2: " + body.shapes[0].planes[2].normal.toString() + "\n"; - s += "Plane 3: " + body.shapes[0].planes[3].normal.toString() + "\n"; - s += "TPlane 0: " + body.shapes[0].tplanes[0].normal.toString() + "\n"; - s += "TPlane 1: " + body.shapes[0].tplanes[1].normal.toString() + "\n"; - s += "TPlane 2: " + body.shapes[0].tplanes[2].normal.toString() + "\n"; - s += "TPlane 3: " + body.shapes[0].tplanes[3].normal.toString() + "\n"; - - Manager.log.push(s); - */ - - } + public gravity: Vec2; + public bounds: Rectangle; + /** + * Called by the main Game.loop + */ public update() { + //this.arcade.updateMotion + } } diff --git a/Phaser/physics/advanced/readme.txt b/Phaser/physics/advanced/readme.txt new file mode 100644 index 00000000..0f1d0d79 --- /dev/null +++ b/Phaser/physics/advanced/readme.txt @@ -0,0 +1,15 @@ +I've been extremely busy working on a proper advanced physics system for Phaser. + +It has all the sorts of things you'd expect from a real 2D physics engine and will allow for a whole new range of cool games to be made. + +However I'm not 100% happy with the implementation right yet, there are still too many rough edges and places where performance can be +improved. It also adds quite a bit of extra file size to the library, so I'm not bundling it with the 1.0 release. It will be released +as a stand-alone extension to Phaser in due course. + +It has been a lot of hard work to create, taking many weeks of development time and money, so be warned I may decide to charge for it. +Or I may just give it away for free, I've not yet decided - but for now I reserve that right at least. + +Cheers, + +Richard Davey +1st August 2013 diff --git a/Phaser/physics/arcade/ArcadePhysics.ts b/Phaser/physics/arcade/ArcadePhysics.ts new file mode 100644 index 00000000..6fbe9864 --- /dev/null +++ b/Phaser/physics/arcade/ArcadePhysics.ts @@ -0,0 +1,1118 @@ +/// +/// +/// +/// +/// + +/** +* Phaser - ArcadePhysics Manager +* +*/ + +module Phaser.Physics { + + export class ArcadePhysics { + + constructor(game: Game, width: number, height: number) { + + this.game = game; + + this.gravity = new Vec2; + this.drag = new Vec2; + this.bounce = new Vec2; + this.angularDrag = 0; + + this.bounds = new Rectangle(0, 0, width, height); + + this._distance = new Vec2; + this._tangent = new Vec2; + + //this.members = new Group(game); + + } + + /** + * Local private reference to Game. + */ + public game: Game; + + /** + * Physics object pool + */ + public members: Group; + + // Temp calculation vars + private _drag: number; + private _delta: number; + private _velocityDelta: number; + private _length: number = 0; + private _distance: Vec2; + private _tangent: Vec2; + private _separatedX: bool; + private _separatedY: bool; + private _overlap: number; + private _maxOverlap: number; + private _obj1Velocity: number; + private _obj2Velocity: number; + private _obj1NewVelocity: number; + private _obj2NewVelocity: number; + private _average: number; + private _quadTree: QuadTree; + private _quadTreeResult: bool; + + 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 = 4; + + /** + * 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 = false; + + /** + * @type {number} + */ + public worldDivisions: number = 6; + + + /* + public update() { + + this._length = this._objects.length; + + for (var i = 0; i < this._length; i++) + { + if (this._objects[i]) + { + this._objects[i].preUpdate(); + this.updateMotion(this._objects[i]); + this.collideWorld(this._objects[i]); + + for (var x = 0; x < this._length; x++) + { + if (this._objects[x] && this._objects[x] !== this._objects[i]) + { + //this.collideShapes(this._objects[i], this._objects[x]); + var r = this.NEWseparate(this._objects[i], this._objects[x]); + //console.log('sep', r); + } + } + + } + } + + } + + public render() { + + // iterate through the objects here, updating and colliding + for (var i = 0; i < this._length; i++) + { + if (this._objects[i]) + { + this._objects[i].render(this.game.stage.context); + } + } + + } +*/ + + public updateMotion(body: Phaser.Physics.Body) { + + if (body.type == Types.BODY_DISABLED) + { + return; + } + + this._velocityDelta = (this.computeVelocity(body.angularVelocity, body.gravity.x, body.angularAcceleration, body.angularDrag, body.maxAngular) - body.angularVelocity) / 2; + body.angularVelocity += this._velocityDelta; + body.sprite.transform.rotation += body.angularVelocity * this.game.time.elapsed; + body.angularVelocity += this._velocityDelta; + + this._velocityDelta = (this.computeVelocity(body.velocity.x, body.gravity.x, body.acceleration.x, body.drag.x) - body.velocity.x) / 2; + body.velocity.x += this._velocityDelta; + this._delta = body.velocity.x * this.game.time.elapsed; + body.velocity.x += this._velocityDelta; + //body.position.x += this._delta; + body.sprite.x += this._delta; + + this._velocityDelta = (this.computeVelocity(body.velocity.y, body.gravity.y, body.acceleration.y, body.drag.y) - body.velocity.y) / 2; + body.velocity.y += this._velocityDelta; + this._delta = body.velocity.y * this.game.time.elapsed; + body.velocity.y += this._velocityDelta; + //body.position.y += this._delta; + body.sprite.y += this._delta; + + } + + /** + * 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 = 0, acceleration: number = 0, drag: number = 0, max: number = 10000): number { + + if (acceleration !== 0) + { + velocity += (acceleration + gravity) * this.game.time.elapsed; + } + else if (drag !== 0) + { + this._drag = drag * this.game.time.elapsed; + + if (velocity - this._drag > 0) + { + velocity = velocity - this._drag; + } + else if (velocity + this._drag < 0) + { + velocity += this._drag; + } + else + { + velocity = 0; + } + + velocity += gravity; + } + + if ((velocity != 0) && (max != 10000)) + { + if (velocity > max) + { + velocity = max; + } + else if (velocity < -max) + { + velocity = -max; + } + } + + return velocity; + + } + + /** + * 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 { + + this._separatedX = this.separateBodyX(body1, body2); + this._separatedY = this.separateBodyY(body1, body2); + + return this._separatedX || this._separatedY; + + } + + public checkHullIntersection(body1: Body, body2:Body): bool { + return ((body1.hullX + body1.hullWidth > body2.hullX) && (body1.hullX < body2.hullX + body2.hullWidth) && (body1.hullY + body1.hullHeight > body2.hullY) && (body1.hullY < body2.hullY + body2.hullHeight)); + } + + /** + * 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 { + + // Can't separate two disabled or static objects + if ((body1.type == Types.BODY_DISABLED || body1.type == Types.BODY_STATIC) && (body2.type == Types.BODY_DISABLED || body2.type == Types.BODY_STATIC)) + { + return false; + } + + // First, get the two object deltas + this._overlap = 0; + + if (body1.deltaX != body2.deltaX) + { + if (RectangleUtils.intersects(body1.bounds, body2.bounds)) + { + this._maxOverlap = body1.deltaXAbs + body2.deltaXAbs + ArcadePhysics.OVERLAP_BIAS; + + // If they did overlap (and can), figure out by how much and flip the corresponding flags + if (body1.deltaX > body2.deltaX) + { + this._overlap = body1.bounds.right - body2.bounds.x; + + if ((this._overlap > this._maxOverlap) || !(body1.allowCollisions & Types.RIGHT) || !(body2.allowCollisions & Types.LEFT)) + { + this._overlap = 0; + } + else + { + body1.touching |= Types.RIGHT; + body2.touching |= Types.LEFT; + } + } + else if (body1.deltaX < body2.deltaX) + { + this._overlap = body1.bounds.x - body2.bounds.width - body2.bounds.x; + + if ((-this._overlap > this._maxOverlap) || !(body1.allowCollisions & Types.LEFT) || !(body2.allowCollisions & Types.RIGHT)) + { + this._overlap = 0; + } + else + { + body1.touching |= Types.LEFT; + body2.touching |= Types.RIGHT; + } + } + } + } + + // Then adjust their positions and velocities accordingly (if there was any overlap) + if (this._overlap != 0) + { + this._obj1Velocity = body1.velocity.x; + this._obj2Velocity = body2.velocity.x; + + /** + * 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 + */ + + // 2 dynamic bodies will exchange velocities + if (body1.type == Types.BODY_DYNAMIC && body2.type == Types.BODY_DYNAMIC) + { + this._overlap *= 0.5; + body1.position.x = body1.position.x - this._overlap; + body2.position.x += this._overlap; + + this._obj1NewVelocity = Math.sqrt((this._obj2Velocity * this._obj2Velocity * body2.mass) / body1.mass) * ((this._obj2Velocity > 0) ? 1 : -1); + this._obj2NewVelocity = Math.sqrt((this._obj1Velocity * this._obj1Velocity * body1.mass) / body2.mass) * ((this._obj1Velocity > 0) ? 1 : -1); + this._average = (this._obj1NewVelocity + this._obj2NewVelocity) * 0.5; + this._obj1NewVelocity -= this._average; + this._obj2NewVelocity -= this._average; + body1.velocity.x = this._average + this._obj1NewVelocity * body1.bounce.x; + body2.velocity.x = this._average + this._obj2NewVelocity * body2.bounce.x; + } + else if (body2.type != Types.BODY_DYNAMIC) + { + // Body 2 is Static or Kinematic + this._overlap *= 2; + body1.position.x -= this._overlap; + body1.velocity.x = this._obj2Velocity - this._obj1Velocity * body1.bounce.x; + } + else if (body1.type != Types.BODY_DYNAMIC) + { + // Body 1 is Static or Kinematic + this._overlap *= 2; + body2.position.x += this._overlap; + body2.velocity.x = this._obj1Velocity - this._obj2Velocity * body2.bounce.x; + } + + return true; + } + else + { + return false; + } + + } + + /** + * 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 { + + // Can't separate two immovable objects + if ((body1.type == Types.BODY_DISABLED || body1.type == Types.BODY_STATIC) && (body2.type == Types.BODY_DISABLED || body2.type == Types.BODY_STATIC)) + { + return false; + } + + // First, get the two object deltas + this._overlap = 0; + + if (body1.deltaY != body2.deltaY) + { + if (RectangleUtils.intersects(body1.bounds, body2.bounds)) + { + // This is the only place to use the DeltaAbs values + this._maxOverlap = body1.deltaYAbs + body2.deltaYAbs + ArcadePhysics.OVERLAP_BIAS; + + // If they did overlap (and can), figure out by how much and flip the corresponding flags + if (body1.deltaY > body2.deltaY) + { + this._overlap = body1.bounds.bottom - body2.bounds.y; + + if ((this._overlap > this._maxOverlap) || !(body1.allowCollisions & Types.DOWN) || !(body2.allowCollisions & Types.UP)) + { + this._overlap = 0; + } + else + { + body1.touching |= Types.DOWN; + body2.touching |= Types.UP; + } + } + else if (body1.deltaY < body2.deltaY) + { + this._overlap = body1.bounds.y - body2.bounds.height - body2.bounds.y; + + if ((-this._overlap > this._maxOverlap) || !(body1.allowCollisions & Types.UP) || !(body2.allowCollisions & Types.DOWN)) + { + this._overlap = 0; + } + else + { + body1.touching |= Types.UP; + body2.touching |= Types.DOWN; + } + } + } + } + + // Then adjust their positions and velocities accordingly (if there was any overlap) + if (this._overlap != 0) + { + this._obj1Velocity = body1.velocity.y; + this._obj2Velocity = body2.velocity.y; + + /** + * 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 + */ + + if (body1.type == Types.BODY_DYNAMIC && body2.type == Types.BODY_DYNAMIC) + { + this._overlap *= 0.5; + body1.position.y = body1.position.y - this._overlap; + body2.position.y += this._overlap; + + this._obj1NewVelocity = Math.sqrt((this._obj2Velocity * this._obj2Velocity * body2.mass) / body1.mass) * ((this._obj2Velocity > 0) ? 1 : -1); + this._obj2NewVelocity = Math.sqrt((this._obj1Velocity * this._obj1Velocity * body1.mass) / body2.mass) * ((this._obj1Velocity > 0) ? 1 : -1); + var average: number = (this._obj1NewVelocity + this._obj2NewVelocity) * 0.5; + this._obj1NewVelocity -= average; + this._obj2NewVelocity -= average; + body1.velocity.y = average + this._obj1NewVelocity * body1.bounce.y; + body2.velocity.y = average + this._obj2NewVelocity * body2.bounce.y; + } + else if (body2.type != Types.BODY_DYNAMIC) + { + this._overlap *= 2; + body1.position.y -= this._overlap; + body1.velocity.y = this._obj2Velocity - this._obj1Velocity * body1.bounce.y; + // This is special case code that handles things like horizontal moving platforms you can ride + //if (body2.parent.active && body2.moves && (body1.deltaY > body2.deltaY)) + if (body2.sprite.active && (body1.deltaY > body2.deltaY)) + { + body1.position.x += body2.position.x - body2.oldPosition.x; + } + } + else if (body1.type != Types.BODY_DYNAMIC) + { + this._overlap *= 2; + body2.position.y += this._overlap; + body2.velocity.y = this._obj1Velocity - this._obj2Velocity * body2.bounce.y; + // This is special case code that handles things like horizontal moving platforms you can ride + //if (object1.active && body1.moves && (body1.deltaY < body2.deltaY)) + if (body1.sprite.active && (body1.deltaY < body2.deltaY)) + { + body2.position.x += body1.position.x - body1.oldPosition.x; + } + } + + return true; + } + else + { + return false; + } + } + + + + + + + + /* + private TILEseparate(shapeA: IPhysicsShape, shapeB: IPhysicsShape, distance: Vec2, tangent: Vec2) { + + if (tangent.x == 1) + { + console.log('1 The left side of ShapeA hit the right side of ShapeB', Math.floor(distance.x)); + shapeA.physics.touching |= Phaser.Types.LEFT; + shapeB.physics.touching |= Phaser.Types.RIGHT; + } + else if (tangent.x == -1) + { + console.log('2 The right side of ShapeA hit the left side of ShapeB', Math.floor(distance.x)); + shapeA.physics.touching |= Phaser.Types.RIGHT; + shapeB.physics.touching |= Phaser.Types.LEFT; + } + + if (tangent.y == 1) + { + console.log('3 The top of ShapeA hit the bottom of ShapeB', Math.floor(distance.y)); + shapeA.physics.touching |= Phaser.Types.UP; + shapeB.physics.touching |= Phaser.Types.DOWN; + } + else if (tangent.y == -1) + { + console.log('4 The bottom of ShapeA hit the top of ShapeB', Math.floor(distance.y)); + shapeA.physics.touching |= Phaser.Types.DOWN; + shapeB.physics.touching |= Phaser.Types.UP; + } + + + // only apply collision response forces if the object is travelling into, and not out of, the collision + var dot = Vec2Utils.dot(shapeA.physics.velocity, tangent); + + if (dot < 0) + { + console.log('in to', dot); + + // Apply horizontal bounce + if (shapeA.physics.bounce.x > 0) + { + shapeA.physics.velocity.x *= -(shapeA.physics.bounce.x); + } + else + { + shapeA.physics.velocity.x = 0; + } + // Apply horizontal bounce + if (shapeA.physics.bounce.y > 0) + { + shapeA.physics.velocity.y *= -(shapeA.physics.bounce.y); + } + else + { + shapeA.physics.velocity.y = 0; + } + } + else + { + console.log('out of', dot); + } + + shapeA.position.x += Math.floor(distance.x); + //shapeA.bounds.x += Math.floor(distance.x); + + shapeA.position.y += Math.floor(distance.y); + //shapeA.bounds.y += distance.y; + + console.log('------------------------------------------------'); + + } + + private collideWorld(shape:IPhysicsShape) { + + // Collide on the x-axis + this._distance.x = shape.world.bounds.x - (shape.position.x - shape.bounds.halfWidth); + + if (0 < this._distance.x) + { + // Hit Left + this._tangent.setTo(1, 0); + this.separateXWall(shape, this._distance, this._tangent); + } + else + { + this._distance.x = (shape.position.x + shape.bounds.halfWidth) - shape.world.bounds.right; + + if (0 < this._distance.x) + { + // Hit Right + this._tangent.setTo(-1, 0); + this._distance.reverse(); + this.separateXWall(shape, this._distance, this._tangent); + } + } + + // Collide on the y-axis + this._distance.y = shape.world.bounds.y - (shape.position.y - shape.bounds.halfHeight); + + if (0 < this._distance.y) + { + // Hit Top + this._tangent.setTo(0, 1); + this.separateYWall(shape, this._distance, this._tangent); + } + else + { + this._distance.y = (shape.position.y + shape.bounds.halfHeight) - shape.world.bounds.bottom; + + if (0 < this._distance.y) + { + // Hit Bottom + this._tangent.setTo(0, -1); + this._distance.reverse(); + this.separateYWall(shape, this._distance, this._tangent); + } + } + + } + + private separateX(shapeA: IPhysicsShape, shapeB: IPhysicsShape, distance: Vec2, tangent: Vec2) { + + if (tangent.x == 1) + { + console.log('The left side of ShapeA hit the right side of ShapeB', distance.x); + shapeA.physics.touching |= Phaser.Types.LEFT; + shapeB.physics.touching |= Phaser.Types.RIGHT; + } + else + { + console.log('The right side of ShapeA hit the left side of ShapeB', distance.x); + shapeA.physics.touching |= Phaser.Types.RIGHT; + shapeB.physics.touching |= Phaser.Types.LEFT; + } + + // collision edges + //shapeA.oH = tangent.x; + + // only apply collision response forces if the object is travelling into, and not out of, the collision + if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) + { + // Apply horizontal bounce + if (shapeA.physics.bounce.x > 0) + { + shapeA.physics.velocity.x *= -(shapeA.physics.bounce.x); + } + else + { + shapeA.physics.velocity.x = 0; + } + } + + shapeA.position.x += distance.x; + shapeA.bounds.x += distance.x; + + } + + private separateY(shapeA: IPhysicsShape, shapeB: IPhysicsShape, distance: Vec2, tangent: Vec2) { + + if (tangent.y == 1) + { + console.log('The top of ShapeA hit the bottom of ShapeB', distance.y); + shapeA.physics.touching |= Phaser.Types.UP; + shapeB.physics.touching |= Phaser.Types.DOWN; + } + else + { + console.log('The bottom of ShapeA hit the top of ShapeB', distance.y); + shapeA.physics.touching |= Phaser.Types.DOWN; + shapeB.physics.touching |= Phaser.Types.UP; + } + + // collision edges + //shapeA.oV = tangent.y; + + // only apply collision response forces if the object is travelling into, and not out of, the collision + if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) + { + // Apply horizontal bounce + if (shapeA.physics.bounce.y > 0) + { + shapeA.physics.velocity.y *= -(shapeA.physics.bounce.y); + } + else + { + shapeA.physics.velocity.y = 0; + } + } + + shapeA.position.y += distance.y; + shapeA.bounds.y += distance.y; + + } + + private separateXWall(shapeA: IPhysicsShape, distance: Vec2, tangent: Vec2) { + + if (tangent.x == 1) + { + console.log('The left side of ShapeA hit the right side of ShapeB', distance.x); + shapeA.physics.touching |= Phaser.Types.LEFT; + } + else + { + console.log('The right side of ShapeA hit the left side of ShapeB', distance.x); + shapeA.physics.touching |= Phaser.Types.RIGHT; + } + + // collision edges + //shapeA.oH = tangent.x; + + // only apply collision response forces if the object is travelling into, and not out of, the collision + if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) + { + // Apply horizontal bounce + if (shapeA.physics.bounce.x > 0) + { + shapeA.physics.velocity.x *= -(shapeA.physics.bounce.x); + } + else + { + shapeA.physics.velocity.x = 0; + } + } + + shapeA.position.x += distance.x; + + } + + private separateYWall(shapeA: IPhysicsShape, distance: Vec2, tangent: Vec2) { + + if (tangent.y == 1) + { + console.log('The top of ShapeA hit the bottom of ShapeB', distance.y); + shapeA.physics.touching |= Phaser.Types.UP; + } + else + { + console.log('The bottom of ShapeA hit the top of ShapeB', distance.y); + shapeA.physics.touching |= Phaser.Types.DOWN; + } + + // collision edges + //shapeA.oV = tangent.y; + + // only apply collision response forces if the object is travelling into, and not out of, the collision + if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) + { + // Apply horizontal bounce + if (shapeA.physics.bounce.y > 0) + { + shapeA.physics.velocity.y *= -(shapeA.physics.bounce.y); + } + else + { + shapeA.physics.velocity.y = 0; + } + } + + shapeA.position.y += distance.y; + + } + */ + + /** + * 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 = null, object2 = null, notifyCallback = null, processCallback = null, context = null): bool { + + /* + if (object1 == null) + { + object1 = this.game.world.group; + } + + if (object2 == object1) + { + object2 = null; + } + + QuadTree.divisions = this.worldDivisions; + + this._quadTree = new Phaser.QuadTree(this, this.bounds.x, this.bounds.y, this.bounds.width, this.bounds.height); + + this._quadTree.load(object1, object2, notifyCallback, processCallback, context); + + this._quadTreeResult = this._quadTree.execute(); + + console.log('over', this._quadTreeResult); + + this._quadTree.destroy(); + + this._quadTree = null; + + return this._quadTreeResult; + */ + + return false; + + } + + + + + + + /** + * 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 { + + //var separatedX: bool = this.separateTileX(object, x, y, width, height, mass, collideLeft, collideRight, separateX); + //var separatedY: bool = this.separateTileY(object, x, y, width, height, mass, collideUp, collideDown, separateY); + + //return separatedX || separatedY; + + return false; + + } + + /** + * Separates the two objects on their x axis + * @param object The GameObject to separate + * @param tile The Tile to separate + * @returns {boolean} Whether the objects in fact touched and were separated along the X axis. + */ + /* + public separateTileX(object:Sprite, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool, separate: bool): bool { + + // Can't separate two immovable objects (tiles are always immovable) + if (object.immovable) + { + return false; + } + + // First, get the object delta + var overlap: number = 0; + var objDelta: number = object.x - object.last.x; + //var objDelta: number = object.collisionMask.deltaX; + + if (objDelta != 0) + { + // Check if the X hulls actually overlap + var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; + //var objDeltaAbs: number = object.collisionMask.deltaXAbs; + var objBounds: Rectangle = new Rectangle(object.x - ((objDelta > 0) ? objDelta : 0), object.last.y, object.width + ((objDelta > 0) ? objDelta : -objDelta), object.height); + + if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) + { + var maxOverlap: number = objDeltaAbs + Collision.OVERLAP_BIAS; + + // If they did overlap (and can), figure out by how much and flip the corresponding flags + if (objDelta > 0) + { + overlap = object.x + object.width - x; + + if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.RIGHT) || collideLeft == false) + { + overlap = 0; + } + else + { + object.touching |= Collision.RIGHT; + } + } + else if (objDelta < 0) + { + overlap = object.x - width - x; + + if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.LEFT) || collideRight == false) + { + overlap = 0; + } + else + { + object.touching |= Collision.LEFT; + } + + } + + } + } + + // Then adjust their positions and velocities accordingly (if there was any overlap) + if (overlap != 0) + { + if (separate == true) + { + //console.log(' + object.x = object.x - overlap; + object.velocity.x = -(object.velocity.x * object.elasticity); + } + + Collision.TILE_OVERLAP = true; + return true; + } + else + { + return false; + } + + } + */ + + /** + * Separates the two objects on their y axis + * @param object The first GameObject to separate + * @param tile The second GameObject to separate + * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis. + */ + /* + public separateTileY(object: Sprite, x: number, y: number, width: number, height: number, mass: number, collideUp: bool, collideDown: bool, separate: bool): bool { + + // Can't separate two immovable objects (tiles are always immovable) + if (object.immovable) + { + return false; + } + + // First, get the two object deltas + var overlap: number = 0; + var objDelta: number = object.y - object.last.y; + + if (objDelta != 0) + { + // Check if the Y hulls actually overlap + var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; + var objBounds: Rectangle = new Rectangle(object.x, object.y - ((objDelta > 0) ? objDelta : 0), object.width, object.height + objDeltaAbs); + + if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) + { + var maxOverlap: number = objDeltaAbs + Collision.OVERLAP_BIAS; + + // If they did overlap (and can), figure out by how much and flip the corresponding flags + if (objDelta > 0) + { + overlap = object.y + object.height - y; + + if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.DOWN) || collideUp == false) + { + overlap = 0; + } + else + { + object.touching |= Collision.DOWN; + } + } + else if (objDelta < 0) + { + overlap = object.y - height - y; + + if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.UP) || collideDown == false) + { + overlap = 0; + } + else + { + object.touching |= Collision.UP; + } + } + } + } + + // TODO - with super low velocities you get lots of stuttering, set some kind of base minimum here + + // Then adjust their positions and velocities accordingly (if there was any overlap) + if (overlap != 0) + { + if (separate == true) + { + object.y = object.y - overlap; + object.velocity.y = -(object.velocity.y * object.elasticity); + } + + Collision.TILE_OVERLAP = true; + return true; + } + else + { + return false; + } + } + */ + + + /** + * Separates the two objects on their x axis + * @param object The GameObject to separate + * @param tile The Tile to separate + * @returns {boolean} Whether the objects in fact touched and were separated along the X axis. + */ + /* + public static NEWseparateTileX(object:Sprite, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool, separate: bool): bool { + + // Can't separate two immovable objects (tiles are always immovable) + if (object.immovable) + { + return false; + } + + // First, get the object delta + var overlap: number = 0; + + if (object.collisionMask.deltaX != 0) + { + // Check if the X hulls actually overlap + //var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; + //var objBounds: Rectangle = new Rectangle(object.x - ((objDelta > 0) ? objDelta : 0), object.last.y, object.width + ((objDelta > 0) ? objDelta : -objDelta), object.height); + + //if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) + if (object.collisionMask.intersectsRaw(x, x + width, y, y + height)) + { + var maxOverlap: number = object.collisionMask.deltaXAbs + Collision.OVERLAP_BIAS; + + // If they did overlap (and can), figure out by how much and flip the corresponding flags + if (object.collisionMask.deltaX > 0) + { + //overlap = object.x + object.width - x; + overlap = object.collisionMask.right - x; + + if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.RIGHT) || collideLeft == false) + { + overlap = 0; + } + else + { + object.touching |= Collision.RIGHT; + } + } + else if (object.collisionMask.deltaX < 0) + { + //overlap = object.x - width - x; + overlap = object.collisionMask.x - width - x; + + if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.LEFT) || collideRight == false) + { + overlap = 0; + } + else + { + object.touching |= Collision.LEFT; + } + + } + + } + } + + // Then adjust their positions and velocities accordingly (if there was any overlap) + if (overlap != 0) + { + if (separate == true) + { + object.x = object.x - overlap; + object.velocity.x = -(object.velocity.x * object.elasticity); + } + + Collision.TILE_OVERLAP = true; + return true; + } + else + { + return false; + } + + } + */ + + /** + * Separates the two objects on their y axis + * @param object The first GameObject to separate + * @param tile The second GameObject to separate + * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis. + */ + /* + public NEWseparateTileY(object: Sprite, x: number, y: number, width: number, height: number, mass: number, collideUp: bool, collideDown: bool, separate: bool): bool { + + // Can't separate two immovable objects (tiles are always immovable) + if (object.immovable) + { + return false; + } + + // First, get the two object deltas + var overlap: number = 0; + //var objDelta: number = object.y - object.last.y; + + if (object.collisionMask.deltaY != 0) + { + // Check if the Y hulls actually overlap + //var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; + //var objBounds: Rectangle = new Rectangle(object.x, object.y - ((objDelta > 0) ? objDelta : 0), object.width, object.height + objDeltaAbs); + + //if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) + if (object.collisionMask.intersectsRaw(x, x + width, y, y + height)) + { + //var maxOverlap: number = objDeltaAbs + Collision.OVERLAP_BIAS; + var maxOverlap: number = object.collisionMask.deltaYAbs + Collision.OVERLAP_BIAS; + + // If they did overlap (and can), figure out by how much and flip the corresponding flags + if (object.collisionMask.deltaY > 0) + { + //overlap = object.y + object.height - y; + overlap = object.collisionMask.bottom - y; + + if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.DOWN) || collideUp == false) + { + overlap = 0; + } + else + { + object.touching |= Collision.DOWN; + } + } + else if (object.collisionMask.deltaY < 0) + { + //overlap = object.y - height - y; + overlap = object.collisionMask.y - height - y; + + if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.UP) || collideDown == false) + { + overlap = 0; + } + else + { + object.touching |= Collision.UP; + } + } + } + } + + // TODO - with super low velocities you get lots of stuttering, set some kind of base minimum here + + // Then adjust their positions and velocities accordingly (if there was any overlap) + if (overlap != 0) + { + if (separate == true) + { + object.y = object.y - overlap; + object.velocity.y = -(object.velocity.y * object.elasticity); + } + + Collision.TILE_OVERLAP = true; + return true; + } + else + { + return false; + } + } + */ + + } + +} \ No newline at end of file diff --git a/Phaser/physics/arcade/Body.ts b/Phaser/physics/arcade/Body.ts new file mode 100644 index 00000000..72aa0be2 --- /dev/null +++ b/Phaser/physics/arcade/Body.ts @@ -0,0 +1,311 @@ +/// +/// +/// +/// + +/** +* Phaser - ArcadePhysics - Body +*/ + +module Phaser.Physics { + + export class Body { + + constructor(sprite: Phaser.Sprite, type: number) { + + this.sprite = sprite; + this.game = sprite.game; + this.type = type; + + // Fixture properties + // Will extend into its own class at a later date - can move the fixture defs there and add shape support, but this will do for 1.0 release + this.bounds = new Rectangle; + + this._width = sprite.width; + this._height = sprite.height; + + + // Body properties + //this.gravity = Vec2Utils.clone(ArcadePhysics.gravity); + //this.bounce = Vec2Utils.clone(ArcadePhysics.bounce); + + this.velocity = new Vec2; + this.acceleration = new Vec2; + //this.drag = Vec2Utils.clone(ArcadePhysics.drag); + this.maxVelocity = new Vec2(10000, 10000); + + this.angularVelocity = 0; + this.angularAcceleration = 0; + this.angularDrag = 0; + + this.touching = Types.NONE; + this.wasTouching = Types.NONE; + this.allowCollisions = Types.ANY; + + this.position = new Vec2(sprite.x + this.bounds.halfWidth, sprite.y + this.bounds.halfHeight); + this.oldPosition = new Vec2(sprite.x + this.bounds.halfWidth, sprite.y + this.bounds.halfHeight); + this.offset = new Vec2; + + } + + /** + * Reference to Phaser.Game + */ + public game: Game; + + /** + * Reference to the parent Sprite + */ + public sprite: Phaser.Sprite; + + /** + * 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 gravity: Vec2; + public bounce: Vec2; + + public velocity: Vec2; + public acceleration: Vec2; + public drag: Vec2; + public maxVelocity: Vec2; + + public angularVelocity: number = 0; + public angularAcceleration: number = 0; + public angularDrag: number = 0; + public maxAngular: number = 10000; + + /** + * Orientation of the object. + * @type {number} + */ + public facing: number; + + public touching: number; + public allowCollisions: number; + public wasTouching: number; + public mass: number = 1; + + public position: Vec2; + public oldPosition: Vec2; + public offset: Vec2; + public bounds: Rectangle; + + + + private _width: number = 0; + private _height: number = 0; + + public get x(): number { + return this.sprite.x + this.offset.x; + } + + public get y(): number { + return this.sprite.y + this.offset.y; + } + + public set width(value: number) { + this._width = value; + } + + public set height(value: number) { + this._height = value; + } + + public get width(): number { + return this._width * this.sprite.transform.scale.x; + } + + public get height(): number { + return this._height * this.sprite.transform.scale.y; + } + + public preUpdate() { + + this.oldPosition.copyFrom(this.position); + + this.bounds.x = this.x; + this.bounds.y = this.y; + this.bounds.width = this.width; + this.bounds.height = this.height; + + } + + // Shall we do this? Or just update the values directly in the separate functions? But then the bounds will be out of sync - as long as + // the bounds are updated and used in calculations then we can do one final sprite movement here I guess? + public postUpdate() { + + // if this is all it does maybe move elsewhere? Sprite postUpdate? + if (this.type !== Phaser.Types.BODY_DISABLED) + { + //this.game.world.physics.updateMotion(this); + + this.wasTouching = this.touching; + this.touching = Phaser.Types.NONE; + + } + + this.position.setTo(this.x, this.y); + + } + + public get hullWidth(): number { + + if (this.deltaX > 0) + { + return this.bounds.width + this.deltaX; + } + else + { + return this.bounds.width - this.deltaX; + } + + } + + public get hullHeight(): number { + + if (this.deltaY > 0) + { + return this.bounds.height + this.deltaY; + } + else + { + return this.bounds.height - this.deltaY; + } + + } + + public get hullX(): number { + + if (this.position.x < this.oldPosition.x) + { + return this.position.x; + } + else + { + return this.oldPosition.x; + } + + } + + public get hullY(): number { + + if (this.position.y < this.oldPosition.y) + { + return this.position.y; + } + else + { + return this.oldPosition.y; + } + + } + + public get deltaXAbs(): number { + return (this.deltaX > 0 ? this.deltaX : -this.deltaX); + } + + public get deltaYAbs(): number { + return (this.deltaY > 0 ? this.deltaY : -this.deltaY); + } + + public get deltaX(): number { + return this.position.x - this.oldPosition.x; + } + + public get deltaY(): number { + return this.position.y - this.oldPosition.y; + } + + + + + + + + + + + // MOVE THESE TO A UTIL + + public render(context:CanvasRenderingContext2D) { + + context.beginPath(); + context.strokeStyle = 'rgb(0,255,0)'; + context.strokeRect(this.position.x - this.bounds.halfWidth, this.position.y - this.bounds.halfHeight, this.bounds.width, this.bounds.height); + context.stroke(); + context.closePath(); + + // center point + context.fillStyle = 'rgb(0,255,0)'; + context.fillRect(this.position.x, this.position.y, 2, 2); + + if (this.touching & Phaser.Types.LEFT) + { + context.beginPath(); + context.strokeStyle = 'rgb(255,0,0)'; + context.moveTo(this.position.x - this.bounds.halfWidth, this.position.y - this.bounds.halfHeight); + context.lineTo(this.position.x - this.bounds.halfWidth, this.position.y + this.bounds.halfHeight); + context.stroke(); + context.closePath(); + } + if (this.touching & Phaser.Types.RIGHT) + { + context.beginPath(); + context.strokeStyle = 'rgb(255,0,0)'; + context.moveTo(this.position.x + this.bounds.halfWidth, this.position.y - this.bounds.halfHeight); + context.lineTo(this.position.x + this.bounds.halfWidth, this.position.y + this.bounds.halfHeight); + context.stroke(); + context.closePath(); + } + + if (this.touching & Phaser.Types.UP) + { + context.beginPath(); + context.strokeStyle = 'rgb(255,0,0)'; + context.moveTo(this.position.x - this.bounds.halfWidth, this.position.y - this.bounds.halfHeight); + context.lineTo(this.position.x + this.bounds.halfWidth, this.position.y - this.bounds.halfHeight); + context.stroke(); + context.closePath(); + } + if (this.touching & Phaser.Types.DOWN) + { + context.beginPath(); + context.strokeStyle = 'rgb(255,0,0)'; + context.moveTo(this.position.x - this.bounds.halfWidth, this.position.y + this.bounds.halfHeight); + context.lineTo(this.position.x + this.bounds.halfWidth, this.position.y + this.bounds.halfHeight); + context.stroke(); + context.closePath(); + } + + } + + + /** + * Render debug infos. (including name, bounds info, position and some other properties) + * @param x {number} X position of the debug info to be rendered. + * @param y {number} Y position of the debug info to be rendered. + * @param [color] {number} color of the debug info to be rendered. (format is css color string) + */ + public renderDebugInfo(x: number, y: number, color?: string = 'rgb(255,255,255)') { + + this.sprite.texture.context.fillStyle = color; + this.sprite.texture.context.fillText('Sprite: (' + this.sprite.width + ' x ' + this.sprite.height + ')', x, y); + //this.sprite.texture.context.fillText('x: ' + this._sprite.frameBounds.x.toFixed(1) + ' y: ' + this._sprite.frameBounds.y.toFixed(1) + ' rotation: ' + this._sprite.rotation.toFixed(1), x, y + 14); + this.sprite.texture.context.fillText('x: ' + this.bounds.x.toFixed(1) + ' y: ' + this.bounds.y.toFixed(1) + ' rotation: ' + this.sprite.transform.rotation.toFixed(0), x, y + 14); + this.sprite.texture.context.fillText('vx: ' + this.velocity.x.toFixed(1) + ' vy: ' + this.velocity.y.toFixed(1), x, y + 28); + this.sprite.texture.context.fillText('acx: ' + this.acceleration.x.toFixed(1) + ' acy: ' + this.acceleration.y.toFixed(1), x, y + 42); + this.sprite.texture.context.fillText('angVx: ' + this.angularVelocity.toFixed(1) + ' angAc: ' + this.angularAcceleration.toFixed(1), x, y + 56); + + } + + + } + +} \ No newline at end of file diff --git a/Phaser/Motion.ts b/Phaser/physics/arcade/Motion.ts similarity index 99% rename from Phaser/Motion.ts rename to Phaser/physics/arcade/Motion.ts index a469c4a7..d99365b3 100644 --- a/Phaser/Motion.ts +++ b/Phaser/physics/arcade/Motion.ts @@ -1,5 +1,5 @@ -/// -/// +/// +/// /** * Phaser - Motion diff --git a/Phaser/renderers/CanvasRenderer.ts b/Phaser/renderers/CanvasRenderer.ts index 1d51ed71..4eda1576 100644 --- a/Phaser/renderers/CanvasRenderer.ts +++ b/Phaser/renderers/CanvasRenderer.ts @@ -458,6 +458,11 @@ module Phaser { return false; } + if (sprite.crop && sprite.crop.empty) + { + return; + } + sprite.renderOrderID = this._count; this._count++; diff --git a/Phaser/utils/DebugUtils.ts b/Phaser/utils/DebugUtils.ts index 2864a1cd..27edfeb9 100644 --- a/Phaser/utils/DebugUtils.ts +++ b/Phaser/utils/DebugUtils.ts @@ -42,38 +42,6 @@ module Phaser { } - /** - * Render debug infos. (including name, bounds info, position and some other properties) - * @param x {number} X position of the debug info to be rendered. - * @param y {number} Y position of the debug info to be rendered. - * @param [color] {number} color of the debug info to be rendered. (format is css color string) - */ - static renderPhysicsBodyInfo(body: Phaser.Physics.Body, x: number, y: number, color?: string = 'rgb(255,255,255)') { - - DebugUtils.context.fillStyle = color; - DebugUtils.context.fillText('Body ID: ' + body.name, x, y); - DebugUtils.context.fillText('Position x: ' + body.position.x.toFixed(1) + ' y: ' + body.position.y.toFixed(1) + ' rotation: ' + body.angle.toFixed(1), x, y + 14); - DebugUtils.context.fillText('World x: ' + (body.position.x * 50).toFixed(1) + ' y: ' + (body.position.y * 50).toFixed(1), x, y + 28); - DebugUtils.context.fillText('Velocity x: ' + body.velocity.x.toFixed(1) + ' y: ' + body.velocity.y.toFixed(1), x, y + 42); - - if (body.shapes[0].verts.length > 0) - { - DebugUtils.context.fillText('Vert 1 x: ' + (body.shapes[0].verts[0].x * 50) + ' y: ' + (body.shapes[0].verts[0].y * 50), x, y + 56); - DebugUtils.context.fillText('Vert 2 x: ' + (body.shapes[0].verts[1].x * 50) + ' y: ' + (body.shapes[0].verts[1].y * 50), x, y + 70); - DebugUtils.context.fillText('Vert 3 x: ' + (body.shapes[0].tverts[2].x * 50) + ' y: ' + (body.shapes[0].tverts[2].y * 50), x, y + 84); - DebugUtils.context.fillText('Vert 4 x: ' + (body.shapes[0].tverts[3].x * 50) + ' y: ' + (body.shapes[0].tverts[3].y * 50), x, y + 98); - - /* - DebugUtils.context.fillText('Vert 1 x: ' + body.shapes[0].verts[0].x.toFixed(1) + ' y: ' + body.shapes[0].verts[0].y.toFixed(1), x, y + 56); - DebugUtils.context.fillText('Vert 2 x: ' + body.shapes[0].verts[1].x.toFixed(1) + ' y: ' + body.shapes[0].verts[1].y.toFixed(1), x, y + 70); - DebugUtils.context.fillText('Vert 3 x: ' + body.shapes[0].verts[2].x.toFixed(1) + ' y: ' + body.shapes[0].verts[2].y.toFixed(1), x, y + 84); - DebugUtils.context.fillText('Vert 4 x: ' + body.shapes[0].verts[3].x.toFixed(1) + ' y: ' + body.shapes[0].verts[3].y.toFixed(1), x, y + 98); - */ - - } - - } - static renderSpriteBounds(sprite: Sprite, camera?: Camera = null, color?: string = 'rgba(0,255,0,0.2)') { if (camera == null) @@ -118,51 +86,6 @@ module Phaser { } - static renderPhysicsBody(body: Phaser.Physics.Body, lineWidth: number = 1, fillStyle: string = 'rgba(0,255,0,0.2)', sleepStyle: string = 'rgba(100,100,100,0.2)') { - - for (var s = 0; s < body.shapesLength; s++) - { - DebugUtils.context.beginPath(); - - if (body.shapes[s].type == Phaser.Physics.AdvancedPhysics.SHAPE_TYPE_POLY) - { - var verts = body.shapes[s].tverts; - - // DebugUtils.context.moveTo(body.position.x * 50 + verts[0].x, body.position.y * 50 + verts[0].y); - DebugUtils.context.moveTo(verts[0].x * 50, verts[0].y * 50); - - for (var i = 1; i < verts.length; i++) - { - // DebugUtils.context.lineTo(body.position.x * 50 + verts[i].x, body.position.y * 50 + verts[i].y); - DebugUtils.context.lineTo(verts[i].x * 50, verts[i].y * 50); - } - - // DebugUtils.context.lineTo(body.position.x * 50 + verts[0].x, body.position.y * 50 + verts[0].y); - DebugUtils.context.lineTo(verts[0].x * 50, verts[0].y * 50); - } - else if (body.shapes[s].type == Phaser.Physics.AdvancedPhysics.SHAPE_TYPE_CIRCLE) - { - var circle = body.shapes[s]; - DebugUtils.context.arc(circle.tc.x * 50, circle.tc.y * 50, circle.radius * 50, 0, Math.PI * 2, false); - } - - DebugUtils.context.closePath(); - - if (body.isAwake) - { - DebugUtils.context.fillStyle = fillStyle; - } - else - { - DebugUtils.context.fillStyle = sleepStyle; - } - - DebugUtils.context.fill(); - - } - - } - } } \ No newline at end of file diff --git a/Tests/groups/bring to top 1.ts b/Tests/groups/bring to top 1.ts new file mode 100644 index 00000000..27f9b746 --- /dev/null +++ b/Tests/groups/bring to top 1.ts @@ -0,0 +1,92 @@ +/// + +(function () { + + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update, render); + + function init() { + + game.load.image('beast', 'assets/pics/shadow_of_the_beast2_karamoon.png'); + game.load.image('snot', 'assets/pics/nslide_snot.png'); + game.load.image('atari1', 'assets/sprites/atari130xe.png'); + game.load.image('sonic', 'assets/sprites/sonic_havok_sanity.png'); + game.load.image('coke', 'assets/sprites/cokecan.png'); + game.load.image('disk', 'assets/sprites/oz_pov_melting_disk.png'); + game.load.start(); + + } + + var group1: Phaser.Group; + var group2: Phaser.Group; + var coke: Phaser.Sprite; + var disk: Phaser.Sprite; + + function create() { + + // Create a background image + game.add.sprite(0, 0, 'beast'); + + // Create a Group that will sit above the background image + group1 = game.add.group(11); + + // Create a Group that will sit above Group 1 + group2 = game.add.group(11); + + // Now let's create some random sprites and enable them all for drag and 'bring to top' + for (var i = 0; i < 10; i++) + { + //var tempSprite: Phaser.Sprite = group1.addNewSprite(game.stage.randomX, game.stage.randomY, 'atari1'); + //var tempSprite: Phaser.Sprite = new Phaser.Sprite(game, game.stage.randomX, game.stage.randomY, 'atari1'); + var tempSprite: Phaser.Sprite = game.add.sprite(game.stage.randomX, game.stage.randomY, 'atari1'); + + tempSprite.name = 'atari' + i; + tempSprite.input.start(i, false, true); + tempSprite.input.enableDrag(false, true); + + group1.add(tempSprite); + + // Sonics + + //var tempSprite: Phaser.Sprite = group2.addNewSprite(game.stage.randomX, game.stage.randomY, 'sonic'); + //var tempSprite: Phaser.Sprite = new Phaser.Sprite(game, game.stage.randomX, game.stage.randomY, 'sonic'); + var tempSprite: Phaser.Sprite = game.add.sprite(game.stage.randomX, game.stage.randomY, 'sonic'); + + tempSprite.name = 'sonic' + i; + tempSprite.input.start(10 + i, false, true); + tempSprite.input.enableDrag(false, true); + + group2.add(tempSprite); + } + + // Add 2 control sprites into each group - these cannot be dragged but should be bought to the top each time + coke = group1.addNewSprite(100, 100, 'coke'); + disk = group2.addNewSprite(400, 300, 'disk'); + + // Create a foreground image - everything should appear behind this, even when dragged + var snot = game.add.sprite(game.stage.centerX, game.stage.height, 'snot'); + snot.origin.setTo(0.5, 1); + + // You can click and drag any sprite but Sonic sprites should always appear above the Atari sprites + // and both types of sprite should only ever appear above the background and behind the + + } + + function update() { + + if (game.input.keyboard.justReleased(Phaser.Keyboard.ONE)) + { + coke.bringToTop(); + } + + if (game.input.keyboard.justReleased(Phaser.Keyboard.TWO)) + { + disk.bringToTop(); + } + + } + + function render() { + game.input.renderDebugInfo(32, 32); + } + +})(); diff --git a/Tests/phaser.js b/Tests/phaser.js index a53e9d94..007bfa83 100644 --- a/Tests/phaser.js +++ b/Tests/phaser.js @@ -3659,9 +3659,9 @@ var Phaser; this.startDrag(pointer); } if(this.bringToTop) { - //this._parent.bringToTop(); - this._parent.game.world.group.bringToTop(this._parent); - } + this._parent.bringToTop(); + //this._parent.game.world.group.bringToTop(this._parent); + } } // Consume the event? return this.consumePointerEvent; @@ -4322,2830 +4322,1348 @@ var Phaser; */ })(Phaser || (Phaser = {})); /// -/// +/// +/// +/// /** -* Phaser - 2D Transform +* Phaser - CircleUtils * -* A 2D Transform +* A collection of methods useful for manipulating and comparing Circle objects. +* +* TODO: */ var Phaser; (function (Phaser) { - var Transform = (function () { - /** - * Creates a new 2D Transform object. - * @class Transform - * @constructor - * @return {Transform} This object + var CircleUtils = (function () { + function CircleUtils() { } + CircleUtils.clone = /** + * Returns a new Circle object with the same values for the x, y, width, and height properties as the original Circle object. + * @method clone + * @param {Circle} a - The Circle object. + * @param {Circle} [optional] out Optional Circle object. If given the values will be set into the object, otherwise a brand new Circle object will be created and returned. + * @return {Phaser.Circle} **/ - function Transform(pos, angle) { - this.t = Phaser.Vec2Utils.clone(pos); - this.c = Math.cos(angle); - this.s = Math.sin(angle); - this.angle = angle; - } - Transform.prototype.toString = function () { - return 't=' + this.t.toString() + ' c=' + this.c + ' s=' + this.s + ' a=' + this.angle; + function clone(a, out) { + if (typeof out === "undefined") { out = new Phaser.Circle(); } + return out.setTo(a.x, a.y, a.diameter); }; - Transform.prototype.setTo = function (pos, angle) { - this.t.copyFrom(pos); - this.c = Math.cos(angle); - this.s = Math.sin(angle); - return this; - }; - Transform.prototype.setRotation = function (angle) { - if(angle !== this.angle) { - this.c = Math.cos(angle); - this.s = Math.sin(angle); - this.angle = angle; + CircleUtils.contains = /** + * Return true if the given x/y coordinates are within the Circle object. + * If you need details about the intersection then use Phaser.Intersect.circleContainsPoint instead. + * @method contains + * @param {Circle} a - The Circle object. + * @param {Number} The X value of the coordinate to test. + * @param {Number} The Y value of the coordinate to test. + * @return {Boolean} True if the coordinates are within this circle, otherwise false. + **/ + function contains(a, x, y) { + // Check if x/y are within the bounds first + if(x >= a.left && x <= a.right && y >= a.top && y <= a.bottom) { + var dx = (a.x - x) * (a.x - x); + var dy = (a.y - y) * (a.y - y); + return (dx + dy) <= (a.radius * a.radius); } - return this; + return false; }; - Transform.prototype.setPosition = function (p) { - this.t.copyFrom(p); - return this; + CircleUtils.containsPoint = /** + * Return true if the coordinates of the given Point object are within this Circle object. + * If you need details about the intersection then use Phaser.Intersect.circleContainsPoint instead. + * @method containsPoint + * @param {Circle} a - The Circle object. + * @param {Point} The Point object to test. + * @return {Boolean} True if the coordinates are within this circle, otherwise false. + **/ + function containsPoint(a, point) { + return CircleUtils.contains(a, point.x, point.y); }; - Transform.prototype.identity = function () { - this.t.setTo(0, 0); - this.c = 1; - this.s = 0; - return this; + CircleUtils.containsCircle = /** + * Return true if the given Circle is contained entirely within this Circle object. + * If you need details about the intersection then use Phaser.Intersect.circleToCircle instead. + * @method containsCircle + * @param {Circle} The Circle object to test. + * @return {Boolean} True if the coordinates are within this circle, otherwise false. + **/ + function containsCircle(a, b) { + //return ((a.radius + b.radius) * (a.radius + b.radius)) >= Collision.distanceSquared(a.x, a.y, b.x, b.y); + return true; }; - return Transform; + CircleUtils.distanceBetween = /** + * Returns the distance from the center of the Circle object to the given object (can be Circle, Point or anything with x/y properties) + * @method distanceBetween + * @param {Circle} a - The Circle object. + * @param {Circle} b - The target object. Must have visible x and y properties that represent the center of the object. + * @param {Boolean} [optional] round - Round the distance to the nearest integer (default false) + * @return {Number} The distance between this Point object and the destination Point object. + **/ + function distanceBetween(a, target, round) { + if (typeof round === "undefined") { round = false; } + var dx = a.x - target.x; + var dy = a.y - target.y; + if(round === true) { + return Math.round(Math.sqrt(dx * dx + dy * dy)); + } else { + return Math.sqrt(dx * dx + dy * dy); + } + }; + CircleUtils.equals = /** + * Determines whether the two Circle objects match. This method compares the x, y and diameter properties. + * @method equals + * @param {Circle} a - The first Circle object. + * @param {Circle} b - The second Circle object. + * @return {Boolean} A value of true if the object has exactly the same values for the x, y and diameter properties as this Circle object; otherwise false. + **/ + function equals(a, b) { + return (a.x == b.x && a.y == b.y && a.diameter == b.diameter); + }; + CircleUtils.intersects = /** + * Determines whether the two Circle objects intersect. + * This method checks the radius distances between the two Circle objects to see if they intersect. + * @method intersects + * @param {Circle} a - The first Circle object. + * @param {Circle} b - The second Circle object. + * @return {Boolean} A value of true if the specified object intersects with this Circle object; otherwise false. + **/ + function intersects(a, b) { + return (CircleUtils.distanceBetween(a, b) <= (a.radius + b.radius)); + }; + CircleUtils.circumferencePoint = /** + * Returns a Point object containing the coordinates of a point on the circumference of the Circle based on the given angle. + * @method circumferencePoint + * @param {Circle} a - The first Circle object. + * @param {Number} angle The angle in radians (unless asDegrees is true) to return the point from. + * @param {Boolean} asDegrees Is the given angle in radians (false) or degrees (true)? + * @param {Phaser.Point} [optional] output An optional Point object to put the result in to. If none specified a new Point object will be created. + * @return {Phaser.Point} The Point object holding the result. + **/ + function circumferencePoint(a, angle, asDegrees, out) { + if (typeof asDegrees === "undefined") { asDegrees = false; } + if (typeof out === "undefined") { out = new Phaser.Point(); } + if(asDegrees === true) { + angle = angle * Phaser.GameMath.DEG_TO_RAD; + } + return out.setTo(a.x + a.radius * Math.cos(angle), a.y + a.radius * Math.sin(angle)); + }; + CircleUtils.intersectsRectangle = /* + public static boolean intersect(Rectangle r, Circle c) + { + float cx = Math.abs(c.x - r.x - r.halfWidth); + float xDist = r.halfWidth + c.radius; + if (cx > xDist) + return false; + float cy = Math.abs(c.y - r.y - r.halfHeight); + float yDist = r.halfHeight + c.radius; + if (cy > yDist) + return false; + if (cx <= r.halfWidth || cy <= r.halfHeight) + return true; + float xCornerDist = cx - r.halfWidth; + float yCornerDist = cy - r.halfHeight; + float xCornerDistSq = xCornerDist * xCornerDist; + float yCornerDistSq = yCornerDist * yCornerDist; + float maxCornerDistSq = c.radius * c.radius; + return xCornerDistSq + yCornerDistSq <= maxCornerDistSq; + } + */ + function intersectsRectangle(c, r) { + var cx = Math.abs(c.x - r.x - r.halfWidth); + var xDist = r.halfWidth + c.radius; + if(cx > xDist) { + return false; + } + var cy = Math.abs(c.y - r.y - r.halfHeight); + var yDist = r.halfHeight + c.radius; + if(cy > yDist) { + return false; + } + if(cx <= r.halfWidth || cy <= r.halfHeight) { + return true; + } + var xCornerDist = cx - r.halfWidth; + var yCornerDist = cy - r.halfHeight; + var xCornerDistSq = xCornerDist * xCornerDist; + var yCornerDistSq = yCornerDist * yCornerDist; + var maxCornerDistSq = c.radius * c.radius; + return xCornerDistSq + yCornerDistSq <= maxCornerDistSq; + }; + return CircleUtils; })(); - Phaser.Transform = Transform; + Phaser.CircleUtils = CircleUtils; })(Phaser || (Phaser = {})); -/// -/// -/// -/** -* Phaser - TransformUtils -* -* A collection of methods useful for manipulating and performing operations on 2D Transforms. -* -*/ var Phaser; (function (Phaser) { - var TransformUtils = (function () { - function TransformUtils() { } - TransformUtils.rotate = function rotate(t, v, out) { - if (typeof out === "undefined") { out = new Phaser.Vec2(); } - //return new vec2(v.x * this.c - v.y * this.s, v.x * this.s + v.y * this.c); - return out.setTo(v.x * t.c - v.y * t.s, v.x * t.s + v.y * t.c); - }; - TransformUtils.unrotate = function unrotate(t, v, out) { - if (typeof out === "undefined") { out = new Phaser.Vec2(); } - //return new vec2(v.x * this.c + v.y * this.s, -v.x * this.s + v.y * this.c); - return out.setTo(v.x * t.c + v.y * t.s, -v.x * t.s + v.y * t.c); - }; - TransformUtils.transform = function transform(t, v, out) { - if (typeof out === "undefined") { out = new Phaser.Vec2(); } - //return new vec2(v.x * this.c - v.y * this.s + this.t.x, v.x * this.s + v.y * this.c + this.t.y); - 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); - }; - TransformUtils.untransform = function untransform(t, v, out) { - if (typeof out === "undefined") { out = new Phaser.Vec2(); } - var px = v.x - t.t.x; - var py = v.y - t.t.y; - //return new vec2(px * this.c + py * this.s, -px * this.s + py * this.c); - return out.setTo(px * t.c + py * t.s, -px * t.s + py * t.c); - }; - return TransformUtils; - })(); - Phaser.TransformUtils = TransformUtils; + /// + /// + /// + /// + /// + /** + * Phaser - ArcadePhysics Manager + * + */ + (function (Physics) { + var ArcadePhysics = (function () { + function ArcadePhysics(game, width, height) { + this._length = 0; + /** + * @type {number} + */ + this.worldDivisions = 6; + this.game = game; + this.gravity = new Phaser.Vec2(); + this.drag = new Phaser.Vec2(); + this.bounce = new Phaser.Vec2(); + this.angularDrag = 0; + this.bounds = new Phaser.Rectangle(0, 0, width, height); + this._distance = new Phaser.Vec2(); + this._tangent = new Phaser.Vec2(); + //this.members = new Group(game); + } + ArcadePhysics.OVERLAP_BIAS = 4; + ArcadePhysics.TILE_OVERLAP = false; + ArcadePhysics.prototype.updateMotion = /* + public update() { + + this._length = this._objects.length; + + for (var i = 0; i < this._length; i++) + { + if (this._objects[i]) + { + this._objects[i].preUpdate(); + this.updateMotion(this._objects[i]); + this.collideWorld(this._objects[i]); + + for (var x = 0; x < this._length; x++) + { + if (this._objects[x] && this._objects[x] !== this._objects[i]) + { + //this.collideShapes(this._objects[i], this._objects[x]); + var r = this.NEWseparate(this._objects[i], this._objects[x]); + //console.log('sep', r); + } + } + + } + } + + } + + public render() { + + // iterate through the objects here, updating and colliding + for (var i = 0; i < this._length; i++) + { + if (this._objects[i]) + { + this._objects[i].render(this.game.stage.context); + } + } + + } + */ + function (body) { + if(body.type == Phaser.Types.BODY_DISABLED) { + return; + } + this._velocityDelta = (this.computeVelocity(body.angularVelocity, body.gravity.x, body.angularAcceleration, body.angularDrag, body.maxAngular) - body.angularVelocity) / 2; + body.angularVelocity += this._velocityDelta; + body.sprite.transform.rotation += body.angularVelocity * this.game.time.elapsed; + body.angularVelocity += this._velocityDelta; + this._velocityDelta = (this.computeVelocity(body.velocity.x, body.gravity.x, body.acceleration.x, body.drag.x) - body.velocity.x) / 2; + body.velocity.x += this._velocityDelta; + this._delta = body.velocity.x * this.game.time.elapsed; + body.velocity.x += this._velocityDelta; + //body.position.x += this._delta; + body.sprite.x += this._delta; + this._velocityDelta = (this.computeVelocity(body.velocity.y, body.gravity.y, body.acceleration.y, body.drag.y) - body.velocity.y) / 2; + body.velocity.y += this._velocityDelta; + this._delta = body.velocity.y * this.game.time.elapsed; + body.velocity.y += this._velocityDelta; + //body.position.y += this._delta; + body.sprite.y += this._delta; + }; + ArcadePhysics.prototype.computeVelocity = /** + * 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. + */ + function (velocity, gravity, acceleration, drag, max) { + if (typeof gravity === "undefined") { gravity = 0; } + if (typeof acceleration === "undefined") { acceleration = 0; } + if (typeof drag === "undefined") { drag = 0; } + if (typeof max === "undefined") { max = 10000; } + if(acceleration !== 0) { + velocity += (acceleration + gravity) * this.game.time.elapsed; + } else if(drag !== 0) { + this._drag = drag * this.game.time.elapsed; + if(velocity - this._drag > 0) { + velocity = velocity - this._drag; + } else if(velocity + this._drag < 0) { + velocity += this._drag; + } else { + velocity = 0; + } + velocity += gravity; + } + if((velocity != 0) && (max != 10000)) { + if(velocity > max) { + velocity = max; + } else if(velocity < -max) { + velocity = -max; + } + } + return velocity; + }; + ArcadePhysics.prototype.separate = /** + * 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. + */ + function (body1, body2) { + this._separatedX = this.separateBodyX(body1, body2); + this._separatedY = this.separateBodyY(body1, body2); + return this._separatedX || this._separatedY; + }; + ArcadePhysics.prototype.checkHullIntersection = function (body1, body2) { + return ((body1.hullX + body1.hullWidth > body2.hullX) && (body1.hullX < body2.hullX + body2.hullWidth) && (body1.hullY + body1.hullHeight > body2.hullY) && (body1.hullY < body2.hullY + body2.hullHeight)); + }; + ArcadePhysics.prototype.separateBodyX = /** + * 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. + */ + function (body1, body2) { + // Can't separate two disabled or static objects + if((body1.type == Phaser.Types.BODY_DISABLED || body1.type == Phaser.Types.BODY_STATIC) && (body2.type == Phaser.Types.BODY_DISABLED || body2.type == Phaser.Types.BODY_STATIC)) { + return false; + } + // First, get the two object deltas + this._overlap = 0; + if(body1.deltaX != body2.deltaX) { + if(Phaser.RectangleUtils.intersects(body1.bounds, body2.bounds)) { + this._maxOverlap = body1.deltaXAbs + body2.deltaXAbs + ArcadePhysics.OVERLAP_BIAS; + // If they did overlap (and can), figure out by how much and flip the corresponding flags + if(body1.deltaX > body2.deltaX) { + this._overlap = body1.bounds.right - body2.bounds.x; + if((this._overlap > this._maxOverlap) || !(body1.allowCollisions & Phaser.Types.RIGHT) || !(body2.allowCollisions & Phaser.Types.LEFT)) { + this._overlap = 0; + } else { + body1.touching |= Phaser.Types.RIGHT; + body2.touching |= Phaser.Types.LEFT; + } + } else if(body1.deltaX < body2.deltaX) { + this._overlap = body1.bounds.x - body2.bounds.width - body2.bounds.x; + if((-this._overlap > this._maxOverlap) || !(body1.allowCollisions & Phaser.Types.LEFT) || !(body2.allowCollisions & Phaser.Types.RIGHT)) { + this._overlap = 0; + } else { + body1.touching |= Phaser.Types.LEFT; + body2.touching |= Phaser.Types.RIGHT; + } + } + } + } + // Then adjust their positions and velocities accordingly (if there was any overlap) + if(this._overlap != 0) { + this._obj1Velocity = body1.velocity.x; + this._obj2Velocity = body2.velocity.x; + /** + * 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 + */ + // 2 dynamic bodies will exchange velocities + if(body1.type == Phaser.Types.BODY_DYNAMIC && body2.type == Phaser.Types.BODY_DYNAMIC) { + this._overlap *= 0.5; + body1.position.x = body1.position.x - this._overlap; + body2.position.x += this._overlap; + this._obj1NewVelocity = Math.sqrt((this._obj2Velocity * this._obj2Velocity * body2.mass) / body1.mass) * ((this._obj2Velocity > 0) ? 1 : -1); + this._obj2NewVelocity = Math.sqrt((this._obj1Velocity * this._obj1Velocity * body1.mass) / body2.mass) * ((this._obj1Velocity > 0) ? 1 : -1); + this._average = (this._obj1NewVelocity + this._obj2NewVelocity) * 0.5; + this._obj1NewVelocity -= this._average; + this._obj2NewVelocity -= this._average; + body1.velocity.x = this._average + this._obj1NewVelocity * body1.bounce.x; + body2.velocity.x = this._average + this._obj2NewVelocity * body2.bounce.x; + } else if(body2.type != Phaser.Types.BODY_DYNAMIC) { + // Body 2 is Static or Kinematic + this._overlap *= 2; + body1.position.x -= this._overlap; + body1.velocity.x = this._obj2Velocity - this._obj1Velocity * body1.bounce.x; + } else if(body1.type != Phaser.Types.BODY_DYNAMIC) { + // Body 1 is Static or Kinematic + this._overlap *= 2; + body2.position.x += this._overlap; + body2.velocity.x = this._obj1Velocity - this._obj2Velocity * body2.bounce.x; + } + return true; + } else { + return false; + } + }; + ArcadePhysics.prototype.separateBodyY = /** + * 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. + */ + function (body1, body2) { + // Can't separate two immovable objects + if((body1.type == Phaser.Types.BODY_DISABLED || body1.type == Phaser.Types.BODY_STATIC) && (body2.type == Phaser.Types.BODY_DISABLED || body2.type == Phaser.Types.BODY_STATIC)) { + return false; + } + // First, get the two object deltas + this._overlap = 0; + if(body1.deltaY != body2.deltaY) { + if(Phaser.RectangleUtils.intersects(body1.bounds, body2.bounds)) { + // This is the only place to use the DeltaAbs values + this._maxOverlap = body1.deltaYAbs + body2.deltaYAbs + ArcadePhysics.OVERLAP_BIAS; + // If they did overlap (and can), figure out by how much and flip the corresponding flags + if(body1.deltaY > body2.deltaY) { + this._overlap = body1.bounds.bottom - body2.bounds.y; + if((this._overlap > this._maxOverlap) || !(body1.allowCollisions & Phaser.Types.DOWN) || !(body2.allowCollisions & Phaser.Types.UP)) { + this._overlap = 0; + } else { + body1.touching |= Phaser.Types.DOWN; + body2.touching |= Phaser.Types.UP; + } + } else if(body1.deltaY < body2.deltaY) { + this._overlap = body1.bounds.y - body2.bounds.height - body2.bounds.y; + if((-this._overlap > this._maxOverlap) || !(body1.allowCollisions & Phaser.Types.UP) || !(body2.allowCollisions & Phaser.Types.DOWN)) { + this._overlap = 0; + } else { + body1.touching |= Phaser.Types.UP; + body2.touching |= Phaser.Types.DOWN; + } + } + } + } + // Then adjust their positions and velocities accordingly (if there was any overlap) + if(this._overlap != 0) { + this._obj1Velocity = body1.velocity.y; + this._obj2Velocity = body2.velocity.y; + /** + * 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 + */ + if(body1.type == Phaser.Types.BODY_DYNAMIC && body2.type == Phaser.Types.BODY_DYNAMIC) { + this._overlap *= 0.5; + body1.position.y = body1.position.y - this._overlap; + body2.position.y += this._overlap; + this._obj1NewVelocity = Math.sqrt((this._obj2Velocity * this._obj2Velocity * body2.mass) / body1.mass) * ((this._obj2Velocity > 0) ? 1 : -1); + this._obj2NewVelocity = Math.sqrt((this._obj1Velocity * this._obj1Velocity * body1.mass) / body2.mass) * ((this._obj1Velocity > 0) ? 1 : -1); + var average = (this._obj1NewVelocity + this._obj2NewVelocity) * 0.5; + this._obj1NewVelocity -= average; + this._obj2NewVelocity -= average; + body1.velocity.y = average + this._obj1NewVelocity * body1.bounce.y; + body2.velocity.y = average + this._obj2NewVelocity * body2.bounce.y; + } else if(body2.type != Phaser.Types.BODY_DYNAMIC) { + this._overlap *= 2; + body1.position.y -= this._overlap; + body1.velocity.y = this._obj2Velocity - this._obj1Velocity * body1.bounce.y; + // This is special case code that handles things like horizontal moving platforms you can ride + //if (body2.parent.active && body2.moves && (body1.deltaY > body2.deltaY)) + if(body2.sprite.active && (body1.deltaY > body2.deltaY)) { + body1.position.x += body2.position.x - body2.oldPosition.x; + } + } else if(body1.type != Phaser.Types.BODY_DYNAMIC) { + this._overlap *= 2; + body2.position.y += this._overlap; + body2.velocity.y = this._obj1Velocity - this._obj2Velocity * body2.bounce.y; + // This is special case code that handles things like horizontal moving platforms you can ride + //if (object1.active && body1.moves && (body1.deltaY < body2.deltaY)) + if(body1.sprite.active && (body1.deltaY < body2.deltaY)) { + body2.position.x += body1.position.x - body1.oldPosition.x; + } + } + return true; + } else { + return false; + } + }; + ArcadePhysics.prototype.overlap = /* + private TILEseparate(shapeA: IPhysicsShape, shapeB: IPhysicsShape, distance: Vec2, tangent: Vec2) { + + if (tangent.x == 1) + { + console.log('1 The left side of ShapeA hit the right side of ShapeB', Math.floor(distance.x)); + shapeA.physics.touching |= Phaser.Types.LEFT; + shapeB.physics.touching |= Phaser.Types.RIGHT; + } + else if (tangent.x == -1) + { + console.log('2 The right side of ShapeA hit the left side of ShapeB', Math.floor(distance.x)); + shapeA.physics.touching |= Phaser.Types.RIGHT; + shapeB.physics.touching |= Phaser.Types.LEFT; + } + + if (tangent.y == 1) + { + console.log('3 The top of ShapeA hit the bottom of ShapeB', Math.floor(distance.y)); + shapeA.physics.touching |= Phaser.Types.UP; + shapeB.physics.touching |= Phaser.Types.DOWN; + } + else if (tangent.y == -1) + { + console.log('4 The bottom of ShapeA hit the top of ShapeB', Math.floor(distance.y)); + shapeA.physics.touching |= Phaser.Types.DOWN; + shapeB.physics.touching |= Phaser.Types.UP; + } + + + // only apply collision response forces if the object is travelling into, and not out of, the collision + var dot = Vec2Utils.dot(shapeA.physics.velocity, tangent); + + if (dot < 0) + { + console.log('in to', dot); + + // Apply horizontal bounce + if (shapeA.physics.bounce.x > 0) + { + shapeA.physics.velocity.x *= -(shapeA.physics.bounce.x); + } + else + { + shapeA.physics.velocity.x = 0; + } + // Apply horizontal bounce + if (shapeA.physics.bounce.y > 0) + { + shapeA.physics.velocity.y *= -(shapeA.physics.bounce.y); + } + else + { + shapeA.physics.velocity.y = 0; + } + } + else + { + console.log('out of', dot); + } + + shapeA.position.x += Math.floor(distance.x); + //shapeA.bounds.x += Math.floor(distance.x); + + shapeA.position.y += Math.floor(distance.y); + //shapeA.bounds.y += distance.y; + + console.log('------------------------------------------------'); + + } + + private collideWorld(shape:IPhysicsShape) { + + // Collide on the x-axis + this._distance.x = shape.world.bounds.x - (shape.position.x - shape.bounds.halfWidth); + + if (0 < this._distance.x) + { + // Hit Left + this._tangent.setTo(1, 0); + this.separateXWall(shape, this._distance, this._tangent); + } + else + { + this._distance.x = (shape.position.x + shape.bounds.halfWidth) - shape.world.bounds.right; + + if (0 < this._distance.x) + { + // Hit Right + this._tangent.setTo(-1, 0); + this._distance.reverse(); + this.separateXWall(shape, this._distance, this._tangent); + } + } + + // Collide on the y-axis + this._distance.y = shape.world.bounds.y - (shape.position.y - shape.bounds.halfHeight); + + if (0 < this._distance.y) + { + // Hit Top + this._tangent.setTo(0, 1); + this.separateYWall(shape, this._distance, this._tangent); + } + else + { + this._distance.y = (shape.position.y + shape.bounds.halfHeight) - shape.world.bounds.bottom; + + if (0 < this._distance.y) + { + // Hit Bottom + this._tangent.setTo(0, -1); + this._distance.reverse(); + this.separateYWall(shape, this._distance, this._tangent); + } + } + + } + + private separateX(shapeA: IPhysicsShape, shapeB: IPhysicsShape, distance: Vec2, tangent: Vec2) { + + if (tangent.x == 1) + { + console.log('The left side of ShapeA hit the right side of ShapeB', distance.x); + shapeA.physics.touching |= Phaser.Types.LEFT; + shapeB.physics.touching |= Phaser.Types.RIGHT; + } + else + { + console.log('The right side of ShapeA hit the left side of ShapeB', distance.x); + shapeA.physics.touching |= Phaser.Types.RIGHT; + shapeB.physics.touching |= Phaser.Types.LEFT; + } + + // collision edges + //shapeA.oH = tangent.x; + + // only apply collision response forces if the object is travelling into, and not out of, the collision + if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) + { + // Apply horizontal bounce + if (shapeA.physics.bounce.x > 0) + { + shapeA.physics.velocity.x *= -(shapeA.physics.bounce.x); + } + else + { + shapeA.physics.velocity.x = 0; + } + } + + shapeA.position.x += distance.x; + shapeA.bounds.x += distance.x; + + } + + private separateY(shapeA: IPhysicsShape, shapeB: IPhysicsShape, distance: Vec2, tangent: Vec2) { + + if (tangent.y == 1) + { + console.log('The top of ShapeA hit the bottom of ShapeB', distance.y); + shapeA.physics.touching |= Phaser.Types.UP; + shapeB.physics.touching |= Phaser.Types.DOWN; + } + else + { + console.log('The bottom of ShapeA hit the top of ShapeB', distance.y); + shapeA.physics.touching |= Phaser.Types.DOWN; + shapeB.physics.touching |= Phaser.Types.UP; + } + + // collision edges + //shapeA.oV = tangent.y; + + // only apply collision response forces if the object is travelling into, and not out of, the collision + if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) + { + // Apply horizontal bounce + if (shapeA.physics.bounce.y > 0) + { + shapeA.physics.velocity.y *= -(shapeA.physics.bounce.y); + } + else + { + shapeA.physics.velocity.y = 0; + } + } + + shapeA.position.y += distance.y; + shapeA.bounds.y += distance.y; + + } + + private separateXWall(shapeA: IPhysicsShape, distance: Vec2, tangent: Vec2) { + + if (tangent.x == 1) + { + console.log('The left side of ShapeA hit the right side of ShapeB', distance.x); + shapeA.physics.touching |= Phaser.Types.LEFT; + } + else + { + console.log('The right side of ShapeA hit the left side of ShapeB', distance.x); + shapeA.physics.touching |= Phaser.Types.RIGHT; + } + + // collision edges + //shapeA.oH = tangent.x; + + // only apply collision response forces if the object is travelling into, and not out of, the collision + if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) + { + // Apply horizontal bounce + if (shapeA.physics.bounce.x > 0) + { + shapeA.physics.velocity.x *= -(shapeA.physics.bounce.x); + } + else + { + shapeA.physics.velocity.x = 0; + } + } + + shapeA.position.x += distance.x; + + } + + private separateYWall(shapeA: IPhysicsShape, distance: Vec2, tangent: Vec2) { + + if (tangent.y == 1) + { + console.log('The top of ShapeA hit the bottom of ShapeB', distance.y); + shapeA.physics.touching |= Phaser.Types.UP; + } + else + { + console.log('The bottom of ShapeA hit the top of ShapeB', distance.y); + shapeA.physics.touching |= Phaser.Types.DOWN; + } + + // collision edges + //shapeA.oV = tangent.y; + + // only apply collision response forces if the object is travelling into, and not out of, the collision + if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) + { + // Apply horizontal bounce + if (shapeA.physics.bounce.y > 0) + { + shapeA.physics.velocity.y *= -(shapeA.physics.bounce.y); + } + else + { + shapeA.physics.velocity.y = 0; + } + } + + shapeA.position.y += distance.y; + + } + */ + /** + * 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. + */ + function (object1, object2, notifyCallback, processCallback, context) { + if (typeof object1 === "undefined") { object1 = null; } + if (typeof object2 === "undefined") { object2 = null; } + if (typeof notifyCallback === "undefined") { notifyCallback = null; } + if (typeof processCallback === "undefined") { processCallback = null; } + if (typeof context === "undefined") { context = null; } + /* + if (object1 == null) + { + object1 = this.game.world.group; + } + + if (object2 == object1) + { + object2 = null; + } + + QuadTree.divisions = this.worldDivisions; + + this._quadTree = new Phaser.QuadTree(this, this.bounds.x, this.bounds.y, this.bounds.width, this.bounds.height); + + this._quadTree.load(object1, object2, notifyCallback, processCallback, context); + + this._quadTreeResult = this._quadTree.execute(); + + console.log('over', this._quadTreeResult); + + this._quadTree.destroy(); + + this._quadTree = null; + + return this._quadTreeResult; + */ + return false; + }; + ArcadePhysics.prototype.separateTile = /** + * 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 + */ + function (object, x, y, width, height, mass, collideLeft, collideRight, collideUp, collideDown, separateX, separateY) { + //var separatedX: bool = this.separateTileX(object, x, y, width, height, mass, collideLeft, collideRight, separateX); + //var separatedY: bool = this.separateTileY(object, x, y, width, height, mass, collideUp, collideDown, separateY); + //return separatedX || separatedY; + return false; + }; + return ArcadePhysics; + })(); + Physics.ArcadePhysics = ArcadePhysics; + /** + * Separates the two objects on their x axis + * @param object The GameObject to separate + * @param tile The Tile to separate + * @returns {boolean} Whether the objects in fact touched and were separated along the X axis. + */ + /* + public separateTileX(object:Sprite, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool, separate: bool): bool { + + // Can't separate two immovable objects (tiles are always immovable) + if (object.immovable) + { + return false; + } + + // First, get the object delta + var overlap: number = 0; + var objDelta: number = object.x - object.last.x; + //var objDelta: number = object.collisionMask.deltaX; + + if (objDelta != 0) + { + // Check if the X hulls actually overlap + var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; + //var objDeltaAbs: number = object.collisionMask.deltaXAbs; + var objBounds: Rectangle = new Rectangle(object.x - ((objDelta > 0) ? objDelta : 0), object.last.y, object.width + ((objDelta > 0) ? objDelta : -objDelta), object.height); + + if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) + { + var maxOverlap: number = objDeltaAbs + Collision.OVERLAP_BIAS; + + // If they did overlap (and can), figure out by how much and flip the corresponding flags + if (objDelta > 0) + { + overlap = object.x + object.width - x; + + if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.RIGHT) || collideLeft == false) + { + overlap = 0; + } + else + { + object.touching |= Collision.RIGHT; + } + } + else if (objDelta < 0) + { + overlap = object.x - width - x; + + if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.LEFT) || collideRight == false) + { + overlap = 0; + } + else + { + object.touching |= Collision.LEFT; + } + + } + + } + } + + // Then adjust their positions and velocities accordingly (if there was any overlap) + if (overlap != 0) + { + if (separate == true) + { + //console.log(' + object.x = object.x - overlap; + object.velocity.x = -(object.velocity.x * object.elasticity); + } + + Collision.TILE_OVERLAP = true; + return true; + } + else + { + return false; + } + + } + */ + /** + * Separates the two objects on their y axis + * @param object The first GameObject to separate + * @param tile The second GameObject to separate + * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis. + */ + /* + public separateTileY(object: Sprite, x: number, y: number, width: number, height: number, mass: number, collideUp: bool, collideDown: bool, separate: bool): bool { + + // Can't separate two immovable objects (tiles are always immovable) + if (object.immovable) + { + return false; + } + + // First, get the two object deltas + var overlap: number = 0; + var objDelta: number = object.y - object.last.y; + + if (objDelta != 0) + { + // Check if the Y hulls actually overlap + var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; + var objBounds: Rectangle = new Rectangle(object.x, object.y - ((objDelta > 0) ? objDelta : 0), object.width, object.height + objDeltaAbs); + + if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) + { + var maxOverlap: number = objDeltaAbs + Collision.OVERLAP_BIAS; + + // If they did overlap (and can), figure out by how much and flip the corresponding flags + if (objDelta > 0) + { + overlap = object.y + object.height - y; + + if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.DOWN) || collideUp == false) + { + overlap = 0; + } + else + { + object.touching |= Collision.DOWN; + } + } + else if (objDelta < 0) + { + overlap = object.y - height - y; + + if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.UP) || collideDown == false) + { + overlap = 0; + } + else + { + object.touching |= Collision.UP; + } + } + } + } + + // TODO - with super low velocities you get lots of stuttering, set some kind of base minimum here + + // Then adjust their positions and velocities accordingly (if there was any overlap) + if (overlap != 0) + { + if (separate == true) + { + object.y = object.y - overlap; + object.velocity.y = -(object.velocity.y * object.elasticity); + } + + Collision.TILE_OVERLAP = true; + return true; + } + else + { + return false; + } + } + */ + /** + * Separates the two objects on their x axis + * @param object The GameObject to separate + * @param tile The Tile to separate + * @returns {boolean} Whether the objects in fact touched and were separated along the X axis. + */ + /* + public static NEWseparateTileX(object:Sprite, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool, separate: bool): bool { + + // Can't separate two immovable objects (tiles are always immovable) + if (object.immovable) + { + return false; + } + + // First, get the object delta + var overlap: number = 0; + + if (object.collisionMask.deltaX != 0) + { + // Check if the X hulls actually overlap + //var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; + //var objBounds: Rectangle = new Rectangle(object.x - ((objDelta > 0) ? objDelta : 0), object.last.y, object.width + ((objDelta > 0) ? objDelta : -objDelta), object.height); + + //if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) + if (object.collisionMask.intersectsRaw(x, x + width, y, y + height)) + { + var maxOverlap: number = object.collisionMask.deltaXAbs + Collision.OVERLAP_BIAS; + + // If they did overlap (and can), figure out by how much and flip the corresponding flags + if (object.collisionMask.deltaX > 0) + { + //overlap = object.x + object.width - x; + overlap = object.collisionMask.right - x; + + if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.RIGHT) || collideLeft == false) + { + overlap = 0; + } + else + { + object.touching |= Collision.RIGHT; + } + } + else if (object.collisionMask.deltaX < 0) + { + //overlap = object.x - width - x; + overlap = object.collisionMask.x - width - x; + + if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.LEFT) || collideRight == false) + { + overlap = 0; + } + else + { + object.touching |= Collision.LEFT; + } + + } + + } + } + + // Then adjust their positions and velocities accordingly (if there was any overlap) + if (overlap != 0) + { + if (separate == true) + { + object.x = object.x - overlap; + object.velocity.x = -(object.velocity.x * object.elasticity); + } + + Collision.TILE_OVERLAP = true; + return true; + } + else + { + return false; + } + + } + */ + /** + * Separates the two objects on their y axis + * @param object The first GameObject to separate + * @param tile The second GameObject to separate + * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis. + */ + /* + public NEWseparateTileY(object: Sprite, x: number, y: number, width: number, height: number, mass: number, collideUp: bool, collideDown: bool, separate: bool): bool { + + // Can't separate two immovable objects (tiles are always immovable) + if (object.immovable) + { + return false; + } + + // First, get the two object deltas + var overlap: number = 0; + //var objDelta: number = object.y - object.last.y; + + if (object.collisionMask.deltaY != 0) + { + // Check if the Y hulls actually overlap + //var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; + //var objBounds: Rectangle = new Rectangle(object.x, object.y - ((objDelta > 0) ? objDelta : 0), object.width, object.height + objDeltaAbs); + + //if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) + if (object.collisionMask.intersectsRaw(x, x + width, y, y + height)) + { + //var maxOverlap: number = objDeltaAbs + Collision.OVERLAP_BIAS; + var maxOverlap: number = object.collisionMask.deltaYAbs + Collision.OVERLAP_BIAS; + + // If they did overlap (and can), figure out by how much and flip the corresponding flags + if (object.collisionMask.deltaY > 0) + { + //overlap = object.y + object.height - y; + overlap = object.collisionMask.bottom - y; + + if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.DOWN) || collideUp == false) + { + overlap = 0; + } + else + { + object.touching |= Collision.DOWN; + } + } + else if (object.collisionMask.deltaY < 0) + { + //overlap = object.y - height - y; + overlap = object.collisionMask.y - height - y; + + if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.UP) || collideDown == false) + { + overlap = 0; + } + else + { + object.touching |= Collision.UP; + } + } + } + } + + // TODO - with super low velocities you get lots of stuttering, set some kind of base minimum here + + // Then adjust their positions and velocities accordingly (if there was any overlap) + if (overlap != 0) + { + if (separate == true) + { + object.y = object.y - overlap; + object.velocity.y = -(object.velocity.y * object.elasticity); + } + + Collision.TILE_OVERLAP = true; + return true; + } + else + { + return false; + } + } + */ + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; })(Phaser || (Phaser = {})); var Phaser; (function (Phaser) { /// /// /// - /// - /// + /// /** - * Phaser - Advanced Physics - Joint - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Physics) { - var Joint = (function () { - function Joint(type, body1, body2, collideConnected) { - this.id = Phaser.Physics.Manager.jointCounter++; - this.type = type; - this.body1 = body1; - this.body2 = body2; - this.collideConnected = collideConnected; - this.maxForce = 9999999999; - this.breakable = false; - } - Joint.prototype.getWorldAnchor1 = function () { - return this.body1.getWorldPoint(this.anchor1); - }; - Joint.prototype.getWorldAnchor2 = function () { - return this.body2.getWorldPoint(this.anchor2); - }; - Joint.prototype.setWorldAnchor1 = function (anchor1) { - this.anchor1 = this.body1.getLocalPoint(anchor1); - }; - Joint.prototype.setWorldAnchor2 = function (anchor2) { - this.anchor2 = this.body2.getLocalPoint(anchor2); - }; - return Joint; - })(); - Physics.Joint = Joint; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - /// - /// - /// - /** - * Phaser - Physics Manager - * - * The Physics Manager is responsible for looking after, creating and colliding - * all of the physics bodies and joints in the world. - */ - (function (Physics) { - var Manager = (function () { - function Manager(game) { - this.lastTime = Date.now(); - this.frameRateHz = 60; - this.timeDelta = 0; - this.paused = false; - this.step = false; - // step through the simulation (i.e. per click) - //public paused: bool = true; - //public step: bool = false; // step through the simulation (i.e. per click) - this.velocityIterations = 8; - this.positionIterations = 4; - this.allowSleep = true; - this.warmStarting = true; - this.game = game; - this.gravity = new Phaser.Vec2(); - this.space = new Physics.Space(this); - Manager.collision = new Physics.Collision(); - } - Manager.clear = function clear() { - //Manager.debug.textContent = ""; - Manager.log = []; - }; - Manager.write = function write(s) { - //Manager.debug.textContent += s + "\n"; - }; - Manager.writeAll = function writeAll() { - for(var i = 0; i < Manager.log.length; i++) { - //Manager.debug.textContent += Manager.log[i]; - } - }; - Manager.log = []; - Manager.dump = function dump(phase, body) { - /* - var s = "\n\nPhase: " + phase + "\n"; - s += "Position: " + body.position.toString() + "\n"; - s += "Velocity: " + body.velocity.toString() + "\n"; - s += "Angle: " + body.angle + "\n"; - s += "Force: " + body.force.toString() + "\n"; - s += "Torque: " + body.torque + "\n"; - s += "Bounds: " + body.bounds.toString() + "\n"; - s += "Shape ***\n"; - s += "Vert 0: " + body.shapes[0].verts[0].toString() + "\n"; - s += "Vert 1: " + body.shapes[0].verts[1].toString() + "\n"; - s += "Vert 2: " + body.shapes[0].verts[2].toString() + "\n"; - s += "Vert 3: " + body.shapes[0].verts[3].toString() + "\n"; - s += "TVert 0: " + body.shapes[0].tverts[0].toString() + "\n"; - s += "TVert 1: " + body.shapes[0].tverts[1].toString() + "\n"; - s += "TVert 2: " + body.shapes[0].tverts[2].toString() + "\n"; - s += "TVert 3: " + body.shapes[0].tverts[3].toString() + "\n"; - s += "Plane 0: " + body.shapes[0].planes[0].normal.toString() + "\n"; - s += "Plane 1: " + body.shapes[0].planes[1].normal.toString() + "\n"; - s += "Plane 2: " + body.shapes[0].planes[2].normal.toString() + "\n"; - s += "Plane 3: " + body.shapes[0].planes[3].normal.toString() + "\n"; - s += "TPlane 0: " + body.shapes[0].tplanes[0].normal.toString() + "\n"; - s += "TPlane 1: " + body.shapes[0].tplanes[1].normal.toString() + "\n"; - s += "TPlane 2: " + body.shapes[0].tplanes[2].normal.toString() + "\n"; - s += "TPlane 3: " + body.shapes[0].tplanes[3].normal.toString() + "\n"; - - Manager.log.push(s); - */ - }; - Manager.SHAPE_TYPE_CIRCLE = 0; - Manager.SHAPE_TYPE_SEGMENT = 1; - Manager.SHAPE_TYPE_POLY = 2; - Manager.SHAPE_NUM_TYPES = 3; - Manager.JOINT_TYPE_ANGLE = 0; - Manager.JOINT_TYPE_REVOLUTE = 1; - Manager.JOINT_TYPE_WELD = 2; - Manager.JOINT_TYPE_WHEEL = 3; - Manager.JOINT_TYPE_PRISMATIC = 4; - Manager.JOINT_TYPE_DISTANCE = 5; - Manager.JOINT_TYPE_ROPE = 6; - Manager.JOINT_TYPE_MOUSE = 7; - Manager.JOINT_LINEAR_SLOP = 0.0008; - Manager.JOINT_ANGULAR_SLOP = 2 * 0.017453292519943294444444444444444; - Manager.JOINT_MAX_LINEAR_CORRECTION = 0.5; - Manager.JOINT_MAX_ANGULAR_CORRECTION = 8 * 0.017453292519943294444444444444444; - Manager.JOINT_LIMIT_STATE_INACTIVE = 0; - Manager.JOINT_LIMIT_STATE_AT_LOWER = 1; - Manager.JOINT_LIMIT_STATE_AT_UPPER = 2; - Manager.JOINT_LIMIT_STATE_EQUAL_LIMITS = 3; - Manager.CONTACT_SOLVER_COLLISION_SLOP = 0.0008; - Manager.CONTACT_SOLVER_BAUMGARTE = 0.28; - Manager.CONTACT_SOLVER_MAX_LINEAR_CORRECTION = 1; - Manager.bodyCounter = 0; - Manager.jointCounter = 0; - Manager.shapeCounter = 0; - Manager.prototype.update = function () { - // Get these from Phaser.Time instead - 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) { - Manager.clear(); - 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; - } - } - //frameCount++; - }; - Manager.prototype.addBody = function (body) { - this.space.addBody(body); - }; - Manager.prototype.removeBody = function (body) { - this.space.removeBody(body); - }; - Manager.prototype.addJoint = function (joint) { - this.space.addJoint(joint); - }; - Manager.prototype.removeJoint = function (joint) { - this.space.removeJoint(joint); - }; - Manager.prototype.pixelsToMeters = function (value) { - return value * 0.02; - }; - Manager.prototype.metersToPixels = function (value) { - return value * 50; - }; - Manager.pixelsToMeters = function pixelsToMeters(value) { - return value * 0.02; - }; - Manager.metersToPixels = function metersToPixels(value) { - return value * 50; - }; - Manager.p2m = function p2m(value) { - return value * 0.02; - }; - Manager.m2p = function m2p(value) { - return value * 50; - }; - Manager.areaForCircle = function areaForCircle(radius_outer, radius_inner) { - return Math.PI * (radius_outer * radius_outer - radius_inner * radius_inner); - }; - Manager.inertiaForCircle = function inertiaForCircle(mass, center, radius_outer, radius_inner) { - return mass * ((radius_outer * radius_outer + radius_inner * radius_inner) * 0.5 + center.lengthSq()); - }; - Manager.areaForSegment = function areaForSegment(a, b, radius) { - return radius * (Math.PI * radius + 2 * Phaser.Vec2Utils.distance(a, b)); - }; - Manager.centroidForSegment = function centroidForSegment(a, b) { - return Phaser.Vec2Utils.scale(Phaser.Vec2Utils.add(a, b), 0.5); - }; - Manager.inertiaForSegment = function inertiaForSegment(mass, a, b) { - var distsq = Phaser.Vec2Utils.distanceSq(b, a); - var offset = Phaser.Vec2Utils.scale(Phaser.Vec2Utils.add(a, b), 0.5); - return mass * (distsq / 12 + offset.lengthSq()); - }; - Manager.areaForPoly = function areaForPoly(verts) { - 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; - }; - Manager.centroidForPoly = function centroidForPoly(verts) { - 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)); - }; - Manager.inertiaForPoly = function inertiaForPoly(mass, verts, offset) { - 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); - }; - Manager.inertiaForBox = function inertiaForBox(mass, w, h) { - return mass * (w * w + h * h) / 12; - }; - Manager.createConvexHull = // Create the convex hull using the Gift wrapping algorithm (http://en.wikipedia.org/wiki/Gift_wrapping_algorithm) - function 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; - }; - return Manager; - })(); - Physics.Manager = Manager; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - /// - /// - /// - /** - * Phaser - 2D AABB - * - * A 2D AABB object - */ - (function (Physics) { - var Bounds = (function () { - /** - * Creates a new 2D AABB object. - * @class Bounds - * @constructor - * @return {Bounds} This object - **/ - function Bounds(mins, maxs) { - if (typeof mins === "undefined") { mins = null; } - if (typeof maxs === "undefined") { maxs = 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); - } - } - Bounds.prototype.toString = function () { - return [ - "mins:", - this.mins.toString(), - "maxs:", - this.maxs.toString() - ].join(" "); - }; - Bounds.prototype.setTo = function (mins, maxs) { - this.mins.setTo(mins.x, mins.y); - this.maxs.setTo(maxs.x, maxs.y); - }; - Bounds.prototype.copy = function (b) { - this.mins.copyFrom(b.mins); - this.maxs.copyFrom(b.maxs); - return this; - }; - Bounds.prototype.clear = function () { - this.mins.setTo(999999, 999999); - this.maxs.setTo(-999999, -999999); - return this; - }; - Object.defineProperty(Bounds.prototype, "x", { - get: function () { - return Phaser.Physics.Manager.metersToPixels(this.mins.x); - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Bounds.prototype, "y", { - get: function () { - return Phaser.Physics.Manager.metersToPixels(this.mins.y); - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Bounds.prototype, "width", { - get: function () { - return Phaser.Physics.Manager.metersToPixels(this.maxs.x - this.mins.x); - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Bounds.prototype, "height", { - get: function () { - return Phaser.Physics.Manager.metersToPixels(this.maxs.y - this.mins.y); - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Bounds.prototype, "right", { - get: function () { - return this.x + this.width; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Bounds.prototype, "bottom", { - get: function () { - return this.y + this.height; - }, - enumerable: true, - configurable: true - }); - Bounds.prototype.isEmpty = function () { - return (this.mins.x > this.maxs.x || this.mins.y > this.maxs.y); - }; - Bounds.prototype.getPerimeter = /* - 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); - } - */ - function () { - return (this.maxs.x - this.mins.x + this.maxs.y - this.mins.y) * 2; - }; - Bounds.prototype.addPoint = function (p) { - 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; - }; - Bounds.prototype.addBounds = function (b) { - 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; - }; - Bounds.prototype.addBounds2 = function (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; - }; - Bounds.prototype.addExtents = function (center, extent_x, extent_y) { - 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; - }; - Bounds.prototype.expand = function (ax, ay) { - this.mins.x -= ax; - this.mins.y -= ay; - this.maxs.x += ax; - this.maxs.y += ay; - return this; - }; - Bounds.prototype.containPoint = function (p) { - 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; - }; - Bounds.prototype.intersectsBounds = function (b) { - 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; - }; - Bounds.expand = function expand(b, ax, ay) { - var b = new Bounds(b.mins, b.maxs); - b.expand(ax, ay); - return b; - }; - return Bounds; - })(); - Physics.Bounds = Bounds; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - })(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - /// - /// - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - Shape - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Physics) { - var Shape = (function () { - function Shape(type) { - this.id = Phaser.Physics.Manager.shapeCounter++; - this.type = type; - this.elasticity = 0.0; - this.friction = 1.0; - this.density = 1; - this.bounds = new Physics.Bounds(); - } - Shape.prototype.findEdgeByPoint = // Over-ridden by ShapePoly - function (p, minDist) { - return -1; - }; - return Shape; - })(); - Physics.Shape = Shape; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - /// - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - Contact - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Physics) { - var Contact = (function () { - function Contact(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(); - } - return Contact; - })(); - Physics.Contact = Contact; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - /// - /// - /// - /// - /// - /// - /// - /** - * 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. - //------------------------------------------------------------------------------------------------- - (function (Physics) { - var ContactSolver = (function () { - function ContactSolver(shape1, shape2) { - this.shape1 = shape1; - this.shape2 = shape2; - this.contacts = []; - this.elasticity = 1; - this.friction = 1; - } - ContactSolver.prototype.update = function (newContactArr) { - 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; - }; - ContactSolver.prototype.initSolver = function (dt_inv) { - var body1 = this.shape1.body; - var body2 = this.shape2.body; - var sum_m_inv = body1.massInverted + body2.massInverted; - for(var i = 0; i < this.contacts.length; i++) { - var con = 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; - } - }; - ContactSolver.prototype.warmStart = function () { - var body1 = this.shape1.body; - var body2 = 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); - //console.log('phaser warmStart impulse ' + i + ' = ' + impulse.toString()); - 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; - } - }; - ContactSolver.prototype.solveVelocityConstraints = function () { - var body1 = this.shape1.body; - var body2 = this.shape2.body; - Physics.Manager.write('solveVelocityConstraints. Body1: ' + body1.name + ' Body2: ' + body2.name); - Physics.Manager.write('Shape 1: ' + this.shape1.type + ' Shape 2: ' + this.shape2.type); - var m1_inv = body1.massInverted; - var i1_inv = body1.inertiaInverted; - var m2_inv = body2.massInverted; - var i2_inv = body2.inertiaInverted; - Physics.Manager.write('m1_inv: ' + m1_inv); - Physics.Manager.write('i1_inv: ' + i1_inv); - Physics.Manager.write('m2_inv: ' + m2_inv); - Physics.Manager.write('i2_inv: ' + i2_inv); - for(var i = 0; i < this.contacts.length; i++) { - Physics.Manager.write('------------ solve con ' + 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); - Physics.Manager.write('v1 ' + v1.toString()); - Phaser.Vec2Utils.multiplyAdd(body2.velocity, Phaser.Vec2Utils.perp(r2), body2.angularVelocity, v2); - //var v2 = vec2.mad(body2.v, vec2.perp(r2), body2.w); - Physics.Manager.write('v2 ' + v2.toString()); - // Relative velocity at contact point - var rv = new Phaser.Vec2(); - Phaser.Vec2Utils.subtract(v2, v1, rv); - //var rv = vec2.sub(v2, v1); - Physics.Manager.write('rv ' + rv.toString()); - // 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); - Physics.Manager.write('lambda_n: ' + lambda_n); - // Accumulate and clamp - var lambda_n_old = con.lambdaNormal; - con.lambdaNormal = Math.max(lambda_n_old + lambda_n, 0); - //con.lambdaNormal = this.clamp(lambda_n_old + lambda_n, 0); - lambda_n = con.lambdaNormal - lambda_n_old; - Physics.Manager.write('lambda_n clamped: ' + lambda_n); - // 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); - Physics.Manager.write('impulse: ' + impulse.toString()); - 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); - body2.angularVelocity += Phaser.Vec2Utils.cross(r2, impulse) * i2_inv; - //body2.w += vec2.cross(r2, impulse) * i2_inv; - Physics.Manager.write('body1: ' + body1.toString()); - Physics.Manager.write('body2: ' + body2.toString()); - } - }; - ContactSolver.prototype.solvePositionConstraints = function () { - var body1 = this.shape1.body; - var body2 = this.shape2.body; - Physics.Manager.write('solvePositionConstraints'); - 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++) { - Physics.Manager.write('------------- solvePositionConstraints ' + 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); - Phaser.Vec2Utils.rotate(con.r2_local, body2.angle, r2); - Physics.Manager.write('r1_local.x = ' + con.r1_local.x + ' r1_local.y = ' + con.r1_local.y + ' angle: ' + body1.angle); - Physics.Manager.write('r1 rotated: r1.x = ' + r1.x + ' r1.y = ' + r1.y); - Physics.Manager.write('r2_local.x = ' + con.r2_local.x + ' r2_local.y = ' + con.r2_local.y + ' angle: ' + body2.angle); - Physics.Manager.write('r2 rotated: r2.x = ' + r2.x + ' r2.y = ' + r2.y); - // Contact points (corrected) - var p1 = new Phaser.Vec2(); - var p2 = new Phaser.Vec2(); - Phaser.Vec2Utils.add(body1.position, r1, p1); - Phaser.Vec2Utils.add(body2.position, r2, p2); - Physics.Manager.write('body1.pos.x=' + body1.position.x + ' y=' + body1.position.y); - Physics.Manager.write('body2.pos.x=' + body2.position.x + ' y=' + body2.position.y); - // Corrected delta vector - var dp = new Phaser.Vec2(); - Phaser.Vec2Utils.subtract(p2, p1, dp); - // Position constraint - var c = Phaser.Vec2Utils.dot(dp, n) + con.depth; - var correction = this.clamp(Physics.Manager.CONTACT_SOLVER_BAUMGARTE * (c + Physics.Manager.CONTACT_SOLVER_COLLISION_SLOP), -Physics.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); - body1.position.multiplyAddByScalar(impulse_dt, -m1_inv); - body1.angle -= sn1 * lambda_dt * i1_inv; - body2.position.multiplyAddByScalar(impulse_dt, m2_inv); - body2.angle += sn2 * lambda_dt * i2_inv; - Physics.Manager.write('body1.pos.x=' + body1.position.x + ' y=' + body1.position.y); - Physics.Manager.write('body2.pos.x=' + body2.position.x + ' y=' + body2.position.y); - } - Physics.Manager.write('max_penetration: ' + max_penetration); - return max_penetration <= Physics.Manager.CONTACT_SOLVER_COLLISION_SLOP * 3; - }; - ContactSolver.prototype.clamp = function (v, min, max) { - return v < min ? min : (v > max ? max : v); - }; - return ContactSolver; - })(); - Physics.ContactSolver = ContactSolver; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - (function (Physics) { - /// - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - Shape - Circle - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Shapes) { - var Circle = (function (_super) { - __extends(Circle, _super); - function Circle(radius, x, y) { - if (typeof x === "undefined") { x = 0; } - if (typeof y === "undefined") { y = 0; } - _super.call(this, Physics.Manager.SHAPE_TYPE_CIRCLE); - x = Physics.Manager.pixelsToMeters(x); - y = Physics.Manager.pixelsToMeters(y); - radius = Physics.Manager.pixelsToMeters(radius); - this.center = new Phaser.Vec2(x, y); - this.radius = radius; - this.tc = new Phaser.Vec2(); - this.finishVerts(); - } - Circle.prototype.finishVerts = function () { - this.radius = Math.abs(this.radius); - }; - Circle.prototype.duplicate = function () { - return new Circle(this.center.x, this.center.y, this.radius); - }; - Circle.prototype.recenter = function (c) { - this.center.subtract(c); - }; - Circle.prototype.transform = function (xf) { - Phaser.TransformUtils.transform(xf, this.center, this.center); - //this.center = xf.transform(this.center); - }; - Circle.prototype.untransform = function (xf) { - Phaser.TransformUtils.untransform(xf, this.center, this.center); - //this.center = xf.untransform(this.center); - }; - Circle.prototype.area = function () { - return Physics.Manager.areaForCircle(this.radius, 0); - }; - Circle.prototype.centroid = function () { - return Phaser.Vec2Utils.clone(this.center); - }; - Circle.prototype.inertia = function (mass) { - return Physics.Manager.inertiaForCircle(mass, this.center, this.radius, 0); - }; - Circle.prototype.cacheData = function (xf) { - 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); - }; - Circle.prototype.pointQuery = function (p) { - //return vec2.distsq(this.tc, p) < (this.r * this.r); - return Phaser.Vec2Utils.distanceSq(this.tc, p) < (this.radius * this.radius); - }; - Circle.prototype.findVertexByPoint = function (p, minDist) { - var dsq = minDist * minDist; - if(Phaser.Vec2Utils.distanceSq(this.tc, p) < dsq) { - return 0; - } - return -1; - }; - Circle.prototype.distanceOnPlane = function (n, d) { - Phaser.Vec2Utils.dot(n, this.tc) - this.radius - d; - }; - return Circle; - })(Phaser.Physics.Shape); - Shapes.Circle = Circle; - })(Physics.Shapes || (Physics.Shapes = {})); - var Shapes = Physics.Shapes; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - Plane - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Physics) { - var Plane = (function () { - function Plane(normal, d) { - this.normal = normal; - this.d = d; - } - return Plane; - })(); - Physics.Plane = Plane; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - (function (Physics) { - /// - /// - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - Shapes - Convex Polygon - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Shapes) { - var Poly = (function (_super) { - __extends(Poly, _super); - // Verts is an optional array of objects, the objects must have public x and y properties which will be used - // to seed this polygon (i.e. Vec2 objects, or just straight JS objects) and must wind COUNTER clockwise - function Poly(verts) { - _super.call(this, Physics.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] = new Phaser.Vec2(verts[i].x, verts[i].y); - this.tverts[i] = this.verts[i]; - //this.tverts[i] = new Phaser.Vec2(verts[i].x, verts[i].y); - this.tplanes[i] = new Phaser.Physics.Plane(new Phaser.Vec2(), 0); - } - } - this.finishVerts(); - } - Poly.prototype.finishVerts = function () { - 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] = new Phaser.Physics.Plane(n, Phaser.Vec2Utils.dot(n, a)); - this.tverts[i] = Phaser.Vec2Utils.clone(this.verts[i])// reference??? - ; - //this.tverts[i] = this.verts[i]; // reference??? - this.tplanes[i] = new Phaser.Physics.Plane(new Phaser.Vec2(), 0); - } - for(var i = 0; i < this.verts.length; i++) { - //var b = this.verts[(i + 2) % this.verts.length]; - //var n = this.planes[i].normal; - //var d = this.planes[i].d; - if(Phaser.Vec2Utils.dot(this.planes[i].normal, this.verts[(i + 2) % this.verts.length]) - this.planes[i].d > 0) { - this.convexity = false; - } - } - }; - Poly.prototype.duplicate = function () { - return new Phaser.Physics.Shapes.Poly(this.verts); - }; - Poly.prototype.recenter = function (c) { - for(var i = 0; i < this.verts.length; i++) { - this.verts[i].subtract(c); - } - }; - Poly.prototype.transform = function (xf) { - for(var i = 0; i < this.verts.length; i++) { - this.verts[i] = Phaser.TransformUtils.transform(xf, this.verts[i]); - //this.verts[i] = xf.transform(this.verts[i]); - } - }; - Poly.prototype.untransform = function (xf) { - for(var i = 0; i < this.verts.length; i++) { - this.verts[i] = Phaser.TransformUtils.untransform(xf, this.verts[i]); - //this.verts[i] = xf.untransform(this.verts[i]); - } - }; - Poly.prototype.area = function () { - return Physics.Manager.areaForPoly(this.verts); - }; - Poly.prototype.centroid = function () { - return Physics.Manager.centroidForPoly(this.verts); - }; - Poly.prototype.inertia = function (mass) { - return Physics.Manager.inertiaForPoly(mass, this.verts, new Phaser.Vec2()); - }; - Poly.prototype.cacheData = function (xf) { - this.bounds.clear(); - var numVerts = this.verts.length; - Physics.Manager.write('----------- Poly cacheData = ' + numVerts); - if(numVerts == 0) { - return; - } - for(var i = 0; i < numVerts; i++) { - this.tverts[i] = Phaser.TransformUtils.transform(xf, this.verts[i]); - //this.tverts[i] = xf.transform(this.verts[i]); - Physics.Manager.write('tvert' + i + ' = ' + this.tverts[i].toString()); - } - 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))); - Physics.Manager.write('a = ' + a.toString()); - Physics.Manager.write('b = ' + b.toString()); - Physics.Manager.write('n = ' + n.toString()); - this.tplanes[i].normal = n; - this.tplanes[i].d = Phaser.Vec2Utils.dot(n, a); - Physics.Manager.write('tplanes' + i + ' n = ' + this.tplanes[i].normal.toString()); - Physics.Manager.write('tplanes' + i + ' d = ' + this.tplanes[i].d.toString()); - this.bounds.addPoint(a); - } - }; - Poly.prototype.pointQuery = function (p) { - if(!this.bounds.containPoint(p)) { - return false; - } - return this.containPoint(p); - }; - Poly.prototype.findVertexByPoint = function (p, minDist) { - 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; - }; - Poly.prototype.findEdgeByPoint = function (p, minDist) { - 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].normal; - 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; - }; - Poly.prototype.distanceOnPlane = function (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; - }; - Poly.prototype.containPoint = function (p) { - for(var i = 0; i < this.verts.length; i++) { - var plane = this.tplanes[i]; - if(Phaser.Vec2Utils.dot(plane.normal, p) - plane.d > 0) { - return false; - } - } - return true; - }; - Poly.prototype.containPointPartial = function (p, n) { - for(var i = 0; i < this.verts.length; i++) { - var plane = this.tplanes[i]; - if(Phaser.Vec2Utils.dot(plane.normal, n) < 0.0001) { - continue; - } - if(Phaser.Vec2Utils.dot(plane.normal, p) - plane.d > 0) { - return false; - } - } - return true; - }; - return Poly; - })(Phaser.Physics.Shape); - Shapes.Poly = Poly; - })(Physics.Shapes || (Physics.Shapes = {})); - var Shapes = Physics.Shapes; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - (function (Physics) { - /// - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - Shapes - Segment - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Shapes) { - var Segment = (function (_super) { - __extends(Segment, _super); - function Segment(a, b, radius) { - _super.call(this, Physics.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(); - } - Segment.prototype.finishVerts = function () { - this.normal = Phaser.Vec2Utils.perp(Phaser.Vec2Utils.subtract(this.b, this.a)); - this.normal.normalize(); - this.radius = Math.abs(this.radius); - }; - Segment.prototype.duplicate = function () { - return new Phaser.Physics.Shapes.Segment(this.a, this.b, this.radius); - }; - Segment.prototype.recenter = function (c) { - this.a.subtract(c); - this.b.subtract(c); - }; - Segment.prototype.transform = function (xf) { - 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); - }; - Segment.prototype.untransform = function (xf) { - 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); - }; - Segment.prototype.area = function () { - return Physics.Manager.areaForSegment(this.a, this.b, this.radius); - }; - Segment.prototype.centroid = function () { - return Physics.Manager.centroidForSegment(this.a, this.b); - }; - Segment.prototype.inertia = function (mass) { - return Physics.Manager.inertiaForSegment(mass, this.a, this.b); - }; - Segment.prototype.cacheData = function (xf) { - 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); - }; - Segment.prototype.pointQuery = function (p) { - 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; - }; - Segment.prototype.findVertexByPoint = function (p, minDist) { - 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; - }; - Segment.prototype.distanceOnPlane = function (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; - }; - return Segment; - })(Phaser.Physics.Shape); - Shapes.Segment = Segment; - })(Physics.Shapes || (Physics.Shapes = {})); - var Shapes = Physics.Shapes; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - Collision Handlers - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Physics) { - var Collision = (function () { - function Collision() { } - Collision.prototype.collide = function (a, b, contacts) { - // Circle (a is the circle) - if(a.type == Physics.Manager.SHAPE_TYPE_CIRCLE) { - if(b.type == Physics.Manager.SHAPE_TYPE_CIRCLE) { - return this.circle2Circle(a, b, contacts); - } else if(b.type == Physics.Manager.SHAPE_TYPE_SEGMENT) { - return this.circle2Segment(a, b, contacts); - } else if(b.type == Physics.Manager.SHAPE_TYPE_POLY) { - return this.circle2Poly(a, b, contacts); - } - } - // Segment (a is the segment) - if(a.type == Physics.Manager.SHAPE_TYPE_SEGMENT) { - if(b.type == Physics.Manager.SHAPE_TYPE_CIRCLE) { - return this.circle2Segment(b, a, contacts); - } else if(b.type == Physics.Manager.SHAPE_TYPE_SEGMENT) { - return this.segment2Segment(a, b, contacts); - } else if(b.type == Physics.Manager.SHAPE_TYPE_POLY) { - return this.segment2Poly(a, b, contacts); - } - } - // Poly (a is the poly) - if(a.type == Physics.Manager.SHAPE_TYPE_POLY) { - if(b.type == Physics.Manager.SHAPE_TYPE_CIRCLE) { - return this.circle2Poly(b, a, contacts); - } else if(b.type == Physics.Manager.SHAPE_TYPE_SEGMENT) { - return this.segment2Poly(b, a, contacts); - } else if(b.type == Physics.Manager.SHAPE_TYPE_POLY) { - return this.poly2Poly(a, b, contacts); - } - } - }; - Collision.prototype._circle2Circle = function (c1, r1, c2, r2, contactArr) { - var rmax = r1 + r2; - var t = 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 = 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 = 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 Physics.Contact(p, n, d, 0)); - return 1; - }; - Collision.prototype.circle2Circle = function (circ1, circ2, contactArr) { - return this._circle2Circle(circ1.tc, circ1.radius, circ2.tc, circ2.radius, contactArr); - }; - Collision.prototype.circle2Segment = function (circ, seg, contactArr) { - 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 = 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 = new Phaser.Vec2(); - Phaser.Vec2Utils.multiplyAdd(circ.tc, n, -(circ.radius + dist * 0.5), c1); - var c2 = new Phaser.Vec2(); - Phaser.Vec2Utils.negative(n, c2); - contactArr.push(new Physics.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; - }; - Collision.prototype.circle2Poly = function (circ, poly, contactArr) { - 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.normal) - plane.d - circ.radius; - if(dist > 0) { - return 0; - } else if(dist > minDist) { - minDist = dist; - minIdx = i; - } - } - var n = poly.tplanes[minIdx].normal; - 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 = new Phaser.Vec2(); - Phaser.Vec2Utils.multiplyAdd(circ.tc, n, -(circ.radius + minDist * 0.5), c1); - var c2 = new Phaser.Vec2(); - Phaser.Vec2Utils.negative(n, c2); - contactArr.push(new Physics.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; - }; - Collision.prototype.segmentPointDistanceSq = function (seg, p) { - var w = new Phaser.Vec2(); - var d = 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; - }; - Collision.prototype.segment2Segment = // FIXME and optimise me lots!!! - function (seg1, seg2, contactArr) { - 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); - }; - Collision.prototype.findPointsBehindSeg = // Identify vertexes that have penetrated the segment. - function (contactArr, seg, poly, dist, coef) { - var dta = Phaser.Vec2Utils.cross(seg.tn, seg.ta); - var dtb = Phaser.Vec2Utils.cross(seg.tn, seg.tb); - var n = 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 Physics.Contact(v, n, dist, (poly.id << 16) | i)); - } - } - } - }; - Collision.prototype.segment2Poly = function (seg, poly, contactArr) { - 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 = 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.normal, plane.d); - if(dist > 0) { - return 0; - } - if(dist > poly_d) { - poly_d = dist; - poly_i = i; - } - } - var poly_n = new Phaser.Vec2(); - Phaser.Vec2Utils.negative(poly.tplanes[poly_i].normal, poly_n); - //var poly_n = vec2.neg(poly.tplanes[poly_i].n); - var va = 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 = 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 Physics.Contact(va, poly_n, poly_d, (seg.id << 16) | 0)); - } - if(poly.containPoint(vb)) { - contactArr.push(new Physics.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; - }; - Collision.prototype.findMSA = // Find the minimum separating axis for the given poly and plane list. - function (poly, planes, num) { - var min_dist = -999999; - var min_index = -1; - for(var i = 0; i < num; i++) { - var dist = poly.distanceOnPlane(planes[i].normal, 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 - }; - }; - Collision.prototype.findVertsFallback = function (contactArr, poly1, poly2, n, dist) { - 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 Physics.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 Physics.Contact(v, n, dist, (poly2.id << 16) | i)); - num++; - } - } - return num; - }; - Collision.prototype.findVerts = // Find the overlapped vertices. - function (contactArr, poly1, poly2, n, dist) { - var num = 0; - for(var i = 0; i < poly1.verts.length; i++) { - var v = poly1.tverts[i]; - if(poly2.containPoint(v)) { - contactArr.push(new Physics.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 Physics.Contact(v, n, dist, (poly2.id << 16) | i)); - num++; - } - } - return num > 0 ? num : this.findVertsFallback(contactArr, poly1, poly2, n, dist); - }; - Collision.prototype.poly2Poly = function (poly1, poly2, contactArr) { - var msa1 = this.findMSA(poly2, poly1.tplanes, poly1.verts.length); - if(msa1.index == -1) { - console.log('poly2poly 0', msa1); - return 0; - } - var msa2 = this.findMSA(poly1, poly2.tplanes, poly2.verts.length); - if(msa2.index == -1) { - console.log('poly2poly 1', msa2); - return 0; - } - // Penetration normal direction should be from poly1 to poly2 - if(msa1.dist > msa2.dist) { - return this.findVerts(contactArr, poly1, poly2, poly1.tplanes[msa1.index].normal, msa1.dist); - } - return this.findVerts(contactArr, poly1, poly2, Phaser.Vec2Utils.negative(poly2.tplanes[msa2.index].normal), msa2.dist); - }; - return Collision; - })(); - Physics.Collision = Collision; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - })(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - /// - /// - /// - /// - /// - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - Space - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Physics) { - var Space = (function () { - function Space(manager) { - this.postSolve = null; - this.stepCount = 0; - this._manager = manager; - this.bodies = []; - this.bodyHash = { - }; - this.joints = []; - this.jointHash = { - }; - this.numContacts = 0; - this.contactSolvers = []; - this.gravity = this._manager.gravity; - this.damping = 0; - this._linTolSqr = Space.SLEEP_LINEAR_TOLERANCE * Space.SLEEP_LINEAR_TOLERANCE; - this._angTolSqr = Space.SLEEP_ANGULAR_TOLERANCE * Space.SLEEP_ANGULAR_TOLERANCE; - } - Space.TIME_TO_SLEEP = 0.5; - Space.SLEEP_LINEAR_TOLERANCE = 0.5; - Space.SLEEP_ANGULAR_TOLERANCE = 2 * 0.017453292519943294444444444444444; - Space.prototype.clear = function () { - Physics.Manager.shapeCounter = 0; - Physics.Manager.bodyCounter = 0; - Physics.Manager.jointCounter = 0; - for(var i = 0; i < this.bodies.length; i++) { - if(this.bodies[i]) { - this.removeBody(this.bodies[i]); - } - } - this.bodies = []; - this.bodyHash = { - }; - this.joints = []; - this.jointHash = { - }; - this.contactSolvers = []; - this.stepCount = 0; - }; - Space.prototype.addBody = function (body) { - if(this.bodyHash[body.id] != undefined) { - return; - } - var index = this.bodies.push(body) - 1; - this.bodyHash[body.id] = index; - body.awake(true); - body.space = this; - body.cacheData('addBody'); - }; - Space.prototype.removeBody = function (body) { - if(this.bodyHash[body.id] == undefined) { - return; - } - // Remove linked joints - 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.bodies[index]; - }; - Space.prototype.addJoint = function (joint) { - if(this.jointHash[joint.id] != undefined) { - return; - } - joint.body1.awake(true); - joint.body2.awake(true); - var index = this.joints.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; - }; - Space.prototype.removeJoint = function (joint) { - 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.joints[index]; - }; - Space.prototype.findShapeByPoint = function (p, refShape) { - var firstShape; - for(var i = 0; i < this.bodies.length; i++) { - var body = this.bodies[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; - }; - Space.prototype.findBodyByPoint = function (p, refBody) { - var firstBody; - for(var i = 0; i < this.bodies.length; i++) { - var body = this.bodies[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; - }; - Space.prototype.shapeById = function (id) { - var shape; - for(var i = 0; i < this.bodies.length; i++) { - var body = this.bodies[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; - }; - Space.prototype.jointById = function (id) { - var index = this.jointHash[id]; - if(index != undefined) { - return this.joints[index]; - } - return null; - }; - Space.prototype.findVertexByPoint = function (p, minDist, refVertexId) { - var firstVertexId = -1; - refVertexId = refVertexId || -1; - for(var i = 0; i < this.bodies.length; i++) { - var body = this.bodies[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; - }; - Space.prototype.findEdgeByPoint = function (p, minDist, refEdgeId) { - var firstEdgeId = -1; - refEdgeId = refEdgeId || -1; - for(var i = 0; i < this.bodies.length; i++) { - var body = this.bodies[i]; - if(!body) { - continue; - } - for(var j = 0; j < body.shapes.length; j++) { - var shape = body.shapes[j]; - if(shape.type != Physics.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; - }; - Space.prototype.findJointByPoint = function (p, minDist, refJointId) { - var firstJointId = -1; - var dsq = minDist * minDist; - refJointId = refJointId || -1; - for(var i = 0; i < this.joints.length; i++) { - var joint = this.joints[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; - }; - Space.prototype.findContactSolver = function (shape1, shape2) { - Physics.Manager.write('findContactSolver. Length: ' + this._cl); - for(var i = 0; i < this._cl; i++) { - var contactSolver = this.contactSolvers[i]; - if(shape1 == contactSolver.shape1 && shape2 == contactSolver.shape2) { - return contactSolver; - } - } - return null; - }; - Space.prototype.genTemporalContactSolvers = function () { - Physics.Manager.write('genTemporalContactSolvers'); - this._cl = 0; - this.contactSolvers.length = 0; - this.numContacts = 0; - for(var body1Index = 0; body1Index < this._bl; body1Index++) { - if(!this.bodies[body1Index]) { - continue; - } - this.bodies[body1Index].stepCount = this.stepCount; - for(var body2Index = 0; body2Index < this._bl; body2Index++) { - if(this.bodies[body1Index].inContact(this.bodies[body2Index]) == false) { - continue; - } - Physics.Manager.write('body1 and body2 intersect'); - for(var i = 0; i < this.bodies[body1Index].shapesLength; i++) { - for(var j = 0; j < this.bodies[body2Index].shapesLength; j++) { - this._shape1 = this.bodies[body1Index].shapes[i]; - this._shape2 = this.bodies[body2Index].shapes[j]; - var contactArr = []; - if(!Physics.Manager.collision.collide(this._shape1, this._shape2, contactArr)) { - continue; - } - if(this._shape1.type > this._shape2.type) { - var temp = this._shape1; - this._shape1 = this._shape2; - this._shape2 = temp; - } - this.numContacts += contactArr.length; - // Result stored in this._contactSolver (see what we can do about generating some re-usable solvers) - var contactSolver = this.findContactSolver(this._shape1, this._shape2); - Physics.Manager.write('findContactSolver result: ' + contactSolver); - if(contactSolver) { - contactSolver.update(contactArr); - this.contactSolvers.push(contactSolver); - } else { - Physics.Manager.write('awake both bodies'); - this.bodies[body1Index].awake(true); - this.bodies[body2Index].awake(true); - var newContactSolver = new Physics.ContactSolver(this._shape1, this._shape2); - newContactSolver.contacts = contactArr; - newContactSolver.elasticity = Math.max(this._shape1.elasticity, this._shape2.elasticity); - newContactSolver.friction = Math.sqrt(this._shape1.friction * this._shape2.friction); - this.contactSolvers.push(newContactSolver); - Physics.Manager.write('new contact solver'); - } - } - } - } - } - this._cl = this.contactSolvers.length; - }; - Space.prototype.initSolver = function (warmStarting) { - Physics.Manager.write('initSolver'); - Physics.Manager.write('contactSolvers.length: ' + this._cl); - // Initialize contact solvers - for(var c = 0; c < this._cl; c++) { - this.contactSolvers[c].initSolver(this._deltaInv); - // Warm starting (apply cached impulse) - if(warmStarting) { - this.contactSolvers[c].warmStart(); - } - } - // Initialize joint solver - for(var j = 0; j < this.joints.length; j++) { - if(this.joints[j]) { - this.joints[j].initSolver(this._delta, warmStarting); - } - } - // Warm starting (apply cached impulse) - /* - if (warmStarting) - { - for (var c = 0; c < this._cl; c++) - { - this.contactSolvers[c].warmStart(); - } - } - */ - }; - Space.prototype.velocitySolver = function (iterations) { - Physics.Manager.write('velocitySolver, iterations: ' + iterations + ' csa len: ' + this._cl); - for(var i = 0; i < iterations; i++) { - for(var j = 0; j < this._jl; j++) { - if(this.joints[j]) { - this.joints[j].solveVelocityConstraints(); - } - } - for(var c = 0; c < this._cl; c++) { - this.contactSolvers[c].solveVelocityConstraints(); - } - } - }; - Space.prototype.positionSolver = function (iterations) { - this._positionSolved = false; - for(var i = 0; i < iterations; i++) { - this._contactsOk = true; - this._jointsOk = true; - for(var c = 0; c < this._cl; c++) { - this._contactsOk = this.contactSolvers[c].solvePositionConstraints() && this._contactsOk; - } - for(var j = 0; j < this._jl; j++) { - if(this.joints[j]) { - this._jointsOk = this.joints[j].solvePositionConstraints() && this._jointsOk; - } - } - if(this._contactsOk && this._jointsOk) { - // exit early if the position errors are small - this._positionSolved = true; - break; - } - } - return this._positionSolved; - }; - Space.prototype.step = // Step through the physics simulation - function (dt, velocityIterations, positionIterations, warmStarting, allowSleep) { - Physics.Manager.clear(); - Physics.Manager.write('Space step ' + this.stepCount); - this._delta = dt; - this._deltaInv = 1 / dt; - this._bl = this.bodies.length; - this._jl = this.joints.length; - this.stepCount++; - // 1) Generate Contact Solvers (into the this.contactSolvers array) - this.genTemporalContactSolvers(); - Physics.Manager.dump("Contact Solvers", this.bodies[1]); - // 2) Initialize the Contact Solvers - this.initSolver(warmStarting); - Physics.Manager.dump("Init Solver", this.bodies[1]); - // 3) Intergrate velocity - for(var i = 0; i < this._bl; i++) { - if(this.bodies[i] && this.bodies[i].isDynamic && this.bodies[i].isAwake) { - this.bodies[i].updateVelocity(this.gravity, this._delta, this.damping); - } - } - Physics.Manager.dump("Update Velocity", this.bodies[1]); - // 4) Awaken bodies via joints - for(var j = 0; i < this._jl; j++) { - if(!this.joints[j]) { - continue; - } - // combine - var awake1 = this.joints[j].body1.isAwake && !this.joints[j].body1.isStatic; - var awake2 = this.joints[j].body2.isAwake && !this.joints[j].body2.isStatic; - if(awake1 ^ awake2) { - if(!awake1) { - this.joints[j].body1.awake(true); - } - if(!awake2) { - this.joints[j].body2.awake(true); - } - } - } - // 5) Iterative velocity constraints solver - this.velocitySolver(velocityIterations); - Physics.Manager.dump("Velocity Solvers", this.bodies[1]); - // 6) Integrate position - for(var i = 0; i < this._bl; i++) { - if(this.bodies[i] && this.bodies[i].isDynamic && this.bodies[i].isAwake) { - this.bodies[i].updatePosition(this._delta); - } - } - Physics.Manager.dump("Update Position", this.bodies[1]); - // 7) Process breakable joint - for(var i = 0; i < this._jl; i++) { - if(this.joints[i] && this.joints[i].breakable && (this.joints[i].getReactionForce(this._deltaInv).lengthSq() >= this.joints[i].maxForce * this.joints[i].maxForce)) { - this.removeJoint(this.joints[i]); - } - } - // 8) Iterative position constraints solver (result stored in this._positionSolved) - this.positionSolver(positionIterations); - Physics.Manager.dump("Position Solver", this.bodies[1]); - // 9) Sync the Transforms - for(var i = 0; i < this._bl; i++) { - if(this.bodies[i]) { - this.bodies[i].syncTransform(); - } - } - Physics.Manager.dump("Sync Transform", this.bodies[1]); - // 10) Post solve collision callback - if(this.postSolve) { - for(var i = 0; i < this._cl; i++) { - this.postSolve(this.contactSolvers[i]); - } - } - // 11) Cache Body Data - for(var i = 0; i < this._bl; i++) { - if(this.bodies[i] && this.bodies[i].isDynamic && this.bodies[i].isAwake) { - this.bodies[i].cacheData('post solve collision callback'); - } - } - Physics.Manager.dump("Cache Data", this.bodies[1]); - Physics.Manager.writeAll(); - // 12) Process sleeping - if(allowSleep) { - this._minSleepTime = 999999; - for(var i = 0; i < this._bl; i++) { - if(!this.bodies[i] || this.bodies[i].isDynamic == false) { - continue; - } - if(this.bodies[i].angularVelocity * this.bodies[i].angularVelocity > this._angTolSqr || this.bodies[i].velocity.dot(this.bodies[i].velocity) > this._linTolSqr) { - this.bodies[i].sleepTime = 0; - this._minSleepTime = 0; - } else { - this.bodies[i].sleepTime += this._delta; - this._minSleepTime = Math.min(this._minSleepTime, this.bodies[i].sleepTime); - } - } - if(this._positionSolved && this._minSleepTime >= Space.TIME_TO_SLEEP) { - for(var i = 0; i < this._bl; i++) { - if(this.bodies[i]) { - this.bodies[i].awake(false); - } - } - } - } - }; - return Space; - })(); - Physics.Space = Space; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - (function (Physics) { - /// - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - Shapes - Triangle - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Shapes) { - var Triangle = (function (_super) { - __extends(Triangle, _super); - function Triangle(x1, y1, x2, y2, x3, y3) { - x1 = Physics.Manager.pixelsToMeters(x1); - y1 = Physics.Manager.pixelsToMeters(y1); - x2 = Physics.Manager.pixelsToMeters(x2); - y2 = Physics.Manager.pixelsToMeters(y2); - x3 = Physics.Manager.pixelsToMeters(x3); - y3 = Physics.Manager.pixelsToMeters(y3); - _super.call(this, [ - { - x: x1, - y: y1 - }, - { - x: x2, - y: y2 - }, - { - x: x3, - y: y3 - } - ]); - } - return Triangle; - })(Phaser.Physics.Shapes.Poly); - Shapes.Triangle = Triangle; - })(Physics.Shapes || (Physics.Shapes = {})); - var Shapes = Physics.Shapes; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - (function (Physics) { - /// - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - Shapes - Box - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Shapes) { - var Box = (function (_super) { - __extends(Box, _super); - // Give in pixels - function Box(x, y, width, height) { - console.log('Box px', x, y, width, height); - x = Physics.Manager.pixelsToMeters(x); - y = Physics.Manager.pixelsToMeters(y); - width = Physics.Manager.pixelsToMeters(width); - height = Physics.Manager.pixelsToMeters(height); - console.log('Box m', x, y, width, height); - var hw = width * 0.5; - var hh = height * 0.5; - console.log('Box hh', hw, hh); - _super.call(this, [ - { - x: -hw + x, - y: +hh + y - }, - { - x: -hw + x, - y: -hh + y - }, - { - x: +hw + x, - y: -hh + y - }, - { - x: +hw + x, - y: +hh + y - } - ]); - } - return Box; - })(Phaser.Physics.Shapes.Poly); - Shapes.Box = Box; - })(Physics.Shapes || (Physics.Shapes = {})); - var Shapes = Physics.Shapes; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - Body - * - * Based on the work Ju Hyung Lee started in JS PhyRus. + * Phaser - ArcadePhysics - Body */ (function (Physics) { var Body = (function () { - function Body(sprite, type, x, y, shapeType) { - if (typeof x === "undefined") { x = 0; } - if (typeof y === "undefined") { y = 0; } - if (typeof shapeType === "undefined") { shapeType = 0; } - this._tempVec2 = new Phaser.Vec2(); - this._fixedRotation = false; - // Shapes - this.shapes = []; - // Joints - this.joints = []; - this.jointHash = { - }; - this.categoryBits = 0x0001; - this.maskBits = 0xFFFF; - this.stepCount = 0; - this._newPosition = new Phaser.Vec2(); - this.id = Phaser.Physics.Manager.bodyCounter++; - this.name = 'body' + this.id; + function Body(sprite, type) { + this.angularVelocity = 0; + this.angularAcceleration = 0; + this.angularDrag = 0; + this.maxAngular = 10000; + this.mass = 1; + this._width = 0; + this._height = 0; + this.sprite = sprite; + this.game = sprite.game; this.type = type; - if(sprite) { - this.sprite = sprite; - this.game = sprite.game; - this.position = new Phaser.Vec2(Phaser.Physics.Manager.pixelsToMeters(sprite.x), Phaser.Physics.Manager.pixelsToMeters(sprite.y)); - this.angle = this.game.math.degreesToRadians(sprite.rotation); - } else { - this.position = new Phaser.Vec2(Phaser.Physics.Manager.pixelsToMeters(x), Phaser.Physics.Manager.pixelsToMeters(y)); - this.angle = 0; - } - this.transform = new Phaser.Transform(this.position, this.angle); - this.centroid = new Phaser.Vec2(); + // Fixture properties + // Will extend into its own class at a later date - can move the fixture defs there and add shape support, but this will do for 1.0 release + this.bounds = new Phaser.Rectangle(); + this._width = sprite.width; + this._height = sprite.height; + // Body properties + //this.gravity = Vec2Utils.clone(ArcadePhysics.gravity); + //this.bounce = Vec2Utils.clone(ArcadePhysics.bounce); this.velocity = new Phaser.Vec2(); - this.force = new Phaser.Vec2(); + this.acceleration = new Phaser.Vec2(); + //this.drag = Vec2Utils.clone(ArcadePhysics.drag); + this.maxVelocity = new Phaser.Vec2(10000, 10000); 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 Physics.Bounds(); + this.angularAcceleration = 0; + this.angularDrag = 0; + this.touching = Phaser.Types.NONE; + this.wasTouching = Phaser.Types.NONE; this.allowCollisions = Phaser.Types.ANY; - this.categoryBits = 0x0001; - this.maskBits = 0xFFFF; - this.stepCount = 0; - if(sprite) { - if(shapeType == 0) { - this.addBox(0, 0, this.sprite.width, this.sprite.height, 1, 1, 1); - } else { - this.addCircle(Math.max(this.sprite.width, this.sprite.height) / 2, 0, 0, 1, 1, 1); - } - } + this.position = new Phaser.Vec2(sprite.x + this.bounds.halfWidth, sprite.y + this.bounds.halfHeight); + this.oldPosition = new Phaser.Vec2(sprite.x + this.bounds.halfWidth, sprite.y + this.bounds.halfHeight); + this.offset = new Phaser.Vec2(); } - Object.defineProperty(Body.prototype, "rotation", { - get: /** - * The rotation of the body in degrees. Phaser uses a right-handed coordinate system, where 0 points to the right. - */ - function () { - return this.game.math.radiansToDegrees(this.angle); - }, - set: /** - * Set the rotation of the body in degrees. Phaser uses a right-handed coordinate system, where 0 points to the right. - * The value is automatically wrapped to be between 0 and 360. - */ - function (value) { - this.angle = this.game.math.degreesToRadians(this.game.math.wrap(value, 360, 0)); + Object.defineProperty(Body.prototype, "x", { + get: function () { + return this.sprite.x + this.offset.x; }, enumerable: true, configurable: true }); - Body.prototype.duplicate = function () { - console.log('body duplicate called'); - //var body = new Body(this.type, this.transform.t, this.rotation); - //for (var i = 0; i < this.shapes.length; i++) - //{ - // body.addShape(this.shapes[i].duplicate()); - //} - //body.resetMassData(); - //return body; - }; - Object.defineProperty(Body.prototype, "isDisabled", { + Object.defineProperty(Body.prototype, "y", { get: function () { - return this.type == Phaser.Types.BODY_DISABLED ? true : false; + return this.sprite.y + this.offset.y; }, enumerable: true, configurable: true }); - Object.defineProperty(Body.prototype, "isStatic", { + Object.defineProperty(Body.prototype, "width", { get: function () { - return this.type == Phaser.Types.BODY_STATIC ? true : false; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Body.prototype, "isKinetic", { - get: function () { - return this.type == Phaser.Types.BODY_KINETIC ? true : false; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Body.prototype, "isDynamic", { - get: function () { - return this.type == Phaser.Types.BODY_DYNAMIC ? true : false; - }, - enumerable: true, - configurable: true - }); - Body.prototype.setType = function (type) { - 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); - }; - Body.prototype.addPoly = function (verts, elasticity, friction, density) { - if (typeof elasticity === "undefined") { elasticity = 1; } - if (typeof friction === "undefined") { friction = 1; } - if (typeof density === "undefined") { density = 1; } - var poly = new Phaser.Physics.Shapes.Poly(verts); - poly.elasticity = elasticity; - poly.friction = friction; - poly.density = density; - this.addShape(poly); - this.resetMassData(); - return poly; - }; - Body.prototype.addTriangle = function (x1, y1, x2, y2, x3, y3, elasticity, friction, density) { - if (typeof elasticity === "undefined") { elasticity = 1; } - if (typeof friction === "undefined") { friction = 1; } - if (typeof density === "undefined") { density = 1; } - var tri = new Phaser.Physics.Shapes.Triangle(x1, y1, x2, y2, x3, y3); - tri.elasticity = elasticity; - tri.friction = friction; - tri.density = density; - this.addShape(tri); - this.resetMassData(); - return tri; - }; - Body.prototype.addBox = function (x, y, width, height, elasticity, friction, density) { - if (typeof elasticity === "undefined") { elasticity = 1; } - if (typeof friction === "undefined") { friction = 1; } - if (typeof density === "undefined") { density = 1; } - var box = new Phaser.Physics.Shapes.Box(x, y, width, height); - box.elasticity = elasticity; - box.friction = friction; - box.density = density; - this.addShape(box); - this.resetMassData(); - return box; - }; - Body.prototype.addCircle = function (radius, x, y, elasticity, friction, density) { - if (typeof x === "undefined") { x = 0; } - if (typeof y === "undefined") { y = 0; } - if (typeof elasticity === "undefined") { elasticity = 1; } - if (typeof friction === "undefined") { friction = 1; } - if (typeof density === "undefined") { density = 1; } - var circle = new Phaser.Physics.Shapes.Circle(radius, x, y); - circle.elasticity = elasticity; - circle.friction = friction; - circle.density = density; - this.addShape(circle); - this.resetMassData(); - return circle; - }; - Body.prototype.addShape = function (shape) { - // Check not already part of this body - shape.body = this; - this.shapes.push(shape); - this.shapesLength = this.shapes.length; - return shape; - }; - Body.prototype.removeShape = function (shape) { - var index = this.shapes.indexOf(shape); - if(index != -1) { - this.shapes.splice(index, 1); - shape.body = undefined; - } - this.shapesLength = this.shapes.length; - }; - Body.prototype.setMass = function (mass) { - this.mass = mass; - this.massInverted = mass > 0 ? 1 / mass : 0; - }; - Body.prototype.setInertia = function (inertia) { - this.inertia = inertia; - this.inertiaInverted = inertia > 0 ? 1 / inertia : 0; - }; - Body.prototype.setPosition = function (x, y) { - this._newPosition.setTo(this.game.physics.pixelsToMeters(x), this.game.physics.pixelsToMeters(y)); - this.setTransform(this._newPosition, this.angle); - }; - Body.prototype.setTransform = function (pos, angle) { - // inject the transform into this.position - this.transform.setTo(pos, angle); - //Manager.write('setTransform: ' + this.position.toString()); - //Manager.write('centroid: ' + this.centroid.toString()); - Phaser.TransformUtils.transform(this.transform, this.centroid, this.position); - //Manager.write('post setTransform: ' + this.position.toString()); - //this.position.copyFrom(this.transform.transform(this.centroid)); - this.angle = angle; - }; - Body.prototype.syncTransform = function () { - //Manager.write('syncTransform:'); - //Manager.write('p: ' + this.position.toString()); - //Manager.write('centroid: ' + this.centroid.toString()); - //Manager.write('xf: ' + this.transform.toString()); - //Manager.write('a: ' + this.angle); - this.transform.setRotation(this.angle); - // OPTIMISE: Creating new vector - Phaser.Vec2Utils.subtract(this.position, Phaser.TransformUtils.rotate(this.transform, this.centroid), this.transform.t); - //Manager.write('--------------------'); - //Manager.write('xf: ' + this.transform.toString()); - //Manager.write('--------------------'); - }; - Body.prototype.getWorldPoint = function (p) { - // OPTIMISE: Creating new vector - return Phaser.TransformUtils.transform(this.transform, p); - }; - Body.prototype.getWorldVector = function (v) { - // OPTIMISE: Creating new vector - return Phaser.TransformUtils.rotate(this.transform, v); - }; - Body.prototype.getLocalPoint = function (p) { - // OPTIMISE: Creating new vector - return Phaser.TransformUtils.untransform(this.transform, p); - }; - Body.prototype.getLocalVector = function (v) { - // OPTIMISE: Creating new vector - return Phaser.TransformUtils.unrotate(this.transform, v); - }; - Object.defineProperty(Body.prototype, "fixedRotation", { - get: function () { - return this._fixedRotation; + return this._width * this.sprite.transform.scale.x; }, set: function (value) { - this._fixedRotation = value; - this.resetMassData(); + this._width = value; }, enumerable: true, configurable: true }); - Body.prototype.resetMassData = function () { - 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); - 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); - totalMassCentroid.multiplyAddByScalar(centroid, mass); - totalMass += mass; - totalInertia += inertia; - } - Phaser.Vec2Utils.scale(totalMassCentroid, 1 / totalMass, this.centroid); - this.setMass(totalMass); - if(!this.fixedRotation) { - this.setInertia(totalInertia - totalMass * Phaser.Vec2Utils.dot(this.centroid, this.centroid)); - } - // Move center of mass - var oldPosition = Phaser.Vec2Utils.clone(this.position); - Phaser.TransformUtils.transform(this.transform, this.centroid, this.position); - // Update center of mass velocity - oldPosition.subtract(this.position); - this.velocity.multiplyAddByScalar(Phaser.Vec2Utils.perp(oldPosition, oldPosition), this.angularVelocity); - }; - Body.prototype.resetJointAnchors = function () { - 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); - } - }; - Body.prototype.cacheData = function (source) { - if (typeof source === "undefined") { source = ''; } - //Manager.write('cacheData -- start'); - //Manager.write('p: ' + this.position.toString()); - //Manager.write('xf: ' + this.transform.toString()); - this.bounds.clear(); - for(var i = 0; i < this.shapesLength; i++) { - var shape = this.shapes[i]; - shape.cacheData(this.transform); - this.bounds.addBounds(shape.bounds); - } - //Manager.write('bounds: ' + this.bounds.toString()); - //Manager.write('p: ' + this.position.toString()); - //Manager.write('xf: ' + this.transform.toString()); - //Manager.write('cacheData -- stop'); - }; - Body.prototype.updateVelocity = function (gravity, dt, damping) { - 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.clamp(1 - dt * (damping + this.linearDamping), 0, 1)); - this.angularVelocity *= this.clamp(1 - dt * (damping + this.angularDamping), 0, 1); - this.force.setTo(0, 0); - this.torque = 0; - }; - Body.prototype.inContact = function (body2) { - if(!body2 || this.stepCount == body2.stepCount) { - return false; - } - if(!(this.isAwake && this.isStatic == false) && !(body2.isAwake && body2.isStatic == false)) { - return false; - } - if(this.isCollidable(body2) == false) { - return false; - } - if(!this.bounds.intersectsBounds(body2.bounds)) { - return false; - } - return true; - }; - Body.prototype.clamp = function (v, min, max) { - return v < min ? min : (v > max ? max : v); - }; - Body.prototype.updatePosition = function (dt) { - this.position.add(Phaser.Vec2Utils.scale(this.velocity, dt, this._tempVec2)); - this.angle += this.angularVelocity * dt; - if(this.sprite) { - this.sprite.x = this.position.x * 50; - this.sprite.y = this.position.y * 50; - this.sprite.transform.rotation = this.game.math.radiansToDegrees(this.angle); - } - }; - Body.prototype.resetForce = function () { - this.force.setTo(0, 0); - this.torque = 0; - }; - Body.prototype.applyForce = function (force, p) { - if(this.isDynamic == false) { - return; - } - if(this.isAwake == false) { - this.awake(true); - } - this.force.add(force); - Phaser.Vec2Utils.subtract(p, this.position, this._tempVec2); - this.torque += Phaser.Vec2Utils.cross(this._tempVec2, force); - }; - Body.prototype.applyForceToCenter = function (force) { - if(this.isDynamic == false) { - return; - } - if(this.isAwake == false) { - this.awake(true); - } - this.force.add(force); - }; - Body.prototype.applyTorque = function (torque) { - if(this.isDynamic == false) { - return; - } - if(this.isAwake == false) { - this.awake(true); - } - this.torque += torque; - }; - Body.prototype.applyLinearImpulse = function (impulse, p) { - if(this.isDynamic == false) { - return; - } - if(this.isAwake == false) { - this.awake(true); - } - this.velocity.multiplyAddByScalar(impulse, this.massInverted); - Phaser.Vec2Utils.subtract(p, this.position, this._tempVec2); - this.angularVelocity += Phaser.Vec2Utils.cross(this._tempVec2, impulse) * this.inertiaInverted; - }; - Body.prototype.applyAngularImpulse = function (impulse) { - if(this.isDynamic == false) { - return; - } - if(this.isAwake == false) { - this.awake(true); - } - this.angularVelocity += impulse * this.inertiaInverted; - }; - Body.prototype.kineticEnergy = function () { - return 0.5 * (this.mass * this.velocity.dot(this.velocity) + this.inertia * (this.angularVelocity * this.angularVelocity)); - }; - Object.defineProperty(Body.prototype, "isAwake", { + Object.defineProperty(Body.prototype, "height", { get: function () { - return this.awaked; + return this._height * this.sprite.transform.scale.y; + }, + set: function (value) { + this._height = value; }, enumerable: true, configurable: true }); - Body.prototype.awake = function (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; - } + Body.prototype.preUpdate = function () { + this.oldPosition.copyFrom(this.position); + this.bounds.x = this.x; + this.bounds.y = this.y; + this.bounds.width = this.width; + this.bounds.height = this.height; }; - Body.prototype.isCollidable = function (other) { - if((this.isDynamic == false && other.isDynamic == false) || this == other) { - return false; + Body.prototype.postUpdate = // Shall we do this? Or just update the values directly in the separate functions? But then the bounds will be out of sync - as long as + // the bounds are updated and used in calculations then we can do one final sprite movement here I guess? + function () { + // if this is all it does maybe move elsewhere? Sprite postUpdate? + if(this.type !== Phaser.Types.BODY_DISABLED) { + //this.game.world.physics.updateMotion(this); + this.wasTouching = this.touching; + this.touching = Phaser.Types.NONE; } - 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(!this.joints[i] || (!this.joints[i].collideConnected && other.jointHash[this.joints[i].id] != undefined)) { - return false; + this.position.setTo(this.x, this.y); + }; + Object.defineProperty(Body.prototype, "hullWidth", { + get: function () { + if(this.deltaX > 0) { + return this.bounds.width + this.deltaX; + } else { + return this.bounds.width - this.deltaX; } + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Body.prototype, "hullHeight", { + get: function () { + if(this.deltaY > 0) { + return this.bounds.height + this.deltaY; + } else { + return this.bounds.height - this.deltaY; + } + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Body.prototype, "hullX", { + get: function () { + if(this.position.x < this.oldPosition.x) { + return this.position.x; + } else { + return this.oldPosition.x; + } + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Body.prototype, "hullY", { + get: function () { + if(this.position.y < this.oldPosition.y) { + return this.position.y; + } else { + return this.oldPosition.y; + } + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Body.prototype, "deltaXAbs", { + get: function () { + return (this.deltaX > 0 ? this.deltaX : -this.deltaX); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Body.prototype, "deltaYAbs", { + get: function () { + return (this.deltaY > 0 ? this.deltaY : -this.deltaY); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Body.prototype, "deltaX", { + get: function () { + return this.position.x - this.oldPosition.x; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Body.prototype, "deltaY", { + get: function () { + return this.position.y - this.oldPosition.y; + }, + enumerable: true, + configurable: true + }); + Body.prototype.render = // MOVE THESE TO A UTIL + function (context) { + context.beginPath(); + context.strokeStyle = 'rgb(0,255,0)'; + context.strokeRect(this.position.x - this.bounds.halfWidth, this.position.y - this.bounds.halfHeight, this.bounds.width, this.bounds.height); + context.stroke(); + context.closePath(); + // center point + context.fillStyle = 'rgb(0,255,0)'; + context.fillRect(this.position.x, this.position.y, 2, 2); + if(this.touching & Phaser.Types.LEFT) { + context.beginPath(); + context.strokeStyle = 'rgb(255,0,0)'; + context.moveTo(this.position.x - this.bounds.halfWidth, this.position.y - this.bounds.halfHeight); + context.lineTo(this.position.x - this.bounds.halfWidth, this.position.y + this.bounds.halfHeight); + context.stroke(); + context.closePath(); + } + if(this.touching & Phaser.Types.RIGHT) { + context.beginPath(); + context.strokeStyle = 'rgb(255,0,0)'; + context.moveTo(this.position.x + this.bounds.halfWidth, this.position.y - this.bounds.halfHeight); + context.lineTo(this.position.x + this.bounds.halfWidth, this.position.y + this.bounds.halfHeight); + context.stroke(); + context.closePath(); + } + if(this.touching & Phaser.Types.UP) { + context.beginPath(); + context.strokeStyle = 'rgb(255,0,0)'; + context.moveTo(this.position.x - this.bounds.halfWidth, this.position.y - this.bounds.halfHeight); + context.lineTo(this.position.x + this.bounds.halfWidth, this.position.y - this.bounds.halfHeight); + context.stroke(); + context.closePath(); + } + if(this.touching & Phaser.Types.DOWN) { + context.beginPath(); + context.strokeStyle = 'rgb(255,0,0)'; + context.moveTo(this.position.x - this.bounds.halfWidth, this.position.y + this.bounds.halfHeight); + context.lineTo(this.position.x + this.bounds.halfWidth, this.position.y + this.bounds.halfHeight); + context.stroke(); + context.closePath(); } - return true; }; - Body.prototype.toString = function () { - return "[{Body (name=" + this.name + " velocity=" + this.velocity.toString() + " angularVelocity: " + this.angularVelocity + ")}]"; + Body.prototype.renderDebugInfo = /** + * Render debug infos. (including name, bounds info, position and some other properties) + * @param x {number} X position of the debug info to be rendered. + * @param y {number} Y position of the debug info to be rendered. + * @param [color] {number} color of the debug info to be rendered. (format is css color string) + */ + function (x, y, color) { + if (typeof color === "undefined") { color = 'rgb(255,255,255)'; } + this.sprite.texture.context.fillStyle = color; + this.sprite.texture.context.fillText('Sprite: (' + this.sprite.width + ' x ' + this.sprite.height + ')', x, y); + //this.sprite.texture.context.fillText('x: ' + this._sprite.frameBounds.x.toFixed(1) + ' y: ' + this._sprite.frameBounds.y.toFixed(1) + ' rotation: ' + this._sprite.rotation.toFixed(1), x, y + 14); + this.sprite.texture.context.fillText('x: ' + this.bounds.x.toFixed(1) + ' y: ' + this.bounds.y.toFixed(1) + ' rotation: ' + this.sprite.transform.rotation.toFixed(0), x, y + 14); + this.sprite.texture.context.fillText('vx: ' + this.velocity.x.toFixed(1) + ' vy: ' + this.velocity.y.toFixed(1), x, y + 28); + this.sprite.texture.context.fillText('acx: ' + this.acceleration.x.toFixed(1) + ' acy: ' + this.acceleration.y.toFixed(1), x, y + 42); + this.sprite.texture.context.fillText('angVx: ' + this.angularVelocity.toFixed(1) + ' angAc: ' + this.angularAcceleration.toFixed(1), x, y + 56); }; return Body; })(); @@ -7161,7 +5679,7 @@ var Phaser; /// /// /// -/// +/// /** * Phaser - Sprite */ @@ -7238,10 +5756,10 @@ var Phaser; } } if(bodyType !== Phaser.Types.BODY_DISABLED) { - this.body = new Phaser.Physics.Body(this, bodyType, 0, 0, shapeType); - this.game.physics.addBody(this.body); - this.transform.origin.setTo(0.5, 0.5); - } + //this.body = new Phaser.Physics.Body(this, bodyType, 0, 0, shapeType); + //this.game.physics.addBody(this.body); + //this.transform.origin.setTo(0.5, 0.5); + } this.worldView = new Phaser.Rectangle(x, y, this.width, this.height); this.cameraView = new Phaser.Rectangle(x, y, this.width, this.height); this.transform.setCache(); @@ -7251,6 +5769,7 @@ var Phaser; this.scale = this.transform.scale; this.alpha = this.texture.alpha; this.origin = this.transform.origin; + this.crop = this.texture.crop; } Object.defineProperty(Sprite.prototype, "rotation", { get: /** @@ -7266,8 +5785,8 @@ var Phaser; function (value) { this.transform.rotation = this.game.math.wrap(value, 360, 0); if(this.body) { - this.body.angle = this.game.math.degreesToRadians(this.game.math.wrap(value, 360, 0)); - } + //this.body.angle = this.game.math.degreesToRadians(this.game.math.wrap(value, 360, 0)); + } }, enumerable: true, configurable: true @@ -7933,7 +6452,7 @@ var Phaser; }; Group.prototype.destroy = /** * Override this function to handle any deleting or "shutdown" type operations you might need, - * such as removing traditional Flash children like Basic objects. + * such as removing traditional children like Basic objects. */ function () { if(this.members != null) { @@ -8198,7 +6717,7 @@ var Phaser; */ function (object, splice) { if (typeof splice === "undefined") { splice = false; } - console.log('removing from group: ', object.name); + //console.log('removing from group: ', object.name); this._i = this.members.indexOf(object); if(this._i < 0 || (this._i >= this.members.length)) { return null; @@ -8209,7 +6728,7 @@ var Phaser; } else { this.members[this._i] = null; } - console.log('nulled'); + //console.log('nulled'); if(object['events']) { object['events'].onRemovedFromGroup.dispatch(object, this); } @@ -14303,8 +12822,8 @@ var Phaser; if(key == this.key) { this._sound = this.game.cache.getSoundData(this.key); this.totalDuration = this._sound.duration; - console.log('sound has unlocked', this._sound); - } + //console.log('sound has unlocked', this._sound); + } }; Object.defineProperty(Sound.prototype, "isDecoding", { get: function () { @@ -14343,22 +12862,22 @@ var Phaser; if(this.isPlaying) { this.currentTime = this.game.time.now - this.startTime; if(this.currentTime >= this.duration) { - console.log(this.currentMarker, 'has hit duration'); + //console.log(this.currentMarker, 'has hit duration'); if(this.usingWebAudio) { if(this.loop) { - console.log('loop1'); + //console.log('loop1'); // won't work with markers, needs to reset the position this.onLoop.dispatch(this); if(this.currentMarker == '') { - console.log('loop2'); + //console.log('loop2'); this.currentTime = 0; this.startTime = this.game.time.now; } else { - console.log('loop3'); + //console.log('loop3'); this.play(this.currentMarker, 0, this.volume, true, true); } } else { - console.log('stopping, no loop for marker'); + //console.log('stopping, no loop for marker'); this.stop(); } } else { @@ -14385,13 +12904,13 @@ var Phaser; if (typeof volume === "undefined") { volume = 1; } if (typeof loop === "undefined") { loop = false; } if (typeof forceRestart === "undefined") { forceRestart = false; } - console.log('play', marker, 'current is', this.currentMarker); + //console.log('play', marker, 'current is', this.currentMarker); if(this.isPlaying == true && forceRestart == false && this.override == false) { // Use Restart instead return; } if(this.isPlaying && this.override) { - console.log('asked to play', marker, 'but already playing', this.currentMarker); + //console.log('asked to play', marker, 'but already playing', this.currentMarker); if(this.usingWebAudio) { if(typeof this._sound.stop === 'undefined') { this._sound.noteOff(0); @@ -14409,7 +12928,7 @@ var Phaser; this.volume = this.markers[marker].volume; this.loop = this.markers[marker].loop; this.duration = this.markers[marker].duration * 1000; - console.log('marker info loaded', this.loop, this.duration); + //console.log('marker info loaded', this.loop, this.duration); this._tempMarker = marker; this._tempPosition = this.position; this._tempVolume = this.volume; @@ -14456,8 +12975,8 @@ var Phaser; this.currentTime = 0; this.stopTime = this.startTime + this.duration; this.onPlay.dispatch(this); - console.log('playing, start', this.startTime, 'stop'); - } else { + //console.log('playing, start', this.startTime, 'stop'); + } else { this.pendingPlayback = true; if(this.game.cache.getSound(this.key) && this.game.cache.getSound(this.key).isDecoding == false) { this.game.sound.decode(this.key, this); @@ -14532,7 +13051,7 @@ var Phaser; * Stop playing this sound. */ function () { - console.log('Sound.stop', this.currentMarker); + //console.log('Sound.stop', this.currentMarker); if(this.isPlaying && this._sound) { if(this.usingWebAudio) { if(typeof this._sound.stop === 'undefined') { @@ -14864,9 +13383,9 @@ var Phaser; /** * Phaser * -* v1.0.0 - June XX 2013 +* v1.0.0 - August 12th 2013 * -* A small and feature-packed 2D canvas game framework born from the firey pits of Flixel and Kiwi. +* A feature-packed 2D canvas game framework born from the firey pits of Flixel and Kiwi. * * Richard Davey (@photonstorm) * @@ -15706,6 +14225,11 @@ var Phaser; * @type {boolean} */ this.disableBootScreen = false; + /** + * If set to true the game will never pause when the browser or browser tab loses focuses + * @type {boolean} + */ + this.disableVisibilityChange = false; this._game = game; this.canvas = document.createElement('canvas'); this.canvas.width = width; @@ -15792,6 +14316,9 @@ var Phaser; * This method is called when the canvas elements visibility is changed. */ function (event) { + if(this.disableVisibilityChange) { + return; + } if(event.type == 'pagehide' || event.type == 'blur' || document['hidden'] == true || document['webkitHidden'] == true) { if(this._game.paused == false) { this.pauseGame(); @@ -16190,6 +14717,35 @@ var Phaser; })(); Phaser.TweenManager = TweenManager; })(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + /// + /** + * Phaser - Physics Manager + * + * Eventually this will handle switching between the default ArcadePhysics manager or the new AdvancedPhysics manager. + * For now we direct everything through ArcadePhysics. + */ + (function (Physics) { + var Manager = (function () { + function Manager(game) { + this.game = game; + this.arcade = new Phaser.Physics.ArcadePhysics(this.game, this.game.stage.width, this.game.stage.height); + this.gravity = this.arcade.gravity; + this.bounds = this.arcade.bounds; + } + Manager.prototype.update = /** + * Called by the main Game.loop + */ + function () { + //this.arcade.updateMotion + }; + return Manager; + })(); + Physics.Manager = Manager; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); /// /// /// @@ -16330,309 +14886,6 @@ var Phaser; })(); Phaser.World = World; })(Phaser || (Phaser = {})); -/// -/// -/** -* Phaser - Motion -* -* The Motion class contains lots of useful functions for moving game objects around in world space. -*/ -var Phaser; -(function (Phaser) { - var Motion = (function () { - function Motion(game) { - this.game = game; - } - Motion.prototype.velocityFromAngle = /** - * Given the angle and speed calculate the velocity and return it as a Point - * - * @param {number} angle The angle (in degrees) calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative) - * @param {number} speed The speed it will move, in pixels per second sq - * - * @return {Point} A Point where Point.x contains the velocity x value and Point.y contains the velocity y value - */ - function (angle, speed) { - if(isNaN(speed)) { - speed = 0; - } - var a = this.game.math.degreesToRadians(angle); - return new Phaser.Point((Math.cos(a) * speed), (Math.sin(a) * speed)); - }; - Motion.prototype.moveTowardsObject = /** - * Sets the source Sprite x/y velocity so it will move directly towards the destination Sprite at the speed given (in pixels per second)
- * If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds.
- * Timings are approximate due to the way Flash timers work, and irrespective of SWF frame rate. Allow for a variance of +- 50ms.
- * The source object doesn't stop moving automatically should it ever reach the destination coordinates.
- * If you need the object to accelerate, see accelerateTowardsObject() instead - * Note: Doesn't take into account acceleration, maxVelocity or drag (if you set drag or acceleration too high this object may not move at all) - * - * @param {Sprite} source The Sprite on which the velocity will be set - * @param {Sprite} dest The Sprite where the source object will move to - * @param {number} speed The speed it will move, in pixels per second (default is 60 pixels/sec) - * @param {number} maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms - */ - function (source, dest, speed, maxTime) { - if (typeof speed === "undefined") { speed = 60; } - if (typeof maxTime === "undefined") { maxTime = 0; } - var a = this.angleBetween(source, dest); - if(maxTime > 0) { - var d = this.distanceBetween(source, dest); - // We know how many pixels we need to move, but how fast? - speed = d / (maxTime / 1000); - } - source.body.velocity.x = Math.cos(a) * speed; - source.body.velocity.y = Math.sin(a) * speed; - }; - Motion.prototype.accelerateTowardsObject = /** - * Sets the x/y acceleration on the source Sprite so it will move towards the destination Sprite at the speed given (in pixels per second)
- * You must give a maximum speed value, beyond which the Sprite won't go any faster.
- * If you don't need acceleration look at moveTowardsObject() instead. - * - * @param {Sprite} source The Sprite on which the acceleration will be set - * @param {Sprite} dest The Sprite where the source object will move towards - * @param {number} speed The speed it will accelerate in pixels per second - * @param {number} xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally - * @param {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically - */ - function (source, dest, speed, xSpeedMax, ySpeedMax) { - /* - var a: number = this.angleBetween(source, dest); - - source.body.velocity.x = 0; - source.body.velocity.y = 0; - - source.body.acceleration.x = Math.cos(a) * speed; - source.body.acceleration.y = Math.sin(a) * speed; - - source.body.maxVelocity.x = xSpeedMax; - source.body.maxVelocity.y = ySpeedMax; - */ - }; - Motion.prototype.moveTowardsMouse = /** - * Move the given Sprite towards the mouse pointer coordinates at a steady velocity - * If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds.
- * Timings are approximate due to the way Flash timers work, and irrespective of SWF frame rate. Allow for a variance of +- 50ms.
- * The source object doesn't stop moving automatically should it ever reach the destination coordinates.
- * - * @param {Sprite} source The Sprite to move - * @param {number} speed The speed it will move, in pixels per second (default is 60 pixels/sec) - * @param {number} maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms - */ - function (source, speed, maxTime) { - if (typeof speed === "undefined") { speed = 60; } - if (typeof maxTime === "undefined") { maxTime = 0; } - var a = this.angleBetweenMouse(source); - if(maxTime > 0) { - var d = this.distanceToMouse(source); - // We know how many pixels we need to move, but how fast? - speed = d / (maxTime / 1000); - } - source.body.velocity.x = Math.cos(a) * speed; - source.body.velocity.y = Math.sin(a) * speed; - }; - Motion.prototype.accelerateTowardsMouse = /** - * Sets the x/y acceleration on the source Sprite so it will move towards the mouse coordinates at the speed given (in pixels per second)
- * You must give a maximum speed value, beyond which the Sprite won't go any faster.
- * If you don't need acceleration look at moveTowardsMouse() instead. - * - * @param {Sprite} source The Sprite on which the acceleration will be set - * @param {number} speed The speed it will accelerate in pixels per second - * @param {number} xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally - * @param {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically - */ - function (source, speed, xSpeedMax, ySpeedMax) { - /* - var a: number = this.angleBetweenMouse(source); - - source.body.velocity.x = 0; - source.body.velocity.y = 0; - - source.body.acceleration.x = Math.cos(a) * speed; - source.body.acceleration.y = Math.sin(a) * speed; - - source.body.maxVelocity.x = xSpeedMax; - source.body.maxVelocity.y = ySpeedMax; - */ - }; - Motion.prototype.moveTowardsPoint = /** - * Sets the x/y velocity on the source Sprite so it will move towards the target coordinates at the speed given (in pixels per second)
- * If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds.
- * Timings are approximate due to the way Flash timers work, and irrespective of SWF frame rate. Allow for a variance of +- 50ms.
- * The source object doesn't stop moving automatically should it ever reach the destination coordinates.
- * - * @param {Sprite} source The Sprite to move - * @param {Point} target The Point coordinates to move the source Sprite towards - * @param {number} speed The speed it will move, in pixels per second (default is 60 pixels/sec) - * @param {number} maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms - */ - function (source, target, speed, maxTime) { - if (typeof speed === "undefined") { speed = 60; } - if (typeof maxTime === "undefined") { maxTime = 0; } - var a = this.angleBetweenPoint(source, target); - if(maxTime > 0) { - var d = this.distanceToPoint(source, target); - // We know how many pixels we need to move, but how fast? - speed = d / (maxTime / 1000); - } - source.body.velocity.x = Math.cos(a) * speed; - source.body.velocity.y = Math.sin(a) * speed; - }; - Motion.prototype.accelerateTowardsPoint = /** - * Sets the x/y acceleration on the source Sprite so it will move towards the target coordinates at the speed given (in pixels per second)
- * You must give a maximum speed value, beyond which the Sprite won't go any faster.
- * If you don't need acceleration look at moveTowardsPoint() instead. - * - * @param {Sprite} source The Sprite on which the acceleration will be set - * @param {Point} target The Point coordinates to move the source Sprite towards - * @param {number} speed The speed it will accelerate in pixels per second - * @param {number} xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally - * @param {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically - */ - function (source, target, speed, xSpeedMax, ySpeedMax) { - /* - var a: number = this.angleBetweenPoint(source, target); - - source.body.velocity.x = 0; - source.body.velocity.y = 0; - - source.body.acceleration.x = Math.cos(a) * speed; - source.body.acceleration.y = Math.sin(a) * speed; - - source.body.maxVelocity.x = xSpeedMax; - source.body.maxVelocity.y = ySpeedMax; - */ - }; - Motion.prototype.distanceBetween = /** - * Find the distance between two Sprites, taking their origin into account - * - * @param {Sprite} a The first Sprite - * @param {Sprite} b The second Sprite - * @return {number} int Distance (in pixels) - */ - function (a, b) { - return Phaser.Vec2Utils.distance(a.body.position, b.body.position); - }; - Motion.prototype.distanceToPoint = /** - * Find the distance from an Sprite to the given Point, taking the source origin into account - * - * @param {Sprite} a The Sprite - * @param {Point} target The Point - * @return {number} Distance (in pixels) - */ - function (a, target) { - var dx = (a.x + a.transform.origin.x) - (target.x); - var dy = (a.y + a.transform.origin.y) - (target.y); - return this.game.math.vectorLength(dx, dy); - }; - Motion.prototype.distanceToMouse = /** - * Find the distance (in pixels, rounded) from the object x/y and the mouse x/y - * - * @param {Sprite} a Sprite to test against - * @return {number} The distance between the given sprite and the mouse coordinates - */ - function (a) { - var dx = (a.x + a.transform.origin.x) - this.game.input.x; - var dy = (a.y + a.transform.origin.y) - this.game.input.y; - return this.game.math.vectorLength(dx, dy); - }; - Motion.prototype.angleBetweenPoint = /** - * Find the angle (in radians) between an Sprite and an Point. The source sprite takes its x/y and origin into account. - * The angle is calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative) - * - * @param {Sprite} a The Sprite to test from - * @param {Point} target The Point to angle the Sprite towards - * @param {boolean} asDegrees If you need the value in degrees instead of radians, set to true - * - * @return {number} The angle (in radians unless asDegrees is true) - */ - function (a, target, asDegrees) { - if (typeof asDegrees === "undefined") { asDegrees = false; } - var dx = (target.x) - (a.x + a.transform.origin.x); - var dy = (target.y) - (a.y + a.transform.origin.y); - if(asDegrees) { - return this.game.math.radiansToDegrees(Math.atan2(dy, dx)); - } else { - return Math.atan2(dy, dx); - } - }; - Motion.prototype.angleBetween = /** - * Find the angle (in radians) between the two Sprite, taking their x/y and origin into account. - * The angle is calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative) - * - * @param {Sprite} a The Sprite to test from - * @param {Sprite} b The Sprite to test to - * @param {boolean} asDegrees If you need the value in degrees instead of radians, set to true - * - * @return {number} The angle (in radians unless asDegrees is true) - */ - function (a, b, asDegrees) { - if (typeof asDegrees === "undefined") { asDegrees = false; } - var dx = (b.x + b.transform.origin.x) - (a.x + a.transform.origin.x); - var dy = (b.y + b.transform.origin.y) - (a.y + a.transform.origin.y); - if(asDegrees) { - return this.game.math.radiansToDegrees(Math.atan2(dy, dx)); - } else { - return Math.atan2(dy, dx); - } - }; - Motion.prototype.velocityFromFacing = /** - * Given the Sprite and speed calculate the velocity and return it as an Point based on the direction the sprite is facing - * - * @param {Sprite} parent The Sprite to get the facing value from - * @param {number} speed The speed it will move, in pixels per second sq - * - * @return {Point} An Point where Point.x contains the velocity x value and Point.y contains the velocity y value - */ - function (parent, speed) { - /* - var a: number; - - if (parent.body.facing == Types.LEFT) - { - a = this.game.math.degreesToRadians(180); - } - else if (parent.body.facing == Types.RIGHT) - { - a = this.game.math.degreesToRadians(0); - } - else if (parent.body.facing == Types.UP) - { - a = this.game.math.degreesToRadians(-90); - } - else if (parent.body.facing == Types.DOWN) - { - a = this.game.math.degreesToRadians(90); - } - - return new Point(Math.cos(a) * speed, Math.sin(a) * speed); - */ - return new Phaser.Point(); - }; - Motion.prototype.angleBetweenMouse = /** - * Find the angle (in radians) between an Sprite and the mouse, taking their x/y and origin into account. - * The angle is calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative) - * - * @param {Sprite} a The Object to test from - * @param {boolean} asDegrees If you need the value in degrees instead of radians, set to true - * - * @return {number} The angle (in radians unless asDegrees is true) - */ - function (a, asDegrees) { - if (typeof asDegrees === "undefined") { asDegrees = false; } - // In order to get the angle between the object and mouse, we need the objects screen coordinates (rather than world coordinates) - var p = Phaser.SpriteUtils.getScreenXY(a); - var dx = a.game.input.x - p.x; - var dy = a.game.input.y - p.y; - if(asDegrees) { - return this.game.math.radiansToDegrees(Math.atan2(dy, dx)); - } else { - return Math.atan2(dy, dx); - } - }; - return Motion; - })(); - Phaser.Motion = Motion; -})(Phaser || (Phaser = {})); /// /** * Phaser - Device @@ -19593,6 +17846,9 @@ var Phaser; if(sprite.transform.scale.x == 0 || sprite.transform.scale.y == 0 || sprite.texture.alpha < 0.1 || this.inCamera(camera, sprite) == false) { return false; } + if(sprite.crop && sprite.crop.empty) { + return; + } sprite.renderOrderID = this._count; this._count++; // Reset our temp vars @@ -19642,6 +17898,16 @@ var Phaser; this._dx -= (this._dw * sprite.transform.origin.x); this._dy -= (this._dh * sprite.transform.origin.y); } + if(sprite.crop) { + this._sx += sprite.crop.x * sprite.transform.scale.x; + this._sy += sprite.crop.y * sprite.transform.scale.y; + this._sw = sprite.crop.width * sprite.transform.scale.x; + this._sh = sprite.crop.height * sprite.transform.scale.y; + this._dx += sprite.crop.x * sprite.transform.scale.x; + this._dy += sprite.crop.y * sprite.transform.scale.y; + this._dw = sprite.crop.width * sprite.transform.scale.x; + this._dh = sprite.crop.height * sprite.transform.scale.y; + } this._sx = Math.round(this._sx); this._sy = Math.round(this._sy); this._sw = Math.round(this._sw); @@ -19857,32 +18123,6 @@ var Phaser; DebugUtils.context.fillText('cx: ' + sprite.cameraView.x + ' cy: ' + sprite.cameraView.y + ' cw: ' + sprite.cameraView.width + ' ch: ' + sprite.cameraView.height + ' cb: ' + sprite.cameraView.bottom + ' cr: ' + sprite.cameraView.right, x, y + 70); DebugUtils.context.fillText('inCamera: ' + DebugUtils.game.renderer.inCamera(DebugUtils.game.camera, sprite), x, y + 84); }; - DebugUtils.renderPhysicsBodyInfo = /** - * Render debug infos. (including name, bounds info, position and some other properties) - * @param x {number} X position of the debug info to be rendered. - * @param y {number} Y position of the debug info to be rendered. - * @param [color] {number} color of the debug info to be rendered. (format is css color string) - */ - function renderPhysicsBodyInfo(body, x, y, color) { - if (typeof color === "undefined") { color = 'rgb(255,255,255)'; } - DebugUtils.context.fillStyle = color; - DebugUtils.context.fillText('Body ID: ' + body.name, x, y); - DebugUtils.context.fillText('Position x: ' + body.position.x.toFixed(1) + ' y: ' + body.position.y.toFixed(1) + ' rotation: ' + body.angle.toFixed(1), x, y + 14); - DebugUtils.context.fillText('World x: ' + (body.position.x * 50).toFixed(1) + ' y: ' + (body.position.y * 50).toFixed(1), x, y + 28); - DebugUtils.context.fillText('Velocity x: ' + body.velocity.x.toFixed(1) + ' y: ' + body.velocity.y.toFixed(1), x, y + 42); - if(body.shapes[0].verts.length > 0) { - DebugUtils.context.fillText('Vert 1 x: ' + (body.shapes[0].verts[0].x * 50) + ' y: ' + (body.shapes[0].verts[0].y * 50), x, y + 56); - DebugUtils.context.fillText('Vert 2 x: ' + (body.shapes[0].verts[1].x * 50) + ' y: ' + (body.shapes[0].verts[1].y * 50), x, y + 70); - DebugUtils.context.fillText('Vert 3 x: ' + (body.shapes[0].tverts[2].x * 50) + ' y: ' + (body.shapes[0].tverts[2].y * 50), x, y + 84); - DebugUtils.context.fillText('Vert 4 x: ' + (body.shapes[0].tverts[3].x * 50) + ' y: ' + (body.shapes[0].tverts[3].y * 50), x, y + 98); - /* - DebugUtils.context.fillText('Vert 1 x: ' + body.shapes[0].verts[0].x.toFixed(1) + ' y: ' + body.shapes[0].verts[0].y.toFixed(1), x, y + 56); - DebugUtils.context.fillText('Vert 2 x: ' + body.shapes[0].verts[1].x.toFixed(1) + ' y: ' + body.shapes[0].verts[1].y.toFixed(1), x, y + 70); - DebugUtils.context.fillText('Vert 3 x: ' + body.shapes[0].verts[2].x.toFixed(1) + ' y: ' + body.shapes[0].verts[2].y.toFixed(1), x, y + 84); - DebugUtils.context.fillText('Vert 4 x: ' + body.shapes[0].verts[3].x.toFixed(1) + ' y: ' + body.shapes[0].verts[3].y.toFixed(1), x, y + 98); - */ - } - }; DebugUtils.renderSpriteBounds = function renderSpriteBounds(sprite, camera, color) { if (typeof camera === "undefined") { camera = null; } if (typeof color === "undefined") { color = 'rgba(0,255,0,0.2)'; } @@ -19917,35 +18157,6 @@ var Phaser; DebugUtils.context.fillStyle = color; DebugUtils.context.fillText(text, x, y); }; - DebugUtils.renderPhysicsBody = function renderPhysicsBody(body, lineWidth, fillStyle, sleepStyle) { - if (typeof lineWidth === "undefined") { lineWidth = 1; } - if (typeof fillStyle === "undefined") { fillStyle = 'rgba(0,255,0,0.2)'; } - if (typeof sleepStyle === "undefined") { sleepStyle = 'rgba(100,100,100,0.2)'; } - for(var s = 0; s < body.shapesLength; s++) { - DebugUtils.context.beginPath(); - if(body.shapes[s].type == Phaser.Physics.Manager.SHAPE_TYPE_POLY) { - var verts = body.shapes[s].tverts; - // DebugUtils.context.moveTo(body.position.x * 50 + verts[0].x, body.position.y * 50 + verts[0].y); - DebugUtils.context.moveTo(verts[0].x * 50, verts[0].y * 50); - for(var i = 1; i < verts.length; i++) { - // DebugUtils.context.lineTo(body.position.x * 50 + verts[i].x, body.position.y * 50 + verts[i].y); - DebugUtils.context.lineTo(verts[i].x * 50, verts[i].y * 50); - } - // DebugUtils.context.lineTo(body.position.x * 50 + verts[0].x, body.position.y * 50 + verts[0].y); - DebugUtils.context.lineTo(verts[0].x * 50, verts[0].y * 50); - } else if(body.shapes[s].type == Phaser.Physics.Manager.SHAPE_TYPE_CIRCLE) { - var circle = body.shapes[s]; - DebugUtils.context.arc(circle.tc.x * 50, circle.tc.y * 50, circle.radius * 50, 0, Math.PI * 2, false); - } - DebugUtils.context.closePath(); - if(body.isAwake) { - DebugUtils.context.fillStyle = fillStyle; - } else { - DebugUtils.context.fillStyle = sleepStyle; - } - DebugUtils.context.fill(); - } - }; return DebugUtils; })(); Phaser.DebugUtils = DebugUtils; @@ -19972,7 +18183,6 @@ var Phaser; /// /// /// -/// /// /// /// @@ -20134,7 +18344,6 @@ var Phaser; } else { this.device = new Phaser.Device(); this.net = new Phaser.Net(this); - this.motion = new Phaser.Motion(this); this.math = new Phaser.GameMath(this); this.stage = new Phaser.Stage(this, parent, width, height); this.world = new Phaser.World(this, width, height); @@ -20770,174 +18979,6 @@ var Phaser; Phaser.Line = Line; })(Phaser || (Phaser = {})); /// -/// -/// -/// -/** -* Phaser - CircleUtils -* -* A collection of methods useful for manipulating and comparing Circle objects. -* -* TODO: -*/ -var Phaser; -(function (Phaser) { - var CircleUtils = (function () { - function CircleUtils() { } - CircleUtils.clone = /** - * Returns a new Circle object with the same values for the x, y, width, and height properties as the original Circle object. - * @method clone - * @param {Circle} a - The Circle object. - * @param {Circle} [optional] out Optional Circle object. If given the values will be set into the object, otherwise a brand new Circle object will be created and returned. - * @return {Phaser.Circle} - **/ - function clone(a, out) { - if (typeof out === "undefined") { out = new Phaser.Circle(); } - return out.setTo(a.x, a.y, a.diameter); - }; - CircleUtils.contains = /** - * Return true if the given x/y coordinates are within the Circle object. - * If you need details about the intersection then use Phaser.Intersect.circleContainsPoint instead. - * @method contains - * @param {Circle} a - The Circle object. - * @param {Number} The X value of the coordinate to test. - * @param {Number} The Y value of the coordinate to test. - * @return {Boolean} True if the coordinates are within this circle, otherwise false. - **/ - function contains(a, x, y) { - // Check if x/y are within the bounds first - if(x >= a.left && x <= a.right && y >= a.top && y <= a.bottom) { - var dx = (a.x - x) * (a.x - x); - var dy = (a.y - y) * (a.y - y); - return (dx + dy) <= (a.radius * a.radius); - } - return false; - }; - CircleUtils.containsPoint = /** - * Return true if the coordinates of the given Point object are within this Circle object. - * If you need details about the intersection then use Phaser.Intersect.circleContainsPoint instead. - * @method containsPoint - * @param {Circle} a - The Circle object. - * @param {Point} The Point object to test. - * @return {Boolean} True if the coordinates are within this circle, otherwise false. - **/ - function containsPoint(a, point) { - return CircleUtils.contains(a, point.x, point.y); - }; - CircleUtils.containsCircle = /** - * Return true if the given Circle is contained entirely within this Circle object. - * If you need details about the intersection then use Phaser.Intersect.circleToCircle instead. - * @method containsCircle - * @param {Circle} The Circle object to test. - * @return {Boolean} True if the coordinates are within this circle, otherwise false. - **/ - function containsCircle(a, b) { - //return ((a.radius + b.radius) * (a.radius + b.radius)) >= Collision.distanceSquared(a.x, a.y, b.x, b.y); - return true; - }; - CircleUtils.distanceBetween = /** - * Returns the distance from the center of the Circle object to the given object (can be Circle, Point or anything with x/y properties) - * @method distanceBetween - * @param {Circle} a - The Circle object. - * @param {Circle} b - The target object. Must have visible x and y properties that represent the center of the object. - * @param {Boolean} [optional] round - Round the distance to the nearest integer (default false) - * @return {Number} The distance between this Point object and the destination Point object. - **/ - function distanceBetween(a, target, round) { - if (typeof round === "undefined") { round = false; } - var dx = a.x - target.x; - var dy = a.y - target.y; - if(round === true) { - return Math.round(Math.sqrt(dx * dx + dy * dy)); - } else { - return Math.sqrt(dx * dx + dy * dy); - } - }; - CircleUtils.equals = /** - * Determines whether the two Circle objects match. This method compares the x, y and diameter properties. - * @method equals - * @param {Circle} a - The first Circle object. - * @param {Circle} b - The second Circle object. - * @return {Boolean} A value of true if the object has exactly the same values for the x, y and diameter properties as this Circle object; otherwise false. - **/ - function equals(a, b) { - return (a.x == b.x && a.y == b.y && a.diameter == b.diameter); - }; - CircleUtils.intersects = /** - * Determines whether the two Circle objects intersect. - * This method checks the radius distances between the two Circle objects to see if they intersect. - * @method intersects - * @param {Circle} a - The first Circle object. - * @param {Circle} b - The second Circle object. - * @return {Boolean} A value of true if the specified object intersects with this Circle object; otherwise false. - **/ - function intersects(a, b) { - return (CircleUtils.distanceBetween(a, b) <= (a.radius + b.radius)); - }; - CircleUtils.circumferencePoint = /** - * Returns a Point object containing the coordinates of a point on the circumference of the Circle based on the given angle. - * @method circumferencePoint - * @param {Circle} a - The first Circle object. - * @param {Number} angle The angle in radians (unless asDegrees is true) to return the point from. - * @param {Boolean} asDegrees Is the given angle in radians (false) or degrees (true)? - * @param {Phaser.Point} [optional] output An optional Point object to put the result in to. If none specified a new Point object will be created. - * @return {Phaser.Point} The Point object holding the result. - **/ - function circumferencePoint(a, angle, asDegrees, out) { - if (typeof asDegrees === "undefined") { asDegrees = false; } - if (typeof out === "undefined") { out = new Phaser.Point(); } - if(asDegrees === true) { - angle = angle * Phaser.GameMath.DEG_TO_RAD; - } - return out.setTo(a.x + a.radius * Math.cos(angle), a.y + a.radius * Math.sin(angle)); - }; - CircleUtils.intersectsRectangle = /* - public static boolean intersect(Rectangle r, Circle c) - { - float cx = Math.abs(c.x - r.x - r.halfWidth); - float xDist = r.halfWidth + c.radius; - if (cx > xDist) - return false; - float cy = Math.abs(c.y - r.y - r.halfHeight); - float yDist = r.halfHeight + c.radius; - if (cy > yDist) - return false; - if (cx <= r.halfWidth || cy <= r.halfHeight) - return true; - float xCornerDist = cx - r.halfWidth; - float yCornerDist = cy - r.halfHeight; - float xCornerDistSq = xCornerDist * xCornerDist; - float yCornerDistSq = yCornerDist * yCornerDist; - float maxCornerDistSq = c.radius * c.radius; - return xCornerDistSq + yCornerDistSq <= maxCornerDistSq; - } - */ - function intersectsRectangle(c, r) { - var cx = Math.abs(c.x - r.x - r.halfWidth); - var xDist = r.halfWidth + c.radius; - if(cx > xDist) { - return false; - } - var cy = Math.abs(c.y - r.y - r.halfHeight); - var yDist = r.halfHeight + c.radius; - if(cy > yDist) { - return false; - } - if(cx <= r.halfWidth || cy <= r.halfHeight) { - return true; - } - var xCornerDist = cx - r.halfWidth; - var yCornerDist = cy - r.halfHeight; - var xCornerDistSq = xCornerDist * xCornerDist; - var yCornerDistSq = yCornerDist * yCornerDist; - var maxCornerDistSq = c.radius * c.radius; - return xCornerDistSq + yCornerDistSq <= maxCornerDistSq; - }; - return CircleUtils; - })(); - Phaser.CircleUtils = CircleUtils; -})(Phaser || (Phaser = {})); -/// /// /// /** @@ -21093,6 +19134,401 @@ var Phaser; Phaser.Mat3Utils = Mat3Utils; })(Phaser || (Phaser = {})); /// +/// +/** +* Phaser - 2D Transform +* +* A 2D Transform +*/ +var Phaser; +(function (Phaser) { + var Transform = (function () { + /** + * Creates a new 2D Transform object. + * @class Transform + * @constructor + * @return {Transform} This object + **/ + function Transform(pos, angle) { + this.t = Phaser.Vec2Utils.clone(pos); + this.c = Math.cos(angle); + this.s = Math.sin(angle); + this.angle = angle; + } + Transform.prototype.toString = function () { + return 't=' + this.t.toString() + ' c=' + this.c + ' s=' + this.s + ' a=' + this.angle; + }; + Transform.prototype.setTo = function (pos, angle) { + this.t.copyFrom(pos); + this.c = Math.cos(angle); + this.s = Math.sin(angle); + return this; + }; + Transform.prototype.setRotation = function (angle) { + if(angle !== this.angle) { + this.c = Math.cos(angle); + this.s = Math.sin(angle); + this.angle = angle; + } + return this; + }; + Transform.prototype.setPosition = function (p) { + this.t.copyFrom(p); + return this; + }; + Transform.prototype.identity = function () { + this.t.setTo(0, 0); + this.c = 1; + this.s = 0; + return this; + }; + return Transform; + })(); + Phaser.Transform = Transform; +})(Phaser || (Phaser = {})); +/// +/// +/// +/** +* Phaser - TransformUtils +* +* A collection of methods useful for manipulating and performing operations on 2D Transforms. +* +*/ +var Phaser; +(function (Phaser) { + var TransformUtils = (function () { + function TransformUtils() { } + TransformUtils.rotate = function rotate(t, v, out) { + if (typeof out === "undefined") { out = new Phaser.Vec2(); } + //return new vec2(v.x * this.c - v.y * this.s, v.x * this.s + v.y * this.c); + return out.setTo(v.x * t.c - v.y * t.s, v.x * t.s + v.y * t.c); + }; + TransformUtils.unrotate = function unrotate(t, v, out) { + if (typeof out === "undefined") { out = new Phaser.Vec2(); } + //return new vec2(v.x * this.c + v.y * this.s, -v.x * this.s + v.y * this.c); + return out.setTo(v.x * t.c + v.y * t.s, -v.x * t.s + v.y * t.c); + }; + TransformUtils.transform = function transform(t, v, out) { + if (typeof out === "undefined") { out = new Phaser.Vec2(); } + //return new vec2(v.x * this.c - v.y * this.s + this.t.x, v.x * this.s + v.y * this.c + this.t.y); + 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); + }; + TransformUtils.untransform = function untransform(t, v, out) { + if (typeof out === "undefined") { out = new Phaser.Vec2(); } + var px = v.x - t.t.x; + var py = v.y - t.t.y; + //return new vec2(px * this.c + py * this.s, -px * this.s + py * this.c); + return out.setTo(px * t.c + py * t.s, -px * t.s + py * t.c); + }; + return TransformUtils; + })(); + Phaser.TransformUtils = TransformUtils; +})(Phaser || (Phaser = {})); +/// +/// +/** +* Phaser - Motion +* +* The Motion class contains lots of useful functions for moving game objects around in world space. +*/ +var Phaser; +(function (Phaser) { + var Motion = (function () { + function Motion(game) { + this.game = game; + } + Motion.prototype.velocityFromAngle = /** + * Given the angle and speed calculate the velocity and return it as a Point + * + * @param {number} angle The angle (in degrees) calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative) + * @param {number} speed The speed it will move, in pixels per second sq + * + * @return {Point} A Point where Point.x contains the velocity x value and Point.y contains the velocity y value + */ + function (angle, speed) { + if(isNaN(speed)) { + speed = 0; + } + var a = this.game.math.degreesToRadians(angle); + return new Phaser.Point((Math.cos(a) * speed), (Math.sin(a) * speed)); + }; + Motion.prototype.moveTowardsObject = /** + * Sets the source Sprite x/y velocity so it will move directly towards the destination Sprite at the speed given (in pixels per second)
+ * If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds.
+ * Timings are approximate due to the way Flash timers work, and irrespective of SWF frame rate. Allow for a variance of +- 50ms.
+ * The source object doesn't stop moving automatically should it ever reach the destination coordinates.
+ * If you need the object to accelerate, see accelerateTowardsObject() instead + * Note: Doesn't take into account acceleration, maxVelocity or drag (if you set drag or acceleration too high this object may not move at all) + * + * @param {Sprite} source The Sprite on which the velocity will be set + * @param {Sprite} dest The Sprite where the source object will move to + * @param {number} speed The speed it will move, in pixels per second (default is 60 pixels/sec) + * @param {number} maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms + */ + function (source, dest, speed, maxTime) { + if (typeof speed === "undefined") { speed = 60; } + if (typeof maxTime === "undefined") { maxTime = 0; } + var a = this.angleBetween(source, dest); + if(maxTime > 0) { + var d = this.distanceBetween(source, dest); + // We know how many pixels we need to move, but how fast? + speed = d / (maxTime / 1000); + } + source.body.velocity.x = Math.cos(a) * speed; + source.body.velocity.y = Math.sin(a) * speed; + }; + Motion.prototype.accelerateTowardsObject = /** + * Sets the x/y acceleration on the source Sprite so it will move towards the destination Sprite at the speed given (in pixels per second)
+ * You must give a maximum speed value, beyond which the Sprite won't go any faster.
+ * If you don't need acceleration look at moveTowardsObject() instead. + * + * @param {Sprite} source The Sprite on which the acceleration will be set + * @param {Sprite} dest The Sprite where the source object will move towards + * @param {number} speed The speed it will accelerate in pixels per second + * @param {number} xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally + * @param {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically + */ + function (source, dest, speed, xSpeedMax, ySpeedMax) { + /* + var a: number = this.angleBetween(source, dest); + + source.body.velocity.x = 0; + source.body.velocity.y = 0; + + source.body.acceleration.x = Math.cos(a) * speed; + source.body.acceleration.y = Math.sin(a) * speed; + + source.body.maxVelocity.x = xSpeedMax; + source.body.maxVelocity.y = ySpeedMax; + */ + }; + Motion.prototype.moveTowardsMouse = /** + * Move the given Sprite towards the mouse pointer coordinates at a steady velocity + * If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds.
+ * Timings are approximate due to the way Flash timers work, and irrespective of SWF frame rate. Allow for a variance of +- 50ms.
+ * The source object doesn't stop moving automatically should it ever reach the destination coordinates.
+ * + * @param {Sprite} source The Sprite to move + * @param {number} speed The speed it will move, in pixels per second (default is 60 pixels/sec) + * @param {number} maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms + */ + function (source, speed, maxTime) { + if (typeof speed === "undefined") { speed = 60; } + if (typeof maxTime === "undefined") { maxTime = 0; } + var a = this.angleBetweenMouse(source); + if(maxTime > 0) { + var d = this.distanceToMouse(source); + // We know how many pixels we need to move, but how fast? + speed = d / (maxTime / 1000); + } + source.body.velocity.x = Math.cos(a) * speed; + source.body.velocity.y = Math.sin(a) * speed; + }; + Motion.prototype.accelerateTowardsMouse = /** + * Sets the x/y acceleration on the source Sprite so it will move towards the mouse coordinates at the speed given (in pixels per second)
+ * You must give a maximum speed value, beyond which the Sprite won't go any faster.
+ * If you don't need acceleration look at moveTowardsMouse() instead. + * + * @param {Sprite} source The Sprite on which the acceleration will be set + * @param {number} speed The speed it will accelerate in pixels per second + * @param {number} xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally + * @param {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically + */ + function (source, speed, xSpeedMax, ySpeedMax) { + /* + var a: number = this.angleBetweenMouse(source); + + source.body.velocity.x = 0; + source.body.velocity.y = 0; + + source.body.acceleration.x = Math.cos(a) * speed; + source.body.acceleration.y = Math.sin(a) * speed; + + source.body.maxVelocity.x = xSpeedMax; + source.body.maxVelocity.y = ySpeedMax; + */ + }; + Motion.prototype.moveTowardsPoint = /** + * Sets the x/y velocity on the source Sprite so it will move towards the target coordinates at the speed given (in pixels per second)
+ * If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds.
+ * Timings are approximate due to the way Flash timers work, and irrespective of SWF frame rate. Allow for a variance of +- 50ms.
+ * The source object doesn't stop moving automatically should it ever reach the destination coordinates.
+ * + * @param {Sprite} source The Sprite to move + * @param {Point} target The Point coordinates to move the source Sprite towards + * @param {number} speed The speed it will move, in pixels per second (default is 60 pixels/sec) + * @param {number} maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms + */ + function (source, target, speed, maxTime) { + if (typeof speed === "undefined") { speed = 60; } + if (typeof maxTime === "undefined") { maxTime = 0; } + var a = this.angleBetweenPoint(source, target); + if(maxTime > 0) { + var d = this.distanceToPoint(source, target); + // We know how many pixels we need to move, but how fast? + speed = d / (maxTime / 1000); + } + source.body.velocity.x = Math.cos(a) * speed; + source.body.velocity.y = Math.sin(a) * speed; + }; + Motion.prototype.accelerateTowardsPoint = /** + * Sets the x/y acceleration on the source Sprite so it will move towards the target coordinates at the speed given (in pixels per second)
+ * You must give a maximum speed value, beyond which the Sprite won't go any faster.
+ * If you don't need acceleration look at moveTowardsPoint() instead. + * + * @param {Sprite} source The Sprite on which the acceleration will be set + * @param {Point} target The Point coordinates to move the source Sprite towards + * @param {number} speed The speed it will accelerate in pixels per second + * @param {number} xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally + * @param {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically + */ + function (source, target, speed, xSpeedMax, ySpeedMax) { + /* + var a: number = this.angleBetweenPoint(source, target); + + source.body.velocity.x = 0; + source.body.velocity.y = 0; + + source.body.acceleration.x = Math.cos(a) * speed; + source.body.acceleration.y = Math.sin(a) * speed; + + source.body.maxVelocity.x = xSpeedMax; + source.body.maxVelocity.y = ySpeedMax; + */ + }; + Motion.prototype.distanceBetween = /** + * Find the distance between two Sprites, taking their origin into account + * + * @param {Sprite} a The first Sprite + * @param {Sprite} b The second Sprite + * @return {number} int Distance (in pixels) + */ + function (a, b) { + return Phaser.Vec2Utils.distance(a.body.position, b.body.position); + }; + Motion.prototype.distanceToPoint = /** + * Find the distance from an Sprite to the given Point, taking the source origin into account + * + * @param {Sprite} a The Sprite + * @param {Point} target The Point + * @return {number} Distance (in pixels) + */ + function (a, target) { + var dx = (a.x + a.transform.origin.x) - (target.x); + var dy = (a.y + a.transform.origin.y) - (target.y); + return this.game.math.vectorLength(dx, dy); + }; + Motion.prototype.distanceToMouse = /** + * Find the distance (in pixels, rounded) from the object x/y and the mouse x/y + * + * @param {Sprite} a Sprite to test against + * @return {number} The distance between the given sprite and the mouse coordinates + */ + function (a) { + var dx = (a.x + a.transform.origin.x) - this.game.input.x; + var dy = (a.y + a.transform.origin.y) - this.game.input.y; + return this.game.math.vectorLength(dx, dy); + }; + Motion.prototype.angleBetweenPoint = /** + * Find the angle (in radians) between an Sprite and an Point. The source sprite takes its x/y and origin into account. + * The angle is calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative) + * + * @param {Sprite} a The Sprite to test from + * @param {Point} target The Point to angle the Sprite towards + * @param {boolean} asDegrees If you need the value in degrees instead of radians, set to true + * + * @return {number} The angle (in radians unless asDegrees is true) + */ + function (a, target, asDegrees) { + if (typeof asDegrees === "undefined") { asDegrees = false; } + var dx = (target.x) - (a.x + a.transform.origin.x); + var dy = (target.y) - (a.y + a.transform.origin.y); + if(asDegrees) { + return this.game.math.radiansToDegrees(Math.atan2(dy, dx)); + } else { + return Math.atan2(dy, dx); + } + }; + Motion.prototype.angleBetween = /** + * Find the angle (in radians) between the two Sprite, taking their x/y and origin into account. + * The angle is calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative) + * + * @param {Sprite} a The Sprite to test from + * @param {Sprite} b The Sprite to test to + * @param {boolean} asDegrees If you need the value in degrees instead of radians, set to true + * + * @return {number} The angle (in radians unless asDegrees is true) + */ + function (a, b, asDegrees) { + if (typeof asDegrees === "undefined") { asDegrees = false; } + var dx = (b.x + b.transform.origin.x) - (a.x + a.transform.origin.x); + var dy = (b.y + b.transform.origin.y) - (a.y + a.transform.origin.y); + if(asDegrees) { + return this.game.math.radiansToDegrees(Math.atan2(dy, dx)); + } else { + return Math.atan2(dy, dx); + } + }; + Motion.prototype.velocityFromFacing = /** + * Given the Sprite and speed calculate the velocity and return it as an Point based on the direction the sprite is facing + * + * @param {Sprite} parent The Sprite to get the facing value from + * @param {number} speed The speed it will move, in pixels per second sq + * + * @return {Point} An Point where Point.x contains the velocity x value and Point.y contains the velocity y value + */ + function (parent, speed) { + /* + var a: number; + + if (parent.body.facing == Types.LEFT) + { + a = this.game.math.degreesToRadians(180); + } + else if (parent.body.facing == Types.RIGHT) + { + a = this.game.math.degreesToRadians(0); + } + else if (parent.body.facing == Types.UP) + { + a = this.game.math.degreesToRadians(-90); + } + else if (parent.body.facing == Types.DOWN) + { + a = this.game.math.degreesToRadians(90); + } + + return new Point(Math.cos(a) * speed, Math.sin(a) * speed); + */ + return new Phaser.Point(); + }; + Motion.prototype.angleBetweenMouse = /** + * Find the angle (in radians) between an Sprite and the mouse, taking their x/y and origin into account. + * The angle is calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative) + * + * @param {Sprite} a The Object to test from + * @param {boolean} asDegrees If you need the value in degrees instead of radians, set to true + * + * @return {number} The angle (in radians unless asDegrees is true) + */ + function (a, asDegrees) { + if (typeof asDegrees === "undefined") { asDegrees = false; } + // In order to get the angle between the object and mouse, we need the objects screen coordinates (rather than world coordinates) + var p = Phaser.SpriteUtils.getScreenXY(a); + var dx = a.game.input.x - p.x; + var dy = a.game.input.y - p.y; + if(asDegrees) { + return this.game.math.radiansToDegrees(Math.atan2(dy, dx)); + } else { + return Math.atan2(dy, dx); + } + }; + return Motion; + })(); + Phaser.Motion = Motion; +})(Phaser || (Phaser = {})); +/// /// /// /// @@ -21186,7 +19622,7 @@ var Phaser; this.input = game.input; this.load = game.load; this.math = game.math; - this.motion = game.motion; + //this.motion = game.motion; this.sound = game.sound; this.stage = game.stage; this.time = game.time; diff --git a/build/phaser.d.ts b/build/phaser.d.ts index 1838b989..d78aeddd 100644 --- a/build/phaser.d.ts +++ b/build/phaser.d.ts @@ -2616,502 +2616,199 @@ module Phaser { } } /** -* Phaser - 2D Transform +* Phaser - CircleUtils * -* A 2D Transform +* A collection of methods useful for manipulating and comparing Circle objects. +* +* TODO: */ module Phaser { - class Transform { + class CircleUtils { /** - * Creates a new 2D Transform object. - * @class Transform - * @constructor - * @return {Transform} This object + * Returns a new Circle object with the same values for the x, y, width, and height properties as the original Circle object. + * @method clone + * @param {Circle} a - The Circle object. + * @param {Circle} [optional] out Optional Circle object. If given the values will be set into the object, otherwise a brand new Circle object will be created and returned. + * @return {Phaser.Circle} **/ - constructor(pos: Vec2, angle: number); - public t: Vec2; - public c: number; - public s: number; - public angle: number; - public toString(): string; - 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 - Advanced Physics - Joint -* -* Based on the work Ju Hyung Lee started in JS PhyRus. -*/ -module Phaser.Physics { - 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 - Physics Manager -* -* The Physics Manager is responsible for looking after, creating and colliding -* all of the physics bodies and joints in the world. -*/ -module Phaser.Physics { - class Manager { - constructor(game: Game); + static clone(a: Circle, out?: Circle): Circle; /** - * Local reference to Game. + * Return true if the given x/y coordinates are within the Circle object. + * If you need details about the intersection then use Phaser.Intersect.circleContainsPoint instead. + * @method contains + * @param {Circle} a - The Circle object. + * @param {Number} The X value of the coordinate to test. + * @param {Number} The Y value of the coordinate to test. + * @return {Boolean} True if the coordinates are within this circle, otherwise false. + **/ + static contains(a: Circle, x: number, y: number): bool; + /** + * Return true if the coordinates of the given Point object are within this Circle object. + * If you need details about the intersection then use Phaser.Intersect.circleContainsPoint instead. + * @method containsPoint + * @param {Circle} a - The Circle object. + * @param {Point} The Point object to test. + * @return {Boolean} True if the coordinates are within this circle, otherwise false. + **/ + static containsPoint(a: Circle, point: Point): bool; + /** + * Return true if the given Circle is contained entirely within this Circle object. + * If you need details about the intersection then use Phaser.Intersect.circleToCircle instead. + * @method containsCircle + * @param {Circle} The Circle object to test. + * @return {Boolean} True if the coordinates are within this circle, otherwise false. + **/ + static containsCircle(a: Circle, b: Circle): bool; + /** + * Returns the distance from the center of the Circle object to the given object (can be Circle, Point or anything with x/y properties) + * @method distanceBetween + * @param {Circle} a - The Circle object. + * @param {Circle} b - The target object. Must have visible x and y properties that represent the center of the object. + * @param {Boolean} [optional] round - Round the distance to the nearest integer (default false) + * @return {Number} The distance between this Point object and the destination Point object. + **/ + static distanceBetween(a: Circle, target: any, round?: bool): number; + /** + * Determines whether the two Circle objects match. This method compares the x, y and diameter properties. + * @method equals + * @param {Circle} a - The first Circle object. + * @param {Circle} b - The second Circle object. + * @return {Boolean} A value of true if the object has exactly the same values for the x, y and diameter properties as this Circle object; otherwise false. + **/ + static equals(a: Circle, b: Circle): bool; + /** + * Determines whether the two Circle objects intersect. + * This method checks the radius distances between the two Circle objects to see if they intersect. + * @method intersects + * @param {Circle} a - The first Circle object. + * @param {Circle} b - The second Circle object. + * @return {Boolean} A value of true if the specified object intersects with this Circle object; otherwise false. + **/ + static intersects(a: Circle, b: Circle): bool; + /** + * Returns a Point object containing the coordinates of a point on the circumference of the Circle based on the given angle. + * @method circumferencePoint + * @param {Circle} a - The first Circle object. + * @param {Number} angle The angle in radians (unless asDegrees is true) to return the point from. + * @param {Boolean} asDegrees Is the given angle in radians (false) or degrees (true)? + * @param {Phaser.Point} [optional] output An optional Point object to put the result in to. If none specified a new Point object will be created. + * @return {Phaser.Point} The Point object holding the result. + **/ + static circumferencePoint(a: Circle, angle: number, asDegrees?: bool, out?: Point): Point; + static intersectsRectangle(c: Circle, r: Rectangle): bool; + } +} +/** +* Phaser - ArcadePhysics Manager +* +*/ +module Phaser.Physics { + class ArcadePhysics { + constructor(game: Game, width: number, height: number); + /** + * Local private reference to Game. */ public game: Game; - static debug: HTMLTextAreaElement; - static clear(): void; - static write(s: string): void; - static writeAll(): void; - static log: any[]; - static dump(phase: string, body: Body): void; - 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 gravity: Vec2; - public update(): void; - public addBody(body: Body): void; - public removeBody(body: Body): void; - public addJoint(joint: IJoint): void; - public removeJoint(joint: IJoint): 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: number, radius_inner: number): number; - static inertiaForCircle(mass: number, center: Vec2, radius_outer: number, radius_inner: number): number; - static areaForSegment(a: Vec2, b: Vec2, radius: number): number; - static centroidForSegment(a: Vec2, b: Vec2): Vec2; - static inertiaForSegment(mass: number, a: Vec2, b: Vec2): number; - static areaForPoly(verts: Vec2[]): number; - static centroidForPoly(verts: Vec2[]): Vec2; - static inertiaForPoly(mass: number, verts: Vec2[], offset: Vec2): number; - static inertiaForBox(mass: number, w: number, h: number): number; - static createConvexHull(points): any[]; - } -} -/** -* Phaser - 2D AABB -* -* A 2D AABB object -*/ -module Phaser.Physics { - 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 x : number; - public y : number; - public width : number; - public height : number; - public right : number; - public bottom : number; - 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 { - 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; - verts: Vec2[]; - planes: Plane[]; - tverts: Vec2[]; - tplanes: Plane[]; - convexity: bool; - } -} -/** -* Phaser - Advanced Physics - Shape -* -* Based on the work Ju Hyung Lee started in JS PhyRus. -*/ -module Phaser.Physics { - class Shape { - constructor(type: number); - public id: number; - public type: number; - public body: Body; - public verts: Vec2[]; - public planes: Plane[]; - public tverts: Vec2[]; - public tplanes: Plane[]; - public convexity: bool; - 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 { - 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 { - 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.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 - Plane -* -* Based on the work Ju Hyung Lee started in JS PhyRus. -*/ -module Phaser.Physics { - class Plane { - constructor(normal: Vec2, d: number); - public normal: Vec2; - public d: number; - } -} -/** -* Phaser - Advanced Physics - Shapes - Convex Polygon -* -* Based on the work Ju Hyung Lee started in JS PhyRus. -*/ -module Phaser.Physics.Shapes { - class Poly extends Shape implements IShape { - constructor(verts?); - public finishVerts(): void; - public duplicate(): Poly; - 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 findEdgeByPoint(p: Vec2, minDist: number): number; - public distanceOnPlane(n: Vec2, d: number): number; - public containPoint(p: Vec2): 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.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 { - class Collision { - 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: Plane[], 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 { - 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 { - class Space { - constructor(manager: Manager); - private _manager; + * Physics object pool + */ + public members: Group; + private _drag; private _delta; - private _deltaInv; - private _bl; - private _jl; - private _cl; - private _linTolSqr; - private _angTolSqr; - private _minSleepTime; - private _positionSolved; - private _shape1; - private _shape2; - private _contactsOk; - private _jointsOk; - private bodyHash; - private jointHash; - static TIME_TO_SLEEP: number; - static SLEEP_LINEAR_TOLERANCE: number; - static SLEEP_ANGULAR_TOLERANCE: number; - public bodies: Body[]; - public joints: IJoint[]; - public numContacts: number; - public contactSolvers: ContactSolver[]; - public postSolve; + 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 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; - private findContactSolver(shape1, shape2); - private genTemporalContactSolvers(); - private initSolver(warmStarting); - private velocitySolver(iterations); - private positionSolver(iterations); - public step(dt: number, velocityIterations: number, positionIterations: number, warmStarting: bool, allowSleep: bool): void; + 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 - Shapes - Triangle -* -* Based on the work Ju Hyung Lee started in JS PhyRus. -*/ -module Phaser.Physics.Shapes { - class Triangle extends Poly { - constructor(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number); - } -} -/** -* Phaser - Advanced Physics - Shapes - Box -* -* Based on the work Ju Hyung Lee started in JS PhyRus. -*/ -module Phaser.Physics.Shapes { - class Box extends Poly { - constructor(x, y, width, height); - } -} -/** -* Phaser - Advanced Physics - Body -* -* Based on the work Ju Hyung Lee started in JS PhyRus. +* Phaser - ArcadePhysics - Body */ module Phaser.Physics { class Body { - constructor(sprite: Sprite, type: number, x?: number, y?: number, shapeType?: number); - private _tempVec2; - private _fixedRotation; + constructor(sprite: Sprite, type: number); /** * Reference to Phaser.Game */ @@ -3121,14 +2818,6 @@ module Phaser.Physics { */ 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 @@ -3137,84 +2826,53 @@ module Phaser.Physics { * @type {number} */ public type: number; - /** - * The angle of the body in radians. Used by all of the internal physics methods. - */ - public angle: number; - /** - * The rotation of the body in degrees. Phaser uses a right-handed coordinate system, where 0 points to the right. - */ - /** - * Set the rotation of the body in degrees. Phaser uses a right-handed coordinate system, where 0 points to the right. - * The value is automatically wrapped to be between 0 and 360. - */ - public rotation : number; - public transform: Transform; - public centroid: Vec2; - public position: Vec2; + public gravity: Vec2; + public bounce: Vec2; public velocity: Vec2; - public force: Vec2; + public acceleration: Vec2; + public drag: Vec2; + public maxVelocity: Vec2; public angularVelocity: number; - public torque: number; - public linearDamping: number; - public angularDamping: number; - public sleepTime: number; - public awaked: bool; + public angularAcceleration: number; + public angularDrag: number; + public maxAngular: number; + /** + * Orientation of the object. + * @type {number} + */ + public facing: number; + public touching: number; public allowCollisions: number; - public shapes: IShape[]; - public shapesLength: number; - public joints: IJoint[]; - public jointHash: {}; - public bounds: Bounds; + public wasTouching: number; public mass: number; - public massInverted: number; - public inertia: number; - public inertiaInverted: number; - 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 addPoly(verts, elasticity?: number, friction?: number, density?: number): Shapes.Poly; - public addTriangle(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, elasticity?: number, friction?: number, density?: number): Shapes.Triangle; - public addBox(x: number, y: number, width: number, height: number, elasticity?: number, friction?: number, density?: number): Shapes.Box; - public addCircle(radius: number, x?: number, y?: number, elasticity?: number, friction?: number, density?: number): Shapes.Circle; - public addShape(shape); - public removeShape(shape): void; - private setMass(mass); - private setInertia(inertia); - private _newPosition; - public setPosition(x: number, y: number): void; - public setTransform(pos: Vec2, angle: number): void; - public syncTransform(): void; - public getWorldPoint(p: Vec2): Vec2; - public getWorldVector(v: Vec2): Vec2; - public getLocalPoint(p: Vec2): Vec2; - public getLocalVector(v: Vec2): Vec2; - public fixedRotation : bool; - public resetMassData(): void; - public resetJointAnchors(): void; - public cacheData(source?: string): void; - public updateVelocity(gravity, dt, damping): void; - public inContact(body2: Body): bool; - public clamp(v, min, max); - public updatePosition(dt: number): void; - public resetForce(): void; - public applyForce(force: Vec2, p: Vec2): void; - public applyForceToCenter(force: Vec2): void; - public applyTorque(torque: number): void; - public applyLinearImpulse(impulse: Vec2, p: Vec2): void; - public applyAngularImpulse(impulse: number): void; - public kineticEnergy(): number; - public isAwake : bool; - public awake(flag): void; - public isCollidable(other: Body): bool; - public toString(): string; + public position: Vec2; + public oldPosition: Vec2; + public offset: Vec2; + public bounds: Rectangle; + private _width; + private _height; + public x : number; + public y : number; + public width : number; + public height : number; + public preUpdate(): void; + public postUpdate(): void; + public hullWidth : number; + public hullHeight : number; + public hullX : number; + public hullY : number; + public deltaXAbs : number; + public deltaYAbs : number; + public deltaX : number; + public deltaY : number; + public render(context: CanvasRenderingContext2D): void; + /** + * Render debug infos. (including name, bounds info, position and some other properties) + * @param x {number} X position of the debug info to be rendered. + * @param y {number} Y position of the debug info to be rendered. + * @param [color] {number} color of the debug info to be rendered. (format is css color string) + */ + public renderDebugInfo(x: number, y: number, color?: string): void; } } /** @@ -7190,9 +6848,9 @@ module Phaser { /** * Phaser * -* v1.0.0 - June XX 2013 +* v1.0.0 - August 12th 2013 * -* A small and feature-packed 2D canvas game framework born from the firey pits of Flixel and Kiwi. +* A feature-packed 2D canvas game framework born from the firey pits of Flixel and Kiwi. * * Richard Davey (@photonstorm) * @@ -7960,6 +7618,31 @@ module Phaser { } } /** +* Phaser - Physics Manager +* +* Eventually this will handle switching between the default ArcadePhysics manager or the new AdvancedPhysics manager. +* For now we direct everything through ArcadePhysics. +*/ +module Phaser.Physics { + class Manager { + constructor(game: Game); + /** + * Local reference to Game. + */ + public game: Game; + /** + * Instance of the ArcadePhysics manager. + */ + public arcade: ArcadePhysics; + public gravity: Vec2; + public bounds: Rectangle; + /** + * Called by the main Game.loop + */ + public update(): void; + } +} +/** * Phaser - World * * "This world is but a canvas to our imagination." - Henry David Thoreau @@ -8047,162 +7730,6 @@ module Phaser { } } /** -* Phaser - Motion -* -* The Motion class contains lots of useful functions for moving game objects around in world space. -*/ -module Phaser { - class Motion { - constructor(game: Game); - public game: Game; - /** - * Given the angle and speed calculate the velocity and return it as a Point - * - * @param {number} angle The angle (in degrees) calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative) - * @param {number} speed The speed it will move, in pixels per second sq - * - * @return {Point} A Point where Point.x contains the velocity x value and Point.y contains the velocity y value - */ - public velocityFromAngle(angle: number, speed: number): Point; - /** - * Sets the source Sprite x/y velocity so it will move directly towards the destination Sprite at the speed given (in pixels per second)
- * If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds.
- * Timings are approximate due to the way Flash timers work, and irrespective of SWF frame rate. Allow for a variance of +- 50ms.
- * The source object doesn't stop moving automatically should it ever reach the destination coordinates.
- * If you need the object to accelerate, see accelerateTowardsObject() instead - * Note: Doesn't take into account acceleration, maxVelocity or drag (if you set drag or acceleration too high this object may not move at all) - * - * @param {Sprite} source The Sprite on which the velocity will be set - * @param {Sprite} dest The Sprite where the source object will move to - * @param {number} speed The speed it will move, in pixels per second (default is 60 pixels/sec) - * @param {number} maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms - */ - public moveTowardsObject(source: Sprite, dest: Sprite, speed?: number, maxTime?: number): void; - /** - * Sets the x/y acceleration on the source Sprite so it will move towards the destination Sprite at the speed given (in pixels per second)
- * You must give a maximum speed value, beyond which the Sprite won't go any faster.
- * If you don't need acceleration look at moveTowardsObject() instead. - * - * @param {Sprite} source The Sprite on which the acceleration will be set - * @param {Sprite} dest The Sprite where the source object will move towards - * @param {number} speed The speed it will accelerate in pixels per second - * @param {number} xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally - * @param {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically - */ - public accelerateTowardsObject(source: Sprite, dest: Sprite, speed: number, xSpeedMax: number, ySpeedMax: number): void; - /** - * Move the given Sprite towards the mouse pointer coordinates at a steady velocity - * If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds.
- * Timings are approximate due to the way Flash timers work, and irrespective of SWF frame rate. Allow for a variance of +- 50ms.
- * The source object doesn't stop moving automatically should it ever reach the destination coordinates.
- * - * @param {Sprite} source The Sprite to move - * @param {number} speed The speed it will move, in pixels per second (default is 60 pixels/sec) - * @param {number} maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms - */ - public moveTowardsMouse(source: Sprite, speed?: number, maxTime?: number): void; - /** - * Sets the x/y acceleration on the source Sprite so it will move towards the mouse coordinates at the speed given (in pixels per second)
- * You must give a maximum speed value, beyond which the Sprite won't go any faster.
- * If you don't need acceleration look at moveTowardsMouse() instead. - * - * @param {Sprite} source The Sprite on which the acceleration will be set - * @param {number} speed The speed it will accelerate in pixels per second - * @param {number} xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally - * @param {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically - */ - public accelerateTowardsMouse(source: Sprite, speed: number, xSpeedMax: number, ySpeedMax: number): void; - /** - * Sets the x/y velocity on the source Sprite so it will move towards the target coordinates at the speed given (in pixels per second)
- * If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds.
- * Timings are approximate due to the way Flash timers work, and irrespective of SWF frame rate. Allow for a variance of +- 50ms.
- * The source object doesn't stop moving automatically should it ever reach the destination coordinates.
- * - * @param {Sprite} source The Sprite to move - * @param {Point} target The Point coordinates to move the source Sprite towards - * @param {number} speed The speed it will move, in pixels per second (default is 60 pixels/sec) - * @param {number} maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms - */ - public moveTowardsPoint(source: Sprite, target: Point, speed?: number, maxTime?: number): void; - /** - * Sets the x/y acceleration on the source Sprite so it will move towards the target coordinates at the speed given (in pixels per second)
- * You must give a maximum speed value, beyond which the Sprite won't go any faster.
- * If you don't need acceleration look at moveTowardsPoint() instead. - * - * @param {Sprite} source The Sprite on which the acceleration will be set - * @param {Point} target The Point coordinates to move the source Sprite towards - * @param {number} speed The speed it will accelerate in pixels per second - * @param {number} xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally - * @param {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically - */ - public accelerateTowardsPoint(source: Sprite, target: Point, speed: number, xSpeedMax: number, ySpeedMax: number): void; - /** - * Find the distance between two Sprites, taking their origin into account - * - * @param {Sprite} a The first Sprite - * @param {Sprite} b The second Sprite - * @return {number} int Distance (in pixels) - */ - public distanceBetween(a: Sprite, b: Sprite): number; - /** - * Find the distance from an Sprite to the given Point, taking the source origin into account - * - * @param {Sprite} a The Sprite - * @param {Point} target The Point - * @return {number} Distance (in pixels) - */ - public distanceToPoint(a: Sprite, target: Point): number; - /** - * Find the distance (in pixels, rounded) from the object x/y and the mouse x/y - * - * @param {Sprite} a Sprite to test against - * @return {number} The distance between the given sprite and the mouse coordinates - */ - public distanceToMouse(a: Sprite): number; - /** - * Find the angle (in radians) between an Sprite and an Point. The source sprite takes its x/y and origin into account. - * The angle is calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative) - * - * @param {Sprite} a The Sprite to test from - * @param {Point} target The Point to angle the Sprite towards - * @param {boolean} asDegrees If you need the value in degrees instead of radians, set to true - * - * @return {number} The angle (in radians unless asDegrees is true) - */ - public angleBetweenPoint(a: Sprite, target: Point, asDegrees?: bool): number; - /** - * Find the angle (in radians) between the two Sprite, taking their x/y and origin into account. - * The angle is calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative) - * - * @param {Sprite} a The Sprite to test from - * @param {Sprite} b The Sprite to test to - * @param {boolean} asDegrees If you need the value in degrees instead of radians, set to true - * - * @return {number} The angle (in radians unless asDegrees is true) - */ - public angleBetween(a: Sprite, b: Sprite, asDegrees?: bool): number; - /** - * Given the Sprite and speed calculate the velocity and return it as an Point based on the direction the sprite is facing - * - * @param {Sprite} parent The Sprite to get the facing value from - * @param {number} speed The speed it will move, in pixels per second sq - * - * @return {Point} An Point where Point.x contains the velocity x value and Point.y contains the velocity y value - */ - public velocityFromFacing(parent: Sprite, speed: number): Point; - /** - * Find the angle (in radians) between an Sprite and the mouse, taking their x/y and origin into account. - * The angle is calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative) - * - * @param {Sprite} a The Object to test from - * @param {boolean} asDegrees If you need the value in degrees instead of radians, set to true - * - * @return {number} The angle (in radians unless asDegrees is true) - */ - public angleBetweenMouse(a: Sprite, asDegrees?: bool): number; - } -} -/** * Phaser - Device * * Detects device support capabilities. Using some elements from System.js by MrDoob and Modernizr @@ -9843,13 +9370,6 @@ module Phaser { * @param [color] {number} color of the debug info to be rendered. (format is css color string) */ static renderSpriteInfo(sprite: Sprite, x: number, y: number, color?: string): void; - /** - * Render debug infos. (including name, bounds info, position and some other properties) - * @param x {number} X position of the debug info to be rendered. - * @param y {number} Y position of the debug info to be rendered. - * @param [color] {number} color of the debug info to be rendered. (format is css color string) - */ - static renderPhysicsBodyInfo(body: Physics.Body, x: number, y: number, color?: string): void; static renderSpriteBounds(sprite: Sprite, camera?: Camera, color?: string): void; static renderRectangle(rect: Rectangle, fillStyle?: string): void; static renderCircle(circle: Circle, fillStyle?: string): void; @@ -9860,7 +9380,6 @@ module Phaser { * @param [color] {number} color of the debug info to be rendered. (format is css color string) */ static renderText(text: string, x: number, y: number, color?: string): void; - static renderPhysicsBody(body: Physics.Body, lineWidth?: number, fillStyle?: string, sleepStyle?: string): void; } } /** @@ -9994,11 +9513,6 @@ module Phaser { */ public math: GameMath; /** - * Reference to the motion helper. - * @type {Motion} - */ - public motion: Motion; - /** * Reference to the network class. * @type {Net} */ @@ -10302,89 +9816,6 @@ module Phaser { } } /** -* Phaser - CircleUtils -* -* A collection of methods useful for manipulating and comparing Circle objects. -* -* TODO: -*/ -module Phaser { - class CircleUtils { - /** - * Returns a new Circle object with the same values for the x, y, width, and height properties as the original Circle object. - * @method clone - * @param {Circle} a - The Circle object. - * @param {Circle} [optional] out Optional Circle object. If given the values will be set into the object, otherwise a brand new Circle object will be created and returned. - * @return {Phaser.Circle} - **/ - static clone(a: Circle, out?: Circle): Circle; - /** - * Return true if the given x/y coordinates are within the Circle object. - * If you need details about the intersection then use Phaser.Intersect.circleContainsPoint instead. - * @method contains - * @param {Circle} a - The Circle object. - * @param {Number} The X value of the coordinate to test. - * @param {Number} The Y value of the coordinate to test. - * @return {Boolean} True if the coordinates are within this circle, otherwise false. - **/ - static contains(a: Circle, x: number, y: number): bool; - /** - * Return true if the coordinates of the given Point object are within this Circle object. - * If you need details about the intersection then use Phaser.Intersect.circleContainsPoint instead. - * @method containsPoint - * @param {Circle} a - The Circle object. - * @param {Point} The Point object to test. - * @return {Boolean} True if the coordinates are within this circle, otherwise false. - **/ - static containsPoint(a: Circle, point: Point): bool; - /** - * Return true if the given Circle is contained entirely within this Circle object. - * If you need details about the intersection then use Phaser.Intersect.circleToCircle instead. - * @method containsCircle - * @param {Circle} The Circle object to test. - * @return {Boolean} True if the coordinates are within this circle, otherwise false. - **/ - static containsCircle(a: Circle, b: Circle): bool; - /** - * Returns the distance from the center of the Circle object to the given object (can be Circle, Point or anything with x/y properties) - * @method distanceBetween - * @param {Circle} a - The Circle object. - * @param {Circle} b - The target object. Must have visible x and y properties that represent the center of the object. - * @param {Boolean} [optional] round - Round the distance to the nearest integer (default false) - * @return {Number} The distance between this Point object and the destination Point object. - **/ - static distanceBetween(a: Circle, target: any, round?: bool): number; - /** - * Determines whether the two Circle objects match. This method compares the x, y and diameter properties. - * @method equals - * @param {Circle} a - The first Circle object. - * @param {Circle} b - The second Circle object. - * @return {Boolean} A value of true if the object has exactly the same values for the x, y and diameter properties as this Circle object; otherwise false. - **/ - static equals(a: Circle, b: Circle): bool; - /** - * Determines whether the two Circle objects intersect. - * This method checks the radius distances between the two Circle objects to see if they intersect. - * @method intersects - * @param {Circle} a - The first Circle object. - * @param {Circle} b - The second Circle object. - * @return {Boolean} A value of true if the specified object intersects with this Circle object; otherwise false. - **/ - static intersects(a: Circle, b: Circle): bool; - /** - * Returns a Point object containing the coordinates of a point on the circumference of the Circle based on the given angle. - * @method circumferencePoint - * @param {Circle} a - The first Circle object. - * @param {Number} angle The angle in radians (unless asDegrees is true) to return the point from. - * @param {Boolean} asDegrees Is the given angle in radians (false) or degrees (true)? - * @param {Phaser.Point} [optional] output An optional Point object to put the result in to. If none specified a new Point object will be created. - * @return {Phaser.Point} The Point object holding the result. - **/ - static circumferencePoint(a: Circle, angle: number, asDegrees?: bool, out?: Point): Point; - static intersectsRectangle(c: Circle, r: Rectangle): bool; - } -} -/** * Phaser - Mat3Utils * * A collection of methods useful for manipulating and performing operations on Mat3 objects. @@ -10416,20 +9847,201 @@ module Phaser { static normalFromMat4(): void; } } -interface IPoint { - getDist(): number; -} -module Shapes { - class Point implements IPoint { - public x: number; - public y: number; - constructor(x: number, y: number); - public getDist(): number; - static origin: Point; +/** +* 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 angle: number; + public toString(): string; + 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 - Motion +* +* The Motion class contains lots of useful functions for moving game objects around in world space. +*/ +module Phaser { + class Motion { + constructor(game: Game); + public game: Game; + /** + * Given the angle and speed calculate the velocity and return it as a Point + * + * @param {number} angle The angle (in degrees) calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative) + * @param {number} speed The speed it will move, in pixels per second sq + * + * @return {Point} A Point where Point.x contains the velocity x value and Point.y contains the velocity y value + */ + public velocityFromAngle(angle: number, speed: number): Point; + /** + * Sets the source Sprite x/y velocity so it will move directly towards the destination Sprite at the speed given (in pixels per second)
+ * If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds.
+ * Timings are approximate due to the way Flash timers work, and irrespective of SWF frame rate. Allow for a variance of +- 50ms.
+ * The source object doesn't stop moving automatically should it ever reach the destination coordinates.
+ * If you need the object to accelerate, see accelerateTowardsObject() instead + * Note: Doesn't take into account acceleration, maxVelocity or drag (if you set drag or acceleration too high this object may not move at all) + * + * @param {Sprite} source The Sprite on which the velocity will be set + * @param {Sprite} dest The Sprite where the source object will move to + * @param {number} speed The speed it will move, in pixels per second (default is 60 pixels/sec) + * @param {number} maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms + */ + public moveTowardsObject(source: Sprite, dest: Sprite, speed?: number, maxTime?: number): void; + /** + * Sets the x/y acceleration on the source Sprite so it will move towards the destination Sprite at the speed given (in pixels per second)
+ * You must give a maximum speed value, beyond which the Sprite won't go any faster.
+ * If you don't need acceleration look at moveTowardsObject() instead. + * + * @param {Sprite} source The Sprite on which the acceleration will be set + * @param {Sprite} dest The Sprite where the source object will move towards + * @param {number} speed The speed it will accelerate in pixels per second + * @param {number} xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally + * @param {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically + */ + public accelerateTowardsObject(source: Sprite, dest: Sprite, speed: number, xSpeedMax: number, ySpeedMax: number): void; + /** + * Move the given Sprite towards the mouse pointer coordinates at a steady velocity + * If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds.
+ * Timings are approximate due to the way Flash timers work, and irrespective of SWF frame rate. Allow for a variance of +- 50ms.
+ * The source object doesn't stop moving automatically should it ever reach the destination coordinates.
+ * + * @param {Sprite} source The Sprite to move + * @param {number} speed The speed it will move, in pixels per second (default is 60 pixels/sec) + * @param {number} maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms + */ + public moveTowardsMouse(source: Sprite, speed?: number, maxTime?: number): void; + /** + * Sets the x/y acceleration on the source Sprite so it will move towards the mouse coordinates at the speed given (in pixels per second)
+ * You must give a maximum speed value, beyond which the Sprite won't go any faster.
+ * If you don't need acceleration look at moveTowardsMouse() instead. + * + * @param {Sprite} source The Sprite on which the acceleration will be set + * @param {number} speed The speed it will accelerate in pixels per second + * @param {number} xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally + * @param {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically + */ + public accelerateTowardsMouse(source: Sprite, speed: number, xSpeedMax: number, ySpeedMax: number): void; + /** + * Sets the x/y velocity on the source Sprite so it will move towards the target coordinates at the speed given (in pixels per second)
+ * If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds.
+ * Timings are approximate due to the way Flash timers work, and irrespective of SWF frame rate. Allow for a variance of +- 50ms.
+ * The source object doesn't stop moving automatically should it ever reach the destination coordinates.
+ * + * @param {Sprite} source The Sprite to move + * @param {Point} target The Point coordinates to move the source Sprite towards + * @param {number} speed The speed it will move, in pixels per second (default is 60 pixels/sec) + * @param {number} maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms + */ + public moveTowardsPoint(source: Sprite, target: Point, speed?: number, maxTime?: number): void; + /** + * Sets the x/y acceleration on the source Sprite so it will move towards the target coordinates at the speed given (in pixels per second)
+ * You must give a maximum speed value, beyond which the Sprite won't go any faster.
+ * If you don't need acceleration look at moveTowardsPoint() instead. + * + * @param {Sprite} source The Sprite on which the acceleration will be set + * @param {Point} target The Point coordinates to move the source Sprite towards + * @param {number} speed The speed it will accelerate in pixels per second + * @param {number} xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally + * @param {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically + */ + public accelerateTowardsPoint(source: Sprite, target: Point, speed: number, xSpeedMax: number, ySpeedMax: number): void; + /** + * Find the distance between two Sprites, taking their origin into account + * + * @param {Sprite} a The first Sprite + * @param {Sprite} b The second Sprite + * @return {number} int Distance (in pixels) + */ + public distanceBetween(a: Sprite, b: Sprite): number; + /** + * Find the distance from an Sprite to the given Point, taking the source origin into account + * + * @param {Sprite} a The Sprite + * @param {Point} target The Point + * @return {number} Distance (in pixels) + */ + public distanceToPoint(a: Sprite, target: Point): number; + /** + * Find the distance (in pixels, rounded) from the object x/y and the mouse x/y + * + * @param {Sprite} a Sprite to test against + * @return {number} The distance between the given sprite and the mouse coordinates + */ + public distanceToMouse(a: Sprite): number; + /** + * Find the angle (in radians) between an Sprite and an Point. The source sprite takes its x/y and origin into account. + * The angle is calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative) + * + * @param {Sprite} a The Sprite to test from + * @param {Point} target The Point to angle the Sprite towards + * @param {boolean} asDegrees If you need the value in degrees instead of radians, set to true + * + * @return {number} The angle (in radians unless asDegrees is true) + */ + public angleBetweenPoint(a: Sprite, target: Point, asDegrees?: bool): number; + /** + * Find the angle (in radians) between the two Sprite, taking their x/y and origin into account. + * The angle is calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative) + * + * @param {Sprite} a The Sprite to test from + * @param {Sprite} b The Sprite to test to + * @param {boolean} asDegrees If you need the value in degrees instead of radians, set to true + * + * @return {number} The angle (in radians unless asDegrees is true) + */ + public angleBetween(a: Sprite, b: Sprite, asDegrees?: bool): number; + /** + * Given the Sprite and speed calculate the velocity and return it as an Point based on the direction the sprite is facing + * + * @param {Sprite} parent The Sprite to get the facing value from + * @param {number} speed The speed it will move, in pixels per second sq + * + * @return {Point} An Point where Point.x contains the velocity x value and Point.y contains the velocity y value + */ + public velocityFromFacing(parent: Sprite, speed: number): Point; + /** + * Find the angle (in radians) between an Sprite and the mouse, taking their x/y and origin into account. + * The angle is calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative) + * + * @param {Sprite} a The Object to test from + * @param {boolean} asDegrees If you need the value in degrees instead of radians, set to true + * + * @return {number} The angle (in radians unless asDegrees is true) + */ + public angleBetweenMouse(a: Sprite, asDegrees?: bool): number; } } -var p: IPoint; -var dist: number; /** * Phaser - PixelUtils * @@ -10564,11 +10176,6 @@ module Phaser { */ public math: GameMath; /** - * Reference to the motion helper. - * @type {Motion} - */ - public motion: Motion; - /** * Reference to the sound manager. * @type {SoundManager} */ diff --git a/build/phaser.js b/build/phaser.js index 4bcb2159..007bfa83 100644 --- a/build/phaser.js +++ b/build/phaser.js @@ -4322,2855 +4322,1348 @@ var Phaser; */ })(Phaser || (Phaser = {})); /// -/// -/** -* Phaser - 2D Transform -* -* A 2D Transform -*/ -var Phaser; -(function (Phaser) { - var Transform = (function () { - /** - * Creates a new 2D Transform object. - * @class Transform - * @constructor - * @return {Transform} This object - **/ - function Transform(pos, angle) { - this.t = Phaser.Vec2Utils.clone(pos); - this.c = Math.cos(angle); - this.s = Math.sin(angle); - this.angle = angle; - } - Transform.prototype.toString = function () { - return 't=' + this.t.toString() + ' c=' + this.c + ' s=' + this.s + ' a=' + this.angle; - }; - Transform.prototype.setTo = function (pos, angle) { - this.t.copyFrom(pos); - this.c = Math.cos(angle); - this.s = Math.sin(angle); - return this; - }; - Transform.prototype.setRotation = function (angle) { - if(angle !== this.angle) { - this.c = Math.cos(angle); - this.s = Math.sin(angle); - this.angle = angle; - } - return this; - }; - Transform.prototype.setPosition = function (p) { - this.t.copyFrom(p); - return this; - }; - Transform.prototype.identity = function () { - this.t.setTo(0, 0); - this.c = 1; - this.s = 0; - return this; - }; - return Transform; - })(); - Phaser.Transform = Transform; -})(Phaser || (Phaser = {})); -/// -/// -/// -/** -* Phaser - TransformUtils -* -* A collection of methods useful for manipulating and performing operations on 2D Transforms. -* -*/ -var Phaser; -(function (Phaser) { - var TransformUtils = (function () { - function TransformUtils() { } - TransformUtils.rotate = function rotate(t, v, out) { - if (typeof out === "undefined") { out = new Phaser.Vec2(); } - //return new vec2(v.x * this.c - v.y * this.s, v.x * this.s + v.y * this.c); - return out.setTo(v.x * t.c - v.y * t.s, v.x * t.s + v.y * t.c); - }; - TransformUtils.unrotate = function unrotate(t, v, out) { - if (typeof out === "undefined") { out = new Phaser.Vec2(); } - //return new vec2(v.x * this.c + v.y * this.s, -v.x * this.s + v.y * this.c); - return out.setTo(v.x * t.c + v.y * t.s, -v.x * t.s + v.y * t.c); - }; - TransformUtils.transform = function transform(t, v, out) { - if (typeof out === "undefined") { out = new Phaser.Vec2(); } - //return new vec2(v.x * this.c - v.y * this.s + this.t.x, v.x * this.s + v.y * this.c + this.t.y); - 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); - }; - TransformUtils.untransform = function untransform(t, v, out) { - if (typeof out === "undefined") { out = new Phaser.Vec2(); } - var px = v.x - t.t.x; - var py = v.y - t.t.y; - //return new vec2(px * this.c + py * this.s, -px * this.s + py * this.c); - return out.setTo(px * t.c + py * t.s, -px * t.s + py * t.c); - }; - return TransformUtils; - })(); - Phaser.TransformUtils = TransformUtils; -})(Phaser || (Phaser = {})); -/// /// /// /// -/// /** -* Phaser - BodyUtils +* Phaser - CircleUtils * -* A collection of methods useful for manipulating AdvancedPhysics Body objects. +* A collection of methods useful for manipulating and comparing Circle objects. +* +* TODO: */ var Phaser; (function (Phaser) { - var BodyUtils = (function () { - function BodyUtils() { } - BodyUtils.duplicate = function duplicate(source, output) { - /* - console.log('body duplicate called'); + var CircleUtils = (function () { + function CircleUtils() { } + CircleUtils.clone = /** + * Returns a new Circle object with the same values for the x, y, width, and height properties as the original Circle object. + * @method clone + * @param {Circle} a - The Circle object. + * @param {Circle} [optional] out Optional Circle object. If given the values will be set into the object, otherwise a brand new Circle object will be created and returned. + * @return {Phaser.Circle} + **/ + function clone(a, out) { + if (typeof out === "undefined") { out = new Phaser.Circle(); } + return out.setTo(a.x, a.y, a.diameter); + }; + CircleUtils.contains = /** + * Return true if the given x/y coordinates are within the Circle object. + * If you need details about the intersection then use Phaser.Intersect.circleContainsPoint instead. + * @method contains + * @param {Circle} a - The Circle object. + * @param {Number} The X value of the coordinate to test. + * @param {Number} The Y value of the coordinate to test. + * @return {Boolean} True if the coordinates are within this circle, otherwise false. + **/ + function contains(a, x, y) { + // Check if x/y are within the bounds first + if(x >= a.left && x <= a.right && y >= a.top && y <= a.bottom) { + var dx = (a.x - x) * (a.x - x); + var dy = (a.y - y) * (a.y - y); + return (dx + dy) <= (a.radius * a.radius); + } + return false; + }; + CircleUtils.containsPoint = /** + * Return true if the coordinates of the given Point object are within this Circle object. + * If you need details about the intersection then use Phaser.Intersect.circleContainsPoint instead. + * @method containsPoint + * @param {Circle} a - The Circle object. + * @param {Point} The Point object to test. + * @return {Boolean} True if the coordinates are within this circle, otherwise false. + **/ + function containsPoint(a, point) { + return CircleUtils.contains(a, point.x, point.y); + }; + CircleUtils.containsCircle = /** + * Return true if the given Circle is contained entirely within this Circle object. + * If you need details about the intersection then use Phaser.Intersect.circleToCircle instead. + * @method containsCircle + * @param {Circle} The Circle object to test. + * @return {Boolean} True if the coordinates are within this circle, otherwise false. + **/ + function containsCircle(a, b) { + //return ((a.radius + b.radius) * (a.radius + b.radius)) >= Collision.distanceSquared(a.x, a.y, b.x, b.y); + return true; + }; + CircleUtils.distanceBetween = /** + * Returns the distance from the center of the Circle object to the given object (can be Circle, Point or anything with x/y properties) + * @method distanceBetween + * @param {Circle} a - The Circle object. + * @param {Circle} b - The target object. Must have visible x and y properties that represent the center of the object. + * @param {Boolean} [optional] round - Round the distance to the nearest integer (default false) + * @return {Number} The distance between this Point object and the destination Point object. + **/ + function distanceBetween(a, target, round) { + if (typeof round === "undefined") { round = false; } + var dx = a.x - target.x; + var dy = a.y - target.y; + if(round === true) { + return Math.round(Math.sqrt(dx * dx + dy * dy)); + } else { + return Math.sqrt(dx * dx + dy * dy); + } + }; + CircleUtils.equals = /** + * Determines whether the two Circle objects match. This method compares the x, y and diameter properties. + * @method equals + * @param {Circle} a - The first Circle object. + * @param {Circle} b - The second Circle object. + * @return {Boolean} A value of true if the object has exactly the same values for the x, y and diameter properties as this Circle object; otherwise false. + **/ + function equals(a, b) { + return (a.x == b.x && a.y == b.y && a.diameter == b.diameter); + }; + CircleUtils.intersects = /** + * Determines whether the two Circle objects intersect. + * This method checks the radius distances between the two Circle objects to see if they intersect. + * @method intersects + * @param {Circle} a - The first Circle object. + * @param {Circle} b - The second Circle object. + * @return {Boolean} A value of true if the specified object intersects with this Circle object; otherwise false. + **/ + function intersects(a, b) { + return (CircleUtils.distanceBetween(a, b) <= (a.radius + b.radius)); + }; + CircleUtils.circumferencePoint = /** + * Returns a Point object containing the coordinates of a point on the circumference of the Circle based on the given angle. + * @method circumferencePoint + * @param {Circle} a - The first Circle object. + * @param {Number} angle The angle in radians (unless asDegrees is true) to return the point from. + * @param {Boolean} asDegrees Is the given angle in radians (false) or degrees (true)? + * @param {Phaser.Point} [optional] output An optional Point object to put the result in to. If none specified a new Point object will be created. + * @return {Phaser.Point} The Point object holding the result. + **/ + function circumferencePoint(a, angle, asDegrees, out) { + if (typeof asDegrees === "undefined") { asDegrees = false; } + if (typeof out === "undefined") { out = new Phaser.Point(); } + if(asDegrees === true) { + angle = angle * Phaser.GameMath.DEG_TO_RAD; + } + return out.setTo(a.x + a.radius * Math.cos(angle), a.y + a.radius * Math.sin(angle)); + }; + CircleUtils.intersectsRectangle = /* + public static boolean intersect(Rectangle r, Circle c) + { + float cx = Math.abs(c.x - r.x - r.halfWidth); + float xDist = r.halfWidth + c.radius; + if (cx > xDist) + return false; + float cy = Math.abs(c.y - r.y - r.halfHeight); + float yDist = r.halfHeight + c.radius; + if (cy > yDist) + return false; + if (cx <= r.halfWidth || cy <= r.halfHeight) + return true; + float xCornerDist = cx - r.halfWidth; + float yCornerDist = cy - r.halfHeight; + float xCornerDistSq = xCornerDist * xCornerDist; + float yCornerDistSq = yCornerDist * yCornerDist; + float maxCornerDistSq = c.radius * c.radius; + return xCornerDistSq + yCornerDistSq <= maxCornerDistSq; + } + */ + function intersectsRectangle(c, r) { + var cx = Math.abs(c.x - r.x - r.halfWidth); + var xDist = r.halfWidth + c.radius; + if(cx > xDist) { + return false; + } + var cy = Math.abs(c.y - r.y - r.halfHeight); + var yDist = r.halfHeight + c.radius; + if(cy > yDist) { + return false; + } + if(cx <= r.halfWidth || cy <= r.halfHeight) { + return true; + } + var xCornerDist = cx - r.halfWidth; + var yCornerDist = cy - r.halfHeight; + var xCornerDistSq = xCornerDist * xCornerDist; + var yCornerDistSq = yCornerDist * yCornerDist; + var maxCornerDistSq = c.radius * c.radius; + return xCornerDistSq + yCornerDistSq <= maxCornerDistSq; + }; + return CircleUtils; + })(); + Phaser.CircleUtils = CircleUtils; +})(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + /// + /// + /// + /// + /// + /** + * Phaser - ArcadePhysics Manager + * + */ + (function (Physics) { + var ArcadePhysics = (function () { + function ArcadePhysics(game, width, height) { + this._length = 0; + /** + * @type {number} + */ + this.worldDivisions = 6; + this.game = game; + this.gravity = new Phaser.Vec2(); + this.drag = new Phaser.Vec2(); + this.bounce = new Phaser.Vec2(); + this.angularDrag = 0; + this.bounds = new Phaser.Rectangle(0, 0, width, height); + this._distance = new Phaser.Vec2(); + this._tangent = new Phaser.Vec2(); + //this.members = new Group(game); + } + ArcadePhysics.OVERLAP_BIAS = 4; + ArcadePhysics.TILE_OVERLAP = false; + ArcadePhysics.prototype.updateMotion = /* + public update() { - var newBody = new Phaser.Physics.Body(source.type, source.transform.t, source.rotation); + this._length = this._objects.length; - for (var i = 0; i < source.shapes.length; i++) + for (var i = 0; i < this._length; i++) { - output.addShape(source.shapes[i].duplicate()); + if (this._objects[i]) + { + this._objects[i].preUpdate(); + this.updateMotion(this._objects[i]); + this.collideWorld(this._objects[i]); + + for (var x = 0; x < this._length; x++) + { + if (this._objects[x] && this._objects[x] !== this._objects[i]) + { + //this.collideShapes(this._objects[i], this._objects[x]); + var r = this.NEWseparate(this._objects[i], this._objects[x]); + //console.log('sep', r); + } } - output.resetMassData(); + } + } + + } + + public render() { + + // iterate through the objects here, updating and colliding + for (var i = 0; i < this._length; i++) + { + if (this._objects[i]) + { + this._objects[i].render(this.game.stage.context); + } + } + + } */ - return output; - }; - BodyUtils.addPoly = function addPoly(body, verts, elasticity, friction, density) { - if (typeof elasticity === "undefined") { elasticity = 1; } - if (typeof friction === "undefined") { friction = 1; } - if (typeof density === "undefined") { density = 1; } - var poly = new Phaser.Physics.Shapes.Poly(verts); - poly.elasticity = elasticity; - poly.friction = friction; - poly.density = density; - body.addShape(poly); - body.resetMassData(); - return poly; - }; - BodyUtils.addTriangle = function addTriangle(body, x1, y1, x2, y2, x3, y3, elasticity, friction, density) { - if (typeof elasticity === "undefined") { elasticity = 1; } - if (typeof friction === "undefined") { friction = 1; } - if (typeof density === "undefined") { density = 1; } - var tri = new Phaser.Physics.Shapes.Triangle(x1, y1, x2, y2, x3, y3); - tri.elasticity = elasticity; - tri.friction = friction; - tri.density = density; - body.addShape(tri); - body.resetMassData(); - return tri; - }; - BodyUtils.addBox = function addBox(body, x, y, width, height, elasticity, friction, density) { - if (typeof elasticity === "undefined") { elasticity = 1; } - if (typeof friction === "undefined") { friction = 1; } - if (typeof density === "undefined") { density = 1; } - var box = new Phaser.Physics.Shapes.Box(x, y, width, height); - box.elasticity = elasticity; - box.friction = friction; - box.density = density; - body.addShape(box); - body.resetMassData(); - return box; - }; - BodyUtils.addCircle = function addCircle(body, radius, x, y, elasticity, friction, density) { - if (typeof x === "undefined") { x = 0; } - if (typeof y === "undefined") { y = 0; } - if (typeof elasticity === "undefined") { elasticity = 1; } - if (typeof friction === "undefined") { friction = 1; } - if (typeof density === "undefined") { density = 1; } - var circle = new Phaser.Physics.Shapes.Circle(radius, x, y); - circle.elasticity = elasticity; - circle.friction = friction; - circle.density = density; - body.addShape(circle); - body.resetMassData(); - return circle; - }; - return BodyUtils; - })(); - Phaser.BodyUtils = BodyUtils; + function (body) { + if(body.type == Phaser.Types.BODY_DISABLED) { + return; + } + this._velocityDelta = (this.computeVelocity(body.angularVelocity, body.gravity.x, body.angularAcceleration, body.angularDrag, body.maxAngular) - body.angularVelocity) / 2; + body.angularVelocity += this._velocityDelta; + body.sprite.transform.rotation += body.angularVelocity * this.game.time.elapsed; + body.angularVelocity += this._velocityDelta; + this._velocityDelta = (this.computeVelocity(body.velocity.x, body.gravity.x, body.acceleration.x, body.drag.x) - body.velocity.x) / 2; + body.velocity.x += this._velocityDelta; + this._delta = body.velocity.x * this.game.time.elapsed; + body.velocity.x += this._velocityDelta; + //body.position.x += this._delta; + body.sprite.x += this._delta; + this._velocityDelta = (this.computeVelocity(body.velocity.y, body.gravity.y, body.acceleration.y, body.drag.y) - body.velocity.y) / 2; + body.velocity.y += this._velocityDelta; + this._delta = body.velocity.y * this.game.time.elapsed; + body.velocity.y += this._velocityDelta; + //body.position.y += this._delta; + body.sprite.y += this._delta; + }; + ArcadePhysics.prototype.computeVelocity = /** + * 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. + */ + function (velocity, gravity, acceleration, drag, max) { + if (typeof gravity === "undefined") { gravity = 0; } + if (typeof acceleration === "undefined") { acceleration = 0; } + if (typeof drag === "undefined") { drag = 0; } + if (typeof max === "undefined") { max = 10000; } + if(acceleration !== 0) { + velocity += (acceleration + gravity) * this.game.time.elapsed; + } else if(drag !== 0) { + this._drag = drag * this.game.time.elapsed; + if(velocity - this._drag > 0) { + velocity = velocity - this._drag; + } else if(velocity + this._drag < 0) { + velocity += this._drag; + } else { + velocity = 0; + } + velocity += gravity; + } + if((velocity != 0) && (max != 10000)) { + if(velocity > max) { + velocity = max; + } else if(velocity < -max) { + velocity = -max; + } + } + return velocity; + }; + ArcadePhysics.prototype.separate = /** + * 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. + */ + function (body1, body2) { + this._separatedX = this.separateBodyX(body1, body2); + this._separatedY = this.separateBodyY(body1, body2); + return this._separatedX || this._separatedY; + }; + ArcadePhysics.prototype.checkHullIntersection = function (body1, body2) { + return ((body1.hullX + body1.hullWidth > body2.hullX) && (body1.hullX < body2.hullX + body2.hullWidth) && (body1.hullY + body1.hullHeight > body2.hullY) && (body1.hullY < body2.hullY + body2.hullHeight)); + }; + ArcadePhysics.prototype.separateBodyX = /** + * 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. + */ + function (body1, body2) { + // Can't separate two disabled or static objects + if((body1.type == Phaser.Types.BODY_DISABLED || body1.type == Phaser.Types.BODY_STATIC) && (body2.type == Phaser.Types.BODY_DISABLED || body2.type == Phaser.Types.BODY_STATIC)) { + return false; + } + // First, get the two object deltas + this._overlap = 0; + if(body1.deltaX != body2.deltaX) { + if(Phaser.RectangleUtils.intersects(body1.bounds, body2.bounds)) { + this._maxOverlap = body1.deltaXAbs + body2.deltaXAbs + ArcadePhysics.OVERLAP_BIAS; + // If they did overlap (and can), figure out by how much and flip the corresponding flags + if(body1.deltaX > body2.deltaX) { + this._overlap = body1.bounds.right - body2.bounds.x; + if((this._overlap > this._maxOverlap) || !(body1.allowCollisions & Phaser.Types.RIGHT) || !(body2.allowCollisions & Phaser.Types.LEFT)) { + this._overlap = 0; + } else { + body1.touching |= Phaser.Types.RIGHT; + body2.touching |= Phaser.Types.LEFT; + } + } else if(body1.deltaX < body2.deltaX) { + this._overlap = body1.bounds.x - body2.bounds.width - body2.bounds.x; + if((-this._overlap > this._maxOverlap) || !(body1.allowCollisions & Phaser.Types.LEFT) || !(body2.allowCollisions & Phaser.Types.RIGHT)) { + this._overlap = 0; + } else { + body1.touching |= Phaser.Types.LEFT; + body2.touching |= Phaser.Types.RIGHT; + } + } + } + } + // Then adjust their positions and velocities accordingly (if there was any overlap) + if(this._overlap != 0) { + this._obj1Velocity = body1.velocity.x; + this._obj2Velocity = body2.velocity.x; + /** + * 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 + */ + // 2 dynamic bodies will exchange velocities + if(body1.type == Phaser.Types.BODY_DYNAMIC && body2.type == Phaser.Types.BODY_DYNAMIC) { + this._overlap *= 0.5; + body1.position.x = body1.position.x - this._overlap; + body2.position.x += this._overlap; + this._obj1NewVelocity = Math.sqrt((this._obj2Velocity * this._obj2Velocity * body2.mass) / body1.mass) * ((this._obj2Velocity > 0) ? 1 : -1); + this._obj2NewVelocity = Math.sqrt((this._obj1Velocity * this._obj1Velocity * body1.mass) / body2.mass) * ((this._obj1Velocity > 0) ? 1 : -1); + this._average = (this._obj1NewVelocity + this._obj2NewVelocity) * 0.5; + this._obj1NewVelocity -= this._average; + this._obj2NewVelocity -= this._average; + body1.velocity.x = this._average + this._obj1NewVelocity * body1.bounce.x; + body2.velocity.x = this._average + this._obj2NewVelocity * body2.bounce.x; + } else if(body2.type != Phaser.Types.BODY_DYNAMIC) { + // Body 2 is Static or Kinematic + this._overlap *= 2; + body1.position.x -= this._overlap; + body1.velocity.x = this._obj2Velocity - this._obj1Velocity * body1.bounce.x; + } else if(body1.type != Phaser.Types.BODY_DYNAMIC) { + // Body 1 is Static or Kinematic + this._overlap *= 2; + body2.position.x += this._overlap; + body2.velocity.x = this._obj1Velocity - this._obj2Velocity * body2.bounce.x; + } + return true; + } else { + return false; + } + }; + ArcadePhysics.prototype.separateBodyY = /** + * 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. + */ + function (body1, body2) { + // Can't separate two immovable objects + if((body1.type == Phaser.Types.BODY_DISABLED || body1.type == Phaser.Types.BODY_STATIC) && (body2.type == Phaser.Types.BODY_DISABLED || body2.type == Phaser.Types.BODY_STATIC)) { + return false; + } + // First, get the two object deltas + this._overlap = 0; + if(body1.deltaY != body2.deltaY) { + if(Phaser.RectangleUtils.intersects(body1.bounds, body2.bounds)) { + // This is the only place to use the DeltaAbs values + this._maxOverlap = body1.deltaYAbs + body2.deltaYAbs + ArcadePhysics.OVERLAP_BIAS; + // If they did overlap (and can), figure out by how much and flip the corresponding flags + if(body1.deltaY > body2.deltaY) { + this._overlap = body1.bounds.bottom - body2.bounds.y; + if((this._overlap > this._maxOverlap) || !(body1.allowCollisions & Phaser.Types.DOWN) || !(body2.allowCollisions & Phaser.Types.UP)) { + this._overlap = 0; + } else { + body1.touching |= Phaser.Types.DOWN; + body2.touching |= Phaser.Types.UP; + } + } else if(body1.deltaY < body2.deltaY) { + this._overlap = body1.bounds.y - body2.bounds.height - body2.bounds.y; + if((-this._overlap > this._maxOverlap) || !(body1.allowCollisions & Phaser.Types.UP) || !(body2.allowCollisions & Phaser.Types.DOWN)) { + this._overlap = 0; + } else { + body1.touching |= Phaser.Types.UP; + body2.touching |= Phaser.Types.DOWN; + } + } + } + } + // Then adjust their positions and velocities accordingly (if there was any overlap) + if(this._overlap != 0) { + this._obj1Velocity = body1.velocity.y; + this._obj2Velocity = body2.velocity.y; + /** + * 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 + */ + if(body1.type == Phaser.Types.BODY_DYNAMIC && body2.type == Phaser.Types.BODY_DYNAMIC) { + this._overlap *= 0.5; + body1.position.y = body1.position.y - this._overlap; + body2.position.y += this._overlap; + this._obj1NewVelocity = Math.sqrt((this._obj2Velocity * this._obj2Velocity * body2.mass) / body1.mass) * ((this._obj2Velocity > 0) ? 1 : -1); + this._obj2NewVelocity = Math.sqrt((this._obj1Velocity * this._obj1Velocity * body1.mass) / body2.mass) * ((this._obj1Velocity > 0) ? 1 : -1); + var average = (this._obj1NewVelocity + this._obj2NewVelocity) * 0.5; + this._obj1NewVelocity -= average; + this._obj2NewVelocity -= average; + body1.velocity.y = average + this._obj1NewVelocity * body1.bounce.y; + body2.velocity.y = average + this._obj2NewVelocity * body2.bounce.y; + } else if(body2.type != Phaser.Types.BODY_DYNAMIC) { + this._overlap *= 2; + body1.position.y -= this._overlap; + body1.velocity.y = this._obj2Velocity - this._obj1Velocity * body1.bounce.y; + // This is special case code that handles things like horizontal moving platforms you can ride + //if (body2.parent.active && body2.moves && (body1.deltaY > body2.deltaY)) + if(body2.sprite.active && (body1.deltaY > body2.deltaY)) { + body1.position.x += body2.position.x - body2.oldPosition.x; + } + } else if(body1.type != Phaser.Types.BODY_DYNAMIC) { + this._overlap *= 2; + body2.position.y += this._overlap; + body2.velocity.y = this._obj1Velocity - this._obj2Velocity * body2.bounce.y; + // This is special case code that handles things like horizontal moving platforms you can ride + //if (object1.active && body1.moves && (body1.deltaY < body2.deltaY)) + if(body1.sprite.active && (body1.deltaY < body2.deltaY)) { + body2.position.x += body1.position.x - body1.oldPosition.x; + } + } + return true; + } else { + return false; + } + }; + ArcadePhysics.prototype.overlap = /* + private TILEseparate(shapeA: IPhysicsShape, shapeB: IPhysicsShape, distance: Vec2, tangent: Vec2) { + + if (tangent.x == 1) + { + console.log('1 The left side of ShapeA hit the right side of ShapeB', Math.floor(distance.x)); + shapeA.physics.touching |= Phaser.Types.LEFT; + shapeB.physics.touching |= Phaser.Types.RIGHT; + } + else if (tangent.x == -1) + { + console.log('2 The right side of ShapeA hit the left side of ShapeB', Math.floor(distance.x)); + shapeA.physics.touching |= Phaser.Types.RIGHT; + shapeB.physics.touching |= Phaser.Types.LEFT; + } + + if (tangent.y == 1) + { + console.log('3 The top of ShapeA hit the bottom of ShapeB', Math.floor(distance.y)); + shapeA.physics.touching |= Phaser.Types.UP; + shapeB.physics.touching |= Phaser.Types.DOWN; + } + else if (tangent.y == -1) + { + console.log('4 The bottom of ShapeA hit the top of ShapeB', Math.floor(distance.y)); + shapeA.physics.touching |= Phaser.Types.DOWN; + shapeB.physics.touching |= Phaser.Types.UP; + } + + + // only apply collision response forces if the object is travelling into, and not out of, the collision + var dot = Vec2Utils.dot(shapeA.physics.velocity, tangent); + + if (dot < 0) + { + console.log('in to', dot); + + // Apply horizontal bounce + if (shapeA.physics.bounce.x > 0) + { + shapeA.physics.velocity.x *= -(shapeA.physics.bounce.x); + } + else + { + shapeA.physics.velocity.x = 0; + } + // Apply horizontal bounce + if (shapeA.physics.bounce.y > 0) + { + shapeA.physics.velocity.y *= -(shapeA.physics.bounce.y); + } + else + { + shapeA.physics.velocity.y = 0; + } + } + else + { + console.log('out of', dot); + } + + shapeA.position.x += Math.floor(distance.x); + //shapeA.bounds.x += Math.floor(distance.x); + + shapeA.position.y += Math.floor(distance.y); + //shapeA.bounds.y += distance.y; + + console.log('------------------------------------------------'); + + } + + private collideWorld(shape:IPhysicsShape) { + + // Collide on the x-axis + this._distance.x = shape.world.bounds.x - (shape.position.x - shape.bounds.halfWidth); + + if (0 < this._distance.x) + { + // Hit Left + this._tangent.setTo(1, 0); + this.separateXWall(shape, this._distance, this._tangent); + } + else + { + this._distance.x = (shape.position.x + shape.bounds.halfWidth) - shape.world.bounds.right; + + if (0 < this._distance.x) + { + // Hit Right + this._tangent.setTo(-1, 0); + this._distance.reverse(); + this.separateXWall(shape, this._distance, this._tangent); + } + } + + // Collide on the y-axis + this._distance.y = shape.world.bounds.y - (shape.position.y - shape.bounds.halfHeight); + + if (0 < this._distance.y) + { + // Hit Top + this._tangent.setTo(0, 1); + this.separateYWall(shape, this._distance, this._tangent); + } + else + { + this._distance.y = (shape.position.y + shape.bounds.halfHeight) - shape.world.bounds.bottom; + + if (0 < this._distance.y) + { + // Hit Bottom + this._tangent.setTo(0, -1); + this._distance.reverse(); + this.separateYWall(shape, this._distance, this._tangent); + } + } + + } + + private separateX(shapeA: IPhysicsShape, shapeB: IPhysicsShape, distance: Vec2, tangent: Vec2) { + + if (tangent.x == 1) + { + console.log('The left side of ShapeA hit the right side of ShapeB', distance.x); + shapeA.physics.touching |= Phaser.Types.LEFT; + shapeB.physics.touching |= Phaser.Types.RIGHT; + } + else + { + console.log('The right side of ShapeA hit the left side of ShapeB', distance.x); + shapeA.physics.touching |= Phaser.Types.RIGHT; + shapeB.physics.touching |= Phaser.Types.LEFT; + } + + // collision edges + //shapeA.oH = tangent.x; + + // only apply collision response forces if the object is travelling into, and not out of, the collision + if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) + { + // Apply horizontal bounce + if (shapeA.physics.bounce.x > 0) + { + shapeA.physics.velocity.x *= -(shapeA.physics.bounce.x); + } + else + { + shapeA.physics.velocity.x = 0; + } + } + + shapeA.position.x += distance.x; + shapeA.bounds.x += distance.x; + + } + + private separateY(shapeA: IPhysicsShape, shapeB: IPhysicsShape, distance: Vec2, tangent: Vec2) { + + if (tangent.y == 1) + { + console.log('The top of ShapeA hit the bottom of ShapeB', distance.y); + shapeA.physics.touching |= Phaser.Types.UP; + shapeB.physics.touching |= Phaser.Types.DOWN; + } + else + { + console.log('The bottom of ShapeA hit the top of ShapeB', distance.y); + shapeA.physics.touching |= Phaser.Types.DOWN; + shapeB.physics.touching |= Phaser.Types.UP; + } + + // collision edges + //shapeA.oV = tangent.y; + + // only apply collision response forces if the object is travelling into, and not out of, the collision + if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) + { + // Apply horizontal bounce + if (shapeA.physics.bounce.y > 0) + { + shapeA.physics.velocity.y *= -(shapeA.physics.bounce.y); + } + else + { + shapeA.physics.velocity.y = 0; + } + } + + shapeA.position.y += distance.y; + shapeA.bounds.y += distance.y; + + } + + private separateXWall(shapeA: IPhysicsShape, distance: Vec2, tangent: Vec2) { + + if (tangent.x == 1) + { + console.log('The left side of ShapeA hit the right side of ShapeB', distance.x); + shapeA.physics.touching |= Phaser.Types.LEFT; + } + else + { + console.log('The right side of ShapeA hit the left side of ShapeB', distance.x); + shapeA.physics.touching |= Phaser.Types.RIGHT; + } + + // collision edges + //shapeA.oH = tangent.x; + + // only apply collision response forces if the object is travelling into, and not out of, the collision + if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) + { + // Apply horizontal bounce + if (shapeA.physics.bounce.x > 0) + { + shapeA.physics.velocity.x *= -(shapeA.physics.bounce.x); + } + else + { + shapeA.physics.velocity.x = 0; + } + } + + shapeA.position.x += distance.x; + + } + + private separateYWall(shapeA: IPhysicsShape, distance: Vec2, tangent: Vec2) { + + if (tangent.y == 1) + { + console.log('The top of ShapeA hit the bottom of ShapeB', distance.y); + shapeA.physics.touching |= Phaser.Types.UP; + } + else + { + console.log('The bottom of ShapeA hit the top of ShapeB', distance.y); + shapeA.physics.touching |= Phaser.Types.DOWN; + } + + // collision edges + //shapeA.oV = tangent.y; + + // only apply collision response forces if the object is travelling into, and not out of, the collision + if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) + { + // Apply horizontal bounce + if (shapeA.physics.bounce.y > 0) + { + shapeA.physics.velocity.y *= -(shapeA.physics.bounce.y); + } + else + { + shapeA.physics.velocity.y = 0; + } + } + + shapeA.position.y += distance.y; + + } + */ + /** + * 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. + */ + function (object1, object2, notifyCallback, processCallback, context) { + if (typeof object1 === "undefined") { object1 = null; } + if (typeof object2 === "undefined") { object2 = null; } + if (typeof notifyCallback === "undefined") { notifyCallback = null; } + if (typeof processCallback === "undefined") { processCallback = null; } + if (typeof context === "undefined") { context = null; } + /* + if (object1 == null) + { + object1 = this.game.world.group; + } + + if (object2 == object1) + { + object2 = null; + } + + QuadTree.divisions = this.worldDivisions; + + this._quadTree = new Phaser.QuadTree(this, this.bounds.x, this.bounds.y, this.bounds.width, this.bounds.height); + + this._quadTree.load(object1, object2, notifyCallback, processCallback, context); + + this._quadTreeResult = this._quadTree.execute(); + + console.log('over', this._quadTreeResult); + + this._quadTree.destroy(); + + this._quadTree = null; + + return this._quadTreeResult; + */ + return false; + }; + ArcadePhysics.prototype.separateTile = /** + * 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 + */ + function (object, x, y, width, height, mass, collideLeft, collideRight, collideUp, collideDown, separateX, separateY) { + //var separatedX: bool = this.separateTileX(object, x, y, width, height, mass, collideLeft, collideRight, separateX); + //var separatedY: bool = this.separateTileY(object, x, y, width, height, mass, collideUp, collideDown, separateY); + //return separatedX || separatedY; + return false; + }; + return ArcadePhysics; + })(); + Physics.ArcadePhysics = ArcadePhysics; + /** + * Separates the two objects on their x axis + * @param object The GameObject to separate + * @param tile The Tile to separate + * @returns {boolean} Whether the objects in fact touched and were separated along the X axis. + */ + /* + public separateTileX(object:Sprite, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool, separate: bool): bool { + + // Can't separate two immovable objects (tiles are always immovable) + if (object.immovable) + { + return false; + } + + // First, get the object delta + var overlap: number = 0; + var objDelta: number = object.x - object.last.x; + //var objDelta: number = object.collisionMask.deltaX; + + if (objDelta != 0) + { + // Check if the X hulls actually overlap + var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; + //var objDeltaAbs: number = object.collisionMask.deltaXAbs; + var objBounds: Rectangle = new Rectangle(object.x - ((objDelta > 0) ? objDelta : 0), object.last.y, object.width + ((objDelta > 0) ? objDelta : -objDelta), object.height); + + if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) + { + var maxOverlap: number = objDeltaAbs + Collision.OVERLAP_BIAS; + + // If they did overlap (and can), figure out by how much and flip the corresponding flags + if (objDelta > 0) + { + overlap = object.x + object.width - x; + + if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.RIGHT) || collideLeft == false) + { + overlap = 0; + } + else + { + object.touching |= Collision.RIGHT; + } + } + else if (objDelta < 0) + { + overlap = object.x - width - x; + + if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.LEFT) || collideRight == false) + { + overlap = 0; + } + else + { + object.touching |= Collision.LEFT; + } + + } + + } + } + + // Then adjust their positions and velocities accordingly (if there was any overlap) + if (overlap != 0) + { + if (separate == true) + { + //console.log(' + object.x = object.x - overlap; + object.velocity.x = -(object.velocity.x * object.elasticity); + } + + Collision.TILE_OVERLAP = true; + return true; + } + else + { + return false; + } + + } + */ + /** + * Separates the two objects on their y axis + * @param object The first GameObject to separate + * @param tile The second GameObject to separate + * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis. + */ + /* + public separateTileY(object: Sprite, x: number, y: number, width: number, height: number, mass: number, collideUp: bool, collideDown: bool, separate: bool): bool { + + // Can't separate two immovable objects (tiles are always immovable) + if (object.immovable) + { + return false; + } + + // First, get the two object deltas + var overlap: number = 0; + var objDelta: number = object.y - object.last.y; + + if (objDelta != 0) + { + // Check if the Y hulls actually overlap + var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; + var objBounds: Rectangle = new Rectangle(object.x, object.y - ((objDelta > 0) ? objDelta : 0), object.width, object.height + objDeltaAbs); + + if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) + { + var maxOverlap: number = objDeltaAbs + Collision.OVERLAP_BIAS; + + // If they did overlap (and can), figure out by how much and flip the corresponding flags + if (objDelta > 0) + { + overlap = object.y + object.height - y; + + if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.DOWN) || collideUp == false) + { + overlap = 0; + } + else + { + object.touching |= Collision.DOWN; + } + } + else if (objDelta < 0) + { + overlap = object.y - height - y; + + if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.UP) || collideDown == false) + { + overlap = 0; + } + else + { + object.touching |= Collision.UP; + } + } + } + } + + // TODO - with super low velocities you get lots of stuttering, set some kind of base minimum here + + // Then adjust their positions and velocities accordingly (if there was any overlap) + if (overlap != 0) + { + if (separate == true) + { + object.y = object.y - overlap; + object.velocity.y = -(object.velocity.y * object.elasticity); + } + + Collision.TILE_OVERLAP = true; + return true; + } + else + { + return false; + } + } + */ + /** + * Separates the two objects on their x axis + * @param object The GameObject to separate + * @param tile The Tile to separate + * @returns {boolean} Whether the objects in fact touched and were separated along the X axis. + */ + /* + public static NEWseparateTileX(object:Sprite, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool, separate: bool): bool { + + // Can't separate two immovable objects (tiles are always immovable) + if (object.immovable) + { + return false; + } + + // First, get the object delta + var overlap: number = 0; + + if (object.collisionMask.deltaX != 0) + { + // Check if the X hulls actually overlap + //var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; + //var objBounds: Rectangle = new Rectangle(object.x - ((objDelta > 0) ? objDelta : 0), object.last.y, object.width + ((objDelta > 0) ? objDelta : -objDelta), object.height); + + //if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) + if (object.collisionMask.intersectsRaw(x, x + width, y, y + height)) + { + var maxOverlap: number = object.collisionMask.deltaXAbs + Collision.OVERLAP_BIAS; + + // If they did overlap (and can), figure out by how much and flip the corresponding flags + if (object.collisionMask.deltaX > 0) + { + //overlap = object.x + object.width - x; + overlap = object.collisionMask.right - x; + + if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.RIGHT) || collideLeft == false) + { + overlap = 0; + } + else + { + object.touching |= Collision.RIGHT; + } + } + else if (object.collisionMask.deltaX < 0) + { + //overlap = object.x - width - x; + overlap = object.collisionMask.x - width - x; + + if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.LEFT) || collideRight == false) + { + overlap = 0; + } + else + { + object.touching |= Collision.LEFT; + } + + } + + } + } + + // Then adjust their positions and velocities accordingly (if there was any overlap) + if (overlap != 0) + { + if (separate == true) + { + object.x = object.x - overlap; + object.velocity.x = -(object.velocity.x * object.elasticity); + } + + Collision.TILE_OVERLAP = true; + return true; + } + else + { + return false; + } + + } + */ + /** + * Separates the two objects on their y axis + * @param object The first GameObject to separate + * @param tile The second GameObject to separate + * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis. + */ + /* + public NEWseparateTileY(object: Sprite, x: number, y: number, width: number, height: number, mass: number, collideUp: bool, collideDown: bool, separate: bool): bool { + + // Can't separate two immovable objects (tiles are always immovable) + if (object.immovable) + { + return false; + } + + // First, get the two object deltas + var overlap: number = 0; + //var objDelta: number = object.y - object.last.y; + + if (object.collisionMask.deltaY != 0) + { + // Check if the Y hulls actually overlap + //var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; + //var objBounds: Rectangle = new Rectangle(object.x, object.y - ((objDelta > 0) ? objDelta : 0), object.width, object.height + objDeltaAbs); + + //if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) + if (object.collisionMask.intersectsRaw(x, x + width, y, y + height)) + { + //var maxOverlap: number = objDeltaAbs + Collision.OVERLAP_BIAS; + var maxOverlap: number = object.collisionMask.deltaYAbs + Collision.OVERLAP_BIAS; + + // If they did overlap (and can), figure out by how much and flip the corresponding flags + if (object.collisionMask.deltaY > 0) + { + //overlap = object.y + object.height - y; + overlap = object.collisionMask.bottom - y; + + if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.DOWN) || collideUp == false) + { + overlap = 0; + } + else + { + object.touching |= Collision.DOWN; + } + } + else if (object.collisionMask.deltaY < 0) + { + //overlap = object.y - height - y; + overlap = object.collisionMask.y - height - y; + + if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.UP) || collideDown == false) + { + overlap = 0; + } + else + { + object.touching |= Collision.UP; + } + } + } + } + + // TODO - with super low velocities you get lots of stuttering, set some kind of base minimum here + + // Then adjust their positions and velocities accordingly (if there was any overlap) + if (overlap != 0) + { + if (separate == true) + { + object.y = object.y - overlap; + object.velocity.y = -(object.velocity.y * object.elasticity); + } + + Collision.TILE_OVERLAP = true; + return true; + } + else + { + return false; + } + } + */ + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; })(Phaser || (Phaser = {})); var Phaser; (function (Phaser) { /// /// /// - /// - /// + /// /** - * Phaser - Advanced Physics - Joint - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Physics) { - var Joint = (function () { - function Joint(type, body1, body2, collideConnected) { - this.id = Physics.AdvancedPhysics.jointCounter++; - this.type = type; - this.body1 = body1; - this.body2 = body2; - this.collideConnected = collideConnected; - this.maxForce = 9999999999; - this.breakable = false; - } - Joint.prototype.getWorldAnchor1 = function () { - return this.body1.getWorldPoint(this.anchor1); - }; - Joint.prototype.getWorldAnchor2 = function () { - return this.body2.getWorldPoint(this.anchor2); - }; - Joint.prototype.setWorldAnchor1 = function (anchor1) { - this.anchor1 = this.body1.getLocalPoint(anchor1); - }; - Joint.prototype.setWorldAnchor2 = function (anchor2) { - this.anchor2 = this.body2.getLocalPoint(anchor2); - }; - return Joint; - })(); - Physics.Joint = Joint; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - /// - /// - /// - /** - * Phaser - 2D AABB - * - * A 2D AABB object - */ - (function (Physics) { - var Bounds = (function () { - /** - * Creates a new 2D AABB object. - * @class Bounds - * @constructor - * @return {Bounds} This object - **/ - function Bounds(mins, maxs) { - if (typeof mins === "undefined") { mins = null; } - if (typeof maxs === "undefined") { maxs = 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); - } - } - Bounds.prototype.toString = function () { - return [ - "mins:", - this.mins.toString(), - "maxs:", - this.maxs.toString() - ].join(" "); - }; - Bounds.prototype.setTo = function (mins, maxs) { - this.mins.setTo(mins.x, mins.y); - this.maxs.setTo(maxs.x, maxs.y); - }; - Bounds.prototype.copy = function (b) { - this.mins.copyFrom(b.mins); - this.maxs.copyFrom(b.maxs); - return this; - }; - Bounds.prototype.clear = function () { - this.mins.setTo(999999, 999999); - this.maxs.setTo(-999999, -999999); - return this; - }; - Object.defineProperty(Bounds.prototype, "x", { - get: function () { - return Physics.AdvancedPhysics.metersToPixels(this.mins.x); - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Bounds.prototype, "y", { - get: function () { - return Physics.AdvancedPhysics.metersToPixels(this.mins.y); - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Bounds.prototype, "width", { - get: function () { - return Physics.AdvancedPhysics.metersToPixels(this.maxs.x - this.mins.x); - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Bounds.prototype, "height", { - get: function () { - return Physics.AdvancedPhysics.metersToPixels(this.maxs.y - this.mins.y); - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Bounds.prototype, "right", { - get: function () { - return this.x + this.width; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Bounds.prototype, "bottom", { - get: function () { - return this.y + this.height; - }, - enumerable: true, - configurable: true - }); - Bounds.prototype.isEmpty = function () { - return (this.mins.x > this.maxs.x || this.mins.y > this.maxs.y); - }; - Bounds.prototype.getPerimeter = /* - 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); - } - */ - function () { - return (this.maxs.x - this.mins.x + this.maxs.y - this.mins.y) * 2; - }; - Bounds.prototype.addPoint = function (p) { - 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; - }; - Bounds.prototype.addBounds = function (b) { - 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; - }; - Bounds.prototype.addBounds2 = function (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; - }; - Bounds.prototype.addExtents = function (center, extent_x, extent_y) { - 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; - }; - Bounds.prototype.expand = function (ax, ay) { - this.mins.x -= ax; - this.mins.y -= ay; - this.maxs.x += ax; - this.maxs.y += ay; - return this; - }; - Bounds.prototype.containPoint = function (p) { - 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; - }; - Bounds.prototype.intersectsBounds = function (b) { - 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; - }; - Bounds.expand = function expand(b, ax, ay) { - var b = new Bounds(b.mins, b.maxs); - b.expand(ax, ay); - return b; - }; - return Bounds; - })(); - Physics.Bounds = Bounds; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - })(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - /// - /// - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - Shape - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Physics) { - var Shape = (function () { - function Shape(type) { - this.id = Physics.AdvancedPhysics.shapeCounter++; - this.type = type; - this.elasticity = 0.0; - this.friction = 1.0; - this.density = 1; - this.bounds = new Physics.Bounds(); - } - Shape.prototype.findEdgeByPoint = // Over-ridden by ShapePoly - function (p, minDist) { - return -1; - }; - return Shape; - })(); - Physics.Shape = Shape; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - /// - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - Contact - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Physics) { - var Contact = (function () { - function Contact(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(); - } - return Contact; - })(); - Physics.Contact = Contact; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - /// - /// - /// - /// - /// - /// - /// - /** - * 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. - //------------------------------------------------------------------------------------------------- - (function (Physics) { - var ContactSolver = (function () { - function ContactSolver(shape1, shape2) { - this.shape1 = shape1; - this.shape2 = shape2; - this.contacts = []; - this.elasticity = 1; - this.friction = 1; - } - ContactSolver.prototype.update = function (newContactArr) { - 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; - }; - ContactSolver.prototype.initSolver = function (dt_inv) { - var body1 = this.shape1.body; - var body2 = this.shape2.body; - var sum_m_inv = body1.massInverted + body2.massInverted; - for(var i = 0; i < this.contacts.length; i++) { - var con = 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; - } - }; - ContactSolver.prototype.warmStart = function () { - var body1 = this.shape1.body; - var body2 = 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); - //console.log('phaser warmStart impulse ' + i + ' = ' + impulse.toString()); - 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; - } - }; - ContactSolver.prototype.solveVelocityConstraints = function () { - var body1 = this.shape1.body; - var body2 = this.shape2.body; - Physics.AdvancedPhysics.write('solveVelocityConstraints. Body1: ' + body1.name + ' Body2: ' + body2.name); - Physics.AdvancedPhysics.write('Shape 1: ' + this.shape1.type + ' Shape 2: ' + this.shape2.type); - var m1_inv = body1.massInverted; - var i1_inv = body1.inertiaInverted; - var m2_inv = body2.massInverted; - var i2_inv = body2.inertiaInverted; - Physics.AdvancedPhysics.write('m1_inv: ' + m1_inv); - Physics.AdvancedPhysics.write('i1_inv: ' + i1_inv); - Physics.AdvancedPhysics.write('m2_inv: ' + m2_inv); - Physics.AdvancedPhysics.write('i2_inv: ' + i2_inv); - for(var i = 0; i < this.contacts.length; i++) { - Physics.AdvancedPhysics.write('------------ solve con ' + 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); - Physics.AdvancedPhysics.write('v1 ' + v1.toString()); - Phaser.Vec2Utils.multiplyAdd(body2.velocity, Phaser.Vec2Utils.perp(r2), body2.angularVelocity, v2); - //var v2 = vec2.mad(body2.v, vec2.perp(r2), body2.w); - Physics.AdvancedPhysics.write('v2 ' + v2.toString()); - // Relative velocity at contact point - var rv = new Phaser.Vec2(); - Phaser.Vec2Utils.subtract(v2, v1, rv); - //var rv = vec2.sub(v2, v1); - Physics.AdvancedPhysics.write('rv ' + rv.toString()); - // 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); - Physics.AdvancedPhysics.write('lambda_n: ' + lambda_n); - // Accumulate and clamp - var lambda_n_old = con.lambdaNormal; - con.lambdaNormal = Math.max(lambda_n_old + lambda_n, 0); - //con.lambdaNormal = this.clamp(lambda_n_old + lambda_n, 0); - lambda_n = con.lambdaNormal - lambda_n_old; - Physics.AdvancedPhysics.write('lambda_n clamped: ' + lambda_n); - // 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); - Physics.AdvancedPhysics.write('impulse: ' + impulse.toString()); - 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); - body2.angularVelocity += Phaser.Vec2Utils.cross(r2, impulse) * i2_inv; - //body2.w += vec2.cross(r2, impulse) * i2_inv; - Physics.AdvancedPhysics.write('body1: ' + body1.toString()); - Physics.AdvancedPhysics.write('body2: ' + body2.toString()); - } - }; - ContactSolver.prototype.solvePositionConstraints = function () { - var body1 = this.shape1.body; - var body2 = this.shape2.body; - Physics.AdvancedPhysics.write('solvePositionConstraints'); - 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++) { - Physics.AdvancedPhysics.write('------------- solvePositionConstraints ' + 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); - Phaser.Vec2Utils.rotate(con.r2_local, body2.angle, r2); - Physics.AdvancedPhysics.write('r1_local.x = ' + con.r1_local.x + ' r1_local.y = ' + con.r1_local.y + ' angle: ' + body1.angle); - Physics.AdvancedPhysics.write('r1 rotated: r1.x = ' + r1.x + ' r1.y = ' + r1.y); - Physics.AdvancedPhysics.write('r2_local.x = ' + con.r2_local.x + ' r2_local.y = ' + con.r2_local.y + ' angle: ' + body2.angle); - Physics.AdvancedPhysics.write('r2 rotated: r2.x = ' + r2.x + ' r2.y = ' + r2.y); - // Contact points (corrected) - var p1 = new Phaser.Vec2(); - var p2 = new Phaser.Vec2(); - Phaser.Vec2Utils.add(body1.position, r1, p1); - Phaser.Vec2Utils.add(body2.position, r2, p2); - Physics.AdvancedPhysics.write('body1.pos.x=' + body1.position.x + ' y=' + body1.position.y); - Physics.AdvancedPhysics.write('body2.pos.x=' + body2.position.x + ' y=' + body2.position.y); - // Corrected delta vector - var dp = new Phaser.Vec2(); - Phaser.Vec2Utils.subtract(p2, p1, dp); - // Position constraint - var c = Phaser.Vec2Utils.dot(dp, n) + con.depth; - var correction = this.clamp(Physics.AdvancedPhysics.CONTACT_SOLVER_BAUMGARTE * (c + Physics.AdvancedPhysics.CONTACT_SOLVER_COLLISION_SLOP), -Physics.AdvancedPhysics.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); - body1.position.multiplyAddByScalar(impulse_dt, -m1_inv); - body1.angle -= sn1 * lambda_dt * i1_inv; - body2.position.multiplyAddByScalar(impulse_dt, m2_inv); - body2.angle += sn2 * lambda_dt * i2_inv; - Physics.AdvancedPhysics.write('body1.pos.x=' + body1.position.x + ' y=' + body1.position.y); - Physics.AdvancedPhysics.write('body2.pos.x=' + body2.position.x + ' y=' + body2.position.y); - } - Physics.AdvancedPhysics.write('max_penetration: ' + max_penetration); - return max_penetration <= Physics.AdvancedPhysics.CONTACT_SOLVER_COLLISION_SLOP * 3; - }; - ContactSolver.prototype.clamp = function (v, min, max) { - return v < min ? min : (v > max ? max : v); - }; - return ContactSolver; - })(); - Physics.ContactSolver = ContactSolver; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - (function (Physics) { - /// - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - Shape - Circle - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Shapes) { - var Circle = (function (_super) { - __extends(Circle, _super); - function Circle(radius, x, y) { - if (typeof x === "undefined") { x = 0; } - if (typeof y === "undefined") { y = 0; } - _super.call(this, Physics.AdvancedPhysics.SHAPE_TYPE_CIRCLE); - x = Physics.AdvancedPhysics.pixelsToMeters(x); - y = Physics.AdvancedPhysics.pixelsToMeters(y); - radius = Physics.AdvancedPhysics.pixelsToMeters(radius); - this.center = new Phaser.Vec2(x, y); - this.radius = radius; - this.tc = new Phaser.Vec2(); - this.finishVerts(); - } - Circle.prototype.finishVerts = function () { - this.radius = Math.abs(this.radius); - }; - Circle.prototype.duplicate = function () { - return new Circle(this.center.x, this.center.y, this.radius); - }; - Circle.prototype.recenter = function (c) { - this.center.subtract(c); - }; - Circle.prototype.transform = function (xf) { - Phaser.TransformUtils.transform(xf, this.center, this.center); - //this.center = xf.transform(this.center); - }; - Circle.prototype.untransform = function (xf) { - Phaser.TransformUtils.untransform(xf, this.center, this.center); - //this.center = xf.untransform(this.center); - }; - Circle.prototype.area = function () { - return Physics.AdvancedPhysics.areaForCircle(this.radius, 0); - }; - Circle.prototype.centroid = function () { - return Phaser.Vec2Utils.clone(this.center); - }; - Circle.prototype.inertia = function (mass) { - return Physics.AdvancedPhysics.inertiaForCircle(mass, this.center, this.radius, 0); - }; - Circle.prototype.cacheData = function (xf) { - 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); - }; - Circle.prototype.pointQuery = function (p) { - //return vec2.distsq(this.tc, p) < (this.r * this.r); - return Phaser.Vec2Utils.distanceSq(this.tc, p) < (this.radius * this.radius); - }; - Circle.prototype.findVertexByPoint = function (p, minDist) { - var dsq = minDist * minDist; - if(Phaser.Vec2Utils.distanceSq(this.tc, p) < dsq) { - return 0; - } - return -1; - }; - Circle.prototype.distanceOnPlane = function (n, d) { - Phaser.Vec2Utils.dot(n, this.tc) - this.radius - d; - }; - return Circle; - })(Phaser.Physics.Shape); - Shapes.Circle = Circle; - })(Physics.Shapes || (Physics.Shapes = {})); - var Shapes = Physics.Shapes; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - Plane - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Physics) { - var Plane = (function () { - function Plane(normal, d) { - this.normal = normal; - this.d = d; - } - return Plane; - })(); - Physics.Plane = Plane; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - (function (Physics) { - /// - /// - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - Shapes - Convex Polygon - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Shapes) { - var Poly = (function (_super) { - __extends(Poly, _super); - // Verts is an optional array of objects, the objects must have public x and y properties which will be used - // to seed this polygon (i.e. Vec2 objects, or just straight JS objects) and must wind COUNTER clockwise - function Poly(verts) { - _super.call(this, Physics.AdvancedPhysics.SHAPE_TYPE_POLY); - this.verts = []; - this.planes = []; - this.tverts = []; - this.tplanes = []; - if(verts) { - for(var i = 0; i < verts.length; i++) { - this.verts[i] = new Phaser.Vec2(verts[i].x, verts[i].y); - this.tverts[i] = this.verts[i]; - //this.tverts[i] = new Phaser.Vec2(verts[i].x, verts[i].y); - this.tplanes[i] = new Phaser.Physics.Plane(new Phaser.Vec2(), 0); - } - } - this.finishVerts(); - } - Poly.prototype.finishVerts = function () { - 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] = new Phaser.Physics.Plane(n, Phaser.Vec2Utils.dot(n, a)); - this.tverts[i] = Phaser.Vec2Utils.clone(this.verts[i])// reference??? - ; - //this.tverts[i] = this.verts[i]; // reference??? - this.tplanes[i] = new Phaser.Physics.Plane(new Phaser.Vec2(), 0); - } - for(var i = 0; i < this.verts.length; i++) { - //var b = this.verts[(i + 2) % this.verts.length]; - //var n = this.planes[i].normal; - //var d = this.planes[i].d; - if(Phaser.Vec2Utils.dot(this.planes[i].normal, this.verts[(i + 2) % this.verts.length]) - this.planes[i].d > 0) { - this.convexity = false; - } - } - }; - Poly.prototype.duplicate = function () { - return new Phaser.Physics.Shapes.Poly(this.verts); - }; - Poly.prototype.recenter = function (c) { - for(var i = 0; i < this.verts.length; i++) { - this.verts[i].subtract(c); - } - }; - Poly.prototype.transform = function (xf) { - for(var i = 0; i < this.verts.length; i++) { - this.verts[i] = Phaser.TransformUtils.transform(xf, this.verts[i]); - //this.verts[i] = xf.transform(this.verts[i]); - } - }; - Poly.prototype.untransform = function (xf) { - for(var i = 0; i < this.verts.length; i++) { - this.verts[i] = Phaser.TransformUtils.untransform(xf, this.verts[i]); - //this.verts[i] = xf.untransform(this.verts[i]); - } - }; - Poly.prototype.area = function () { - return Physics.AdvancedPhysics.areaForPoly(this.verts); - }; - Poly.prototype.centroid = function () { - return Physics.AdvancedPhysics.centroidForPoly(this.verts); - }; - Poly.prototype.inertia = function (mass) { - return Physics.AdvancedPhysics.inertiaForPoly(mass, this.verts, new Phaser.Vec2()); - }; - Poly.prototype.cacheData = function (xf) { - this.bounds.clear(); - var numVerts = this.verts.length; - Physics.AdvancedPhysics.write('----------- Poly cacheData = ' + numVerts); - if(numVerts == 0) { - return; - } - for(var i = 0; i < numVerts; i++) { - this.tverts[i] = Phaser.TransformUtils.transform(xf, this.verts[i]); - //this.tverts[i] = xf.transform(this.verts[i]); - Physics.AdvancedPhysics.write('tvert' + i + ' = ' + this.tverts[i].toString()); - } - 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))); - Physics.AdvancedPhysics.write('a = ' + a.toString()); - Physics.AdvancedPhysics.write('b = ' + b.toString()); - Physics.AdvancedPhysics.write('n = ' + n.toString()); - this.tplanes[i].normal = n; - this.tplanes[i].d = Phaser.Vec2Utils.dot(n, a); - Physics.AdvancedPhysics.write('tplanes' + i + ' n = ' + this.tplanes[i].normal.toString()); - Physics.AdvancedPhysics.write('tplanes' + i + ' d = ' + this.tplanes[i].d.toString()); - this.bounds.addPoint(a); - } - }; - Poly.prototype.pointQuery = function (p) { - if(!this.bounds.containPoint(p)) { - return false; - } - return this.containPoint(p); - }; - Poly.prototype.findVertexByPoint = function (p, minDist) { - 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; - }; - Poly.prototype.findEdgeByPoint = function (p, minDist) { - 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].normal; - 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; - }; - Poly.prototype.distanceOnPlane = function (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; - }; - Poly.prototype.containPoint = function (p) { - for(var i = 0; i < this.verts.length; i++) { - var plane = this.tplanes[i]; - if(Phaser.Vec2Utils.dot(plane.normal, p) - plane.d > 0) { - return false; - } - } - return true; - }; - Poly.prototype.containPointPartial = function (p, n) { - for(var i = 0; i < this.verts.length; i++) { - var plane = this.tplanes[i]; - if(Phaser.Vec2Utils.dot(plane.normal, n) < 0.0001) { - continue; - } - if(Phaser.Vec2Utils.dot(plane.normal, p) - plane.d > 0) { - return false; - } - } - return true; - }; - return Poly; - })(Phaser.Physics.Shape); - Shapes.Poly = Poly; - })(Physics.Shapes || (Physics.Shapes = {})); - var Shapes = Physics.Shapes; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - (function (Physics) { - /// - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - Shapes - Segment - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Shapes) { - var Segment = (function (_super) { - __extends(Segment, _super); - function Segment(a, b, radius) { - _super.call(this, Physics.AdvancedPhysics.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(); - } - Segment.prototype.finishVerts = function () { - this.normal = Phaser.Vec2Utils.perp(Phaser.Vec2Utils.subtract(this.b, this.a)); - this.normal.normalize(); - this.radius = Math.abs(this.radius); - }; - Segment.prototype.duplicate = function () { - return new Phaser.Physics.Shapes.Segment(this.a, this.b, this.radius); - }; - Segment.prototype.recenter = function (c) { - this.a.subtract(c); - this.b.subtract(c); - }; - Segment.prototype.transform = function (xf) { - 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); - }; - Segment.prototype.untransform = function (xf) { - 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); - }; - Segment.prototype.area = function () { - return Physics.AdvancedPhysics.areaForSegment(this.a, this.b, this.radius); - }; - Segment.prototype.centroid = function () { - return Physics.AdvancedPhysics.centroidForSegment(this.a, this.b); - }; - Segment.prototype.inertia = function (mass) { - return Physics.AdvancedPhysics.inertiaForSegment(mass, this.a, this.b); - }; - Segment.prototype.cacheData = function (xf) { - 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); - }; - Segment.prototype.pointQuery = function (p) { - 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; - }; - Segment.prototype.findVertexByPoint = function (p, minDist) { - 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; - }; - Segment.prototype.distanceOnPlane = function (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; - }; - return Segment; - })(Phaser.Physics.Shape); - Shapes.Segment = Segment; - })(Physics.Shapes || (Physics.Shapes = {})); - var Shapes = Physics.Shapes; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - Collision Handlers - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Physics) { - var Collision = (function () { - function Collision() { } - Collision.prototype.collide = function (a, b, contacts) { - // Circle (a is the circle) - if(a.type == Physics.AdvancedPhysics.SHAPE_TYPE_CIRCLE) { - if(b.type == Physics.AdvancedPhysics.SHAPE_TYPE_CIRCLE) { - return this.circle2Circle(a, b, contacts); - } else if(b.type == Physics.AdvancedPhysics.SHAPE_TYPE_SEGMENT) { - return this.circle2Segment(a, b, contacts); - } else if(b.type == Physics.AdvancedPhysics.SHAPE_TYPE_POLY) { - return this.circle2Poly(a, b, contacts); - } - } - // Segment (a is the segment) - if(a.type == Physics.AdvancedPhysics.SHAPE_TYPE_SEGMENT) { - if(b.type == Physics.AdvancedPhysics.SHAPE_TYPE_CIRCLE) { - return this.circle2Segment(b, a, contacts); - } else if(b.type == Physics.AdvancedPhysics.SHAPE_TYPE_SEGMENT) { - return this.segment2Segment(a, b, contacts); - } else if(b.type == Physics.AdvancedPhysics.SHAPE_TYPE_POLY) { - return this.segment2Poly(a, b, contacts); - } - } - // Poly (a is the poly) - if(a.type == Physics.AdvancedPhysics.SHAPE_TYPE_POLY) { - if(b.type == Physics.AdvancedPhysics.SHAPE_TYPE_CIRCLE) { - return this.circle2Poly(b, a, contacts); - } else if(b.type == Physics.AdvancedPhysics.SHAPE_TYPE_SEGMENT) { - return this.segment2Poly(b, a, contacts); - } else if(b.type == Physics.AdvancedPhysics.SHAPE_TYPE_POLY) { - return this.poly2Poly(a, b, contacts); - } - } - }; - Collision.prototype._circle2Circle = function (c1, r1, c2, r2, contactArr) { - var rmax = r1 + r2; - var t = 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 = 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 = 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 Physics.Contact(p, n, d, 0)); - return 1; - }; - Collision.prototype.circle2Circle = function (circ1, circ2, contactArr) { - return this._circle2Circle(circ1.tc, circ1.radius, circ2.tc, circ2.radius, contactArr); - }; - Collision.prototype.circle2Segment = function (circ, seg, contactArr) { - 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 = 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 = new Phaser.Vec2(); - Phaser.Vec2Utils.multiplyAdd(circ.tc, n, -(circ.radius + dist * 0.5), c1); - var c2 = new Phaser.Vec2(); - Phaser.Vec2Utils.negative(n, c2); - contactArr.push(new Physics.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; - }; - Collision.prototype.circle2Poly = function (circ, poly, contactArr) { - 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.normal) - plane.d - circ.radius; - if(dist > 0) { - return 0; - } else if(dist > minDist) { - minDist = dist; - minIdx = i; - } - } - var n = poly.tplanes[minIdx].normal; - 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 = new Phaser.Vec2(); - Phaser.Vec2Utils.multiplyAdd(circ.tc, n, -(circ.radius + minDist * 0.5), c1); - var c2 = new Phaser.Vec2(); - Phaser.Vec2Utils.negative(n, c2); - contactArr.push(new Physics.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; - }; - Collision.prototype.segmentPointDistanceSq = function (seg, p) { - var w = new Phaser.Vec2(); - var d = 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; - }; - Collision.prototype.segment2Segment = // FIXME and optimise me lots!!! - function (seg1, seg2, contactArr) { - 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); - }; - Collision.prototype.findPointsBehindSeg = // Identify vertexes that have penetrated the segment. - function (contactArr, seg, poly, dist, coef) { - var dta = Phaser.Vec2Utils.cross(seg.tn, seg.ta); - var dtb = Phaser.Vec2Utils.cross(seg.tn, seg.tb); - var n = 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 Physics.Contact(v, n, dist, (poly.id << 16) | i)); - } - } - } - }; - Collision.prototype.segment2Poly = function (seg, poly, contactArr) { - 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 = 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.normal, plane.d); - if(dist > 0) { - return 0; - } - if(dist > poly_d) { - poly_d = dist; - poly_i = i; - } - } - var poly_n = new Phaser.Vec2(); - Phaser.Vec2Utils.negative(poly.tplanes[poly_i].normal, poly_n); - //var poly_n = vec2.neg(poly.tplanes[poly_i].n); - var va = 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 = 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 Physics.Contact(va, poly_n, poly_d, (seg.id << 16) | 0)); - } - if(poly.containPoint(vb)) { - contactArr.push(new Physics.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; - }; - Collision.prototype.findMSA = // Find the minimum separating axis for the given poly and plane list. - function (poly, planes, num) { - var min_dist = -999999; - var min_index = -1; - for(var i = 0; i < num; i++) { - var dist = poly.distanceOnPlane(planes[i].normal, 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 - }; - }; - Collision.prototype.findVertsFallback = function (contactArr, poly1, poly2, n, dist) { - 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 Physics.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 Physics.Contact(v, n, dist, (poly2.id << 16) | i)); - num++; - } - } - return num; - }; - Collision.prototype.findVerts = // Find the overlapped vertices. - function (contactArr, poly1, poly2, n, dist) { - var num = 0; - for(var i = 0; i < poly1.verts.length; i++) { - var v = poly1.tverts[i]; - if(poly2.containPoint(v)) { - contactArr.push(new Physics.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 Physics.Contact(v, n, dist, (poly2.id << 16) | i)); - num++; - } - } - return num > 0 ? num : this.findVertsFallback(contactArr, poly1, poly2, n, dist); - }; - Collision.prototype.poly2Poly = function (poly1, poly2, contactArr) { - var msa1 = this.findMSA(poly2, poly1.tplanes, poly1.verts.length); - if(msa1.index == -1) { - console.log('poly2poly 0', msa1); - return 0; - } - var msa2 = this.findMSA(poly1, poly2.tplanes, poly2.verts.length); - if(msa2.index == -1) { - console.log('poly2poly 1', msa2); - return 0; - } - // Penetration normal direction should be from poly1 to poly2 - if(msa1.dist > msa2.dist) { - return this.findVerts(contactArr, poly1, poly2, poly1.tplanes[msa1.index].normal, msa1.dist); - } - return this.findVerts(contactArr, poly1, poly2, Phaser.Vec2Utils.negative(poly2.tplanes[msa2.index].normal), msa2.dist); - }; - return Collision; - })(); - Physics.Collision = Collision; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - })(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - /// - /// - /// - /// - /// - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - Space - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Physics) { - var Space = (function () { - function Space(manager) { - this.postSolve = null; - this.stepCount = 0; - this._manager = manager; - this.bodies = []; - this.bodyHash = { - }; - this.joints = []; - this.jointHash = { - }; - this.numContacts = 0; - this.contactSolvers = []; - this.gravity = this._manager.gravity; - this.damping = 0; - this._linTolSqr = Space.SLEEP_LINEAR_TOLERANCE * Space.SLEEP_LINEAR_TOLERANCE; - this._angTolSqr = Space.SLEEP_ANGULAR_TOLERANCE * Space.SLEEP_ANGULAR_TOLERANCE; - } - Space.TIME_TO_SLEEP = 0.5; - Space.SLEEP_LINEAR_TOLERANCE = 0.5; - Space.SLEEP_ANGULAR_TOLERANCE = 2 * 0.017453292519943294444444444444444; - Space.prototype.clear = function () { - Physics.AdvancedPhysics.shapeCounter = 0; - Physics.AdvancedPhysics.bodyCounter = 0; - Physics.AdvancedPhysics.jointCounter = 0; - for(var i = 0; i < this.bodies.length; i++) { - if(this.bodies[i]) { - this.removeBody(this.bodies[i]); - } - } - this.bodies = []; - this.bodyHash = { - }; - this.joints = []; - this.jointHash = { - }; - this.contactSolvers = []; - this.stepCount = 0; - }; - Space.prototype.addBody = function (body) { - if(this.bodyHash[body.id] != undefined) { - return; - } - var index = this.bodies.push(body) - 1; - this.bodyHash[body.id] = index; - body.awake(true); - body.space = this; - body.cacheData('addBody'); - }; - Space.prototype.removeBody = function (body) { - if(this.bodyHash[body.id] == undefined) { - return; - } - // Remove linked joints - 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.bodies[index]; - }; - Space.prototype.addJoint = function (joint) { - if(this.jointHash[joint.id] != undefined) { - return; - } - joint.body1.awake(true); - joint.body2.awake(true); - var index = this.joints.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; - }; - Space.prototype.removeJoint = function (joint) { - 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.joints[index]; - }; - Space.prototype.findShapeByPoint = function (p, refShape) { - var firstShape; - for(var i = 0; i < this.bodies.length; i++) { - var body = this.bodies[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; - }; - Space.prototype.findBodyByPoint = function (p, refBody) { - var firstBody; - for(var i = 0; i < this.bodies.length; i++) { - var body = this.bodies[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; - }; - Space.prototype.shapeById = function (id) { - var shape; - for(var i = 0; i < this.bodies.length; i++) { - var body = this.bodies[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; - }; - Space.prototype.jointById = function (id) { - var index = this.jointHash[id]; - if(index != undefined) { - return this.joints[index]; - } - return null; - }; - Space.prototype.findVertexByPoint = function (p, minDist, refVertexId) { - var firstVertexId = -1; - refVertexId = refVertexId || -1; - for(var i = 0; i < this.bodies.length; i++) { - var body = this.bodies[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; - }; - Space.prototype.findEdgeByPoint = function (p, minDist, refEdgeId) { - var firstEdgeId = -1; - refEdgeId = refEdgeId || -1; - for(var i = 0; i < this.bodies.length; i++) { - var body = this.bodies[i]; - if(!body) { - continue; - } - for(var j = 0; j < body.shapes.length; j++) { - var shape = body.shapes[j]; - if(shape.type != Physics.AdvancedPhysics.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; - }; - Space.prototype.findJointByPoint = function (p, minDist, refJointId) { - var firstJointId = -1; - var dsq = minDist * minDist; - refJointId = refJointId || -1; - for(var i = 0; i < this.joints.length; i++) { - var joint = this.joints[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; - }; - Space.prototype.findContactSolver = function (shape1, shape2) { - Physics.Manager.write('findContactSolver. Length: ' + this._cl); - for(var i = 0; i < this._cl; i++) { - var contactSolver = this.contactSolvers[i]; - if(shape1 == contactSolver.shape1 && shape2 == contactSolver.shape2) { - return contactSolver; - } - } - return null; - }; - Space.prototype.genTemporalContactSolvers = function () { - Physics.Manager.write('genTemporalContactSolvers'); - this._cl = 0; - this.contactSolvers.length = 0; - this.numContacts = 0; - for(var body1Index = 0; body1Index < this._bl; body1Index++) { - if(!this.bodies[body1Index]) { - continue; - } - this.bodies[body1Index].stepCount = this.stepCount; - for(var body2Index = 0; body2Index < this._bl; body2Index++) { - if(this.bodies[body1Index].inContact(this.bodies[body2Index]) == false) { - continue; - } - Physics.Manager.write('body1 and body2 intersect'); - for(var i = 0; i < this.bodies[body1Index].shapesLength; i++) { - for(var j = 0; j < this.bodies[body2Index].shapesLength; j++) { - this._shape1 = this.bodies[body1Index].shapes[i]; - this._shape2 = this.bodies[body2Index].shapes[j]; - var contactArr = []; - if(!Physics.AdvancedPhysics.collision.collide(this._shape1, this._shape2, contactArr)) { - continue; - } - if(this._shape1.type > this._shape2.type) { - var temp = this._shape1; - this._shape1 = this._shape2; - this._shape2 = temp; - } - this.numContacts += contactArr.length; - // Result stored in this._contactSolver (see what we can do about generating some re-usable solvers) - var contactSolver = this.findContactSolver(this._shape1, this._shape2); - Physics.Manager.write('findContactSolver result: ' + contactSolver); - if(contactSolver) { - contactSolver.update(contactArr); - this.contactSolvers.push(contactSolver); - } else { - Physics.Manager.write('awake both bodies'); - this.bodies[body1Index].awake(true); - this.bodies[body2Index].awake(true); - var newContactSolver = new Physics.ContactSolver(this._shape1, this._shape2); - newContactSolver.contacts = contactArr; - newContactSolver.elasticity = Math.max(this._shape1.elasticity, this._shape2.elasticity); - newContactSolver.friction = Math.sqrt(this._shape1.friction * this._shape2.friction); - this.contactSolvers.push(newContactSolver); - Physics.Manager.write('new contact solver'); - } - } - } - } - } - this._cl = this.contactSolvers.length; - }; - Space.prototype.initSolver = function (warmStarting) { - Physics.Manager.write('initSolver'); - Physics.Manager.write('contactSolvers.length: ' + this._cl); - // Initialize contact solvers - for(var c = 0; c < this._cl; c++) { - this.contactSolvers[c].initSolver(this._deltaInv); - // Warm starting (apply cached impulse) - if(warmStarting) { - this.contactSolvers[c].warmStart(); - } - } - // Initialize joint solver - for(var j = 0; j < this.joints.length; j++) { - if(this.joints[j]) { - this.joints[j].initSolver(this._delta, warmStarting); - } - } - // Warm starting (apply cached impulse) - /* - if (warmStarting) - { - for (var c = 0; c < this._cl; c++) - { - this.contactSolvers[c].warmStart(); - } - } - */ - }; - Space.prototype.velocitySolver = function (iterations) { - Physics.Manager.write('velocitySolver, iterations: ' + iterations + ' csa len: ' + this._cl); - for(var i = 0; i < iterations; i++) { - for(var j = 0; j < this._jl; j++) { - if(this.joints[j]) { - this.joints[j].solveVelocityConstraints(); - } - } - for(var c = 0; c < this._cl; c++) { - this.contactSolvers[c].solveVelocityConstraints(); - } - } - }; - Space.prototype.positionSolver = function (iterations) { - this._positionSolved = false; - for(var i = 0; i < iterations; i++) { - this._contactsOk = true; - this._jointsOk = true; - for(var c = 0; c < this._cl; c++) { - this._contactsOk = this.contactSolvers[c].solvePositionConstraints() && this._contactsOk; - } - for(var j = 0; j < this._jl; j++) { - if(this.joints[j]) { - this._jointsOk = this.joints[j].solvePositionConstraints() && this._jointsOk; - } - } - if(this._contactsOk && this._jointsOk) { - // exit early if the position errors are small - this._positionSolved = true; - break; - } - } - return this._positionSolved; - }; - Space.prototype.step = // Step through the physics simulation - function (dt, velocityIterations, positionIterations, warmStarting, allowSleep) { - Physics.Manager.clear(); - Physics.Manager.write('Space step ' + this.stepCount); - this._delta = dt; - this._deltaInv = 1 / dt; - this._bl = this.bodies.length; - this._jl = this.joints.length; - this.stepCount++; - // 1) Generate Contact Solvers (into the this.contactSolvers array) - this.genTemporalContactSolvers(); - Physics.Manager.dump("Contact Solvers", this.bodies[1]); - // 2) Initialize the Contact Solvers - this.initSolver(warmStarting); - Physics.Manager.dump("Init Solver", this.bodies[1]); - // 3) Intergrate velocity - for(var i = 0; i < this._bl; i++) { - if(this.bodies[i] && this.bodies[i].isDynamic && this.bodies[i].isAwake) { - this.bodies[i].updateVelocity(this.gravity, this._delta, this.damping); - } - } - Physics.Manager.dump("Update Velocity", this.bodies[1]); - // 4) Awaken bodies via joints - for(var j = 0; i < this._jl; j++) { - if(!this.joints[j]) { - continue; - } - // combine - var awake1 = this.joints[j].body1.isAwake && !this.joints[j].body1.isStatic; - var awake2 = this.joints[j].body2.isAwake && !this.joints[j].body2.isStatic; - if(awake1 ^ awake2) { - if(!awake1) { - this.joints[j].body1.awake(true); - } - if(!awake2) { - this.joints[j].body2.awake(true); - } - } - } - // 5) Iterative velocity constraints solver - this.velocitySolver(velocityIterations); - Physics.Manager.dump("Velocity Solvers", this.bodies[1]); - // 6) Integrate position - for(var i = 0; i < this._bl; i++) { - if(this.bodies[i] && this.bodies[i].isDynamic && this.bodies[i].isAwake) { - this.bodies[i].updatePosition(this._delta); - } - } - Physics.Manager.dump("Update Position", this.bodies[1]); - // 7) Process breakable joint - for(var i = 0; i < this._jl; i++) { - if(this.joints[i] && this.joints[i].breakable && (this.joints[i].getReactionForce(this._deltaInv).lengthSq() >= this.joints[i].maxForce * this.joints[i].maxForce)) { - this.removeJoint(this.joints[i]); - } - } - // 8) Iterative position constraints solver (result stored in this._positionSolved) - this.positionSolver(positionIterations); - Physics.Manager.dump("Position Solver", this.bodies[1]); - // 9) Sync the Transforms - for(var i = 0; i < this._bl; i++) { - if(this.bodies[i]) { - this.bodies[i].syncTransform(); - } - } - Physics.Manager.dump("Sync Transform", this.bodies[1]); - // 10) Post solve collision callback - if(this.postSolve) { - for(var i = 0; i < this._cl; i++) { - this.postSolve(this.contactSolvers[i]); - } - } - // 11) Cache Body Data - for(var i = 0; i < this._bl; i++) { - if(this.bodies[i] && this.bodies[i].isDynamic && this.bodies[i].isAwake) { - this.bodies[i].cacheData('post solve collision callback'); - } - } - Physics.Manager.dump("Cache Data", this.bodies[1]); - Physics.Manager.writeAll(); - // 12) Process sleeping - if(allowSleep) { - this._minSleepTime = 999999; - for(var i = 0; i < this._bl; i++) { - if(!this.bodies[i] || this.bodies[i].isDynamic == false) { - continue; - } - if(this.bodies[i].angularVelocity * this.bodies[i].angularVelocity > this._angTolSqr || this.bodies[i].velocity.dot(this.bodies[i].velocity) > this._linTolSqr) { - this.bodies[i].sleepTime = 0; - this._minSleepTime = 0; - } else { - this.bodies[i].sleepTime += this._delta; - this._minSleepTime = Math.min(this._minSleepTime, this.bodies[i].sleepTime); - } - } - if(this._positionSolved && this._minSleepTime >= Space.TIME_TO_SLEEP) { - for(var i = 0; i < this._bl; i++) { - if(this.bodies[i]) { - this.bodies[i].awake(false); - } - } - } - } - }; - return Space; - })(); - Physics.Space = Space; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - /// - /// - /// - /// - /** - * Phaser - Physics Manager - * - * The Physics Manager is responsible for looking after, creating and colliding - * all of the physics bodies and joints in the world. - */ - (function (Physics) { - var AdvancedPhysics = (function () { - function AdvancedPhysics(game) { - this.lastTime = Date.now(); - this.frameRateHz = 60; - this.timeDelta = 0; - this.paused = false; - this.step = false; - // step through the simulation (i.e. per click) - //public paused: bool = true; - //public step: bool = false; // step through the simulation (i.e. per click) - this.velocityIterations = 8; - this.positionIterations = 4; - this.allowSleep = true; - this.warmStarting = true; - this.game = game; - this.gravity = new Phaser.Vec2(); - this.space = new Physics.Space(this); - this.collision = new Physics.Collision(); - } - AdvancedPhysics.clear = function clear() { - //Manager.debug.textContent = ""; - Physics.Manager.log = []; - }; - AdvancedPhysics.write = function write(s) { - //Manager.debug.textContent += s + "\n"; - }; - AdvancedPhysics.writeAll = function writeAll() { - for(var i = 0; i < Physics.Manager.log.length; i++) { - //Manager.debug.textContent += Manager.log[i]; - } - }; - AdvancedPhysics.log = []; - AdvancedPhysics.dump = function dump(phase, body) { - /* - var s = "\n\nPhase: " + phase + "\n"; - s += "Position: " + body.position.toString() + "\n"; - s += "Velocity: " + body.velocity.toString() + "\n"; - s += "Angle: " + body.angle + "\n"; - s += "Force: " + body.force.toString() + "\n"; - s += "Torque: " + body.torque + "\n"; - s += "Bounds: " + body.bounds.toString() + "\n"; - s += "Shape ***\n"; - s += "Vert 0: " + body.shapes[0].verts[0].toString() + "\n"; - s += "Vert 1: " + body.shapes[0].verts[1].toString() + "\n"; - s += "Vert 2: " + body.shapes[0].verts[2].toString() + "\n"; - s += "Vert 3: " + body.shapes[0].verts[3].toString() + "\n"; - s += "TVert 0: " + body.shapes[0].tverts[0].toString() + "\n"; - s += "TVert 1: " + body.shapes[0].tverts[1].toString() + "\n"; - s += "TVert 2: " + body.shapes[0].tverts[2].toString() + "\n"; - s += "TVert 3: " + body.shapes[0].tverts[3].toString() + "\n"; - s += "Plane 0: " + body.shapes[0].planes[0].normal.toString() + "\n"; - s += "Plane 1: " + body.shapes[0].planes[1].normal.toString() + "\n"; - s += "Plane 2: " + body.shapes[0].planes[2].normal.toString() + "\n"; - s += "Plane 3: " + body.shapes[0].planes[3].normal.toString() + "\n"; - s += "TPlane 0: " + body.shapes[0].tplanes[0].normal.toString() + "\n"; - s += "TPlane 1: " + body.shapes[0].tplanes[1].normal.toString() + "\n"; - s += "TPlane 2: " + body.shapes[0].tplanes[2].normal.toString() + "\n"; - s += "TPlane 3: " + body.shapes[0].tplanes[3].normal.toString() + "\n"; - - Manager.log.push(s); - */ - }; - AdvancedPhysics.SHAPE_TYPE_CIRCLE = 0; - AdvancedPhysics.SHAPE_TYPE_SEGMENT = 1; - AdvancedPhysics.SHAPE_TYPE_POLY = 2; - AdvancedPhysics.SHAPE_NUM_TYPES = 3; - AdvancedPhysics.JOINT_TYPE_ANGLE = 0; - AdvancedPhysics.JOINT_TYPE_REVOLUTE = 1; - AdvancedPhysics.JOINT_TYPE_WELD = 2; - AdvancedPhysics.JOINT_TYPE_WHEEL = 3; - AdvancedPhysics.JOINT_TYPE_PRISMATIC = 4; - AdvancedPhysics.JOINT_TYPE_DISTANCE = 5; - AdvancedPhysics.JOINT_TYPE_ROPE = 6; - AdvancedPhysics.JOINT_TYPE_MOUSE = 7; - AdvancedPhysics.JOINT_LINEAR_SLOP = 0.0008; - AdvancedPhysics.JOINT_ANGULAR_SLOP = 2 * 0.017453292519943294444444444444444; - AdvancedPhysics.JOINT_MAX_LINEAR_CORRECTION = 0.5; - AdvancedPhysics.JOINT_MAX_ANGULAR_CORRECTION = 8 * 0.017453292519943294444444444444444; - AdvancedPhysics.JOINT_LIMIT_STATE_INACTIVE = 0; - AdvancedPhysics.JOINT_LIMIT_STATE_AT_LOWER = 1; - AdvancedPhysics.JOINT_LIMIT_STATE_AT_UPPER = 2; - AdvancedPhysics.JOINT_LIMIT_STATE_EQUAL_LIMITS = 3; - AdvancedPhysics.CONTACT_SOLVER_COLLISION_SLOP = 0.0008; - AdvancedPhysics.CONTACT_SOLVER_BAUMGARTE = 0.28; - AdvancedPhysics.CONTACT_SOLVER_MAX_LINEAR_CORRECTION = 1; - AdvancedPhysics.bodyCounter = 0; - AdvancedPhysics.jointCounter = 0; - AdvancedPhysics.shapeCounter = 0; - AdvancedPhysics.prototype.update = function () { - // Get these from Phaser.Time instead - 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) { - Physics.Manager.clear(); - 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; - } - } - //frameCount++; - }; - AdvancedPhysics.prototype.addBody = function (body) { - this.space.addBody(body); - }; - AdvancedPhysics.prototype.removeBody = function (body) { - this.space.removeBody(body); - }; - AdvancedPhysics.prototype.addJoint = function (joint) { - this.space.addJoint(joint); - }; - AdvancedPhysics.prototype.removeJoint = function (joint) { - this.space.removeJoint(joint); - }; - AdvancedPhysics.prototype.pixelsToMeters = function (value) { - return value * 0.02; - }; - AdvancedPhysics.prototype.metersToPixels = function (value) { - return value * 50; - }; - AdvancedPhysics.pixelsToMeters = function pixelsToMeters(value) { - return value * 0.02; - }; - AdvancedPhysics.metersToPixels = function metersToPixels(value) { - return value * 50; - }; - AdvancedPhysics.p2m = function p2m(value) { - return value * 0.02; - }; - AdvancedPhysics.m2p = function m2p(value) { - return value * 50; - }; - AdvancedPhysics.areaForCircle = function areaForCircle(radius_outer, radius_inner) { - return Math.PI * (radius_outer * radius_outer - radius_inner * radius_inner); - }; - AdvancedPhysics.inertiaForCircle = function inertiaForCircle(mass, center, radius_outer, radius_inner) { - return mass * ((radius_outer * radius_outer + radius_inner * radius_inner) * 0.5 + center.lengthSq()); - }; - AdvancedPhysics.areaForSegment = function areaForSegment(a, b, radius) { - return radius * (Math.PI * radius + 2 * Phaser.Vec2Utils.distance(a, b)); - }; - AdvancedPhysics.centroidForSegment = function centroidForSegment(a, b) { - return Phaser.Vec2Utils.scale(Phaser.Vec2Utils.add(a, b), 0.5); - }; - AdvancedPhysics.inertiaForSegment = function inertiaForSegment(mass, a, b) { - var distsq = Phaser.Vec2Utils.distanceSq(b, a); - var offset = Phaser.Vec2Utils.scale(Phaser.Vec2Utils.add(a, b), 0.5); - return mass * (distsq / 12 + offset.lengthSq()); - }; - AdvancedPhysics.areaForPoly = function areaForPoly(verts) { - 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; - }; - AdvancedPhysics.centroidForPoly = function centroidForPoly(verts) { - 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)); - }; - AdvancedPhysics.inertiaForPoly = function inertiaForPoly(mass, verts, offset) { - 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); - }; - AdvancedPhysics.inertiaForBox = function inertiaForBox(mass, w, h) { - return mass * (w * w + h * h) / 12; - }; - AdvancedPhysics.createConvexHull = // Create the convex hull using the Gift wrapping algorithm (http://en.wikipedia.org/wiki/Gift_wrapping_algorithm) - function 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; - }; - return AdvancedPhysics; - })(); - Physics.AdvancedPhysics = AdvancedPhysics; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - (function (Physics) { - /// - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - Shapes - Triangle - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Shapes) { - var Triangle = (function (_super) { - __extends(Triangle, _super); - function Triangle(x1, y1, x2, y2, x3, y3) { - x1 = Phaser.Physics.AdvancedPhysics.pixelsToMeters(x1); - y1 = Phaser.Physics.AdvancedPhysics.pixelsToMeters(y1); - x2 = Phaser.Physics.AdvancedPhysics.pixelsToMeters(x2); - y2 = Phaser.Physics.AdvancedPhysics.pixelsToMeters(y2); - x3 = Phaser.Physics.AdvancedPhysics.pixelsToMeters(x3); - y3 = Phaser.Physics.AdvancedPhysics.pixelsToMeters(y3); - _super.call(this, [ - { - x: x1, - y: y1 - }, - { - x: x2, - y: y2 - }, - { - x: x3, - y: y3 - } - ]); - } - return Triangle; - })(Phaser.Physics.Shapes.Poly); - Shapes.Triangle = Triangle; - })(Physics.Shapes || (Physics.Shapes = {})); - var Shapes = Physics.Shapes; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - (function (Physics) { - /// - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - Shapes - Box - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Shapes) { - var Box = (function (_super) { - __extends(Box, _super); - // Give in pixels - function Box(x, y, width, height) { - console.log('Box px', x, y, width, height); - x = Phaser.Physics.AdvancedPhysics.pixelsToMeters(x); - y = Phaser.Physics.AdvancedPhysics.pixelsToMeters(y); - width = Phaser.Physics.AdvancedPhysics.pixelsToMeters(width); - height = Phaser.Physics.AdvancedPhysics.pixelsToMeters(height); - console.log('Box m', x, y, width, height); - var hw = width * 0.5; - var hh = height * 0.5; - console.log('Box hh', hw, hh); - _super.call(this, [ - { - x: -hw + x, - y: +hh + y - }, - { - x: -hw + x, - y: -hh + y - }, - { - x: +hw + x, - y: -hh + y - }, - { - x: +hw + x, - y: +hh + y - } - ]); - } - return Box; - })(Phaser.Physics.Shapes.Poly); - Shapes.Box = Box; - })(Physics.Shapes || (Physics.Shapes = {})); - var Shapes = Physics.Shapes; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - Body - * - * Based on the work Ju Hyung Lee started in JS PhyRus. + * Phaser - ArcadePhysics - Body */ (function (Physics) { var Body = (function () { - function Body(sprite, type, x, y, shapeType) { - if (typeof x === "undefined") { x = 0; } - if (typeof y === "undefined") { y = 0; } - if (typeof shapeType === "undefined") { shapeType = 0; } - this._tempVec2 = new Phaser.Vec2(); - this._fixedRotation = false; - // Shapes - this.shapes = []; - // Joints - this.joints = []; - this.jointHash = { - }; - this.categoryBits = 0x0001; - this.maskBits = 0xFFFF; - this.stepCount = 0; - this._newPosition = new Phaser.Vec2(); - this.id = Phaser.Physics.AdvancedPhysics.bodyCounter++; - this.name = 'body' + this.id; + function Body(sprite, type) { + this.angularVelocity = 0; + this.angularAcceleration = 0; + this.angularDrag = 0; + this.maxAngular = 10000; + this.mass = 1; + this._width = 0; + this._height = 0; + this.sprite = sprite; + this.game = sprite.game; this.type = type; - if(sprite) { - this.sprite = sprite; - this.game = sprite.game; - this.position = new Phaser.Vec2(Phaser.Physics.AdvancedPhysics.pixelsToMeters(sprite.x), Phaser.Physics.AdvancedPhysics.pixelsToMeters(sprite.y)); - this.angle = this.game.math.degreesToRadians(sprite.rotation); - } else { - this.position = new Phaser.Vec2(Phaser.Physics.AdvancedPhysics.pixelsToMeters(x), Phaser.Physics.AdvancedPhysics.pixelsToMeters(y)); - this.angle = 0; - } - this.transform = new Phaser.Transform(this.position, this.angle); - this.centroid = new Phaser.Vec2(); + // Fixture properties + // Will extend into its own class at a later date - can move the fixture defs there and add shape support, but this will do for 1.0 release + this.bounds = new Phaser.Rectangle(); + this._width = sprite.width; + this._height = sprite.height; + // Body properties + //this.gravity = Vec2Utils.clone(ArcadePhysics.gravity); + //this.bounce = Vec2Utils.clone(ArcadePhysics.bounce); this.velocity = new Phaser.Vec2(); - this.force = new Phaser.Vec2(); + this.acceleration = new Phaser.Vec2(); + //this.drag = Vec2Utils.clone(ArcadePhysics.drag); + this.maxVelocity = new Phaser.Vec2(10000, 10000); 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 Physics.Bounds(); + this.angularAcceleration = 0; + this.angularDrag = 0; + this.touching = Phaser.Types.NONE; + this.wasTouching = Phaser.Types.NONE; this.allowCollisions = Phaser.Types.ANY; - this.categoryBits = 0x0001; - this.maskBits = 0xFFFF; - this.stepCount = 0; - if(sprite) { - if(shapeType == 0) { - Phaser.BodyUtils.addBox(this, 0, 0, this.sprite.width, this.sprite.height, 1, 1, 1); - } else { - Phaser.BodyUtils.addCircle(this, Math.max(this.sprite.width, this.sprite.height) / 2, 0, 0, 1, 1, 1); - } - } + this.position = new Phaser.Vec2(sprite.x + this.bounds.halfWidth, sprite.y + this.bounds.halfHeight); + this.oldPosition = new Phaser.Vec2(sprite.x + this.bounds.halfWidth, sprite.y + this.bounds.halfHeight); + this.offset = new Phaser.Vec2(); } - Object.defineProperty(Body.prototype, "rotation", { - get: /** - * The rotation of the body in degrees. Phaser uses a right-handed coordinate system, where 0 points to the right. - */ - function () { - return this.game.math.radiansToDegrees(this.angle); - }, - set: /** - * Set the rotation of the body in degrees. Phaser uses a right-handed coordinate system, where 0 points to the right. - * The value is automatically wrapped to be between 0 and 360. - */ - function (value) { - this.angle = this.game.math.degreesToRadians(this.game.math.wrap(value, 360, 0)); + Object.defineProperty(Body.prototype, "x", { + get: function () { + return this.sprite.x + this.offset.x; }, enumerable: true, configurable: true }); - Object.defineProperty(Body.prototype, "isDisabled", { + Object.defineProperty(Body.prototype, "y", { get: function () { - return this.type == Phaser.Types.BODY_DISABLED ? true : false; + return this.sprite.y + this.offset.y; }, enumerable: true, configurable: true }); - Object.defineProperty(Body.prototype, "isStatic", { + Object.defineProperty(Body.prototype, "width", { get: function () { - return this.type == Phaser.Types.BODY_STATIC ? true : false; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Body.prototype, "isKinetic", { - get: function () { - return this.type == Phaser.Types.BODY_KINETIC ? true : false; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Body.prototype, "isDynamic", { - get: function () { - return this.type == Phaser.Types.BODY_DYNAMIC ? true : false; - }, - enumerable: true, - configurable: true - }); - Body.prototype.setType = function (type) { - 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); - }; - Body.prototype.addShape = function (shape) { - // Check not already part of this body - shape.body = this; - this.shapes.push(shape); - this.shapesLength = this.shapes.length; - return shape; - }; - Body.prototype.removeShape = function (shape) { - var index = this.shapes.indexOf(shape); - if(index != -1) { - this.shapes.splice(index, 1); - shape.body = undefined; - } - this.shapesLength = this.shapes.length; - }; - Body.prototype.setMass = function (mass) { - this.mass = mass; - this.massInverted = mass > 0 ? 1 / mass : 0; - }; - Body.prototype.setInertia = function (inertia) { - this.inertia = inertia; - this.inertiaInverted = inertia > 0 ? 1 / inertia : 0; - }; - Body.prototype.setPosition = function (x, y) { - this._newPosition.setTo(Phaser.Physics.AdvancedPhysics.pixelsToMeters(x), Phaser.Physics.AdvancedPhysics.pixelsToMeters(y)); - this.setTransform(this._newPosition, this.angle); - }; - Body.prototype.setTransform = function (pos, angle) { - // inject the transform into this.position - this.transform.setTo(pos, angle); - //Manager.write('setTransform: ' + this.position.toString()); - //Manager.write('centroid: ' + this.centroid.toString()); - Phaser.TransformUtils.transform(this.transform, this.centroid, this.position); - //Manager.write('post setTransform: ' + this.position.toString()); - //this.position.copyFrom(this.transform.transform(this.centroid)); - this.angle = angle; - }; - Body.prototype.syncTransform = function () { - //Manager.write('syncTransform:'); - //Manager.write('p: ' + this.position.toString()); - //Manager.write('centroid: ' + this.centroid.toString()); - //Manager.write('xf: ' + this.transform.toString()); - //Manager.write('a: ' + this.angle); - this.transform.setRotation(this.angle); - // OPTIMISE: Creating new vector - Phaser.Vec2Utils.subtract(this.position, Phaser.TransformUtils.rotate(this.transform, this.centroid), this.transform.t); - //Manager.write('--------------------'); - //Manager.write('xf: ' + this.transform.toString()); - //Manager.write('--------------------'); - }; - Body.prototype.getWorldPoint = function (p) { - // OPTIMISE: Creating new vector - return Phaser.TransformUtils.transform(this.transform, p); - }; - Body.prototype.getWorldVector = function (v) { - // OPTIMISE: Creating new vector - return Phaser.TransformUtils.rotate(this.transform, v); - }; - Body.prototype.getLocalPoint = function (p) { - // OPTIMISE: Creating new vector - return Phaser.TransformUtils.untransform(this.transform, p); - }; - Body.prototype.getLocalVector = function (v) { - // OPTIMISE: Creating new vector - return Phaser.TransformUtils.unrotate(this.transform, v); - }; - Object.defineProperty(Body.prototype, "fixedRotation", { - get: function () { - return this._fixedRotation; + return this._width * this.sprite.transform.scale.x; }, set: function (value) { - this._fixedRotation = value; - this.resetMassData(); + this._width = value; }, enumerable: true, configurable: true }); - Body.prototype.resetMassData = function () { - 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); - 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); - totalMassCentroid.multiplyAddByScalar(centroid, mass); - totalMass += mass; - totalInertia += inertia; - } - Phaser.Vec2Utils.scale(totalMassCentroid, 1 / totalMass, this.centroid); - this.setMass(totalMass); - if(!this.fixedRotation) { - this.setInertia(totalInertia - totalMass * Phaser.Vec2Utils.dot(this.centroid, this.centroid)); - } - // Move center of mass - var oldPosition = Phaser.Vec2Utils.clone(this.position); - Phaser.TransformUtils.transform(this.transform, this.centroid, this.position); - // Update center of mass velocity - oldPosition.subtract(this.position); - this.velocity.multiplyAddByScalar(Phaser.Vec2Utils.perp(oldPosition, oldPosition), this.angularVelocity); - }; - Body.prototype.resetJointAnchors = function () { - 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); - } - }; - Body.prototype.cacheData = function (source) { - if (typeof source === "undefined") { source = ''; } - //Manager.write('cacheData -- start'); - //Manager.write('p: ' + this.position.toString()); - //Manager.write('xf: ' + this.transform.toString()); - this.bounds.clear(); - for(var i = 0; i < this.shapesLength; i++) { - var shape = this.shapes[i]; - shape.cacheData(this.transform); - this.bounds.addBounds(shape.bounds); - } - //Manager.write('bounds: ' + this.bounds.toString()); - //Manager.write('p: ' + this.position.toString()); - //Manager.write('xf: ' + this.transform.toString()); - //Manager.write('cacheData -- stop'); - }; - Body.prototype.updateVelocity = function (gravity, dt, damping) { - 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.clamp(1 - dt * (damping + this.linearDamping), 0, 1)); - this.angularVelocity *= this.clamp(1 - dt * (damping + this.angularDamping), 0, 1); - this.force.setTo(0, 0); - this.torque = 0; - }; - Body.prototype.inContact = function (body2) { - if(!body2 || this.stepCount == body2.stepCount) { - return false; - } - if(!(this.isAwake && this.isStatic == false) && !(body2.isAwake && body2.isStatic == false)) { - return false; - } - if(this.isCollidable(body2) == false) { - return false; - } - if(!this.bounds.intersectsBounds(body2.bounds)) { - return false; - } - return true; - }; - Body.prototype.clamp = function (v, min, max) { - return v < min ? min : (v > max ? max : v); - }; - Body.prototype.updatePosition = function (dt) { - this.position.add(Phaser.Vec2Utils.scale(this.velocity, dt, this._tempVec2)); - this.angle += this.angularVelocity * dt; - if(this.sprite) { - this.sprite.x = this.position.x * 50; - this.sprite.y = this.position.y * 50; - this.sprite.transform.rotation = this.game.math.radiansToDegrees(this.angle); - } - }; - Body.prototype.resetForce = function () { - this.force.setTo(0, 0); - this.torque = 0; - }; - Body.prototype.applyForce = function (force, p) { - if(this.isDynamic == false) { - return; - } - if(this.isAwake == false) { - this.awake(true); - } - this.force.add(force); - Phaser.Vec2Utils.subtract(p, this.position, this._tempVec2); - this.torque += Phaser.Vec2Utils.cross(this._tempVec2, force); - }; - Body.prototype.applyForceToCenter = function (force) { - if(this.isDynamic == false) { - return; - } - if(this.isAwake == false) { - this.awake(true); - } - this.force.add(force); - }; - Body.prototype.applyTorque = function (torque) { - if(this.isDynamic == false) { - return; - } - if(this.isAwake == false) { - this.awake(true); - } - this.torque += torque; - }; - Body.prototype.applyLinearImpulse = function (impulse, p) { - if(this.isDynamic == false) { - return; - } - if(this.isAwake == false) { - this.awake(true); - } - this.velocity.multiplyAddByScalar(impulse, this.massInverted); - Phaser.Vec2Utils.subtract(p, this.position, this._tempVec2); - this.angularVelocity += Phaser.Vec2Utils.cross(this._tempVec2, impulse) * this.inertiaInverted; - }; - Body.prototype.applyAngularImpulse = function (impulse) { - if(this.isDynamic == false) { - return; - } - if(this.isAwake == false) { - this.awake(true); - } - this.angularVelocity += impulse * this.inertiaInverted; - }; - Body.prototype.kineticEnergy = function () { - return 0.5 * (this.mass * this.velocity.dot(this.velocity) + this.inertia * (this.angularVelocity * this.angularVelocity)); - }; - Object.defineProperty(Body.prototype, "isAwake", { + Object.defineProperty(Body.prototype, "height", { get: function () { - return this.awaked; + return this._height * this.sprite.transform.scale.y; + }, + set: function (value) { + this._height = value; }, enumerable: true, configurable: true }); - Body.prototype.awake = function (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; - } + Body.prototype.preUpdate = function () { + this.oldPosition.copyFrom(this.position); + this.bounds.x = this.x; + this.bounds.y = this.y; + this.bounds.width = this.width; + this.bounds.height = this.height; }; - Body.prototype.isCollidable = function (other) { - if((this.isDynamic == false && other.isDynamic == false) || this == other) { - return false; + Body.prototype.postUpdate = // Shall we do this? Or just update the values directly in the separate functions? But then the bounds will be out of sync - as long as + // the bounds are updated and used in calculations then we can do one final sprite movement here I guess? + function () { + // if this is all it does maybe move elsewhere? Sprite postUpdate? + if(this.type !== Phaser.Types.BODY_DISABLED) { + //this.game.world.physics.updateMotion(this); + this.wasTouching = this.touching; + this.touching = Phaser.Types.NONE; } - 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(!this.joints[i] || (!this.joints[i].collideConnected && other.jointHash[this.joints[i].id] != undefined)) { - return false; + this.position.setTo(this.x, this.y); + }; + Object.defineProperty(Body.prototype, "hullWidth", { + get: function () { + if(this.deltaX > 0) { + return this.bounds.width + this.deltaX; + } else { + return this.bounds.width - this.deltaX; } + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Body.prototype, "hullHeight", { + get: function () { + if(this.deltaY > 0) { + return this.bounds.height + this.deltaY; + } else { + return this.bounds.height - this.deltaY; + } + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Body.prototype, "hullX", { + get: function () { + if(this.position.x < this.oldPosition.x) { + return this.position.x; + } else { + return this.oldPosition.x; + } + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Body.prototype, "hullY", { + get: function () { + if(this.position.y < this.oldPosition.y) { + return this.position.y; + } else { + return this.oldPosition.y; + } + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Body.prototype, "deltaXAbs", { + get: function () { + return (this.deltaX > 0 ? this.deltaX : -this.deltaX); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Body.prototype, "deltaYAbs", { + get: function () { + return (this.deltaY > 0 ? this.deltaY : -this.deltaY); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Body.prototype, "deltaX", { + get: function () { + return this.position.x - this.oldPosition.x; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Body.prototype, "deltaY", { + get: function () { + return this.position.y - this.oldPosition.y; + }, + enumerable: true, + configurable: true + }); + Body.prototype.render = // MOVE THESE TO A UTIL + function (context) { + context.beginPath(); + context.strokeStyle = 'rgb(0,255,0)'; + context.strokeRect(this.position.x - this.bounds.halfWidth, this.position.y - this.bounds.halfHeight, this.bounds.width, this.bounds.height); + context.stroke(); + context.closePath(); + // center point + context.fillStyle = 'rgb(0,255,0)'; + context.fillRect(this.position.x, this.position.y, 2, 2); + if(this.touching & Phaser.Types.LEFT) { + context.beginPath(); + context.strokeStyle = 'rgb(255,0,0)'; + context.moveTo(this.position.x - this.bounds.halfWidth, this.position.y - this.bounds.halfHeight); + context.lineTo(this.position.x - this.bounds.halfWidth, this.position.y + this.bounds.halfHeight); + context.stroke(); + context.closePath(); + } + if(this.touching & Phaser.Types.RIGHT) { + context.beginPath(); + context.strokeStyle = 'rgb(255,0,0)'; + context.moveTo(this.position.x + this.bounds.halfWidth, this.position.y - this.bounds.halfHeight); + context.lineTo(this.position.x + this.bounds.halfWidth, this.position.y + this.bounds.halfHeight); + context.stroke(); + context.closePath(); + } + if(this.touching & Phaser.Types.UP) { + context.beginPath(); + context.strokeStyle = 'rgb(255,0,0)'; + context.moveTo(this.position.x - this.bounds.halfWidth, this.position.y - this.bounds.halfHeight); + context.lineTo(this.position.x + this.bounds.halfWidth, this.position.y - this.bounds.halfHeight); + context.stroke(); + context.closePath(); + } + if(this.touching & Phaser.Types.DOWN) { + context.beginPath(); + context.strokeStyle = 'rgb(255,0,0)'; + context.moveTo(this.position.x - this.bounds.halfWidth, this.position.y + this.bounds.halfHeight); + context.lineTo(this.position.x + this.bounds.halfWidth, this.position.y + this.bounds.halfHeight); + context.stroke(); + context.closePath(); } - return true; }; - Body.prototype.toString = function () { - return "[{Body (name=" + this.name + " velocity=" + this.velocity.toString() + " angularVelocity: " + this.angularVelocity + ")}]"; + Body.prototype.renderDebugInfo = /** + * Render debug infos. (including name, bounds info, position and some other properties) + * @param x {number} X position of the debug info to be rendered. + * @param y {number} Y position of the debug info to be rendered. + * @param [color] {number} color of the debug info to be rendered. (format is css color string) + */ + function (x, y, color) { + if (typeof color === "undefined") { color = 'rgb(255,255,255)'; } + this.sprite.texture.context.fillStyle = color; + this.sprite.texture.context.fillText('Sprite: (' + this.sprite.width + ' x ' + this.sprite.height + ')', x, y); + //this.sprite.texture.context.fillText('x: ' + this._sprite.frameBounds.x.toFixed(1) + ' y: ' + this._sprite.frameBounds.y.toFixed(1) + ' rotation: ' + this._sprite.rotation.toFixed(1), x, y + 14); + this.sprite.texture.context.fillText('x: ' + this.bounds.x.toFixed(1) + ' y: ' + this.bounds.y.toFixed(1) + ' rotation: ' + this.sprite.transform.rotation.toFixed(0), x, y + 14); + this.sprite.texture.context.fillText('vx: ' + this.velocity.x.toFixed(1) + ' vy: ' + this.velocity.y.toFixed(1), x, y + 28); + this.sprite.texture.context.fillText('acx: ' + this.acceleration.x.toFixed(1) + ' acy: ' + this.acceleration.y.toFixed(1), x, y + 42); + this.sprite.texture.context.fillText('angVx: ' + this.angularVelocity.toFixed(1) + ' angAc: ' + this.angularAcceleration.toFixed(1), x, y + 56); }; return Body; })(); @@ -7186,7 +5679,7 @@ var Phaser; /// /// /// -/// +/// /** * Phaser - Sprite */ @@ -7292,8 +5785,8 @@ var Phaser; function (value) { this.transform.rotation = this.game.math.wrap(value, 360, 0); if(this.body) { - this.body.angle = this.game.math.degreesToRadians(this.game.math.wrap(value, 360, 0)); - } + //this.body.angle = this.game.math.degreesToRadians(this.game.math.wrap(value, 360, 0)); + } }, enumerable: true, configurable: true @@ -14890,9 +13383,9 @@ var Phaser; /** * Phaser * -* v1.0.0 - June XX 2013 +* v1.0.0 - August 12th 2013 * -* A small and feature-packed 2D canvas game framework born from the firey pits of Flixel and Kiwi. +* A feature-packed 2D canvas game framework born from the firey pits of Flixel and Kiwi. * * Richard Davey (@photonstorm) * @@ -16227,64 +14720,26 @@ var Phaser; var Phaser; (function (Phaser) { /// - /// - /// /** * Phaser - Physics Manager * - * The Physics Manager is responsible for looking after, creating and colliding - * all of the physics bodies and joints in the world. + * Eventually this will handle switching between the default ArcadePhysics manager or the new AdvancedPhysics manager. + * For now we direct everything through ArcadePhysics. */ (function (Physics) { var Manager = (function () { function Manager(game) { this.game = game; + this.arcade = new Phaser.Physics.ArcadePhysics(this.game, this.game.stage.width, this.game.stage.height); + this.gravity = this.arcade.gravity; + this.bounds = this.arcade.bounds; } - Manager.clear = function clear() { - //Manager.debug.textContent = ""; - Manager.log = []; - }; - Manager.write = function write(s) { - //Manager.debug.textContent += s + "\n"; + Manager.prototype.update = /** + * Called by the main Game.loop + */ + function () { + //this.arcade.updateMotion }; - Manager.writeAll = function writeAll() { - for(var i = 0; i < Manager.log.length; i++) { - //Manager.debug.textContent += Manager.log[i]; - } - }; - Manager.log = []; - Manager.dump = function dump(phase, body) { - /* - var s = "\n\nPhase: " + phase + "\n"; - s += "Position: " + body.position.toString() + "\n"; - s += "Velocity: " + body.velocity.toString() + "\n"; - s += "Angle: " + body.angle + "\n"; - s += "Force: " + body.force.toString() + "\n"; - s += "Torque: " + body.torque + "\n"; - s += "Bounds: " + body.bounds.toString() + "\n"; - s += "Shape ***\n"; - s += "Vert 0: " + body.shapes[0].verts[0].toString() + "\n"; - s += "Vert 1: " + body.shapes[0].verts[1].toString() + "\n"; - s += "Vert 2: " + body.shapes[0].verts[2].toString() + "\n"; - s += "Vert 3: " + body.shapes[0].verts[3].toString() + "\n"; - s += "TVert 0: " + body.shapes[0].tverts[0].toString() + "\n"; - s += "TVert 1: " + body.shapes[0].tverts[1].toString() + "\n"; - s += "TVert 2: " + body.shapes[0].tverts[2].toString() + "\n"; - s += "TVert 3: " + body.shapes[0].tverts[3].toString() + "\n"; - s += "Plane 0: " + body.shapes[0].planes[0].normal.toString() + "\n"; - s += "Plane 1: " + body.shapes[0].planes[1].normal.toString() + "\n"; - s += "Plane 2: " + body.shapes[0].planes[2].normal.toString() + "\n"; - s += "Plane 3: " + body.shapes[0].planes[3].normal.toString() + "\n"; - s += "TPlane 0: " + body.shapes[0].tplanes[0].normal.toString() + "\n"; - s += "TPlane 1: " + body.shapes[0].tplanes[1].normal.toString() + "\n"; - s += "TPlane 2: " + body.shapes[0].tplanes[2].normal.toString() + "\n"; - s += "TPlane 3: " + body.shapes[0].tplanes[3].normal.toString() + "\n"; - - Manager.log.push(s); - */ - }; - Manager.prototype.update = function () { - }; return Manager; })(); Physics.Manager = Manager; @@ -16431,309 +14886,6 @@ var Phaser; })(); Phaser.World = World; })(Phaser || (Phaser = {})); -/// -/// -/** -* Phaser - Motion -* -* The Motion class contains lots of useful functions for moving game objects around in world space. -*/ -var Phaser; -(function (Phaser) { - var Motion = (function () { - function Motion(game) { - this.game = game; - } - Motion.prototype.velocityFromAngle = /** - * Given the angle and speed calculate the velocity and return it as a Point - * - * @param {number} angle The angle (in degrees) calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative) - * @param {number} speed The speed it will move, in pixels per second sq - * - * @return {Point} A Point where Point.x contains the velocity x value and Point.y contains the velocity y value - */ - function (angle, speed) { - if(isNaN(speed)) { - speed = 0; - } - var a = this.game.math.degreesToRadians(angle); - return new Phaser.Point((Math.cos(a) * speed), (Math.sin(a) * speed)); - }; - Motion.prototype.moveTowardsObject = /** - * Sets the source Sprite x/y velocity so it will move directly towards the destination Sprite at the speed given (in pixels per second)
- * If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds.
- * Timings are approximate due to the way Flash timers work, and irrespective of SWF frame rate. Allow for a variance of +- 50ms.
- * The source object doesn't stop moving automatically should it ever reach the destination coordinates.
- * If you need the object to accelerate, see accelerateTowardsObject() instead - * Note: Doesn't take into account acceleration, maxVelocity or drag (if you set drag or acceleration too high this object may not move at all) - * - * @param {Sprite} source The Sprite on which the velocity will be set - * @param {Sprite} dest The Sprite where the source object will move to - * @param {number} speed The speed it will move, in pixels per second (default is 60 pixels/sec) - * @param {number} maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms - */ - function (source, dest, speed, maxTime) { - if (typeof speed === "undefined") { speed = 60; } - if (typeof maxTime === "undefined") { maxTime = 0; } - var a = this.angleBetween(source, dest); - if(maxTime > 0) { - var d = this.distanceBetween(source, dest); - // We know how many pixels we need to move, but how fast? - speed = d / (maxTime / 1000); - } - source.body.velocity.x = Math.cos(a) * speed; - source.body.velocity.y = Math.sin(a) * speed; - }; - Motion.prototype.accelerateTowardsObject = /** - * Sets the x/y acceleration on the source Sprite so it will move towards the destination Sprite at the speed given (in pixels per second)
- * You must give a maximum speed value, beyond which the Sprite won't go any faster.
- * If you don't need acceleration look at moveTowardsObject() instead. - * - * @param {Sprite} source The Sprite on which the acceleration will be set - * @param {Sprite} dest The Sprite where the source object will move towards - * @param {number} speed The speed it will accelerate in pixels per second - * @param {number} xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally - * @param {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically - */ - function (source, dest, speed, xSpeedMax, ySpeedMax) { - /* - var a: number = this.angleBetween(source, dest); - - source.body.velocity.x = 0; - source.body.velocity.y = 0; - - source.body.acceleration.x = Math.cos(a) * speed; - source.body.acceleration.y = Math.sin(a) * speed; - - source.body.maxVelocity.x = xSpeedMax; - source.body.maxVelocity.y = ySpeedMax; - */ - }; - Motion.prototype.moveTowardsMouse = /** - * Move the given Sprite towards the mouse pointer coordinates at a steady velocity - * If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds.
- * Timings are approximate due to the way Flash timers work, and irrespective of SWF frame rate. Allow for a variance of +- 50ms.
- * The source object doesn't stop moving automatically should it ever reach the destination coordinates.
- * - * @param {Sprite} source The Sprite to move - * @param {number} speed The speed it will move, in pixels per second (default is 60 pixels/sec) - * @param {number} maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms - */ - function (source, speed, maxTime) { - if (typeof speed === "undefined") { speed = 60; } - if (typeof maxTime === "undefined") { maxTime = 0; } - var a = this.angleBetweenMouse(source); - if(maxTime > 0) { - var d = this.distanceToMouse(source); - // We know how many pixels we need to move, but how fast? - speed = d / (maxTime / 1000); - } - source.body.velocity.x = Math.cos(a) * speed; - source.body.velocity.y = Math.sin(a) * speed; - }; - Motion.prototype.accelerateTowardsMouse = /** - * Sets the x/y acceleration on the source Sprite so it will move towards the mouse coordinates at the speed given (in pixels per second)
- * You must give a maximum speed value, beyond which the Sprite won't go any faster.
- * If you don't need acceleration look at moveTowardsMouse() instead. - * - * @param {Sprite} source The Sprite on which the acceleration will be set - * @param {number} speed The speed it will accelerate in pixels per second - * @param {number} xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally - * @param {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically - */ - function (source, speed, xSpeedMax, ySpeedMax) { - /* - var a: number = this.angleBetweenMouse(source); - - source.body.velocity.x = 0; - source.body.velocity.y = 0; - - source.body.acceleration.x = Math.cos(a) * speed; - source.body.acceleration.y = Math.sin(a) * speed; - - source.body.maxVelocity.x = xSpeedMax; - source.body.maxVelocity.y = ySpeedMax; - */ - }; - Motion.prototype.moveTowardsPoint = /** - * Sets the x/y velocity on the source Sprite so it will move towards the target coordinates at the speed given (in pixels per second)
- * If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds.
- * Timings are approximate due to the way Flash timers work, and irrespective of SWF frame rate. Allow for a variance of +- 50ms.
- * The source object doesn't stop moving automatically should it ever reach the destination coordinates.
- * - * @param {Sprite} source The Sprite to move - * @param {Point} target The Point coordinates to move the source Sprite towards - * @param {number} speed The speed it will move, in pixels per second (default is 60 pixels/sec) - * @param {number} maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms - */ - function (source, target, speed, maxTime) { - if (typeof speed === "undefined") { speed = 60; } - if (typeof maxTime === "undefined") { maxTime = 0; } - var a = this.angleBetweenPoint(source, target); - if(maxTime > 0) { - var d = this.distanceToPoint(source, target); - // We know how many pixels we need to move, but how fast? - speed = d / (maxTime / 1000); - } - source.body.velocity.x = Math.cos(a) * speed; - source.body.velocity.y = Math.sin(a) * speed; - }; - Motion.prototype.accelerateTowardsPoint = /** - * Sets the x/y acceleration on the source Sprite so it will move towards the target coordinates at the speed given (in pixels per second)
- * You must give a maximum speed value, beyond which the Sprite won't go any faster.
- * If you don't need acceleration look at moveTowardsPoint() instead. - * - * @param {Sprite} source The Sprite on which the acceleration will be set - * @param {Point} target The Point coordinates to move the source Sprite towards - * @param {number} speed The speed it will accelerate in pixels per second - * @param {number} xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally - * @param {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically - */ - function (source, target, speed, xSpeedMax, ySpeedMax) { - /* - var a: number = this.angleBetweenPoint(source, target); - - source.body.velocity.x = 0; - source.body.velocity.y = 0; - - source.body.acceleration.x = Math.cos(a) * speed; - source.body.acceleration.y = Math.sin(a) * speed; - - source.body.maxVelocity.x = xSpeedMax; - source.body.maxVelocity.y = ySpeedMax; - */ - }; - Motion.prototype.distanceBetween = /** - * Find the distance between two Sprites, taking their origin into account - * - * @param {Sprite} a The first Sprite - * @param {Sprite} b The second Sprite - * @return {number} int Distance (in pixels) - */ - function (a, b) { - return Phaser.Vec2Utils.distance(a.body.position, b.body.position); - }; - Motion.prototype.distanceToPoint = /** - * Find the distance from an Sprite to the given Point, taking the source origin into account - * - * @param {Sprite} a The Sprite - * @param {Point} target The Point - * @return {number} Distance (in pixels) - */ - function (a, target) { - var dx = (a.x + a.transform.origin.x) - (target.x); - var dy = (a.y + a.transform.origin.y) - (target.y); - return this.game.math.vectorLength(dx, dy); - }; - Motion.prototype.distanceToMouse = /** - * Find the distance (in pixels, rounded) from the object x/y and the mouse x/y - * - * @param {Sprite} a Sprite to test against - * @return {number} The distance between the given sprite and the mouse coordinates - */ - function (a) { - var dx = (a.x + a.transform.origin.x) - this.game.input.x; - var dy = (a.y + a.transform.origin.y) - this.game.input.y; - return this.game.math.vectorLength(dx, dy); - }; - Motion.prototype.angleBetweenPoint = /** - * Find the angle (in radians) between an Sprite and an Point. The source sprite takes its x/y and origin into account. - * The angle is calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative) - * - * @param {Sprite} a The Sprite to test from - * @param {Point} target The Point to angle the Sprite towards - * @param {boolean} asDegrees If you need the value in degrees instead of radians, set to true - * - * @return {number} The angle (in radians unless asDegrees is true) - */ - function (a, target, asDegrees) { - if (typeof asDegrees === "undefined") { asDegrees = false; } - var dx = (target.x) - (a.x + a.transform.origin.x); - var dy = (target.y) - (a.y + a.transform.origin.y); - if(asDegrees) { - return this.game.math.radiansToDegrees(Math.atan2(dy, dx)); - } else { - return Math.atan2(dy, dx); - } - }; - Motion.prototype.angleBetween = /** - * Find the angle (in radians) between the two Sprite, taking their x/y and origin into account. - * The angle is calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative) - * - * @param {Sprite} a The Sprite to test from - * @param {Sprite} b The Sprite to test to - * @param {boolean} asDegrees If you need the value in degrees instead of radians, set to true - * - * @return {number} The angle (in radians unless asDegrees is true) - */ - function (a, b, asDegrees) { - if (typeof asDegrees === "undefined") { asDegrees = false; } - var dx = (b.x + b.transform.origin.x) - (a.x + a.transform.origin.x); - var dy = (b.y + b.transform.origin.y) - (a.y + a.transform.origin.y); - if(asDegrees) { - return this.game.math.radiansToDegrees(Math.atan2(dy, dx)); - } else { - return Math.atan2(dy, dx); - } - }; - Motion.prototype.velocityFromFacing = /** - * Given the Sprite and speed calculate the velocity and return it as an Point based on the direction the sprite is facing - * - * @param {Sprite} parent The Sprite to get the facing value from - * @param {number} speed The speed it will move, in pixels per second sq - * - * @return {Point} An Point where Point.x contains the velocity x value and Point.y contains the velocity y value - */ - function (parent, speed) { - /* - var a: number; - - if (parent.body.facing == Types.LEFT) - { - a = this.game.math.degreesToRadians(180); - } - else if (parent.body.facing == Types.RIGHT) - { - a = this.game.math.degreesToRadians(0); - } - else if (parent.body.facing == Types.UP) - { - a = this.game.math.degreesToRadians(-90); - } - else if (parent.body.facing == Types.DOWN) - { - a = this.game.math.degreesToRadians(90); - } - - return new Point(Math.cos(a) * speed, Math.sin(a) * speed); - */ - return new Phaser.Point(); - }; - Motion.prototype.angleBetweenMouse = /** - * Find the angle (in radians) between an Sprite and the mouse, taking their x/y and origin into account. - * The angle is calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative) - * - * @param {Sprite} a The Object to test from - * @param {boolean} asDegrees If you need the value in degrees instead of radians, set to true - * - * @return {number} The angle (in radians unless asDegrees is true) - */ - function (a, asDegrees) { - if (typeof asDegrees === "undefined") { asDegrees = false; } - // In order to get the angle between the object and mouse, we need the objects screen coordinates (rather than world coordinates) - var p = Phaser.SpriteUtils.getScreenXY(a); - var dx = a.game.input.x - p.x; - var dy = a.game.input.y - p.y; - if(asDegrees) { - return this.game.math.radiansToDegrees(Math.atan2(dy, dx)); - } else { - return Math.atan2(dy, dx); - } - }; - return Motion; - })(); - Phaser.Motion = Motion; -})(Phaser || (Phaser = {})); /// /** * Phaser - Device @@ -19694,6 +17846,9 @@ var Phaser; if(sprite.transform.scale.x == 0 || sprite.transform.scale.y == 0 || sprite.texture.alpha < 0.1 || this.inCamera(camera, sprite) == false) { return false; } + if(sprite.crop && sprite.crop.empty) { + return; + } sprite.renderOrderID = this._count; this._count++; // Reset our temp vars @@ -19968,32 +18123,6 @@ var Phaser; DebugUtils.context.fillText('cx: ' + sprite.cameraView.x + ' cy: ' + sprite.cameraView.y + ' cw: ' + sprite.cameraView.width + ' ch: ' + sprite.cameraView.height + ' cb: ' + sprite.cameraView.bottom + ' cr: ' + sprite.cameraView.right, x, y + 70); DebugUtils.context.fillText('inCamera: ' + DebugUtils.game.renderer.inCamera(DebugUtils.game.camera, sprite), x, y + 84); }; - DebugUtils.renderPhysicsBodyInfo = /** - * Render debug infos. (including name, bounds info, position and some other properties) - * @param x {number} X position of the debug info to be rendered. - * @param y {number} Y position of the debug info to be rendered. - * @param [color] {number} color of the debug info to be rendered. (format is css color string) - */ - function renderPhysicsBodyInfo(body, x, y, color) { - if (typeof color === "undefined") { color = 'rgb(255,255,255)'; } - DebugUtils.context.fillStyle = color; - DebugUtils.context.fillText('Body ID: ' + body.name, x, y); - DebugUtils.context.fillText('Position x: ' + body.position.x.toFixed(1) + ' y: ' + body.position.y.toFixed(1) + ' rotation: ' + body.angle.toFixed(1), x, y + 14); - DebugUtils.context.fillText('World x: ' + (body.position.x * 50).toFixed(1) + ' y: ' + (body.position.y * 50).toFixed(1), x, y + 28); - DebugUtils.context.fillText('Velocity x: ' + body.velocity.x.toFixed(1) + ' y: ' + body.velocity.y.toFixed(1), x, y + 42); - if(body.shapes[0].verts.length > 0) { - DebugUtils.context.fillText('Vert 1 x: ' + (body.shapes[0].verts[0].x * 50) + ' y: ' + (body.shapes[0].verts[0].y * 50), x, y + 56); - DebugUtils.context.fillText('Vert 2 x: ' + (body.shapes[0].verts[1].x * 50) + ' y: ' + (body.shapes[0].verts[1].y * 50), x, y + 70); - DebugUtils.context.fillText('Vert 3 x: ' + (body.shapes[0].tverts[2].x * 50) + ' y: ' + (body.shapes[0].tverts[2].y * 50), x, y + 84); - DebugUtils.context.fillText('Vert 4 x: ' + (body.shapes[0].tverts[3].x * 50) + ' y: ' + (body.shapes[0].tverts[3].y * 50), x, y + 98); - /* - DebugUtils.context.fillText('Vert 1 x: ' + body.shapes[0].verts[0].x.toFixed(1) + ' y: ' + body.shapes[0].verts[0].y.toFixed(1), x, y + 56); - DebugUtils.context.fillText('Vert 2 x: ' + body.shapes[0].verts[1].x.toFixed(1) + ' y: ' + body.shapes[0].verts[1].y.toFixed(1), x, y + 70); - DebugUtils.context.fillText('Vert 3 x: ' + body.shapes[0].verts[2].x.toFixed(1) + ' y: ' + body.shapes[0].verts[2].y.toFixed(1), x, y + 84); - DebugUtils.context.fillText('Vert 4 x: ' + body.shapes[0].verts[3].x.toFixed(1) + ' y: ' + body.shapes[0].verts[3].y.toFixed(1), x, y + 98); - */ - } - }; DebugUtils.renderSpriteBounds = function renderSpriteBounds(sprite, camera, color) { if (typeof camera === "undefined") { camera = null; } if (typeof color === "undefined") { color = 'rgba(0,255,0,0.2)'; } @@ -20028,35 +18157,6 @@ var Phaser; DebugUtils.context.fillStyle = color; DebugUtils.context.fillText(text, x, y); }; - DebugUtils.renderPhysicsBody = function renderPhysicsBody(body, lineWidth, fillStyle, sleepStyle) { - if (typeof lineWidth === "undefined") { lineWidth = 1; } - if (typeof fillStyle === "undefined") { fillStyle = 'rgba(0,255,0,0.2)'; } - if (typeof sleepStyle === "undefined") { sleepStyle = 'rgba(100,100,100,0.2)'; } - for(var s = 0; s < body.shapesLength; s++) { - DebugUtils.context.beginPath(); - if(body.shapes[s].type == Phaser.Physics.AdvancedPhysics.SHAPE_TYPE_POLY) { - var verts = body.shapes[s].tverts; - // DebugUtils.context.moveTo(body.position.x * 50 + verts[0].x, body.position.y * 50 + verts[0].y); - DebugUtils.context.moveTo(verts[0].x * 50, verts[0].y * 50); - for(var i = 1; i < verts.length; i++) { - // DebugUtils.context.lineTo(body.position.x * 50 + verts[i].x, body.position.y * 50 + verts[i].y); - DebugUtils.context.lineTo(verts[i].x * 50, verts[i].y * 50); - } - // DebugUtils.context.lineTo(body.position.x * 50 + verts[0].x, body.position.y * 50 + verts[0].y); - DebugUtils.context.lineTo(verts[0].x * 50, verts[0].y * 50); - } else if(body.shapes[s].type == Phaser.Physics.AdvancedPhysics.SHAPE_TYPE_CIRCLE) { - var circle = body.shapes[s]; - DebugUtils.context.arc(circle.tc.x * 50, circle.tc.y * 50, circle.radius * 50, 0, Math.PI * 2, false); - } - DebugUtils.context.closePath(); - if(body.isAwake) { - DebugUtils.context.fillStyle = fillStyle; - } else { - DebugUtils.context.fillStyle = sleepStyle; - } - DebugUtils.context.fill(); - } - }; return DebugUtils; })(); Phaser.DebugUtils = DebugUtils; @@ -20083,7 +18183,6 @@ var Phaser; /// /// /// -/// /// /// /// @@ -20245,7 +18344,6 @@ var Phaser; } else { this.device = new Phaser.Device(); this.net = new Phaser.Net(this); - this.motion = new Phaser.Motion(this); this.math = new Phaser.GameMath(this); this.stage = new Phaser.Stage(this, parent, width, height); this.world = new Phaser.World(this, width, height); @@ -20881,174 +18979,6 @@ var Phaser; Phaser.Line = Line; })(Phaser || (Phaser = {})); /// -/// -/// -/// -/** -* Phaser - CircleUtils -* -* A collection of methods useful for manipulating and comparing Circle objects. -* -* TODO: -*/ -var Phaser; -(function (Phaser) { - var CircleUtils = (function () { - function CircleUtils() { } - CircleUtils.clone = /** - * Returns a new Circle object with the same values for the x, y, width, and height properties as the original Circle object. - * @method clone - * @param {Circle} a - The Circle object. - * @param {Circle} [optional] out Optional Circle object. If given the values will be set into the object, otherwise a brand new Circle object will be created and returned. - * @return {Phaser.Circle} - **/ - function clone(a, out) { - if (typeof out === "undefined") { out = new Phaser.Circle(); } - return out.setTo(a.x, a.y, a.diameter); - }; - CircleUtils.contains = /** - * Return true if the given x/y coordinates are within the Circle object. - * If you need details about the intersection then use Phaser.Intersect.circleContainsPoint instead. - * @method contains - * @param {Circle} a - The Circle object. - * @param {Number} The X value of the coordinate to test. - * @param {Number} The Y value of the coordinate to test. - * @return {Boolean} True if the coordinates are within this circle, otherwise false. - **/ - function contains(a, x, y) { - // Check if x/y are within the bounds first - if(x >= a.left && x <= a.right && y >= a.top && y <= a.bottom) { - var dx = (a.x - x) * (a.x - x); - var dy = (a.y - y) * (a.y - y); - return (dx + dy) <= (a.radius * a.radius); - } - return false; - }; - CircleUtils.containsPoint = /** - * Return true if the coordinates of the given Point object are within this Circle object. - * If you need details about the intersection then use Phaser.Intersect.circleContainsPoint instead. - * @method containsPoint - * @param {Circle} a - The Circle object. - * @param {Point} The Point object to test. - * @return {Boolean} True if the coordinates are within this circle, otherwise false. - **/ - function containsPoint(a, point) { - return CircleUtils.contains(a, point.x, point.y); - }; - CircleUtils.containsCircle = /** - * Return true if the given Circle is contained entirely within this Circle object. - * If you need details about the intersection then use Phaser.Intersect.circleToCircle instead. - * @method containsCircle - * @param {Circle} The Circle object to test. - * @return {Boolean} True if the coordinates are within this circle, otherwise false. - **/ - function containsCircle(a, b) { - //return ((a.radius + b.radius) * (a.radius + b.radius)) >= Collision.distanceSquared(a.x, a.y, b.x, b.y); - return true; - }; - CircleUtils.distanceBetween = /** - * Returns the distance from the center of the Circle object to the given object (can be Circle, Point or anything with x/y properties) - * @method distanceBetween - * @param {Circle} a - The Circle object. - * @param {Circle} b - The target object. Must have visible x and y properties that represent the center of the object. - * @param {Boolean} [optional] round - Round the distance to the nearest integer (default false) - * @return {Number} The distance between this Point object and the destination Point object. - **/ - function distanceBetween(a, target, round) { - if (typeof round === "undefined") { round = false; } - var dx = a.x - target.x; - var dy = a.y - target.y; - if(round === true) { - return Math.round(Math.sqrt(dx * dx + dy * dy)); - } else { - return Math.sqrt(dx * dx + dy * dy); - } - }; - CircleUtils.equals = /** - * Determines whether the two Circle objects match. This method compares the x, y and diameter properties. - * @method equals - * @param {Circle} a - The first Circle object. - * @param {Circle} b - The second Circle object. - * @return {Boolean} A value of true if the object has exactly the same values for the x, y and diameter properties as this Circle object; otherwise false. - **/ - function equals(a, b) { - return (a.x == b.x && a.y == b.y && a.diameter == b.diameter); - }; - CircleUtils.intersects = /** - * Determines whether the two Circle objects intersect. - * This method checks the radius distances between the two Circle objects to see if they intersect. - * @method intersects - * @param {Circle} a - The first Circle object. - * @param {Circle} b - The second Circle object. - * @return {Boolean} A value of true if the specified object intersects with this Circle object; otherwise false. - **/ - function intersects(a, b) { - return (CircleUtils.distanceBetween(a, b) <= (a.radius + b.radius)); - }; - CircleUtils.circumferencePoint = /** - * Returns a Point object containing the coordinates of a point on the circumference of the Circle based on the given angle. - * @method circumferencePoint - * @param {Circle} a - The first Circle object. - * @param {Number} angle The angle in radians (unless asDegrees is true) to return the point from. - * @param {Boolean} asDegrees Is the given angle in radians (false) or degrees (true)? - * @param {Phaser.Point} [optional] output An optional Point object to put the result in to. If none specified a new Point object will be created. - * @return {Phaser.Point} The Point object holding the result. - **/ - function circumferencePoint(a, angle, asDegrees, out) { - if (typeof asDegrees === "undefined") { asDegrees = false; } - if (typeof out === "undefined") { out = new Phaser.Point(); } - if(asDegrees === true) { - angle = angle * Phaser.GameMath.DEG_TO_RAD; - } - return out.setTo(a.x + a.radius * Math.cos(angle), a.y + a.radius * Math.sin(angle)); - }; - CircleUtils.intersectsRectangle = /* - public static boolean intersect(Rectangle r, Circle c) - { - float cx = Math.abs(c.x - r.x - r.halfWidth); - float xDist = r.halfWidth + c.radius; - if (cx > xDist) - return false; - float cy = Math.abs(c.y - r.y - r.halfHeight); - float yDist = r.halfHeight + c.radius; - if (cy > yDist) - return false; - if (cx <= r.halfWidth || cy <= r.halfHeight) - return true; - float xCornerDist = cx - r.halfWidth; - float yCornerDist = cy - r.halfHeight; - float xCornerDistSq = xCornerDist * xCornerDist; - float yCornerDistSq = yCornerDist * yCornerDist; - float maxCornerDistSq = c.radius * c.radius; - return xCornerDistSq + yCornerDistSq <= maxCornerDistSq; - } - */ - function intersectsRectangle(c, r) { - var cx = Math.abs(c.x - r.x - r.halfWidth); - var xDist = r.halfWidth + c.radius; - if(cx > xDist) { - return false; - } - var cy = Math.abs(c.y - r.y - r.halfHeight); - var yDist = r.halfHeight + c.radius; - if(cy > yDist) { - return false; - } - if(cx <= r.halfWidth || cy <= r.halfHeight) { - return true; - } - var xCornerDist = cx - r.halfWidth; - var yCornerDist = cy - r.halfHeight; - var xCornerDistSq = xCornerDist * xCornerDist; - var yCornerDistSq = yCornerDist * yCornerDist; - var maxCornerDistSq = c.radius * c.radius; - return xCornerDistSq + yCornerDistSq <= maxCornerDistSq; - }; - return CircleUtils; - })(); - Phaser.CircleUtils = CircleUtils; -})(Phaser || (Phaser = {})); -/// /// /// /** @@ -21203,956 +19133,400 @@ var Phaser; })(); Phaser.Mat3Utils = Mat3Utils; })(Phaser || (Phaser = {})); +/// +/// +/** +* Phaser - 2D Transform +* +* A 2D Transform +*/ var Phaser; (function (Phaser) { - /// - /// - /// - /// - /// - /** - * 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. - */ - (function (Physics) { - var ArcadePhysics = (function () { - function ArcadePhysics(game, width, height) { - this._length = 0; - /** - * @type {number} - */ - this.worldDivisions = 6; - this.game = game; - this.gravity = new Phaser.Vec2(); - this.drag = new Phaser.Vec2(); - this.bounce = new Phaser.Vec2(); - this.angularDrag = 0; - this.bounds = new Phaser.Rectangle(0, 0, width, height); - this._distance = new Phaser.Vec2(); - this._tangent = new Phaser.Vec2(); - this.members = new Phaser.Group(game); - } - ArcadePhysics.OVERLAP_BIAS = 4; - ArcadePhysics.TILE_OVERLAP = false; - ArcadePhysics.prototype.updateMotion = /* - public update() { - - this._length = this._objects.length; - - for (var i = 0; i < this._length; i++) - { - if (this._objects[i]) - { - this._objects[i].preUpdate(); - this.updateMotion(this._objects[i]); - this.collideWorld(this._objects[i]); - - for (var x = 0; x < this._length; x++) - { - if (this._objects[x] && this._objects[x] !== this._objects[i]) - { - //this.collideShapes(this._objects[i], this._objects[x]); - var r = this.NEWseparate(this._objects[i], this._objects[x]); - //console.log('sep', r); - } - } - - } - } - - } - - public render() { - - // iterate through the objects here, updating and colliding - for (var i = 0; i < this._length; i++) - { - if (this._objects[i]) - { - this._objects[i].render(this.game.stage.context); - } - } - - } - */ - function (body) { - if(body.type == Phaser.Types.BODY_DISABLED) { - return; - } - this._velocityDelta = (this.computeVelocity(body.angularVelocity, body.gravity.x, body.angularAcceleration, body.angularDrag, body.maxAngular) - body.angularVelocity) / 2; - body.angularVelocity += this._velocityDelta; - body.sprite.transform.rotation += body.angularVelocity * this.game.time.elapsed; - body.angularVelocity += this._velocityDelta; - this._velocityDelta = (this.computeVelocity(body.velocity.x, body.gravity.x, body.acceleration.x, body.drag.x) - body.velocity.x) / 2; - body.velocity.x += this._velocityDelta; - this._delta = body.velocity.x * this.game.time.elapsed; - body.velocity.x += this._velocityDelta; - //body.position.x += this._delta; - body.sprite.x += this._delta; - this._velocityDelta = (this.computeVelocity(body.velocity.y, body.gravity.y, body.acceleration.y, body.drag.y) - body.velocity.y) / 2; - body.velocity.y += this._velocityDelta; - this._delta = body.velocity.y * this.game.time.elapsed; - body.velocity.y += this._velocityDelta; - //body.position.y += this._delta; - body.sprite.y += this._delta; - }; - ArcadePhysics.prototype.computeVelocity = /** - * 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. - */ - function (velocity, gravity, acceleration, drag, max) { - if (typeof gravity === "undefined") { gravity = 0; } - if (typeof acceleration === "undefined") { acceleration = 0; } - if (typeof drag === "undefined") { drag = 0; } - if (typeof max === "undefined") { max = 10000; } - if(acceleration !== 0) { - velocity += (acceleration + gravity) * this.game.time.elapsed; - } else if(drag !== 0) { - this._drag = drag * this.game.time.elapsed; - if(velocity - this._drag > 0) { - velocity = velocity - this._drag; - } else if(velocity + this._drag < 0) { - velocity += this._drag; - } else { - velocity = 0; - } - velocity += gravity; - } - if((velocity != 0) && (max != 10000)) { - if(velocity > max) { - velocity = max; - } else if(velocity < -max) { - velocity = -max; - } - } - return velocity; - }; - ArcadePhysics.prototype.separate = /** - * 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. - */ - function (body1, body2) { - this._separatedX = this.separateBodyX(body1, body2); - this._separatedY = this.separateBodyY(body1, body2); - return this._separatedX || this._separatedY; - }; - ArcadePhysics.prototype.checkHullIntersection = function (body1, body2) { - return ((body1.hullX + body1.hullWidth > body2.hullX) && (body1.hullX < body2.hullX + body2.hullWidth) && (body1.hullY + body1.hullHeight > body2.hullY) && (body1.hullY < body2.hullY + body2.hullHeight)); - }; - ArcadePhysics.prototype.separateBodyX = /** - * 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. - */ - function (body1, body2) { - // Can't separate two disabled or static objects - if((body1.type == Phaser.Types.BODY_DISABLED || body1.type == Phaser.Types.BODY_STATIC) && (body2.type == Phaser.Types.BODY_DISABLED || body2.type == Phaser.Types.BODY_STATIC)) { - return false; - } - // First, get the two object deltas - this._overlap = 0; - if(body1.deltaX != body2.deltaX) { - if(Phaser.RectangleUtils.intersects(body1.bounds, body2.bounds)) { - this._maxOverlap = body1.deltaXAbs + body2.deltaXAbs + PhysicsManager.OVERLAP_BIAS; - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if(body1.deltaX > body2.deltaX) { - this._overlap = body1.bounds.right - body2.bounds.x; - if((this._overlap > this._maxOverlap) || !(body1.allowCollisions & Phaser.Types.RIGHT) || !(body2.allowCollisions & Phaser.Types.LEFT)) { - this._overlap = 0; - } else { - body1.touching |= Phaser.Types.RIGHT; - body2.touching |= Phaser.Types.LEFT; - } - } else if(body1.deltaX < body2.deltaX) { - this._overlap = body1.bounds.x - body2.bounds.width - body2.bounds.x; - if((-this._overlap > this._maxOverlap) || !(body1.allowCollisions & Phaser.Types.LEFT) || !(body2.allowCollisions & Phaser.Types.RIGHT)) { - this._overlap = 0; - } else { - body1.touching |= Phaser.Types.LEFT; - body2.touching |= Phaser.Types.RIGHT; - } - } - } - } - // Then adjust their positions and velocities accordingly (if there was any overlap) - if(this._overlap != 0) { - this._obj1Velocity = body1.velocity.x; - this._obj2Velocity = body2.velocity.x; - /** - * 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 - */ - // 2 dynamic bodies will exchange velocities - if(body1.type == Phaser.Types.BODY_DYNAMIC && body2.type == Phaser.Types.BODY_DYNAMIC) { - this._overlap *= 0.5; - body1.position.x = body1.position.x - this._overlap; - body2.position.x += this._overlap; - this._obj1NewVelocity = Math.sqrt((this._obj2Velocity * this._obj2Velocity * body2.mass) / body1.mass) * ((this._obj2Velocity > 0) ? 1 : -1); - this._obj2NewVelocity = Math.sqrt((this._obj1Velocity * this._obj1Velocity * body1.mass) / body2.mass) * ((this._obj1Velocity > 0) ? 1 : -1); - this._average = (this._obj1NewVelocity + this._obj2NewVelocity) * 0.5; - this._obj1NewVelocity -= this._average; - this._obj2NewVelocity -= this._average; - body1.velocity.x = this._average + this._obj1NewVelocity * body1.bounce.x; - body2.velocity.x = this._average + this._obj2NewVelocity * body2.bounce.x; - } else if(body2.type != Phaser.Types.BODY_DYNAMIC) { - // Body 2 is Static or Kinematic - this._overlap *= 2; - body1.position.x -= this._overlap; - body1.velocity.x = this._obj2Velocity - this._obj1Velocity * body1.bounce.x; - } else if(body1.type != Phaser.Types.BODY_DYNAMIC) { - // Body 1 is Static or Kinematic - this._overlap *= 2; - body2.position.x += this._overlap; - body2.velocity.x = this._obj1Velocity - this._obj2Velocity * body2.bounce.x; - } - return true; - } else { - return false; - } - }; - ArcadePhysics.prototype.separateBodyY = /** - * 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. - */ - function (body1, body2) { - // Can't separate two immovable objects - if((body1.type == Phaser.Types.BODY_DISABLED || body1.type == Phaser.Types.BODY_STATIC) && (body2.type == Phaser.Types.BODY_DISABLED || body2.type == Phaser.Types.BODY_STATIC)) { - return false; - } - // First, get the two object deltas - this._overlap = 0; - if(body1.deltaY != body2.deltaY) { - if(Phaser.RectangleUtils.intersects(body1.bounds, body2.bounds)) { - // This is the only place to use the DeltaAbs values - this._maxOverlap = body1.deltaYAbs + body2.deltaYAbs + PhysicsManager.OVERLAP_BIAS; - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if(body1.deltaY > body2.deltaY) { - this._overlap = body1.bounds.bottom - body2.bounds.y; - if((this._overlap > this._maxOverlap) || !(body1.allowCollisions & Phaser.Types.DOWN) || !(body2.allowCollisions & Phaser.Types.UP)) { - this._overlap = 0; - } else { - body1.touching |= Phaser.Types.DOWN; - body2.touching |= Phaser.Types.UP; - } - } else if(body1.deltaY < body2.deltaY) { - this._overlap = body1.bounds.y - body2.bounds.height - body2.bounds.y; - if((-this._overlap > this._maxOverlap) || !(body1.allowCollisions & Phaser.Types.UP) || !(body2.allowCollisions & Phaser.Types.DOWN)) { - this._overlap = 0; - } else { - body1.touching |= Phaser.Types.UP; - body2.touching |= Phaser.Types.DOWN; - } - } - } - } - // Then adjust their positions and velocities accordingly (if there was any overlap) - if(this._overlap != 0) { - this._obj1Velocity = body1.velocity.y; - this._obj2Velocity = body2.velocity.y; - /** - * 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 - */ - if(body1.type == Phaser.Types.BODY_DYNAMIC && body2.type == Phaser.Types.BODY_DYNAMIC) { - this._overlap *= 0.5; - body1.position.y = body1.position.y - this._overlap; - body2.position.y += this._overlap; - this._obj1NewVelocity = Math.sqrt((this._obj2Velocity * this._obj2Velocity * body2.mass) / body1.mass) * ((this._obj2Velocity > 0) ? 1 : -1); - this._obj2NewVelocity = Math.sqrt((this._obj1Velocity * this._obj1Velocity * body1.mass) / body2.mass) * ((this._obj1Velocity > 0) ? 1 : -1); - var average = (this._obj1NewVelocity + this._obj2NewVelocity) * 0.5; - this._obj1NewVelocity -= average; - this._obj2NewVelocity -= average; - body1.velocity.y = average + this._obj1NewVelocity * body1.bounce.y; - body2.velocity.y = average + this._obj2NewVelocity * body2.bounce.y; - } else if(body2.type != Phaser.Types.BODY_DYNAMIC) { - this._overlap *= 2; - body1.position.y -= this._overlap; - body1.velocity.y = this._obj2Velocity - this._obj1Velocity * body1.bounce.y; - // This is special case code that handles things like horizontal moving platforms you can ride - //if (body2.parent.active && body2.moves && (body1.deltaY > body2.deltaY)) - if(body2.sprite.active && (body1.deltaY > body2.deltaY)) { - body1.position.x += body2.position.x - body2.oldPosition.x; - } - } else if(body1.type != Phaser.Types.BODY_DYNAMIC) { - this._overlap *= 2; - body2.position.y += this._overlap; - body2.velocity.y = this._obj1Velocity - this._obj2Velocity * body2.bounce.y; - // This is special case code that handles things like horizontal moving platforms you can ride - //if (object1.active && body1.moves && (body1.deltaY < body2.deltaY)) - if(body1.sprite.active && (body1.deltaY < body2.deltaY)) { - body2.position.x += body1.position.x - body1.oldPosition.x; - } - } - return true; - } else { - return false; - } - }; - ArcadePhysics.prototype.overlap = /* - private TILEseparate(shapeA: IPhysicsShape, shapeB: IPhysicsShape, distance: Vec2, tangent: Vec2) { - - if (tangent.x == 1) - { - console.log('1 The left side of ShapeA hit the right side of ShapeB', Math.floor(distance.x)); - shapeA.physics.touching |= Phaser.Types.LEFT; - shapeB.physics.touching |= Phaser.Types.RIGHT; - } - else if (tangent.x == -1) - { - console.log('2 The right side of ShapeA hit the left side of ShapeB', Math.floor(distance.x)); - shapeA.physics.touching |= Phaser.Types.RIGHT; - shapeB.physics.touching |= Phaser.Types.LEFT; - } - - if (tangent.y == 1) - { - console.log('3 The top of ShapeA hit the bottom of ShapeB', Math.floor(distance.y)); - shapeA.physics.touching |= Phaser.Types.UP; - shapeB.physics.touching |= Phaser.Types.DOWN; - } - else if (tangent.y == -1) - { - console.log('4 The bottom of ShapeA hit the top of ShapeB', Math.floor(distance.y)); - shapeA.physics.touching |= Phaser.Types.DOWN; - shapeB.physics.touching |= Phaser.Types.UP; - } - - - // only apply collision response forces if the object is travelling into, and not out of, the collision - var dot = Vec2Utils.dot(shapeA.physics.velocity, tangent); - - if (dot < 0) - { - console.log('in to', dot); - - // Apply horizontal bounce - if (shapeA.physics.bounce.x > 0) - { - shapeA.physics.velocity.x *= -(shapeA.physics.bounce.x); - } - else - { - shapeA.physics.velocity.x = 0; - } - // Apply horizontal bounce - if (shapeA.physics.bounce.y > 0) - { - shapeA.physics.velocity.y *= -(shapeA.physics.bounce.y); - } - else - { - shapeA.physics.velocity.y = 0; - } - } - else - { - console.log('out of', dot); - } - - shapeA.position.x += Math.floor(distance.x); - //shapeA.bounds.x += Math.floor(distance.x); - - shapeA.position.y += Math.floor(distance.y); - //shapeA.bounds.y += distance.y; - - console.log('------------------------------------------------'); - - } - - private collideWorld(shape:IPhysicsShape) { - - // Collide on the x-axis - this._distance.x = shape.world.bounds.x - (shape.position.x - shape.bounds.halfWidth); - - if (0 < this._distance.x) - { - // Hit Left - this._tangent.setTo(1, 0); - this.separateXWall(shape, this._distance, this._tangent); - } - else - { - this._distance.x = (shape.position.x + shape.bounds.halfWidth) - shape.world.bounds.right; - - if (0 < this._distance.x) - { - // Hit Right - this._tangent.setTo(-1, 0); - this._distance.reverse(); - this.separateXWall(shape, this._distance, this._tangent); - } - } - - // Collide on the y-axis - this._distance.y = shape.world.bounds.y - (shape.position.y - shape.bounds.halfHeight); - - if (0 < this._distance.y) - { - // Hit Top - this._tangent.setTo(0, 1); - this.separateYWall(shape, this._distance, this._tangent); - } - else - { - this._distance.y = (shape.position.y + shape.bounds.halfHeight) - shape.world.bounds.bottom; - - if (0 < this._distance.y) - { - // Hit Bottom - this._tangent.setTo(0, -1); - this._distance.reverse(); - this.separateYWall(shape, this._distance, this._tangent); - } - } - - } - - private separateX(shapeA: IPhysicsShape, shapeB: IPhysicsShape, distance: Vec2, tangent: Vec2) { - - if (tangent.x == 1) - { - console.log('The left side of ShapeA hit the right side of ShapeB', distance.x); - shapeA.physics.touching |= Phaser.Types.LEFT; - shapeB.physics.touching |= Phaser.Types.RIGHT; - } - else - { - console.log('The right side of ShapeA hit the left side of ShapeB', distance.x); - shapeA.physics.touching |= Phaser.Types.RIGHT; - shapeB.physics.touching |= Phaser.Types.LEFT; - } - - // collision edges - //shapeA.oH = tangent.x; - - // only apply collision response forces if the object is travelling into, and not out of, the collision - if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) - { - // Apply horizontal bounce - if (shapeA.physics.bounce.x > 0) - { - shapeA.physics.velocity.x *= -(shapeA.physics.bounce.x); - } - else - { - shapeA.physics.velocity.x = 0; - } - } - - shapeA.position.x += distance.x; - shapeA.bounds.x += distance.x; - - } - - private separateY(shapeA: IPhysicsShape, shapeB: IPhysicsShape, distance: Vec2, tangent: Vec2) { - - if (tangent.y == 1) - { - console.log('The top of ShapeA hit the bottom of ShapeB', distance.y); - shapeA.physics.touching |= Phaser.Types.UP; - shapeB.physics.touching |= Phaser.Types.DOWN; - } - else - { - console.log('The bottom of ShapeA hit the top of ShapeB', distance.y); - shapeA.physics.touching |= Phaser.Types.DOWN; - shapeB.physics.touching |= Phaser.Types.UP; - } - - // collision edges - //shapeA.oV = tangent.y; - - // only apply collision response forces if the object is travelling into, and not out of, the collision - if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) - { - // Apply horizontal bounce - if (shapeA.physics.bounce.y > 0) - { - shapeA.physics.velocity.y *= -(shapeA.physics.bounce.y); - } - else - { - shapeA.physics.velocity.y = 0; - } - } - - shapeA.position.y += distance.y; - shapeA.bounds.y += distance.y; - - } - - private separateXWall(shapeA: IPhysicsShape, distance: Vec2, tangent: Vec2) { - - if (tangent.x == 1) - { - console.log('The left side of ShapeA hit the right side of ShapeB', distance.x); - shapeA.physics.touching |= Phaser.Types.LEFT; - } - else - { - console.log('The right side of ShapeA hit the left side of ShapeB', distance.x); - shapeA.physics.touching |= Phaser.Types.RIGHT; - } - - // collision edges - //shapeA.oH = tangent.x; - - // only apply collision response forces if the object is travelling into, and not out of, the collision - if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) - { - // Apply horizontal bounce - if (shapeA.physics.bounce.x > 0) - { - shapeA.physics.velocity.x *= -(shapeA.physics.bounce.x); - } - else - { - shapeA.physics.velocity.x = 0; - } - } - - shapeA.position.x += distance.x; - - } - - private separateYWall(shapeA: IPhysicsShape, distance: Vec2, tangent: Vec2) { - - if (tangent.y == 1) - { - console.log('The top of ShapeA hit the bottom of ShapeB', distance.y); - shapeA.physics.touching |= Phaser.Types.UP; - } - else - { - console.log('The bottom of ShapeA hit the top of ShapeB', distance.y); - shapeA.physics.touching |= Phaser.Types.DOWN; - } - - // collision edges - //shapeA.oV = tangent.y; - - // only apply collision response forces if the object is travelling into, and not out of, the collision - if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) - { - // Apply horizontal bounce - if (shapeA.physics.bounce.y > 0) - { - shapeA.physics.velocity.y *= -(shapeA.physics.bounce.y); - } - else - { - shapeA.physics.velocity.y = 0; - } - } - - shapeA.position.y += distance.y; - - } - */ - /** - * 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. - */ - function (object1, object2, notifyCallback, processCallback, context) { - if (typeof object1 === "undefined") { object1 = null; } - if (typeof object2 === "undefined") { object2 = null; } - if (typeof notifyCallback === "undefined") { notifyCallback = null; } - if (typeof processCallback === "undefined") { processCallback = null; } - if (typeof context === "undefined") { context = null; } - /* - if (object1 == null) - { - object1 = this.game.world.group; - } - - if (object2 == object1) - { - object2 = null; - } - - QuadTree.divisions = this.worldDivisions; - - this._quadTree = new Phaser.QuadTree(this, this.bounds.x, this.bounds.y, this.bounds.width, this.bounds.height); - - this._quadTree.load(object1, object2, notifyCallback, processCallback, context); - - this._quadTreeResult = this._quadTree.execute(); - - console.log('over', this._quadTreeResult); - - this._quadTree.destroy(); - - this._quadTree = null; - - return this._quadTreeResult; - */ - return false; - }; - ArcadePhysics.prototype.separateTile = /** - * 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 - */ - function (object, x, y, width, height, mass, collideLeft, collideRight, collideUp, collideDown, separateX, separateY) { - //var separatedX: bool = this.separateTileX(object, x, y, width, height, mass, collideLeft, collideRight, separateX); - //var separatedY: bool = this.separateTileY(object, x, y, width, height, mass, collideUp, collideDown, separateY); - //return separatedX || separatedY; - return false; - }; - return ArcadePhysics; - })(); - Physics.ArcadePhysics = ArcadePhysics; + var Transform = (function () { /** - * Separates the two objects on their x axis - * @param object The GameObject to separate - * @param tile The Tile to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the X axis. + * Creates a new 2D Transform object. + * @class Transform + * @constructor + * @return {Transform} This object + **/ + function Transform(pos, angle) { + this.t = Phaser.Vec2Utils.clone(pos); + this.c = Math.cos(angle); + this.s = Math.sin(angle); + this.angle = angle; + } + Transform.prototype.toString = function () { + return 't=' + this.t.toString() + ' c=' + this.c + ' s=' + this.s + ' a=' + this.angle; + }; + Transform.prototype.setTo = function (pos, angle) { + this.t.copyFrom(pos); + this.c = Math.cos(angle); + this.s = Math.sin(angle); + return this; + }; + Transform.prototype.setRotation = function (angle) { + if(angle !== this.angle) { + this.c = Math.cos(angle); + this.s = Math.sin(angle); + this.angle = angle; + } + return this; + }; + Transform.prototype.setPosition = function (p) { + this.t.copyFrom(p); + return this; + }; + Transform.prototype.identity = function () { + this.t.setTo(0, 0); + this.c = 1; + this.s = 0; + return this; + }; + return Transform; + })(); + Phaser.Transform = Transform; +})(Phaser || (Phaser = {})); +/// +/// +/// +/** +* Phaser - TransformUtils +* +* A collection of methods useful for manipulating and performing operations on 2D Transforms. +* +*/ +var Phaser; +(function (Phaser) { + var TransformUtils = (function () { + function TransformUtils() { } + TransformUtils.rotate = function rotate(t, v, out) { + if (typeof out === "undefined") { out = new Phaser.Vec2(); } + //return new vec2(v.x * this.c - v.y * this.s, v.x * this.s + v.y * this.c); + return out.setTo(v.x * t.c - v.y * t.s, v.x * t.s + v.y * t.c); + }; + TransformUtils.unrotate = function unrotate(t, v, out) { + if (typeof out === "undefined") { out = new Phaser.Vec2(); } + //return new vec2(v.x * this.c + v.y * this.s, -v.x * this.s + v.y * this.c); + return out.setTo(v.x * t.c + v.y * t.s, -v.x * t.s + v.y * t.c); + }; + TransformUtils.transform = function transform(t, v, out) { + if (typeof out === "undefined") { out = new Phaser.Vec2(); } + //return new vec2(v.x * this.c - v.y * this.s + this.t.x, v.x * this.s + v.y * this.c + this.t.y); + 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); + }; + TransformUtils.untransform = function untransform(t, v, out) { + if (typeof out === "undefined") { out = new Phaser.Vec2(); } + var px = v.x - t.t.x; + var py = v.y - t.t.y; + //return new vec2(px * this.c + py * this.s, -px * this.s + py * this.c); + return out.setTo(px * t.c + py * t.s, -px * t.s + py * t.c); + }; + return TransformUtils; + })(); + Phaser.TransformUtils = TransformUtils; +})(Phaser || (Phaser = {})); +/// +/// +/** +* Phaser - Motion +* +* The Motion class contains lots of useful functions for moving game objects around in world space. +*/ +var Phaser; +(function (Phaser) { + var Motion = (function () { + function Motion(game) { + this.game = game; + } + Motion.prototype.velocityFromAngle = /** + * Given the angle and speed calculate the velocity and return it as a Point + * + * @param {number} angle The angle (in degrees) calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative) + * @param {number} speed The speed it will move, in pixels per second sq + * + * @return {Point} A Point where Point.x contains the velocity x value and Point.y contains the velocity y value */ - /* - public separateTileX(object:Sprite, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool, separate: bool): bool { - - // Can't separate two immovable objects (tiles are always immovable) - if (object.immovable) - { - return false; - } - - // First, get the object delta - var overlap: number = 0; - var objDelta: number = object.x - object.last.x; - //var objDelta: number = object.collisionMask.deltaX; - - if (objDelta != 0) - { - // Check if the X hulls actually overlap - var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; - //var objDeltaAbs: number = object.collisionMask.deltaXAbs; - var objBounds: Rectangle = new Rectangle(object.x - ((objDelta > 0) ? objDelta : 0), object.last.y, object.width + ((objDelta > 0) ? objDelta : -objDelta), object.height); - - if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) - { - var maxOverlap: number = objDeltaAbs + Collision.OVERLAP_BIAS; - - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if (objDelta > 0) - { - overlap = object.x + object.width - x; - - if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.RIGHT) || collideLeft == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.RIGHT; - } - } - else if (objDelta < 0) - { - overlap = object.x - width - x; - - if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.LEFT) || collideRight == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.LEFT; - } - - } - - } - } - - // Then adjust their positions and velocities accordingly (if there was any overlap) - if (overlap != 0) - { - if (separate == true) - { - //console.log(' - object.x = object.x - overlap; - object.velocity.x = -(object.velocity.x * object.elasticity); - } - - Collision.TILE_OVERLAP = true; - return true; - } - else - { - return false; - } - - } + function (angle, speed) { + if(isNaN(speed)) { + speed = 0; + } + var a = this.game.math.degreesToRadians(angle); + return new Phaser.Point((Math.cos(a) * speed), (Math.sin(a) * speed)); + }; + Motion.prototype.moveTowardsObject = /** + * Sets the source Sprite x/y velocity so it will move directly towards the destination Sprite at the speed given (in pixels per second)
+ * If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds.
+ * Timings are approximate due to the way Flash timers work, and irrespective of SWF frame rate. Allow for a variance of +- 50ms.
+ * The source object doesn't stop moving automatically should it ever reach the destination coordinates.
+ * If you need the object to accelerate, see accelerateTowardsObject() instead + * Note: Doesn't take into account acceleration, maxVelocity or drag (if you set drag or acceleration too high this object may not move at all) + * + * @param {Sprite} source The Sprite on which the velocity will be set + * @param {Sprite} dest The Sprite where the source object will move to + * @param {number} speed The speed it will move, in pixels per second (default is 60 pixels/sec) + * @param {number} maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms */ - /** - * Separates the two objects on their y axis - * @param object The first GameObject to separate - * @param tile The second GameObject to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis. + function (source, dest, speed, maxTime) { + if (typeof speed === "undefined") { speed = 60; } + if (typeof maxTime === "undefined") { maxTime = 0; } + var a = this.angleBetween(source, dest); + if(maxTime > 0) { + var d = this.distanceBetween(source, dest); + // We know how many pixels we need to move, but how fast? + speed = d / (maxTime / 1000); + } + source.body.velocity.x = Math.cos(a) * speed; + source.body.velocity.y = Math.sin(a) * speed; + }; + Motion.prototype.accelerateTowardsObject = /** + * Sets the x/y acceleration on the source Sprite so it will move towards the destination Sprite at the speed given (in pixels per second)
+ * You must give a maximum speed value, beyond which the Sprite won't go any faster.
+ * If you don't need acceleration look at moveTowardsObject() instead. + * + * @param {Sprite} source The Sprite on which the acceleration will be set + * @param {Sprite} dest The Sprite where the source object will move towards + * @param {number} speed The speed it will accelerate in pixels per second + * @param {number} xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally + * @param {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically */ - /* - public separateTileY(object: Sprite, x: number, y: number, width: number, height: number, mass: number, collideUp: bool, collideDown: bool, separate: bool): bool { - - // Can't separate two immovable objects (tiles are always immovable) - if (object.immovable) - { - return false; - } - - // First, get the two object deltas - var overlap: number = 0; - var objDelta: number = object.y - object.last.y; - - if (objDelta != 0) - { - // Check if the Y hulls actually overlap - var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; - var objBounds: Rectangle = new Rectangle(object.x, object.y - ((objDelta > 0) ? objDelta : 0), object.width, object.height + objDeltaAbs); - - if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) - { - var maxOverlap: number = objDeltaAbs + Collision.OVERLAP_BIAS; - - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if (objDelta > 0) - { - overlap = object.y + object.height - y; - - if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.DOWN) || collideUp == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.DOWN; - } - } - else if (objDelta < 0) - { - overlap = object.y - height - y; - - if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.UP) || collideDown == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.UP; - } - } - } - } - - // TODO - with super low velocities you get lots of stuttering, set some kind of base minimum here - - // Then adjust their positions and velocities accordingly (if there was any overlap) - if (overlap != 0) - { - if (separate == true) - { - object.y = object.y - overlap; - object.velocity.y = -(object.velocity.y * object.elasticity); - } - - Collision.TILE_OVERLAP = true; - return true; - } - else - { - return false; - } - } + function (source, dest, speed, xSpeedMax, ySpeedMax) { + /* + var a: number = this.angleBetween(source, dest); + + source.body.velocity.x = 0; + source.body.velocity.y = 0; + + source.body.acceleration.x = Math.cos(a) * speed; + source.body.acceleration.y = Math.sin(a) * speed; + + source.body.maxVelocity.x = xSpeedMax; + source.body.maxVelocity.y = ySpeedMax; + */ + }; + Motion.prototype.moveTowardsMouse = /** + * Move the given Sprite towards the mouse pointer coordinates at a steady velocity + * If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds.
+ * Timings are approximate due to the way Flash timers work, and irrespective of SWF frame rate. Allow for a variance of +- 50ms.
+ * The source object doesn't stop moving automatically should it ever reach the destination coordinates.
+ * + * @param {Sprite} source The Sprite to move + * @param {number} speed The speed it will move, in pixels per second (default is 60 pixels/sec) + * @param {number} maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms */ - /** - * Separates the two objects on their x axis - * @param object The GameObject to separate - * @param tile The Tile to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the X axis. + function (source, speed, maxTime) { + if (typeof speed === "undefined") { speed = 60; } + if (typeof maxTime === "undefined") { maxTime = 0; } + var a = this.angleBetweenMouse(source); + if(maxTime > 0) { + var d = this.distanceToMouse(source); + // We know how many pixels we need to move, but how fast? + speed = d / (maxTime / 1000); + } + source.body.velocity.x = Math.cos(a) * speed; + source.body.velocity.y = Math.sin(a) * speed; + }; + Motion.prototype.accelerateTowardsMouse = /** + * Sets the x/y acceleration on the source Sprite so it will move towards the mouse coordinates at the speed given (in pixels per second)
+ * You must give a maximum speed value, beyond which the Sprite won't go any faster.
+ * If you don't need acceleration look at moveTowardsMouse() instead. + * + * @param {Sprite} source The Sprite on which the acceleration will be set + * @param {number} speed The speed it will accelerate in pixels per second + * @param {number} xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally + * @param {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically */ - /* - public static NEWseparateTileX(object:Sprite, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool, separate: bool): bool { - - // Can't separate two immovable objects (tiles are always immovable) - if (object.immovable) - { - return false; - } - - // First, get the object delta - var overlap: number = 0; - - if (object.collisionMask.deltaX != 0) - { - // Check if the X hulls actually overlap - //var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; - //var objBounds: Rectangle = new Rectangle(object.x - ((objDelta > 0) ? objDelta : 0), object.last.y, object.width + ((objDelta > 0) ? objDelta : -objDelta), object.height); - - //if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) - if (object.collisionMask.intersectsRaw(x, x + width, y, y + height)) - { - var maxOverlap: number = object.collisionMask.deltaXAbs + Collision.OVERLAP_BIAS; - - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if (object.collisionMask.deltaX > 0) - { - //overlap = object.x + object.width - x; - overlap = object.collisionMask.right - x; - - if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.RIGHT) || collideLeft == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.RIGHT; - } - } - else if (object.collisionMask.deltaX < 0) - { - //overlap = object.x - width - x; - overlap = object.collisionMask.x - width - x; - - if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.LEFT) || collideRight == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.LEFT; - } - - } - - } - } - - // Then adjust their positions and velocities accordingly (if there was any overlap) - if (overlap != 0) - { - if (separate == true) - { - object.x = object.x - overlap; - object.velocity.x = -(object.velocity.x * object.elasticity); - } - - Collision.TILE_OVERLAP = true; - return true; - } - else - { - return false; - } - - } + function (source, speed, xSpeedMax, ySpeedMax) { + /* + var a: number = this.angleBetweenMouse(source); + + source.body.velocity.x = 0; + source.body.velocity.y = 0; + + source.body.acceleration.x = Math.cos(a) * speed; + source.body.acceleration.y = Math.sin(a) * speed; + + source.body.maxVelocity.x = xSpeedMax; + source.body.maxVelocity.y = ySpeedMax; + */ + }; + Motion.prototype.moveTowardsPoint = /** + * Sets the x/y velocity on the source Sprite so it will move towards the target coordinates at the speed given (in pixels per second)
+ * If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds.
+ * Timings are approximate due to the way Flash timers work, and irrespective of SWF frame rate. Allow for a variance of +- 50ms.
+ * The source object doesn't stop moving automatically should it ever reach the destination coordinates.
+ * + * @param {Sprite} source The Sprite to move + * @param {Point} target The Point coordinates to move the source Sprite towards + * @param {number} speed The speed it will move, in pixels per second (default is 60 pixels/sec) + * @param {number} maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms */ - /** - * Separates the two objects on their y axis - * @param object The first GameObject to separate - * @param tile The second GameObject to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis. + function (source, target, speed, maxTime) { + if (typeof speed === "undefined") { speed = 60; } + if (typeof maxTime === "undefined") { maxTime = 0; } + var a = this.angleBetweenPoint(source, target); + if(maxTime > 0) { + var d = this.distanceToPoint(source, target); + // We know how many pixels we need to move, but how fast? + speed = d / (maxTime / 1000); + } + source.body.velocity.x = Math.cos(a) * speed; + source.body.velocity.y = Math.sin(a) * speed; + }; + Motion.prototype.accelerateTowardsPoint = /** + * Sets the x/y acceleration on the source Sprite so it will move towards the target coordinates at the speed given (in pixels per second)
+ * You must give a maximum speed value, beyond which the Sprite won't go any faster.
+ * If you don't need acceleration look at moveTowardsPoint() instead. + * + * @param {Sprite} source The Sprite on which the acceleration will be set + * @param {Point} target The Point coordinates to move the source Sprite towards + * @param {number} speed The speed it will accelerate in pixels per second + * @param {number} xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally + * @param {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically */ - /* - public NEWseparateTileY(object: Sprite, x: number, y: number, width: number, height: number, mass: number, collideUp: bool, collideDown: bool, separate: bool): bool { - - // Can't separate two immovable objects (tiles are always immovable) - if (object.immovable) - { - return false; - } - - // First, get the two object deltas - var overlap: number = 0; - //var objDelta: number = object.y - object.last.y; - - if (object.collisionMask.deltaY != 0) - { - // Check if the Y hulls actually overlap - //var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; - //var objBounds: Rectangle = new Rectangle(object.x, object.y - ((objDelta > 0) ? objDelta : 0), object.width, object.height + objDeltaAbs); - - //if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) - if (object.collisionMask.intersectsRaw(x, x + width, y, y + height)) - { - //var maxOverlap: number = objDeltaAbs + Collision.OVERLAP_BIAS; - var maxOverlap: number = object.collisionMask.deltaYAbs + Collision.OVERLAP_BIAS; - - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if (object.collisionMask.deltaY > 0) - { - //overlap = object.y + object.height - y; - overlap = object.collisionMask.bottom - y; - - if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.DOWN) || collideUp == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.DOWN; - } - } - else if (object.collisionMask.deltaY < 0) - { - //overlap = object.y - height - y; - overlap = object.collisionMask.y - height - y; - - if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.UP) || collideDown == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.UP; - } - } - } - } - - // TODO - with super low velocities you get lots of stuttering, set some kind of base minimum here - - // Then adjust their positions and velocities accordingly (if there was any overlap) - if (overlap != 0) - { - if (separate == true) - { - object.y = object.y - overlap; - object.velocity.y = -(object.velocity.y * object.elasticity); - } - - Collision.TILE_OVERLAP = true; - return true; - } - else - { - return false; - } - } + function (source, target, speed, xSpeedMax, ySpeedMax) { + /* + var a: number = this.angleBetweenPoint(source, target); + + source.body.velocity.x = 0; + source.body.velocity.y = 0; + + source.body.acceleration.x = Math.cos(a) * speed; + source.body.acceleration.y = Math.sin(a) * speed; + + source.body.maxVelocity.x = xSpeedMax; + source.body.maxVelocity.y = ySpeedMax; + */ + }; + Motion.prototype.distanceBetween = /** + * Find the distance between two Sprites, taking their origin into account + * + * @param {Sprite} a The first Sprite + * @param {Sprite} b The second Sprite + * @return {number} int Distance (in pixels) */ - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; + function (a, b) { + return Phaser.Vec2Utils.distance(a.body.position, b.body.position); + }; + Motion.prototype.distanceToPoint = /** + * Find the distance from an Sprite to the given Point, taking the source origin into account + * + * @param {Sprite} a The Sprite + * @param {Point} target The Point + * @return {number} Distance (in pixels) + */ + function (a, target) { + var dx = (a.x + a.transform.origin.x) - (target.x); + var dy = (a.y + a.transform.origin.y) - (target.y); + return this.game.math.vectorLength(dx, dy); + }; + Motion.prototype.distanceToMouse = /** + * Find the distance (in pixels, rounded) from the object x/y and the mouse x/y + * + * @param {Sprite} a Sprite to test against + * @return {number} The distance between the given sprite and the mouse coordinates + */ + function (a) { + var dx = (a.x + a.transform.origin.x) - this.game.input.x; + var dy = (a.y + a.transform.origin.y) - this.game.input.y; + return this.game.math.vectorLength(dx, dy); + }; + Motion.prototype.angleBetweenPoint = /** + * Find the angle (in radians) between an Sprite and an Point. The source sprite takes its x/y and origin into account. + * The angle is calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative) + * + * @param {Sprite} a The Sprite to test from + * @param {Point} target The Point to angle the Sprite towards + * @param {boolean} asDegrees If you need the value in degrees instead of radians, set to true + * + * @return {number} The angle (in radians unless asDegrees is true) + */ + function (a, target, asDegrees) { + if (typeof asDegrees === "undefined") { asDegrees = false; } + var dx = (target.x) - (a.x + a.transform.origin.x); + var dy = (target.y) - (a.y + a.transform.origin.y); + if(asDegrees) { + return this.game.math.radiansToDegrees(Math.atan2(dy, dx)); + } else { + return Math.atan2(dy, dx); + } + }; + Motion.prototype.angleBetween = /** + * Find the angle (in radians) between the two Sprite, taking their x/y and origin into account. + * The angle is calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative) + * + * @param {Sprite} a The Sprite to test from + * @param {Sprite} b The Sprite to test to + * @param {boolean} asDegrees If you need the value in degrees instead of radians, set to true + * + * @return {number} The angle (in radians unless asDegrees is true) + */ + function (a, b, asDegrees) { + if (typeof asDegrees === "undefined") { asDegrees = false; } + var dx = (b.x + b.transform.origin.x) - (a.x + a.transform.origin.x); + var dy = (b.y + b.transform.origin.y) - (a.y + a.transform.origin.y); + if(asDegrees) { + return this.game.math.radiansToDegrees(Math.atan2(dy, dx)); + } else { + return Math.atan2(dy, dx); + } + }; + Motion.prototype.velocityFromFacing = /** + * Given the Sprite and speed calculate the velocity and return it as an Point based on the direction the sprite is facing + * + * @param {Sprite} parent The Sprite to get the facing value from + * @param {number} speed The speed it will move, in pixels per second sq + * + * @return {Point} An Point where Point.x contains the velocity x value and Point.y contains the velocity y value + */ + function (parent, speed) { + /* + var a: number; + + if (parent.body.facing == Types.LEFT) + { + a = this.game.math.degreesToRadians(180); + } + else if (parent.body.facing == Types.RIGHT) + { + a = this.game.math.degreesToRadians(0); + } + else if (parent.body.facing == Types.UP) + { + a = this.game.math.degreesToRadians(-90); + } + else if (parent.body.facing == Types.DOWN) + { + a = this.game.math.degreesToRadians(90); + } + + return new Point(Math.cos(a) * speed, Math.sin(a) * speed); + */ + return new Phaser.Point(); + }; + Motion.prototype.angleBetweenMouse = /** + * Find the angle (in radians) between an Sprite and the mouse, taking their x/y and origin into account. + * The angle is calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative) + * + * @param {Sprite} a The Object to test from + * @param {boolean} asDegrees If you need the value in degrees instead of radians, set to true + * + * @return {number} The angle (in radians unless asDegrees is true) + */ + function (a, asDegrees) { + if (typeof asDegrees === "undefined") { asDegrees = false; } + // In order to get the angle between the object and mouse, we need the objects screen coordinates (rather than world coordinates) + var p = Phaser.SpriteUtils.getScreenXY(a); + var dx = a.game.input.x - p.x; + var dy = a.game.input.y - p.y; + if(asDegrees) { + return this.game.math.radiansToDegrees(Math.atan2(dy, dx)); + } else { + return Math.atan2(dy, dx); + } + }; + return Motion; + })(); + Phaser.Motion = Motion; })(Phaser || (Phaser = {})); /// /// @@ -22248,7 +19622,7 @@ var Phaser; this.input = game.input; this.load = game.load; this.math = game.math; - this.motion = game.motion; + //this.motion = game.motion; this.sound = game.sound; this.stage = game.stage; this.time = game.time; diff --git a/todo/physics/AdvancedPhysics.js b/todo/physics/AdvancedPhysics.js new file mode 100644 index 00000000..b65b373d --- /dev/null +++ b/todo/physics/AdvancedPhysics.js @@ -0,0 +1,269 @@ +var Phaser; +(function (Phaser) { + /// + /// + /// + /// + /** + * Phaser - Physics Manager + * + * The Physics Manager is responsible for looking after, creating and colliding + * all of the physics bodies and joints in the world. + */ + (function (Physics) { + var AdvancedPhysics = (function () { + function AdvancedPhysics(game) { + this.lastTime = Date.now(); + this.frameRateHz = 60; + this.timeDelta = 0; + this.paused = false; + this.step = false; + // step through the simulation (i.e. per click) + //public paused: bool = true; + //public step: bool = false; // step through the simulation (i.e. per click) + this.velocityIterations = 8; + this.positionIterations = 4; + this.allowSleep = true; + this.warmStarting = true; + this.game = game; + this.gravity = new Phaser.Vec2(); + this.space = new Physics.Space(this); + this.collision = new Physics.Collision(); + } + AdvancedPhysics.clear = function clear() { + //Manager.debug.textContent = ""; + Physics.Manager.log = []; + }; + AdvancedPhysics.write = function write(s) { + //Manager.debug.textContent += s + "\n"; + }; + AdvancedPhysics.writeAll = function writeAll() { + for(var i = 0; i < Physics.Manager.log.length; i++) { + //Manager.debug.textContent += Manager.log[i]; + } + }; + AdvancedPhysics.log = []; + AdvancedPhysics.dump = function dump(phase, body) { + /* + var s = "\n\nPhase: " + phase + "\n"; + s += "Position: " + body.position.toString() + "\n"; + s += "Velocity: " + body.velocity.toString() + "\n"; + s += "Angle: " + body.angle + "\n"; + s += "Force: " + body.force.toString() + "\n"; + s += "Torque: " + body.torque + "\n"; + s += "Bounds: " + body.bounds.toString() + "\n"; + s += "Shape ***\n"; + s += "Vert 0: " + body.shapes[0].verts[0].toString() + "\n"; + s += "Vert 1: " + body.shapes[0].verts[1].toString() + "\n"; + s += "Vert 2: " + body.shapes[0].verts[2].toString() + "\n"; + s += "Vert 3: " + body.shapes[0].verts[3].toString() + "\n"; + s += "TVert 0: " + body.shapes[0].tverts[0].toString() + "\n"; + s += "TVert 1: " + body.shapes[0].tverts[1].toString() + "\n"; + s += "TVert 2: " + body.shapes[0].tverts[2].toString() + "\n"; + s += "TVert 3: " + body.shapes[0].tverts[3].toString() + "\n"; + s += "Plane 0: " + body.shapes[0].planes[0].normal.toString() + "\n"; + s += "Plane 1: " + body.shapes[0].planes[1].normal.toString() + "\n"; + s += "Plane 2: " + body.shapes[0].planes[2].normal.toString() + "\n"; + s += "Plane 3: " + body.shapes[0].planes[3].normal.toString() + "\n"; + s += "TPlane 0: " + body.shapes[0].tplanes[0].normal.toString() + "\n"; + s += "TPlane 1: " + body.shapes[0].tplanes[1].normal.toString() + "\n"; + s += "TPlane 2: " + body.shapes[0].tplanes[2].normal.toString() + "\n"; + s += "TPlane 3: " + body.shapes[0].tplanes[3].normal.toString() + "\n"; + + Manager.log.push(s); + */ + }; + AdvancedPhysics.SHAPE_TYPE_CIRCLE = 0; + AdvancedPhysics.SHAPE_TYPE_SEGMENT = 1; + AdvancedPhysics.SHAPE_TYPE_POLY = 2; + AdvancedPhysics.SHAPE_NUM_TYPES = 3; + AdvancedPhysics.JOINT_TYPE_ANGLE = 0; + AdvancedPhysics.JOINT_TYPE_REVOLUTE = 1; + AdvancedPhysics.JOINT_TYPE_WELD = 2; + AdvancedPhysics.JOINT_TYPE_WHEEL = 3; + AdvancedPhysics.JOINT_TYPE_PRISMATIC = 4; + AdvancedPhysics.JOINT_TYPE_DISTANCE = 5; + AdvancedPhysics.JOINT_TYPE_ROPE = 6; + AdvancedPhysics.JOINT_TYPE_MOUSE = 7; + AdvancedPhysics.JOINT_LINEAR_SLOP = 0.0008; + AdvancedPhysics.JOINT_ANGULAR_SLOP = 2 * 0.017453292519943294444444444444444; + AdvancedPhysics.JOINT_MAX_LINEAR_CORRECTION = 0.5; + AdvancedPhysics.JOINT_MAX_ANGULAR_CORRECTION = 8 * 0.017453292519943294444444444444444; + AdvancedPhysics.JOINT_LIMIT_STATE_INACTIVE = 0; + AdvancedPhysics.JOINT_LIMIT_STATE_AT_LOWER = 1; + AdvancedPhysics.JOINT_LIMIT_STATE_AT_UPPER = 2; + AdvancedPhysics.JOINT_LIMIT_STATE_EQUAL_LIMITS = 3; + AdvancedPhysics.CONTACT_SOLVER_COLLISION_SLOP = 0.0008; + AdvancedPhysics.CONTACT_SOLVER_BAUMGARTE = 0.28; + AdvancedPhysics.CONTACT_SOLVER_MAX_LINEAR_CORRECTION = 1; + AdvancedPhysics.bodyCounter = 0; + AdvancedPhysics.jointCounter = 0; + AdvancedPhysics.shapeCounter = 0; + AdvancedPhysics.prototype.update = function () { + // Get these from Phaser.Time instead + 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) { + Physics.Manager.clear(); + 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; + } + } + //frameCount++; + }; + AdvancedPhysics.prototype.addBody = function (body) { + this.space.addBody(body); + }; + AdvancedPhysics.prototype.removeBody = function (body) { + this.space.removeBody(body); + }; + AdvancedPhysics.prototype.addJoint = function (joint) { + this.space.addJoint(joint); + }; + AdvancedPhysics.prototype.removeJoint = function (joint) { + this.space.removeJoint(joint); + }; + AdvancedPhysics.prototype.pixelsToMeters = function (value) { + return value * 0.02; + }; + AdvancedPhysics.prototype.metersToPixels = function (value) { + return value * 50; + }; + AdvancedPhysics.pixelsToMeters = function pixelsToMeters(value) { + return value * 0.02; + }; + AdvancedPhysics.metersToPixels = function metersToPixels(value) { + return value * 50; + }; + AdvancedPhysics.p2m = function p2m(value) { + return value * 0.02; + }; + AdvancedPhysics.m2p = function m2p(value) { + return value * 50; + }; + AdvancedPhysics.areaForCircle = function areaForCircle(radius_outer, radius_inner) { + return Math.PI * (radius_outer * radius_outer - radius_inner * radius_inner); + }; + AdvancedPhysics.inertiaForCircle = function inertiaForCircle(mass, center, radius_outer, radius_inner) { + return mass * ((radius_outer * radius_outer + radius_inner * radius_inner) * 0.5 + center.lengthSq()); + }; + AdvancedPhysics.areaForSegment = function areaForSegment(a, b, radius) { + return radius * (Math.PI * radius + 2 * Phaser.Vec2Utils.distance(a, b)); + }; + AdvancedPhysics.centroidForSegment = function centroidForSegment(a, b) { + return Phaser.Vec2Utils.scale(Phaser.Vec2Utils.add(a, b), 0.5); + }; + AdvancedPhysics.inertiaForSegment = function inertiaForSegment(mass, a, b) { + var distsq = Phaser.Vec2Utils.distanceSq(b, a); + var offset = Phaser.Vec2Utils.scale(Phaser.Vec2Utils.add(a, b), 0.5); + return mass * (distsq / 12 + offset.lengthSq()); + }; + AdvancedPhysics.areaForPoly = function areaForPoly(verts) { + 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; + }; + AdvancedPhysics.centroidForPoly = function centroidForPoly(verts) { + 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)); + }; + AdvancedPhysics.inertiaForPoly = function inertiaForPoly(mass, verts, offset) { + 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); + }; + AdvancedPhysics.inertiaForBox = function inertiaForBox(mass, w, h) { + return mass * (w * w + h * h) / 12; + }; + AdvancedPhysics.createConvexHull = // Create the convex hull using the Gift wrapping algorithm (http://en.wikipedia.org/wiki/Gift_wrapping_algorithm) + function 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; + }; + return AdvancedPhysics; + })(); + Physics.AdvancedPhysics = AdvancedPhysics; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); diff --git a/Phaser/physics/AdvancedPhysics.ts b/todo/physics/AdvancedPhysics.ts similarity index 100% rename from Phaser/physics/AdvancedPhysics.ts rename to todo/physics/AdvancedPhysics.ts diff --git a/todo/physics/ArcadePhysics.js b/todo/physics/ArcadePhysics.js new file mode 100644 index 00000000..2f9b5688 --- /dev/null +++ b/todo/physics/ArcadePhysics.js @@ -0,0 +1,19 @@ +var Shapes; +(function (Shapes) { + + var Point = Shapes.Point = (function () { + function Point(x, y) { + this.x = x; + this.y = y; + } + Point.prototype.getDist = function () { + return Math.sqrt((this.x * this.x) + (this.y * this.y)); + }; + Point.origin = new Point(0, 0); + return Point; + })(); + +})(Shapes || (Shapes = {})); + +var p = new Shapes.Point(3, 4); +var dist = p.getDist(); diff --git a/Phaser/physics/ArcadePhysics.ts b/todo/physics/ArcadePhysics.ts similarity index 100% rename from Phaser/physics/ArcadePhysics.ts rename to todo/physics/ArcadePhysics.ts diff --git a/todo/physics/Body.js b/todo/physics/Body.js new file mode 100644 index 00000000..6f12a4b8 --- /dev/null +++ b/todo/physics/Body.js @@ -0,0 +1,416 @@ +var Phaser; +(function (Phaser) { + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Body + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + (function (Physics) { + var Body = (function () { + function Body(sprite, type, x, y, shapeType) { + if (typeof x === "undefined") { x = 0; } + if (typeof y === "undefined") { y = 0; } + if (typeof shapeType === "undefined") { shapeType = 0; } + this._tempVec2 = new Phaser.Vec2(); + this._fixedRotation = false; + // Shapes + this.shapes = []; + // Joints + this.joints = []; + this.jointHash = { + }; + this.categoryBits = 0x0001; + this.maskBits = 0xFFFF; + this.stepCount = 0; + this._newPosition = new Phaser.Vec2(); + this.id = Phaser.Physics.AdvancedPhysics.bodyCounter++; + this.name = 'body' + this.id; + this.type = type; + if(sprite) { + this.sprite = sprite; + this.game = sprite.game; + this.position = new Phaser.Vec2(Phaser.Physics.AdvancedPhysics.pixelsToMeters(sprite.x), Phaser.Physics.AdvancedPhysics.pixelsToMeters(sprite.y)); + this.angle = this.game.math.degreesToRadians(sprite.rotation); + } else { + this.position = new Phaser.Vec2(Phaser.Physics.AdvancedPhysics.pixelsToMeters(x), Phaser.Physics.AdvancedPhysics.pixelsToMeters(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 Physics.Bounds(); + this.allowCollisions = Phaser.Types.ANY; + this.categoryBits = 0x0001; + this.maskBits = 0xFFFF; + this.stepCount = 0; + if(sprite) { + if(shapeType == 0) { + Phaser.BodyUtils.addBox(this, 0, 0, this.sprite.width, this.sprite.height, 1, 1, 1); + } else { + Phaser.BodyUtils.addCircle(this, Math.max(this.sprite.width, this.sprite.height) / 2, 0, 0, 1, 1, 1); + } + } + } + Object.defineProperty(Body.prototype, "rotation", { + get: /** + * The rotation of the body in degrees. Phaser uses a right-handed coordinate system, where 0 points to the right. + */ + function () { + return this.game.math.radiansToDegrees(this.angle); + }, + set: /** + * Set the rotation of the body in degrees. Phaser uses a right-handed coordinate system, where 0 points to the right. + * The value is automatically wrapped to be between 0 and 360. + */ + function (value) { + this.angle = this.game.math.degreesToRadians(this.game.math.wrap(value, 360, 0)); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Body.prototype, "isDisabled", { + get: function () { + return this.type == Phaser.Types.BODY_DISABLED ? true : false; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Body.prototype, "isStatic", { + get: function () { + return this.type == Phaser.Types.BODY_STATIC ? true : false; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Body.prototype, "isKinetic", { + get: function () { + return this.type == Phaser.Types.BODY_KINETIC ? true : false; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Body.prototype, "isDynamic", { + get: function () { + return this.type == Phaser.Types.BODY_DYNAMIC ? true : false; + }, + enumerable: true, + configurable: true + }); + Body.prototype.setType = function (type) { + 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); + }; + Body.prototype.addShape = function (shape) { + // Check not already part of this body + shape.body = this; + this.shapes.push(shape); + this.shapesLength = this.shapes.length; + return shape; + }; + Body.prototype.removeShape = function (shape) { + var index = this.shapes.indexOf(shape); + if(index != -1) { + this.shapes.splice(index, 1); + shape.body = undefined; + } + this.shapesLength = this.shapes.length; + }; + Body.prototype.setMass = function (mass) { + this.mass = mass; + this.massInverted = mass > 0 ? 1 / mass : 0; + }; + Body.prototype.setInertia = function (inertia) { + this.inertia = inertia; + this.inertiaInverted = inertia > 0 ? 1 / inertia : 0; + }; + Body.prototype.setPosition = function (x, y) { + this._newPosition.setTo(Phaser.Physics.AdvancedPhysics.pixelsToMeters(x), Phaser.Physics.AdvancedPhysics.pixelsToMeters(y)); + this.setTransform(this._newPosition, this.angle); + }; + Body.prototype.setTransform = function (pos, angle) { + // inject the transform into this.position + this.transform.setTo(pos, angle); + //Manager.write('setTransform: ' + this.position.toString()); + //Manager.write('centroid: ' + this.centroid.toString()); + Phaser.TransformUtils.transform(this.transform, this.centroid, this.position); + //Manager.write('post setTransform: ' + this.position.toString()); + //this.position.copyFrom(this.transform.transform(this.centroid)); + this.angle = angle; + }; + Body.prototype.syncTransform = function () { + //Manager.write('syncTransform:'); + //Manager.write('p: ' + this.position.toString()); + //Manager.write('centroid: ' + this.centroid.toString()); + //Manager.write('xf: ' + this.transform.toString()); + //Manager.write('a: ' + this.angle); + this.transform.setRotation(this.angle); + // OPTIMISE: Creating new vector + Phaser.Vec2Utils.subtract(this.position, Phaser.TransformUtils.rotate(this.transform, this.centroid), this.transform.t); + //Manager.write('--------------------'); + //Manager.write('xf: ' + this.transform.toString()); + //Manager.write('--------------------'); + }; + Body.prototype.getWorldPoint = function (p) { + // OPTIMISE: Creating new vector + return Phaser.TransformUtils.transform(this.transform, p); + }; + Body.prototype.getWorldVector = function (v) { + // OPTIMISE: Creating new vector + return Phaser.TransformUtils.rotate(this.transform, v); + }; + Body.prototype.getLocalPoint = function (p) { + // OPTIMISE: Creating new vector + return Phaser.TransformUtils.untransform(this.transform, p); + }; + Body.prototype.getLocalVector = function (v) { + // OPTIMISE: Creating new vector + return Phaser.TransformUtils.unrotate(this.transform, v); + }; + Object.defineProperty(Body.prototype, "fixedRotation", { + get: function () { + return this._fixedRotation; + }, + set: function (value) { + this._fixedRotation = value; + this.resetMassData(); + }, + enumerable: true, + configurable: true + }); + Body.prototype.resetMassData = function () { + 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); + 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); + totalMassCentroid.multiplyAddByScalar(centroid, mass); + totalMass += mass; + totalInertia += inertia; + } + Phaser.Vec2Utils.scale(totalMassCentroid, 1 / totalMass, this.centroid); + this.setMass(totalMass); + if(!this.fixedRotation) { + this.setInertia(totalInertia - totalMass * Phaser.Vec2Utils.dot(this.centroid, this.centroid)); + } + // Move center of mass + var oldPosition = Phaser.Vec2Utils.clone(this.position); + Phaser.TransformUtils.transform(this.transform, this.centroid, this.position); + // Update center of mass velocity + oldPosition.subtract(this.position); + this.velocity.multiplyAddByScalar(Phaser.Vec2Utils.perp(oldPosition, oldPosition), this.angularVelocity); + }; + Body.prototype.resetJointAnchors = function () { + 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); + } + }; + Body.prototype.cacheData = function (source) { + if (typeof source === "undefined") { source = ''; } + //Manager.write('cacheData -- start'); + //Manager.write('p: ' + this.position.toString()); + //Manager.write('xf: ' + this.transform.toString()); + this.bounds.clear(); + for(var i = 0; i < this.shapesLength; i++) { + var shape = this.shapes[i]; + shape.cacheData(this.transform); + this.bounds.addBounds(shape.bounds); + } + //Manager.write('bounds: ' + this.bounds.toString()); + //Manager.write('p: ' + this.position.toString()); + //Manager.write('xf: ' + this.transform.toString()); + //Manager.write('cacheData -- stop'); + }; + Body.prototype.updateVelocity = function (gravity, dt, damping) { + 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.clamp(1 - dt * (damping + this.linearDamping), 0, 1)); + this.angularVelocity *= this.clamp(1 - dt * (damping + this.angularDamping), 0, 1); + this.force.setTo(0, 0); + this.torque = 0; + }; + Body.prototype.inContact = function (body2) { + if(!body2 || this.stepCount == body2.stepCount) { + return false; + } + if(!(this.isAwake && this.isStatic == false) && !(body2.isAwake && body2.isStatic == false)) { + return false; + } + if(this.isCollidable(body2) == false) { + return false; + } + if(!this.bounds.intersectsBounds(body2.bounds)) { + return false; + } + return true; + }; + Body.prototype.clamp = function (v, min, max) { + return v < min ? min : (v > max ? max : v); + }; + Body.prototype.updatePosition = function (dt) { + this.position.add(Phaser.Vec2Utils.scale(this.velocity, dt, this._tempVec2)); + this.angle += this.angularVelocity * dt; + if(this.sprite) { + this.sprite.x = this.position.x * 50; + this.sprite.y = this.position.y * 50; + this.sprite.transform.rotation = this.game.math.radiansToDegrees(this.angle); + } + }; + Body.prototype.resetForce = function () { + this.force.setTo(0, 0); + this.torque = 0; + }; + Body.prototype.applyForce = function (force, p) { + if(this.isDynamic == false) { + return; + } + if(this.isAwake == false) { + this.awake(true); + } + this.force.add(force); + Phaser.Vec2Utils.subtract(p, this.position, this._tempVec2); + this.torque += Phaser.Vec2Utils.cross(this._tempVec2, force); + }; + Body.prototype.applyForceToCenter = function (force) { + if(this.isDynamic == false) { + return; + } + if(this.isAwake == false) { + this.awake(true); + } + this.force.add(force); + }; + Body.prototype.applyTorque = function (torque) { + if(this.isDynamic == false) { + return; + } + if(this.isAwake == false) { + this.awake(true); + } + this.torque += torque; + }; + Body.prototype.applyLinearImpulse = function (impulse, p) { + if(this.isDynamic == false) { + return; + } + if(this.isAwake == false) { + this.awake(true); + } + this.velocity.multiplyAddByScalar(impulse, this.massInverted); + Phaser.Vec2Utils.subtract(p, this.position, this._tempVec2); + this.angularVelocity += Phaser.Vec2Utils.cross(this._tempVec2, impulse) * this.inertiaInverted; + }; + Body.prototype.applyAngularImpulse = function (impulse) { + if(this.isDynamic == false) { + return; + } + if(this.isAwake == false) { + this.awake(true); + } + this.angularVelocity += impulse * this.inertiaInverted; + }; + Body.prototype.kineticEnergy = function () { + return 0.5 * (this.mass * this.velocity.dot(this.velocity) + this.inertia * (this.angularVelocity * this.angularVelocity)); + }; + Object.defineProperty(Body.prototype, "isAwake", { + get: function () { + return this.awaked; + }, + enumerable: true, + configurable: true + }); + Body.prototype.awake = function (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; + } + }; + Body.prototype.isCollidable = function (other) { + if((this.isDynamic == false && other.isDynamic == false) || this == other) { + 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(!this.joints[i] || (!this.joints[i].collideConnected && other.jointHash[this.joints[i].id] != undefined)) { + return false; + } + } + return true; + }; + Body.prototype.toString = function () { + return "[{Body (name=" + this.name + " velocity=" + this.velocity.toString() + " angularVelocity: " + this.angularVelocity + ")}]"; + }; + return Body; + })(); + Physics.Body = Body; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); diff --git a/Phaser/physics/Body.ts b/todo/physics/Body.ts similarity index 100% rename from Phaser/physics/Body.ts rename to todo/physics/Body.ts diff --git a/Phaser/utils/BodyUtils.ts b/todo/physics/BodyUtils.ts similarity index 100% rename from Phaser/utils/BodyUtils.ts rename to todo/physics/BodyUtils.ts diff --git a/todo/physics/Bounds.js b/todo/physics/Bounds.js new file mode 100644 index 00000000..47b9ef6e --- /dev/null +++ b/todo/physics/Bounds.js @@ -0,0 +1,201 @@ +var Phaser; +(function (Phaser) { + /// + /// + /// + /** + * Phaser - 2D AABB + * + * A 2D AABB object + */ + (function (Physics) { + var Bounds = (function () { + /** + * Creates a new 2D AABB object. + * @class Bounds + * @constructor + * @return {Bounds} This object + **/ + function Bounds(mins, maxs) { + if (typeof mins === "undefined") { mins = null; } + if (typeof maxs === "undefined") { maxs = 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); + } + } + Bounds.prototype.toString = function () { + return [ + "mins:", + this.mins.toString(), + "maxs:", + this.maxs.toString() + ].join(" "); + }; + Bounds.prototype.setTo = function (mins, maxs) { + this.mins.setTo(mins.x, mins.y); + this.maxs.setTo(maxs.x, maxs.y); + }; + Bounds.prototype.copy = function (b) { + this.mins.copyFrom(b.mins); + this.maxs.copyFrom(b.maxs); + return this; + }; + Bounds.prototype.clear = function () { + this.mins.setTo(999999, 999999); + this.maxs.setTo(-999999, -999999); + return this; + }; + Object.defineProperty(Bounds.prototype, "x", { + get: function () { + return Physics.AdvancedPhysics.metersToPixels(this.mins.x); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Bounds.prototype, "y", { + get: function () { + return Physics.AdvancedPhysics.metersToPixels(this.mins.y); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Bounds.prototype, "width", { + get: function () { + return Physics.AdvancedPhysics.metersToPixels(this.maxs.x - this.mins.x); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Bounds.prototype, "height", { + get: function () { + return Physics.AdvancedPhysics.metersToPixels(this.maxs.y - this.mins.y); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Bounds.prototype, "right", { + get: function () { + return this.x + this.width; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Bounds.prototype, "bottom", { + get: function () { + return this.y + this.height; + }, + enumerable: true, + configurable: true + }); + Bounds.prototype.isEmpty = function () { + return (this.mins.x > this.maxs.x || this.mins.y > this.maxs.y); + }; + Bounds.prototype.getPerimeter = /* + 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); + } + */ + function () { + return (this.maxs.x - this.mins.x + this.maxs.y - this.mins.y) * 2; + }; + Bounds.prototype.addPoint = function (p) { + 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; + }; + Bounds.prototype.addBounds = function (b) { + 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; + }; + Bounds.prototype.addBounds2 = function (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; + }; + Bounds.prototype.addExtents = function (center, extent_x, extent_y) { + 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; + }; + Bounds.prototype.expand = function (ax, ay) { + this.mins.x -= ax; + this.mins.y -= ay; + this.maxs.x += ax; + this.maxs.y += ay; + return this; + }; + Bounds.prototype.containPoint = function (p) { + 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; + }; + Bounds.prototype.intersectsBounds = function (b) { + 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; + }; + Bounds.expand = function expand(b, ax, ay) { + var b = new Bounds(b.mins, b.maxs); + b.expand(ax, ay); + return b; + }; + return Bounds; + })(); + Physics.Bounds = Bounds; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); diff --git a/Phaser/physics/Bounds.ts b/todo/physics/Bounds.ts similarity index 100% rename from Phaser/physics/Bounds.ts rename to todo/physics/Bounds.ts diff --git a/todo/physics/Collision.js b/todo/physics/Collision.js new file mode 100644 index 00000000..4ea803a9 --- /dev/null +++ b/todo/physics/Collision.js @@ -0,0 +1,373 @@ +var Phaser; +(function (Phaser) { + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Collision Handlers + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + (function (Physics) { + var Collision = (function () { + function Collision() { } + Collision.prototype.collide = function (a, b, contacts) { + // Circle (a is the circle) + if(a.type == Physics.AdvancedPhysics.SHAPE_TYPE_CIRCLE) { + if(b.type == Physics.AdvancedPhysics.SHAPE_TYPE_CIRCLE) { + return this.circle2Circle(a, b, contacts); + } else if(b.type == Physics.AdvancedPhysics.SHAPE_TYPE_SEGMENT) { + return this.circle2Segment(a, b, contacts); + } else if(b.type == Physics.AdvancedPhysics.SHAPE_TYPE_POLY) { + return this.circle2Poly(a, b, contacts); + } + } + // Segment (a is the segment) + if(a.type == Physics.AdvancedPhysics.SHAPE_TYPE_SEGMENT) { + if(b.type == Physics.AdvancedPhysics.SHAPE_TYPE_CIRCLE) { + return this.circle2Segment(b, a, contacts); + } else if(b.type == Physics.AdvancedPhysics.SHAPE_TYPE_SEGMENT) { + return this.segment2Segment(a, b, contacts); + } else if(b.type == Physics.AdvancedPhysics.SHAPE_TYPE_POLY) { + return this.segment2Poly(a, b, contacts); + } + } + // Poly (a is the poly) + if(a.type == Physics.AdvancedPhysics.SHAPE_TYPE_POLY) { + if(b.type == Physics.AdvancedPhysics.SHAPE_TYPE_CIRCLE) { + return this.circle2Poly(b, a, contacts); + } else if(b.type == Physics.AdvancedPhysics.SHAPE_TYPE_SEGMENT) { + return this.segment2Poly(b, a, contacts); + } else if(b.type == Physics.AdvancedPhysics.SHAPE_TYPE_POLY) { + return this.poly2Poly(a, b, contacts); + } + } + }; + Collision.prototype._circle2Circle = function (c1, r1, c2, r2, contactArr) { + var rmax = r1 + r2; + var t = 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 = 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 = 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 Physics.Contact(p, n, d, 0)); + return 1; + }; + Collision.prototype.circle2Circle = function (circ1, circ2, contactArr) { + return this._circle2Circle(circ1.tc, circ1.radius, circ2.tc, circ2.radius, contactArr); + }; + Collision.prototype.circle2Segment = function (circ, seg, contactArr) { + 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 = 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 = new Phaser.Vec2(); + Phaser.Vec2Utils.multiplyAdd(circ.tc, n, -(circ.radius + dist * 0.5), c1); + var c2 = new Phaser.Vec2(); + Phaser.Vec2Utils.negative(n, c2); + contactArr.push(new Physics.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; + }; + Collision.prototype.circle2Poly = function (circ, poly, contactArr) { + 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.normal) - plane.d - circ.radius; + if(dist > 0) { + return 0; + } else if(dist > minDist) { + minDist = dist; + minIdx = i; + } + } + var n = poly.tplanes[minIdx].normal; + 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 = new Phaser.Vec2(); + Phaser.Vec2Utils.multiplyAdd(circ.tc, n, -(circ.radius + minDist * 0.5), c1); + var c2 = new Phaser.Vec2(); + Phaser.Vec2Utils.negative(n, c2); + contactArr.push(new Physics.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; + }; + Collision.prototype.segmentPointDistanceSq = function (seg, p) { + var w = new Phaser.Vec2(); + var d = 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; + }; + Collision.prototype.segment2Segment = // FIXME and optimise me lots!!! + function (seg1, seg2, contactArr) { + 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); + }; + Collision.prototype.findPointsBehindSeg = // Identify vertexes that have penetrated the segment. + function (contactArr, seg, poly, dist, coef) { + var dta = Phaser.Vec2Utils.cross(seg.tn, seg.ta); + var dtb = Phaser.Vec2Utils.cross(seg.tn, seg.tb); + var n = 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 Physics.Contact(v, n, dist, (poly.id << 16) | i)); + } + } + } + }; + Collision.prototype.segment2Poly = function (seg, poly, contactArr) { + 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 = 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.normal, plane.d); + if(dist > 0) { + return 0; + } + if(dist > poly_d) { + poly_d = dist; + poly_i = i; + } + } + var poly_n = new Phaser.Vec2(); + Phaser.Vec2Utils.negative(poly.tplanes[poly_i].normal, poly_n); + //var poly_n = vec2.neg(poly.tplanes[poly_i].n); + var va = 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 = 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 Physics.Contact(va, poly_n, poly_d, (seg.id << 16) | 0)); + } + if(poly.containPoint(vb)) { + contactArr.push(new Physics.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; + }; + Collision.prototype.findMSA = // Find the minimum separating axis for the given poly and plane list. + function (poly, planes, num) { + var min_dist = -999999; + var min_index = -1; + for(var i = 0; i < num; i++) { + var dist = poly.distanceOnPlane(planes[i].normal, 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 + }; + }; + Collision.prototype.findVertsFallback = function (contactArr, poly1, poly2, n, dist) { + 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 Physics.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 Physics.Contact(v, n, dist, (poly2.id << 16) | i)); + num++; + } + } + return num; + }; + Collision.prototype.findVerts = // Find the overlapped vertices. + function (contactArr, poly1, poly2, n, dist) { + var num = 0; + for(var i = 0; i < poly1.verts.length; i++) { + var v = poly1.tverts[i]; + if(poly2.containPoint(v)) { + contactArr.push(new Physics.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 Physics.Contact(v, n, dist, (poly2.id << 16) | i)); + num++; + } + } + return num > 0 ? num : this.findVertsFallback(contactArr, poly1, poly2, n, dist); + }; + Collision.prototype.poly2Poly = function (poly1, poly2, contactArr) { + var msa1 = this.findMSA(poly2, poly1.tplanes, poly1.verts.length); + if(msa1.index == -1) { + console.log('poly2poly 0', msa1); + return 0; + } + var msa2 = this.findMSA(poly1, poly2.tplanes, poly2.verts.length); + if(msa2.index == -1) { + console.log('poly2poly 1', msa2); + return 0; + } + // Penetration normal direction should be from poly1 to poly2 + if(msa1.dist > msa2.dist) { + return this.findVerts(contactArr, poly1, poly2, poly1.tplanes[msa1.index].normal, msa1.dist); + } + return this.findVerts(contactArr, poly1, poly2, Phaser.Vec2Utils.negative(poly2.tplanes[msa2.index].normal), msa2.dist); + }; + return Collision; + })(); + Physics.Collision = Collision; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); diff --git a/todo/physics/Collision.js.map b/todo/physics/Collision.js.map new file mode 100644 index 00000000..e32c246a --- /dev/null +++ b/todo/physics/Collision.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Collision.js","sources":["Collision.ts"],"names":["Phaser","Phaser.Physics","Phaser.Physics.Collision","Phaser.Physics.Collision.constructor","Phaser.Physics.Collision.collide","Phaser.Physics.Collision._circle2Circle","Phaser.Physics.Collision.circle2Circle","Phaser.Physics.Collision.circle2Segment","Phaser.Physics.Collision.circle2Poly","Phaser.Physics.Collision.segmentPointDistanceSq","Phaser.Physics.Collision.segment2Segment","Phaser.Physics.Collision.findPointsBehindSeg","Phaser.Physics.Collision.segment2Poly","Phaser.Physics.Collision.findMSA","Phaser.Physics.Collision.findVertsFallback","Phaser.Physics.Collision.findVerts","Phaser.Physics.Collision.poly2Poly"],"mappings":"AAiBA,IAAO,MAAM;AA6hBZ,CA7hBD,UAAO,MAAM;IAjBbA,wCAAwCA;IACxCA,yCAAyCA;IACzCA,6CAA6CA;IAC7CA,wCAAwCA;IACxCA,yCAAyCA;IACzCA,uCAAuCA;IACvCA,0CAA0CA;IAC1CA,mCAAmCA;IACnCA,gCAAgCA;IAChCA,mCAAmCA;IAEnCA;;;;MAIEA;KAEKA,UAAOA,OAAOA;QAEjBC;YAAAC;AAyhBCA,YAvhBGA,8BAAAA,UAAeA,CAACA,EAAEA,CAACA,EAAEA,QAAmBA;gBAEpCE,4BAA4BA;gBAC5BA,GAAIA,CAACA,CAACA,IAAIA,IAAIA,eAAOA,CAACA,iBAAiBA,CAACA;oBAEpCA,GAAIA,CAACA,CAACA,IAAIA,IAAIA,eAAOA,CAACA,iBAAiBA,CAACA;wBAEpCA,OAAOA,IAAIA,CAACA,aAAaA,CAACA,CAACA,EAAEA,CAACA,EAAEA,QAAQA,CAACA,CAACA;qBAC7CA,MACIA,GAAIA,CAACA,CAACA,IAAIA,IAAIA,eAAOA,CAACA,kBAAkBA,CAACA;wBAE1CA,OAAOA,IAAIA,CAACA,cAAcA,CAACA,CAACA,EAAEA,CAACA,EAAEA,QAAQA,CAACA,CAACA;qBAC9CA,MACIA,GAAIA,CAACA,CAACA,IAAIA,IAAIA,eAAOA,CAACA,eAAeA,CAACA;wBAEvCA,OAAOA,IAAIA,CAACA,WAAWA,CAACA,CAACA,EAAEA,CAACA,EAAEA,QAAQA,CAACA,CAACA;qBAC3CA;iBACJA;gBAEDA,8BAA8BA;gBAC9BA,GAAIA,CAACA,CAACA,IAAIA,IAAIA,eAAOA,CAACA,kBAAkBA,CAACA;oBAErCA,GAAIA,CAACA,CAACA,IAAIA,IAAIA,eAAOA,CAACA,iBAAiBA,CAACA;wBAEpCA,OAAOA,IAAIA,CAACA,cAAcA,CAACA,CAACA,EAAEA,CAACA,EAAEA,QAAQA,CAACA,CAACA;qBAC9CA,MACIA,GAAIA,CAACA,CAACA,IAAIA,IAAIA,eAAOA,CAACA,kBAAkBA,CAACA;wBAE1CA,OAAOA,IAAIA,CAACA,eAAeA,CAACA,CAACA,EAAEA,CAACA,EAAEA,QAAQA,CAACA,CAACA;qBAC/CA,MACIA,GAAIA,CAACA,CAACA,IAAIA,IAAIA,eAAOA,CAACA,eAAeA,CAACA;wBAEvCA,OAAOA,IAAIA,CAACA,YAAYA,CAACA,CAACA,EAAEA,CAACA,EAAEA,QAAQA,CAACA,CAACA;qBAC5CA;iBACJA;gBAEDA,wBAAwBA;gBACxBA,GAAIA,CAACA,CAACA,IAAIA,IAAIA,eAAOA,CAACA,eAAeA,CAACA;oBAElCA,GAAIA,CAACA,CAACA,IAAIA,IAAIA,eAAOA,CAACA,iBAAiBA,CAACA;wBAEpCA,OAAOA,IAAIA,CAACA,WAAWA,CAACA,CAACA,EAAEA,CAACA,EAAEA,QAAQA,CAACA,CAACA;qBAC3CA,MACIA,GAAIA,CAACA,CAACA,IAAIA,IAAIA,eAAOA,CAACA,kBAAkBA,CAACA;wBAE1CA,OAAOA,IAAIA,CAACA,YAAYA,CAACA,CAACA,EAAEA,CAACA,EAAEA,QAAQA,CAACA,CAACA;qBAC5CA,MACIA,GAAIA,CAACA,CAACA,IAAIA,IAAIA,eAAOA,CAACA,eAAeA,CAACA;wBAEvCA,OAAOA,IAAIA,CAACA,SAASA,CAACA,CAACA,EAAEA,CAACA,EAAEA,QAAQA,CAACA,CAACA;qBACzCA;iBACJA;YAELA,CAACA;YAEDF,qCAAAA,UAAuBA,EAAEA,EAAEA,EAAEA,EAAEA,EAAEA,EAAEA,EAAEA,EAAEA,UAAUA;gBAE7CG,IAAIA,IAAIA,GAAGA,EAAEA,GAAGA,EAAEA,CAACA;gBAEnBA,IAAIA,CAACA,GAAgBA,IAAIA,MAAMA,CAACA,IAAIA,EAAAA,CAACA;gBACrCA,2BAA2BA;gBAC3BA,MAAMA,CAACA,SAASA,CAACA,QAAQA,CAACA,EAAEA,EAAEA,EAAEA,EAAEA,CAACA,CAACA;gBAEpCA,IAAIA,MAAMA,GAAGA,CAACA,CAACA,QAAQA,EAAEA,CAACA;gBAE1BA,GAAIA,MAAMA,GAAGA,IAAIA,GAAGA,IAAIA,CAACA;oBAErBA,OAAOA,CAACA,CAACA;iBACZA;gBAEDA,IAAIA,IAAIA,GAAGA,IAAIA,CAACA,IAAIA,CAACA,MAAMA,CAACA,CAACA;gBAE7BA,IAAIA,CAACA,GAAgBA,IAAIA,MAAMA,CAACA,IAAIA,EAAAA,CAACA;gBACrCA,MAAMA,CAACA,SAASA,CAACA,WAAWA,CAACA,EAAEA,EAAEA,CAACA,EAAEA,GAAGA,GAAGA,CAACA,EAAEA,GAAGA,EAAEA,IAAIA,GAAGA,GAAGA,IAAIA,EAAEA,CAACA,CAACA;gBACpEA,wDAAwDA;gBAExDA,IAAIA,CAACA,GAAgBA,IAAIA,MAAMA,CAACA,IAAIA,EAAAA,CAACA;gBACrCA,4DAA4DA;gBAE5DA,GAAIA,IAAIA,IAAIA,CAACA,CAACA;oBAEVA,MAAMA,CAACA,SAASA,CAACA,KAAKA,CAACA,CAACA,EAAEA,CAACA,GAAGA,IAAIA,EAAEA,CAACA,CAACA;iBACzCA;gBAEDA,IAAIA,CAACA,GAAGA,IAAIA,GAAGA,IAAIA,CAACA;gBAEpBA,UAAUA,CAACA,IAAIA,CAACA,IAAIA,eAAOA,CAACA,CAACA,EAAEA,CAACA,EAAEA,CAACA,EAAEA,CAACA,CAACA,CAACA;gBAExCA,OAAOA,CAACA,CAACA;YAEbA,CAACA;YAEDH,oCAAAA,UAAqBA,KAAmCA,EAAEA,KAAmCA,EAAEA,UAAqBA;gBAChHI,OAAOA,IAAIA,CAACA,cAAcA,CAACA,KAAKA,CAACA,EAAEA,EAAEA,KAAKA,CAACA,MAAMA,EAAEA,KAAKA,CAACA,EAAEA,EAAEA,KAAKA,CAACA,MAAMA,EAAEA,UAAUA,CAACA,CAACA;YAC3FA,CAACA;YAEDJ,qCAAAA,UAAsBA,IAAkCA,EAAEA,GAAkCA,EAAEA,UAAqBA;gBAE/GK,IAAIA,IAAIA,GAAGA,IAAIA,CAACA,MAAMA,GAAGA,GAAGA,CAACA,MAAMA,CAACA;gBAEpCA,+BAA+BA;gBAC/BA,IAAIA,EAAEA,GAAGA,MAAMA,CAACA,SAASA,CAACA,GAAGA,CAACA,IAAIA,CAACA,EAAEA,EAAEA,GAAGA,CAACA,EAAEA,CAACA,GAAGA,MAAMA,CAACA,SAASA,CAACA,GAAGA,CAACA,GAAGA,CAACA,EAAEA,EAAEA,GAAGA,CAACA,EAAEA,CAACA,CAACA;gBACtFA,IAAIA,IAAIA,GAAGA,CAACA,EAAEA,GAAGA,CAACA,GAAGA,EAAEA,GAAGA,CAACA,CAACA,GAAGA,EAAEA,IAAIA,IAAIA,CAACA;gBAC1CA,GAAIA,IAAIA,GAAGA,CAACA,CAACA;oBAETA,OAAOA,CAACA,CAACA;iBACZA;gBAEDA,oCAAoCA;gBACpCA,IAAIA,EAAEA,GAAGA,MAAMA,CAACA,SAASA,CAACA,KAAKA,CAACA,IAAIA,CAACA,EAAEA,EAAEA,GAAGA,CAACA,EAAEA,CAACA,CAACA;gBACjDA,IAAIA,KAAKA,GAAGA,MAAMA,CAACA,SAASA,CAACA,KAAKA,CAACA,GAAGA,CAACA,EAAEA,EAAEA,GAAGA,CAACA,EAAEA,CAACA,CAACA;gBACnDA,IAAIA,KAAKA,GAAGA,MAAMA,CAACA,SAASA,CAACA,KAAKA,CAACA,GAAGA,CAACA,EAAEA,EAAEA,GAAGA,CAACA,EAAEA,CAACA,CAACA;gBAEnDA,GAAIA,EAAEA,GAAGA,KAAKA,CAACA;oBAEXA,GAAIA,EAAEA,GAAGA,KAAKA,GAAGA,IAAIA,CAACA;wBAElBA,OAAOA,CAACA,CAACA;qBACZA;oBAEDA,OAAOA,IAAIA,CAACA,cAAcA,CAACA,IAAIA,CAACA,EAAEA,EAAEA,IAAIA,CAACA,MAAMA,EAAEA,GAAGA,CAACA,EAAEA,EAAEA,GAAGA,CAACA,MAAMA,EAAEA,UAAUA,CAACA,CAACA;iBACpFA,MACIA,GAAIA,EAAEA,GAAGA,KAAKA,CAACA;oBAEhBA,GAAIA,EAAEA,GAAGA,KAAKA,GAAGA,IAAIA,CAACA;wBAElBA,OAAOA,CAACA,CAACA;qBACZA;oBAEDA,OAAOA,IAAIA,CAACA,cAAcA,CAACA,IAAIA,CAACA,EAAEA,EAAEA,IAAIA,CAACA,MAAMA,EAAEA,GAAGA,CAACA,EAAEA,EAAEA,GAAGA,CAACA,MAAMA,EAAEA,UAAUA,CAACA,CAACA;iBACpFA;gBAEDA,IAAIA,CAACA,GAAgBA,IAAIA,MAAMA,CAACA,IAAIA,EAAAA,CAACA;gBAErCA,GAAIA,EAAEA,GAAGA,CAACA,CAACA;oBAEPA,CAACA,CAACA,QAAQA,CAACA,GAAGA,CAACA,EAAEA,CAACA;iBACrBA,KAEDA;oBACIA,MAAMA,CAACA,SAASA,CAACA,QAAQA,CAACA,GAAGA,CAACA,EAAEA,EAAEA,CAACA,CAACA;iBACvCA;gBACDA,+CAA+CA;gBAE/CA,IAAIA,EAAEA,GAAgBA,IAAIA,MAAMA,CAACA,IAAIA,EAAAA,CAACA;gBACtCA,MAAMA,CAACA,SAASA,CAACA,WAAWA,CAACA,IAAIA,CAACA,EAAEA,EAAEA,CAACA,EAAEA,EAACA,IAAKA,CAACA,MAAMA,GAAGA,IAAIA,GAAGA,GAAGA,CAACA,EAAEA,EAAEA,CAACA;gBAEzEA,IAAIA,EAAEA,GAAgBA,IAAIA,MAAMA,CAACA,IAAIA,EAAAA,CAACA;gBACtCA,MAAMA,CAACA,SAASA,CAACA,QAAQA,CAACA,CAACA,EAAEA,EAAEA,CAACA;gBAEhCA,UAAUA,CAACA,IAAIA,CAACA,IAAIA,eAAOA,CAACA,EAAEA,EAAEA,EAAEA,EAAEA,IAAIA,EAAEA,CAACA,CAACA,CAACA;gBAC7CA,mGAAmGA;gBAEnGA,OAAOA,CAACA,CAACA;YAEbA,CAACA;YAEDL,kCAAAA,UAAmBA,IAAkCA,EAAEA,IAAgCA,EAAEA,UAAqBA;gBAE1GM,IAAIA,OAAOA,GAAGA,CAACA,MAAMA,CAACA;gBACtBA,IAAIA,MAAMA,GAAGA,CAACA,CAACA,CAACA;gBAEhBA,IAAKA,IAAIA,CAACA,GAAGA,CAACA,EAAEA,CAACA,GAAGA,IAAIA,CAACA,KAAKA,CAACA,MAAMA,EAAEA,CAACA,EAAEA,CAC1CA;oBACIA,IAAIA,KAAKA,GAAGA,IAAIA,CAACA,OAAOA,CAACA,CAACA,CAACA,CAACA;oBAC5BA,IAAIA,IAAIA,GAAGA,MAAMA,CAACA,SAASA,CAACA,GAAGA,CAACA,IAAIA,CAACA,EAAEA,EAAEA,KAAKA,CAACA,MAAMA,CAACA,GAAGA,KAAKA,CAACA,CAACA,GAAGA,IAAIA,CAACA,MAAMA,CAACA;oBAE/EA,GAAIA,IAAIA,GAAGA,CAACA,CAACA;wBAETA,OAAOA,CAACA,CAACA;qBACZA,MACIA,GAAIA,IAAIA,GAAGA,OAAOA,CAACA;wBAEpBA,OAAOA,GAAGA,IAAIA;wBACdA,MAAMA,GAAGA,CAACA;qBACbA;iBACJA;gBAEDA,IAAIA,CAACA,GAAGA,IAAIA,CAACA,OAAOA,CAACA,MAAMA,CAACA,CAACA,MAAMA,CAACA;gBACpCA,IAAIA,CAACA,GAAGA,IAAIA,CAACA,MAAMA,CAACA,MAAMA,CAACA,CAACA;gBAC5BA,IAAIA,CAACA,GAAGA,IAAIA,CAACA,MAAMA,CAACA,CAACA,MAAMA,GAAGA,CAACA,IAAIA,IAAIA,CAACA,KAAKA,CAACA,MAAMA,CAACA,CAACA;gBACtDA,IAAIA,GAAGA,GAAGA,MAAMA,CAACA,SAASA,CAACA,KAAKA,CAACA,CAACA,EAAEA,CAACA,CAACA,CAACA;gBACvCA,IAAIA,GAAGA,GAAGA,MAAMA,CAACA,SAASA,CAACA,KAAKA,CAACA,CAACA,EAAEA,CAACA,CAACA,CAACA;gBACvCA,IAAIA,EAAEA,GAAGA,MAAMA,CAACA,SAASA,CAACA,KAAKA,CAACA,IAAIA,CAACA,EAAEA,EAAEA,CAACA,CAACA,CAACA;gBAE5CA,GAAIA,EAAEA,GAAGA,GAAGA,CAACA;oBAETA,OAAOA,IAAIA,CAACA,cAAcA,CAACA,IAAIA,CAACA,EAAEA,EAAEA,IAAIA,CAACA,MAAMA,EAAEA,CAACA,EAAEA,CAACA,EAAEA,UAAUA,CAACA,CAACA;iBACtEA,MACIA,GAAIA,EAAEA,GAAGA,GAAGA,CAACA;oBAEdA,OAAOA,IAAIA,CAACA,cAAcA,CAACA,IAAIA,CAACA,EAAEA,EAAEA,IAAIA,CAACA,MAAMA,EAAEA,CAACA,EAAEA,CAACA,EAAEA,UAAUA,CAACA,CAACA;iBACtEA;gBAEDA,IAAIA,EAAEA,GAAgBA,IAAIA,MAAMA,CAACA,IAAIA,EAAAA,CAACA;gBACtCA,MAAMA,CAACA,SAASA,CAACA,WAAWA,CAACA,IAAIA,CAACA,EAAEA,EAAEA,CAACA,EAAEA,EAACA,IAAKA,CAACA,MAAMA,GAAGA,OAAOA,GAAGA,GAAGA,CAACA,EAAEA,EAAEA,CAACA;gBAE5EA,IAAIA,EAAEA,GAAgBA,IAAIA,MAAMA,CAACA,IAAIA,EAAAA,CAACA;gBACtCA,MAAMA,CAACA,SAASA,CAACA,QAAQA,CAACA,CAACA,EAAEA,EAAEA,CAACA;gBAEhCA,UAAUA,CAACA,IAAIA,CAACA,IAAIA,eAAOA,CAACA,EAAEA,EAAEA,EAAEA,EAAEA,OAAOA,EAAEA,CAACA,CAACA,CAACA;gBAEhDA,yGAAyGA;gBAEzGA,OAAOA,CAACA,CAACA;YAEbA,CAACA;YAEDN,6CAAAA,UAA8BA,GAAkCA,EAAEA,CAACA;gBAE/DO,IAAIA,CAACA,GAAgBA,IAAIA,MAAMA,CAACA,IAAIA,EAAAA,CAACA;gBACrCA,IAAIA,CAACA,GAAgBA,IAAIA,MAAMA,CAACA,IAAIA,EAAAA,CAACA;gBACrCA,MAAMA,CAACA,SAASA,CAACA,QAAQA,CAACA,CAACA,EAAEA,GAAGA,CAACA,EAAEA,EAAEA,CAACA,CAACA;gBACvCA,MAAMA,CAACA,SAASA,CAACA,QAAQA,CAACA,GAAGA,CAACA,EAAEA,EAAEA,GAAGA,CAACA,EAAEA,EAAEA,CAACA,CAACA;gBAE5CA,8BAA8BA;gBAC9BA,mCAAmCA;gBAEnCA,IAAIA,IAAIA,GAAGA,CAACA,CAACA,GAAGA,CAACA,CAACA,CAACA,CAACA;gBAEpBA,GAAIA,IAAIA,IAAIA,CAACA,CAACA;oBAEVA,OAAOA,CAACA,CAACA,GAAGA,CAACA,CAACA,CAACA,CAACA;iBACnBA;gBAEDA,IAAIA,GAAGA,GAAGA,CAACA,CAACA,GAAGA,CAACA,CAACA,CAACA,CAACA;gBAEnBA,GAAIA,IAAIA,IAAIA,GAAGA,CAACA;oBAEZA,OAAOA,CAACA,CAACA,GAAGA,CAACA,CAACA,CAACA,GAAGA,CAACA,GAAGA,IAAIA,GAAGA,GAAGA,CAACA;iBACpCA;gBAEDA,OAAOA,CAACA,CAACA,GAAGA,CAACA,CAACA,CAACA,GAAGA,IAAIA,GAAGA,IAAIA,GAAGA,GAAGA,CAACA;YAExCA,CAACA;YAGDP,sCADAA,gCAAgCA;YAChCA,UAAuBA,IAAmCA,EAAEA,IAAmCA,EAAEA,UAAqBA;gBAElHQ,IAAIA,CAACA,GAAGA,EAAEA,CAACA;gBACXA,CAACA,CAACA,CAACA,CAACA,GAAGA,IAAIA,CAACA,sBAAsBA,CAACA,IAAIA,EAAEA,IAAIA,CAACA,EAAEA,CAACA;gBACjDA,CAACA,CAACA,CAACA,CAACA,GAAGA,IAAIA,CAACA,sBAAsBA,CAACA,IAAIA,EAAEA,IAAIA,CAACA,EAAEA,CAACA;gBACjDA,CAACA,CAACA,CAACA,CAACA,GAAGA,IAAIA,CAACA,sBAAsBA,CAACA,IAAIA,EAAEA,IAAIA,CAACA,EAAEA,CAACA;gBACjDA,CAACA,CAACA,CAACA,CAACA,GAAGA,IAAIA,CAACA,sBAAsBA,CAACA,IAAIA,EAAEA,IAAIA,CAACA,EAAEA,CAACA;gBAEjDA,IAAIA,IAAIA,GAAGA,CAACA,CAACA,CAACA,CAACA,GAAGA,CAACA,CAACA,CAACA,CAACA,GAAGA,CAACA,GAAGA,CAACA,CAACA;gBAC/BA,IAAIA,IAAIA,GAAGA,CAACA,CAACA,CAACA,CAACA,GAAGA,CAACA,CAACA,CAACA,CAACA,GAAGA,CAACA,GAAGA,CAACA,CAACA;gBAC/BA,IAAIA,IAAIA,GAAGA,CAACA,CAACA,IAAIA,CAACA,GAAGA,CAACA,CAACA,IAAIA,CAACA,GAAGA,IAAIA,GAAGA,IAAIA,CAACA;AAC3CA,gBAAAA,IAAIA,CAACA,EAACA,CAAEA,CAACA;AAAAA,gBAETA,IAAIA,CAACA,GAAGA,MAAMA,CAACA,SAASA,CAACA,QAAQA,CAACA,IAAIA,CAACA,EAAEA,EAAEA,IAAIA,CAACA,EAAEA,CAACA,CAACA;gBACpDA,IAAIA,CAACA,GAAGA,MAAMA,CAACA,SAASA,CAACA,QAAQA,CAACA,IAAIA,CAACA,EAAEA,EAAEA,IAAIA,CAACA,EAAEA,CAACA,CAACA;gBAEpDA,OAAQA,IAAIA,CAACA;oBAETA,KAAKA,CAACA,CAACA;wBACHA,CAACA,GAAGA,MAAMA,CAACA,SAASA,CAACA,GAAGA,CAACA,MAAMA,CAACA,SAASA,CAACA,QAAQA,CAACA,IAAIA,CAACA,EAAEA,EAAEA,IAAIA,CAACA,EAAEA,CAACA,EAAEA,CAACA,CAACA,GAAGA,MAAMA,CAACA,SAASA,CAACA,GAAGA,CAACA,CAACA,EAAEA,CAACA,CAACA;wBACrGA,CAACA,GAAGA,CAACA,GAAGA,CAACA,GAAGA,CAACA,IAAGA,CAAEA,GAAGA,CAACA,GAAGA,CAACA,GAAGA,CAACA,CAACA;wBAC/BA,CAACA,GAAGA,CAACA;wBACLA,KAAMA;AAAAA,oBACVA,KAAKA,CAACA,CAACA;wBACHA,CAACA,GAAGA,MAAMA,CAACA,SAASA,CAACA,GAAGA,CAACA,MAAMA,CAACA,SAASA,CAACA,QAAQA,CAACA,IAAIA,CAACA,EAAEA,EAAEA,IAAIA,CAACA,EAAEA,CAACA,EAAEA,CAACA,CAACA,GAAGA,MAAMA,CAACA,SAASA,CAACA,GAAGA,CAACA,CAACA,EAAEA,CAACA,CAACA;wBACrGA,CAACA,GAAGA,CAACA,GAAGA,CAACA,GAAGA,CAACA,IAAGA,CAAEA,GAAGA,CAACA,GAAGA,CAACA,GAAGA,CAACA,CAACA;wBAC/BA,CAACA,GAAGA,CAACA;wBACLA,KAAMA;AAAAA,oBACVA,KAAKA,CAACA,CAACA;wBACHA,CAACA,GAAGA,CAACA;wBACLA,CAACA,GAAGA,MAAMA,CAACA,SAASA,CAACA,GAAGA,CAACA,MAAMA,CAACA,SAASA,CAACA,QAAQA,CAACA,IAAIA,CAACA,EAAEA,EAAEA,IAAIA,CAACA,EAAEA,CAACA,EAAEA,CAACA,CAACA,GAAGA,MAAMA,CAACA,SAASA,CAACA,GAAGA,CAACA,CAACA,EAAEA,CAACA,CAACA;wBACrGA,CAACA,GAAGA,CAACA,GAAGA,CAACA,GAAGA,CAACA,IAAGA,CAAEA,GAAGA,CAACA,GAAGA,CAACA,GAAGA,CAACA,CAACA;wBAC/BA,KAAMA;AAAAA,oBACVA,KAAKA,CAACA,CAACA;wBACHA,CAACA,GAAGA,CAACA;wBACLA,CAA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"} \ No newline at end of file diff --git a/Phaser/physics/Collision.ts b/todo/physics/Collision.ts similarity index 100% rename from Phaser/physics/Collision.ts rename to todo/physics/Collision.ts diff --git a/todo/physics/Contact.js b/todo/physics/Contact.js new file mode 100644 index 00000000..61569c60 --- /dev/null +++ b/todo/physics/Contact.js @@ -0,0 +1,32 @@ +var Phaser; +(function (Phaser) { + /// + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Contact + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + (function (Physics) { + var Contact = (function () { + function Contact(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(); + } + return Contact; + })(); + Physics.Contact = Contact; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); diff --git a/todo/physics/Contact.js.map b/todo/physics/Contact.js.map new file mode 100644 index 00000000..87e8e5bd --- /dev/null +++ b/todo/physics/Contact.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Contact.js","sources":["Contact.ts"],"names":["Phaser","Phaser.Physics","Phaser.Physics.Contact","Phaser.Physics.Contact.constructor"],"mappings":"AAYA,IAAO,MAAM;AAiDZ,CAjDD,UAAO,MAAM;IAZbA,wCAAwCA;IACxCA,6CAA6CA;IAC7CA,mCAAmCA;IACnCA,gCAAgCA;IAChCA,wCAAwCA;IAExCA;;;;MAIEA;KAEKA,UAAOA,OAAOA;QAEjBC;YAEIC,SAFSA,OAAOA,CAEJA,CAACA,EAAEA,CAACA,EAAEA,CAACA,EAAEA,IAAIA;gBAErBC,IAAIA,CAACA,IAAIA,GAAGA,IAAIA;gBAChBA,IAAIA,CAACA,KAAKA,GAAGA,CAACA;gBACdA,IAAIA,CAACA,MAAMA,GAAGA,CAACA;gBACfA,IAAIA,CAACA,KAAKA,GAAGA,CAACA;gBACdA,IAAIA,CAACA,YAAYA,GAAGA,CAACA;gBACrBA,IAAIA,CAACA,gBAAgBA,GAAGA,CAACA;gBAEzBA,IAAIA,CAACA,EAAEA,GAAGA,IAAIA,MAAMA,CAACA,IAAIA,EAAAA;gBACzBA,IAAIA,CAACA,EAAEA,GAAGA,IAAIA,MAAMA,CAACA,IAAIA,EAAAA;gBACzBA,IAAIA,CAACA,QAAQA,GAAGA,IAAIA,MAAMA,CAACA,IAAIA,EAAAA;gBAC/BA,IAAIA,CAACA,QAAQA,GAAGA,IAAIA,MAAMA,CAACA,IAAIA,EAAAA;YAEnCA,CAACA;YA6BLD;AAACA,QAADA,CAACA,IAAAD;QA7CDA,0BA6CCA,QAAAA;IAELA,CAACA,2CAAAD;IAjDMA;AAiDNA,CAAAA,2BAAA"} \ No newline at end of file diff --git a/Phaser/physics/Contact.ts b/todo/physics/Contact.ts similarity index 100% rename from Phaser/physics/Contact.ts rename to todo/physics/Contact.ts diff --git a/todo/physics/ContactSolver.js b/todo/physics/ContactSolver.js new file mode 100644 index 00000000..203a8740 --- /dev/null +++ b/todo/physics/ContactSolver.js @@ -0,0 +1,269 @@ +var Phaser; +(function (Phaser) { + /// + /// + /// + /// + /// + /// + /// + /** + * 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. + //------------------------------------------------------------------------------------------------- + (function (Physics) { + var ContactSolver = (function () { + function ContactSolver(shape1, shape2) { + this.shape1 = shape1; + this.shape2 = shape2; + this.contacts = []; + this.elasticity = 1; + this.friction = 1; + } + ContactSolver.prototype.update = function (newContactArr) { + 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; + }; + ContactSolver.prototype.initSolver = function (dt_inv) { + var body1 = this.shape1.body; + var body2 = this.shape2.body; + var sum_m_inv = body1.massInverted + body2.massInverted; + for(var i = 0; i < this.contacts.length; i++) { + var con = 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; + } + }; + ContactSolver.prototype.warmStart = function () { + var body1 = this.shape1.body; + var body2 = 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); + //console.log('phaser warmStart impulse ' + i + ' = ' + impulse.toString()); + 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; + } + }; + ContactSolver.prototype.solveVelocityConstraints = function () { + var body1 = this.shape1.body; + var body2 = this.shape2.body; + Physics.AdvancedPhysics.write('solveVelocityConstraints. Body1: ' + body1.name + ' Body2: ' + body2.name); + Physics.AdvancedPhysics.write('Shape 1: ' + this.shape1.type + ' Shape 2: ' + this.shape2.type); + var m1_inv = body1.massInverted; + var i1_inv = body1.inertiaInverted; + var m2_inv = body2.massInverted; + var i2_inv = body2.inertiaInverted; + Physics.AdvancedPhysics.write('m1_inv: ' + m1_inv); + Physics.AdvancedPhysics.write('i1_inv: ' + i1_inv); + Physics.AdvancedPhysics.write('m2_inv: ' + m2_inv); + Physics.AdvancedPhysics.write('i2_inv: ' + i2_inv); + for(var i = 0; i < this.contacts.length; i++) { + Physics.AdvancedPhysics.write('------------ solve con ' + 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); + Physics.AdvancedPhysics.write('v1 ' + v1.toString()); + Phaser.Vec2Utils.multiplyAdd(body2.velocity, Phaser.Vec2Utils.perp(r2), body2.angularVelocity, v2); + //var v2 = vec2.mad(body2.v, vec2.perp(r2), body2.w); + Physics.AdvancedPhysics.write('v2 ' + v2.toString()); + // Relative velocity at contact point + var rv = new Phaser.Vec2(); + Phaser.Vec2Utils.subtract(v2, v1, rv); + //var rv = vec2.sub(v2, v1); + Physics.AdvancedPhysics.write('rv ' + rv.toString()); + // 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); + Physics.AdvancedPhysics.write('lambda_n: ' + lambda_n); + // Accumulate and clamp + var lambda_n_old = con.lambdaNormal; + con.lambdaNormal = Math.max(lambda_n_old + lambda_n, 0); + //con.lambdaNormal = this.clamp(lambda_n_old + lambda_n, 0); + lambda_n = con.lambdaNormal - lambda_n_old; + Physics.AdvancedPhysics.write('lambda_n clamped: ' + lambda_n); + // 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); + Physics.AdvancedPhysics.write('impulse: ' + impulse.toString()); + 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); + body2.angularVelocity += Phaser.Vec2Utils.cross(r2, impulse) * i2_inv; + //body2.w += vec2.cross(r2, impulse) * i2_inv; + Physics.AdvancedPhysics.write('body1: ' + body1.toString()); + Physics.AdvancedPhysics.write('body2: ' + body2.toString()); + } + }; + ContactSolver.prototype.solvePositionConstraints = function () { + var body1 = this.shape1.body; + var body2 = this.shape2.body; + Physics.AdvancedPhysics.write('solvePositionConstraints'); + 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++) { + Physics.AdvancedPhysics.write('------------- solvePositionConstraints ' + 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); + Phaser.Vec2Utils.rotate(con.r2_local, body2.angle, r2); + Physics.AdvancedPhysics.write('r1_local.x = ' + con.r1_local.x + ' r1_local.y = ' + con.r1_local.y + ' angle: ' + body1.angle); + Physics.AdvancedPhysics.write('r1 rotated: r1.x = ' + r1.x + ' r1.y = ' + r1.y); + Physics.AdvancedPhysics.write('r2_local.x = ' + con.r2_local.x + ' r2_local.y = ' + con.r2_local.y + ' angle: ' + body2.angle); + Physics.AdvancedPhysics.write('r2 rotated: r2.x = ' + r2.x + ' r2.y = ' + r2.y); + // Contact points (corrected) + var p1 = new Phaser.Vec2(); + var p2 = new Phaser.Vec2(); + Phaser.Vec2Utils.add(body1.position, r1, p1); + Phaser.Vec2Utils.add(body2.position, r2, p2); + Physics.AdvancedPhysics.write('body1.pos.x=' + body1.position.x + ' y=' + body1.position.y); + Physics.AdvancedPhysics.write('body2.pos.x=' + body2.position.x + ' y=' + body2.position.y); + // Corrected delta vector + var dp = new Phaser.Vec2(); + Phaser.Vec2Utils.subtract(p2, p1, dp); + // Position constraint + var c = Phaser.Vec2Utils.dot(dp, n) + con.depth; + var correction = this.clamp(Physics.AdvancedPhysics.CONTACT_SOLVER_BAUMGARTE * (c + Physics.AdvancedPhysics.CONTACT_SOLVER_COLLISION_SLOP), -Physics.AdvancedPhysics.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); + body1.position.multiplyAddByScalar(impulse_dt, -m1_inv); + body1.angle -= sn1 * lambda_dt * i1_inv; + body2.position.multiplyAddByScalar(impulse_dt, m2_inv); + body2.angle += sn2 * lambda_dt * i2_inv; + Physics.AdvancedPhysics.write('body1.pos.x=' + body1.position.x + ' y=' + body1.position.y); + Physics.AdvancedPhysics.write('body2.pos.x=' + body2.position.x + ' y=' + body2.position.y); + } + Physics.AdvancedPhysics.write('max_penetration: ' + max_penetration); + return max_penetration <= Physics.AdvancedPhysics.CONTACT_SOLVER_COLLISION_SLOP * 3; + }; + ContactSolver.prototype.clamp = function (v, min, max) { + return v < min ? min : (v > max ? max : v); + }; + return ContactSolver; + })(); + Physics.ContactSolver = ContactSolver; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); diff --git a/todo/physics/ContactSolver.js.map b/todo/physics/ContactSolver.js.map new file mode 100644 index 00000000..35b14607 --- /dev/null +++ b/todo/physics/ContactSolver.js.map @@ -0,0 +1 @@ +{"version":3,"file":"ContactSolver.js","sources":["ContactSolver.ts"],"names":["Phaser","Phaser.Physics","Phaser.Physics.ContactSolver","Phaser.Physics.ContactSolver.constructor","Phaser.Physics.ContactSolver.update","Phaser.Physics.ContactSolver.initSolver","Phaser.Physics.ContactSolver.warmStart","Phaser.Physics.ContactSolver.solveVelocityConstraints","Phaser.Physics.ContactSolver.solvePositionConstraints","Phaser.Physics.ContactSolver.clamp"],"mappings":"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"} \ No newline at end of file diff --git a/Phaser/physics/ContactSolver.ts b/todo/physics/ContactSolver.ts similarity index 100% rename from Phaser/physics/ContactSolver.ts rename to todo/physics/ContactSolver.ts diff --git a/todo/physics/Manager.js b/todo/physics/Manager.js new file mode 100644 index 00000000..517e40c6 --- /dev/null +++ b/todo/physics/Manager.js @@ -0,0 +1,67 @@ +var Phaser; +(function (Phaser) { + /// + /// + /// + /** + * Phaser - Physics Manager + * + * The Physics Manager is responsible for looking after, creating and colliding + * all of the physics bodies and joints in the world. + */ + (function (Physics) { + var Manager = (function () { + function Manager(game) { + this.game = game; + } + Manager.clear = function clear() { + //Manager.debug.textContent = ""; + Manager.log = []; + }; + Manager.write = function write(s) { + //Manager.debug.textContent += s + "\n"; + }; + Manager.writeAll = function writeAll() { + for(var i = 0; i < Manager.log.length; i++) { + //Manager.debug.textContent += Manager.log[i]; + } + }; + Manager.log = []; + Manager.dump = function dump(phase, body) { + /* + var s = "\n\nPhase: " + phase + "\n"; + s += "Position: " + body.position.toString() + "\n"; + s += "Velocity: " + body.velocity.toString() + "\n"; + s += "Angle: " + body.angle + "\n"; + s += "Force: " + body.force.toString() + "\n"; + s += "Torque: " + body.torque + "\n"; + s += "Bounds: " + body.bounds.toString() + "\n"; + s += "Shape ***\n"; + s += "Vert 0: " + body.shapes[0].verts[0].toString() + "\n"; + s += "Vert 1: " + body.shapes[0].verts[1].toString() + "\n"; + s += "Vert 2: " + body.shapes[0].verts[2].toString() + "\n"; + s += "Vert 3: " + body.shapes[0].verts[3].toString() + "\n"; + s += "TVert 0: " + body.shapes[0].tverts[0].toString() + "\n"; + s += "TVert 1: " + body.shapes[0].tverts[1].toString() + "\n"; + s += "TVert 2: " + body.shapes[0].tverts[2].toString() + "\n"; + s += "TVert 3: " + body.shapes[0].tverts[3].toString() + "\n"; + s += "Plane 0: " + body.shapes[0].planes[0].normal.toString() + "\n"; + s += "Plane 1: " + body.shapes[0].planes[1].normal.toString() + "\n"; + s += "Plane 2: " + body.shapes[0].planes[2].normal.toString() + "\n"; + s += "Plane 3: " + body.shapes[0].planes[3].normal.toString() + "\n"; + s += "TPlane 0: " + body.shapes[0].tplanes[0].normal.toString() + "\n"; + s += "TPlane 1: " + body.shapes[0].tplanes[1].normal.toString() + "\n"; + s += "TPlane 2: " + body.shapes[0].tplanes[2].normal.toString() + "\n"; + s += "TPlane 3: " + body.shapes[0].tplanes[3].normal.toString() + "\n"; + + Manager.log.push(s); + */ + }; + Manager.prototype.update = function () { + }; + return Manager; + })(); + Physics.Manager = Manager; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); diff --git a/todo/physics/Manager.js.map b/todo/physics/Manager.js.map new file mode 100644 index 00000000..ee7bf986 --- /dev/null +++ b/todo/physics/Manager.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Manager.js","sources":["Manager.ts"],"names":["Phaser","Phaser.Physics","Phaser.Physics.Manager","Phaser.Physics.Manager.constructor","Phaser.Physics.Manager.clear","Phaser.Physics.Manager.write","Phaser.Physics.Manager.writeAll","Phaser.Physics.Manager.dump","Phaser.Physics.Manager.update","Phaser.Physics.Manager.addBody","Phaser.Physics.Manager.removeBody","Phaser.Physics.Manager.addJoint","Phaser.Physics.Manager.removeJoint","Phaser.Physics.Manager.pixelsToMeters","Phaser.Physics.Manager.metersToPixels","Phaser.Physics.Manager.pixelsToMeters","Phaser.Physics.Manager.metersToPixels","Phaser.Physics.Manager.p2m","Phaser.Physics.Manager.m2p","Phaser.Physics.Manager.areaForCircle","Phaser.Physics.Manager.inertiaForCircle","Phaser.Physics.Manager.areaForSegment","Phaser.Physics.Manager.centroidForSegment","Phaser.Physics.Manager.inertiaForSegment","Phaser.Physics.Manager.areaForPoly","Phaser.Physics.Manager.centroidForPoly","Phaser.Physics.Manager.inertiaForPoly","Phaser.Physics.Manager.inertiaForBox","Phaser.Physics.Manager.createConvexHull"],"mappings":"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"} \ No newline at end of file diff --git a/todo/physics/Manager.ts b/todo/physics/Manager.ts new file mode 100644 index 00000000..519e3cd8 --- /dev/null +++ b/todo/physics/Manager.ts @@ -0,0 +1,86 @@ +/// +/// +/// + +/** +* Phaser - Physics Manager +* +* The Physics Manager is responsible for looking after, creating and colliding +* all of the physics bodies and joints in the world. +*/ + +module Phaser.Physics { + + export class Manager { + + constructor(game: Game) { + this.game = game; + } + + /** + * Local reference to Game. + */ + public game: Game; + + public static debug: HTMLTextAreaElement; + + public static clear() { + //Manager.debug.textContent = ""; + Manager.log = []; + } + + public static write(s: string) { + //Manager.debug.textContent += s + "\n"; + } + + public static writeAll() { + + for (var i = 0; i < Manager.log.length; i++) + { + //Manager.debug.textContent += Manager.log[i]; + } + + } + + public static log = []; + + public static dump(phase: string, body: Body) { + + /* + var s = "\n\nPhase: " + phase + "\n"; + s += "Position: " + body.position.toString() + "\n"; + s += "Velocity: " + body.velocity.toString() + "\n"; + s += "Angle: " + body.angle + "\n"; + s += "Force: " + body.force.toString() + "\n"; + s += "Torque: " + body.torque + "\n"; + s += "Bounds: " + body.bounds.toString() + "\n"; + s += "Shape ***\n"; + s += "Vert 0: " + body.shapes[0].verts[0].toString() + "\n"; + s += "Vert 1: " + body.shapes[0].verts[1].toString() + "\n"; + s += "Vert 2: " + body.shapes[0].verts[2].toString() + "\n"; + s += "Vert 3: " + body.shapes[0].verts[3].toString() + "\n"; + s += "TVert 0: " + body.shapes[0].tverts[0].toString() + "\n"; + s += "TVert 1: " + body.shapes[0].tverts[1].toString() + "\n"; + s += "TVert 2: " + body.shapes[0].tverts[2].toString() + "\n"; + s += "TVert 3: " + body.shapes[0].tverts[3].toString() + "\n"; + s += "Plane 0: " + body.shapes[0].planes[0].normal.toString() + "\n"; + s += "Plane 1: " + body.shapes[0].planes[1].normal.toString() + "\n"; + s += "Plane 2: " + body.shapes[0].planes[2].normal.toString() + "\n"; + s += "Plane 3: " + body.shapes[0].planes[3].normal.toString() + "\n"; + s += "TPlane 0: " + body.shapes[0].tplanes[0].normal.toString() + "\n"; + s += "TPlane 1: " + body.shapes[0].tplanes[1].normal.toString() + "\n"; + s += "TPlane 2: " + body.shapes[0].tplanes[2].normal.toString() + "\n"; + s += "TPlane 3: " + body.shapes[0].tplanes[3].normal.toString() + "\n"; + + Manager.log.push(s); + */ + + } + + public update() { + + } + + } + +} \ No newline at end of file diff --git a/todo/physics/Plane.js b/todo/physics/Plane.js new file mode 100644 index 00000000..3e73d78b --- /dev/null +++ b/todo/physics/Plane.js @@ -0,0 +1,23 @@ +var Phaser; +(function (Phaser) { + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Plane + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + (function (Physics) { + var Plane = (function () { + function Plane(normal, d) { + this.normal = normal; + this.d = d; + } + return Plane; + })(); + Physics.Plane = Plane; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); diff --git a/todo/physics/Plane.js.map b/todo/physics/Plane.js.map new file mode 100644 index 00000000..767e24d3 --- /dev/null +++ b/todo/physics/Plane.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Plane.js","sources":["Plane.ts"],"names":["Phaser","Phaser.Physics","Phaser.Physics.Plane","Phaser.Physics.Plane.constructor"],"mappings":"AAWA,IAAO,MAAM;AAgBZ,CAhBD,UAAO,MAAM;IAXbA,wCAAwCA;IACxCA,6CAA6CA;IAC7CA,mCAAmCA;IACnCA,gCAAgCA;IAEhCA;;;;MAIEA;KAEKA,UAAOA,OAAOA;QAEjBC;YAEIC,SAFSA,KAAKA,CAEFA,MAAmBA,EAAEA,CAASA;gBAEtCC,IAAIA,CAACA,MAAMA,GAAGA,MAAMA;gBACpBA,IAAIA,CAACA,CAACA,GAAGA,CAACA;YAEdA,CAACA;YAKLD;AAACA,QAADA,CAACA,IAAAD;QAZDA,sBAYCA,QAAAA;IAELA,CAACA,2CAAAD;IAhBMA;AAgBNA,CAAAA,2BAAA"} \ No newline at end of file diff --git a/Phaser/physics/Plane.ts b/todo/physics/Plane.ts similarity index 100% rename from Phaser/physics/Plane.ts rename to todo/physics/Plane.ts diff --git a/todo/physics/Space.js b/todo/physics/Space.js new file mode 100644 index 00000000..0021e9e8 --- /dev/null +++ b/todo/physics/Space.js @@ -0,0 +1,500 @@ +var Phaser; +(function (Phaser) { + /// + /// + /// + /// + /// + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Space + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + (function (Physics) { + var Space = (function () { + function Space(manager) { + this.postSolve = null; + this.stepCount = 0; + this._manager = manager; + this.bodies = []; + this.bodyHash = { + }; + this.joints = []; + this.jointHash = { + }; + this.numContacts = 0; + this.contactSolvers = []; + this.gravity = this._manager.gravity; + this.damping = 0; + this._linTolSqr = Space.SLEEP_LINEAR_TOLERANCE * Space.SLEEP_LINEAR_TOLERANCE; + this._angTolSqr = Space.SLEEP_ANGULAR_TOLERANCE * Space.SLEEP_ANGULAR_TOLERANCE; + } + Space.TIME_TO_SLEEP = 0.5; + Space.SLEEP_LINEAR_TOLERANCE = 0.5; + Space.SLEEP_ANGULAR_TOLERANCE = 2 * 0.017453292519943294444444444444444; + Space.prototype.clear = function () { + Physics.AdvancedPhysics.shapeCounter = 0; + Physics.AdvancedPhysics.bodyCounter = 0; + Physics.AdvancedPhysics.jointCounter = 0; + for(var i = 0; i < this.bodies.length; i++) { + if(this.bodies[i]) { + this.removeBody(this.bodies[i]); + } + } + this.bodies = []; + this.bodyHash = { + }; + this.joints = []; + this.jointHash = { + }; + this.contactSolvers = []; + this.stepCount = 0; + }; + Space.prototype.addBody = function (body) { + if(this.bodyHash[body.id] != undefined) { + return; + } + var index = this.bodies.push(body) - 1; + this.bodyHash[body.id] = index; + body.awake(true); + body.space = this; + body.cacheData('addBody'); + }; + Space.prototype.removeBody = function (body) { + if(this.bodyHash[body.id] == undefined) { + return; + } + // Remove linked joints + 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.bodies[index]; + }; + Space.prototype.addJoint = function (joint) { + if(this.jointHash[joint.id] != undefined) { + return; + } + joint.body1.awake(true); + joint.body2.awake(true); + var index = this.joints.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; + }; + Space.prototype.removeJoint = function (joint) { + 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.joints[index]; + }; + Space.prototype.findShapeByPoint = function (p, refShape) { + var firstShape; + for(var i = 0; i < this.bodies.length; i++) { + var body = this.bodies[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; + }; + Space.prototype.findBodyByPoint = function (p, refBody) { + var firstBody; + for(var i = 0; i < this.bodies.length; i++) { + var body = this.bodies[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; + }; + Space.prototype.shapeById = function (id) { + var shape; + for(var i = 0; i < this.bodies.length; i++) { + var body = this.bodies[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; + }; + Space.prototype.jointById = function (id) { + var index = this.jointHash[id]; + if(index != undefined) { + return this.joints[index]; + } + return null; + }; + Space.prototype.findVertexByPoint = function (p, minDist, refVertexId) { + var firstVertexId = -1; + refVertexId = refVertexId || -1; + for(var i = 0; i < this.bodies.length; i++) { + var body = this.bodies[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; + }; + Space.prototype.findEdgeByPoint = function (p, minDist, refEdgeId) { + var firstEdgeId = -1; + refEdgeId = refEdgeId || -1; + for(var i = 0; i < this.bodies.length; i++) { + var body = this.bodies[i]; + if(!body) { + continue; + } + for(var j = 0; j < body.shapes.length; j++) { + var shape = body.shapes[j]; + if(shape.type != Physics.AdvancedPhysics.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; + }; + Space.prototype.findJointByPoint = function (p, minDist, refJointId) { + var firstJointId = -1; + var dsq = minDist * minDist; + refJointId = refJointId || -1; + for(var i = 0; i < this.joints.length; i++) { + var joint = this.joints[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; + }; + Space.prototype.findContactSolver = function (shape1, shape2) { + Physics.Manager.write('findContactSolver. Length: ' + this._cl); + for(var i = 0; i < this._cl; i++) { + var contactSolver = this.contactSolvers[i]; + if(shape1 == contactSolver.shape1 && shape2 == contactSolver.shape2) { + return contactSolver; + } + } + return null; + }; + Space.prototype.genTemporalContactSolvers = function () { + Physics.Manager.write('genTemporalContactSolvers'); + this._cl = 0; + this.contactSolvers.length = 0; + this.numContacts = 0; + for(var body1Index = 0; body1Index < this._bl; body1Index++) { + if(!this.bodies[body1Index]) { + continue; + } + this.bodies[body1Index].stepCount = this.stepCount; + for(var body2Index = 0; body2Index < this._bl; body2Index++) { + if(this.bodies[body1Index].inContact(this.bodies[body2Index]) == false) { + continue; + } + Physics.Manager.write('body1 and body2 intersect'); + for(var i = 0; i < this.bodies[body1Index].shapesLength; i++) { + for(var j = 0; j < this.bodies[body2Index].shapesLength; j++) { + this._shape1 = this.bodies[body1Index].shapes[i]; + this._shape2 = this.bodies[body2Index].shapes[j]; + var contactArr = []; + if(!Physics.AdvancedPhysics.collision.collide(this._shape1, this._shape2, contactArr)) { + continue; + } + if(this._shape1.type > this._shape2.type) { + var temp = this._shape1; + this._shape1 = this._shape2; + this._shape2 = temp; + } + this.numContacts += contactArr.length; + // Result stored in this._contactSolver (see what we can do about generating some re-usable solvers) + var contactSolver = this.findContactSolver(this._shape1, this._shape2); + Physics.Manager.write('findContactSolver result: ' + contactSolver); + if(contactSolver) { + contactSolver.update(contactArr); + this.contactSolvers.push(contactSolver); + } else { + Physics.Manager.write('awake both bodies'); + this.bodies[body1Index].awake(true); + this.bodies[body2Index].awake(true); + var newContactSolver = new Physics.ContactSolver(this._shape1, this._shape2); + newContactSolver.contacts = contactArr; + newContactSolver.elasticity = Math.max(this._shape1.elasticity, this._shape2.elasticity); + newContactSolver.friction = Math.sqrt(this._shape1.friction * this._shape2.friction); + this.contactSolvers.push(newContactSolver); + Physics.Manager.write('new contact solver'); + } + } + } + } + } + this._cl = this.contactSolvers.length; + }; + Space.prototype.initSolver = function (warmStarting) { + Physics.Manager.write('initSolver'); + Physics.Manager.write('contactSolvers.length: ' + this._cl); + // Initialize contact solvers + for(var c = 0; c < this._cl; c++) { + this.contactSolvers[c].initSolver(this._deltaInv); + // Warm starting (apply cached impulse) + if(warmStarting) { + this.contactSolvers[c].warmStart(); + } + } + // Initialize joint solver + for(var j = 0; j < this.joints.length; j++) { + if(this.joints[j]) { + this.joints[j].initSolver(this._delta, warmStarting); + } + } + // Warm starting (apply cached impulse) + /* + if (warmStarting) + { + for (var c = 0; c < this._cl; c++) + { + this.contactSolvers[c].warmStart(); + } + } + */ + }; + Space.prototype.velocitySolver = function (iterations) { + Physics.Manager.write('velocitySolver, iterations: ' + iterations + ' csa len: ' + this._cl); + for(var i = 0; i < iterations; i++) { + for(var j = 0; j < this._jl; j++) { + if(this.joints[j]) { + this.joints[j].solveVelocityConstraints(); + } + } + for(var c = 0; c < this._cl; c++) { + this.contactSolvers[c].solveVelocityConstraints(); + } + } + }; + Space.prototype.positionSolver = function (iterations) { + this._positionSolved = false; + for(var i = 0; i < iterations; i++) { + this._contactsOk = true; + this._jointsOk = true; + for(var c = 0; c < this._cl; c++) { + this._contactsOk = this.contactSolvers[c].solvePositionConstraints() && this._contactsOk; + } + for(var j = 0; j < this._jl; j++) { + if(this.joints[j]) { + this._jointsOk = this.joints[j].solvePositionConstraints() && this._jointsOk; + } + } + if(this._contactsOk && this._jointsOk) { + // exit early if the position errors are small + this._positionSolved = true; + break; + } + } + return this._positionSolved; + }; + Space.prototype.step = // Step through the physics simulation + function (dt, velocityIterations, positionIterations, warmStarting, allowSleep) { + Physics.Manager.clear(); + Physics.Manager.write('Space step ' + this.stepCount); + this._delta = dt; + this._deltaInv = 1 / dt; + this._bl = this.bodies.length; + this._jl = this.joints.length; + this.stepCount++; + // 1) Generate Contact Solvers (into the this.contactSolvers array) + this.genTemporalContactSolvers(); + Physics.Manager.dump("Contact Solvers", this.bodies[1]); + // 2) Initialize the Contact Solvers + this.initSolver(warmStarting); + Physics.Manager.dump("Init Solver", this.bodies[1]); + // 3) Intergrate velocity + for(var i = 0; i < this._bl; i++) { + if(this.bodies[i] && this.bodies[i].isDynamic && this.bodies[i].isAwake) { + this.bodies[i].updateVelocity(this.gravity, this._delta, this.damping); + } + } + Physics.Manager.dump("Update Velocity", this.bodies[1]); + // 4) Awaken bodies via joints + for(var j = 0; i < this._jl; j++) { + if(!this.joints[j]) { + continue; + } + // combine + var awake1 = this.joints[j].body1.isAwake && !this.joints[j].body1.isStatic; + var awake2 = this.joints[j].body2.isAwake && !this.joints[j].body2.isStatic; + if(awake1 ^ awake2) { + if(!awake1) { + this.joints[j].body1.awake(true); + } + if(!awake2) { + this.joints[j].body2.awake(true); + } + } + } + // 5) Iterative velocity constraints solver + this.velocitySolver(velocityIterations); + Physics.Manager.dump("Velocity Solvers", this.bodies[1]); + // 6) Integrate position + for(var i = 0; i < this._bl; i++) { + if(this.bodies[i] && this.bodies[i].isDynamic && this.bodies[i].isAwake) { + this.bodies[i].updatePosition(this._delta); + } + } + Physics.Manager.dump("Update Position", this.bodies[1]); + // 7) Process breakable joint + for(var i = 0; i < this._jl; i++) { + if(this.joints[i] && this.joints[i].breakable && (this.joints[i].getReactionForce(this._deltaInv).lengthSq() >= this.joints[i].maxForce * this.joints[i].maxForce)) { + this.removeJoint(this.joints[i]); + } + } + // 8) Iterative position constraints solver (result stored in this._positionSolved) + this.positionSolver(positionIterations); + Physics.Manager.dump("Position Solver", this.bodies[1]); + // 9) Sync the Transforms + for(var i = 0; i < this._bl; i++) { + if(this.bodies[i]) { + this.bodies[i].syncTransform(); + } + } + Physics.Manager.dump("Sync Transform", this.bodies[1]); + // 10) Post solve collision callback + if(this.postSolve) { + for(var i = 0; i < this._cl; i++) { + this.postSolve(this.contactSolvers[i]); + } + } + // 11) Cache Body Data + for(var i = 0; i < this._bl; i++) { + if(this.bodies[i] && this.bodies[i].isDynamic && this.bodies[i].isAwake) { + this.bodies[i].cacheData('post solve collision callback'); + } + } + Physics.Manager.dump("Cache Data", this.bodies[1]); + Physics.Manager.writeAll(); + // 12) Process sleeping + if(allowSleep) { + this._minSleepTime = 999999; + for(var i = 0; i < this._bl; i++) { + if(!this.bodies[i] || this.bodies[i].isDynamic == false) { + continue; + } + if(this.bodies[i].angularVelocity * this.bodies[i].angularVelocity > this._angTolSqr || this.bodies[i].velocity.dot(this.bodies[i].velocity) > this._linTolSqr) { + this.bodies[i].sleepTime = 0; + this._minSleepTime = 0; + } else { + this.bodies[i].sleepTime += this._delta; + this._minSleepTime = Math.min(this._minSleepTime, this.bodies[i].sleepTime); + } + } + if(this._positionSolved && this._minSleepTime >= Space.TIME_TO_SLEEP) { + for(var i = 0; i < this._bl; i++) { + if(this.bodies[i]) { + this.bodies[i].awake(false); + } + } + } + } + }; + return Space; + })(); + Physics.Space = Space; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); diff --git a/todo/physics/Space.js.map b/todo/physics/Space.js.map new file mode 100644 index 00000000..04454257 --- /dev/null +++ b/todo/physics/Space.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Space.js","sources":["Space.ts"],"names":["Phaser","Phaser.Physics","Phaser.Physics.Space","Phaser.Physics.Space.constructor","Phaser.Physics.Space.clear","Phaser.Physics.Space.addBody","Phaser.Physics.Space.removeBody","Phaser.Physics.Space.addJoint","Phaser.Physics.Space.removeJoint","Phaser.Physics.Space.findShapeByPoint","Phaser.Physics.Space.findBodyByPoint","Phaser.Physics.Space.shapeById","Phaser.Physics.Space.jointById","Phaser.Physics.Space.findVertexByPoint","Phaser.Physics.Space.findEdgeByPoint","Phaser.Physics.Space.findJointByPoint","Phaser.Physics.Space.findContactSolver","Phaser.Physics.Space.genTemporalContactSolvers","Phaser.Physics.Space.initSolver","Phaser.Physics.Space.velocitySolver","Phaser.Physics.Space.positionSolver","Phaser.Physics.Space.step"],"mappings":"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"} \ No newline at end of file diff --git a/Phaser/physics/Space.ts b/todo/physics/Space.ts similarity index 100% rename from Phaser/physics/Space.ts rename to todo/physics/Space.ts diff --git a/todo/physics/joints/IJoint.js b/todo/physics/joints/IJoint.js new file mode 100644 index 00000000..38c4f862 --- /dev/null +++ b/todo/physics/joints/IJoint.js @@ -0,0 +1,3 @@ +var Phaser; +(function (Phaser) { + })(Phaser || (Phaser = {})); diff --git a/todo/physics/joints/IJoint.js.map b/todo/physics/joints/IJoint.js.map new file mode 100644 index 00000000..715856b3 --- /dev/null +++ b/todo/physics/joints/IJoint.js.map @@ -0,0 +1 @@ +{"version":3,"file":"IJoint.js","sources":["IJoint.ts"],"names":["Phaser"],"mappings":"AAYA,IAAO,MAAM;AA6BZ,CA7BD,UAAO,MAAM;IA6BbA,CAACA,2BAAA"} \ No newline at end of file diff --git a/Phaser/physics/joints/IJoint.ts b/todo/physics/joints/IJoint.ts similarity index 100% rename from Phaser/physics/joints/IJoint.ts rename to todo/physics/joints/IJoint.ts diff --git a/todo/physics/joints/Joint.js b/todo/physics/joints/Joint.js new file mode 100644 index 00000000..8999f0e3 --- /dev/null +++ b/todo/physics/joints/Joint.js @@ -0,0 +1,41 @@ +var Phaser; +(function (Phaser) { + /// + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Joint + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + (function (Physics) { + var Joint = (function () { + function Joint(type, body1, body2, collideConnected) { + this.id = Physics.AdvancedPhysics.jointCounter++; + this.type = type; + this.body1 = body1; + this.body2 = body2; + this.collideConnected = collideConnected; + this.maxForce = 9999999999; + this.breakable = false; + } + Joint.prototype.getWorldAnchor1 = function () { + return this.body1.getWorldPoint(this.anchor1); + }; + Joint.prototype.getWorldAnchor2 = function () { + return this.body2.getWorldPoint(this.anchor2); + }; + Joint.prototype.setWorldAnchor1 = function (anchor1) { + this.anchor1 = this.body1.getLocalPoint(anchor1); + }; + Joint.prototype.setWorldAnchor2 = function (anchor2) { + this.anchor2 = this.body2.getLocalPoint(anchor2); + }; + return Joint; + })(); + Physics.Joint = Joint; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); diff --git a/todo/physics/joints/Joint.js.map b/todo/physics/joints/Joint.js.map new file mode 100644 index 00000000..90974efb --- /dev/null +++ b/todo/physics/joints/Joint.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Joint.js","sources":["Joint.ts"],"names":["Phaser","Phaser.Physics","Phaser.Physics.Joint","Phaser.Physics.Joint.constructor","Phaser.Physics.Joint.getWorldAnchor1","Phaser.Physics.Joint.getWorldAnchor2","Phaser.Physics.Joint.setWorldAnchor1","Phaser.Physics.Joint.setWorldAnchor2"],"mappings":"AAYA,IAAO,MAAM;AAmDZ,CAnDD,UAAO,MAAM;IAZbA,2CAA2CA;IAC3CA,4CAA4CA;IAC5CA,gDAAgDA;IAChDA,sCAAsCA;IACtCA,mCAAmCA;IAEnCA;;;;MAIEA;KAEKA,UAAOA,OAAOA;QAEjBC;YAEIC,SAFSA,KAAKA,CAEFA,IAAYA,EAAEA,KAAyBA,EAAEA,KAAyBA,EAAEA,gBAAgBA;gBAE5FC,IAAIA,CAACA,EAAEA,GAAGA,MAAMA,CAACA,OAAOA,CAACA,OAAOA,CAACA,YAAYA,EAAEA;gBAC/CA,IAAIA,CAACA,IAAIA,GAAGA,IAAIA;gBAEhBA,IAAIA,CAACA,KAAKA,GAAGA,KAAKA;gBAClBA,IAAIA,CAACA,KAAKA,GAAGA,KAAKA;gBAElBA,IAAIA,CAACA,gBAAgBA,GAAGA,gBAAgBA;gBAExCA,IAAIA,CAACA,QAAQA,GAAGA,UAAUA;gBAC1BA,IAAIA,CAACA,SAASA,GAAGA,KAAKA;YAE1BA,CAACA;YAeDD,kCAAAA;gBACIE,OAAOA,IAAIA,CAACA,KAAKA,CAACA,aAAaA,CAACA,IAAIA,CAACA,OAAOA,CAACA,CAACA;YAClDA,CAACA;YAEDF,kCAAAA;gBACIG,OAAOA,IAAIA,CAACA,KAAKA,CAACA,aAAaA,CAACA,IAAIA,CAACA,OAAOA,CAACA,CAACA;YAClDA,CAACA;YAEDH,kCAAAA,UAAuBA,OAAOA;gBAC1BI,IAAIA,CAACA,OAAOA,GAAGA,IAAIA,CAACA,KAAKA,CAACA,aAAaA,CAACA,OAAOA,CAACA;YACpDA,CAACA;YAEDJ,kCAAAA,UAAuBA,OAAOA;gBAC1BK,IAAIA,CAACA,OAAOA,GAAGA,IAAIA,CAACA,KAAKA,CAACA,aAAaA,CAACA,OAAOA,CAACA;YACpDA,CAACA;YAELL;AAACA,QAADA,CAACA,IAAAD;QA9CDA,sBA8CCA,QAAAA;IAGLA,CAACA,2CAAAD;IAnDMA;AAmDNA,CAAAA,2BAAA"} \ No newline at end of file diff --git a/Phaser/physics/joints/Joint.ts b/todo/physics/joints/Joint.ts similarity index 100% rename from Phaser/physics/joints/Joint.ts rename to todo/physics/joints/Joint.ts diff --git a/todo/physics/shapes/Box.js b/todo/physics/shapes/Box.js new file mode 100644 index 00000000..892a27f2 --- /dev/null +++ b/todo/physics/shapes/Box.js @@ -0,0 +1,59 @@ +var __extends = this.__extends || function (d, b) { + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); +}; +var Phaser; +(function (Phaser) { + (function (Physics) { + /// + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Shapes - Box + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + (function (Shapes) { + var Box = (function (_super) { + __extends(Box, _super); + // Give in pixels + function Box(x, y, width, height) { + console.log('Box px', x, y, width, height); + x = Phaser.Physics.AdvancedPhysics.pixelsToMeters(x); + y = Phaser.Physics.AdvancedPhysics.pixelsToMeters(y); + width = Phaser.Physics.AdvancedPhysics.pixelsToMeters(width); + height = Phaser.Physics.AdvancedPhysics.pixelsToMeters(height); + console.log('Box m', x, y, width, height); + var hw = width * 0.5; + var hh = height * 0.5; + console.log('Box hh', hw, hh); + _super.call(this, [ + { + x: -hw + x, + y: +hh + y + }, + { + x: -hw + x, + y: -hh + y + }, + { + x: +hw + x, + y: -hh + y + }, + { + x: +hw + x, + y: +hh + y + } + ]); + } + return Box; + })(Phaser.Physics.Shapes.Poly); + Shapes.Box = Box; + })(Physics.Shapes || (Physics.Shapes = {})); + var Shapes = Physics.Shapes; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); diff --git a/todo/physics/shapes/Box.js.map b/todo/physics/shapes/Box.js.map new file mode 100644 index 00000000..1870ec11 --- /dev/null +++ b/todo/physics/shapes/Box.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Box.js","sources":["Box.ts"],"names":["Phaser","Phaser.Physics","Phaser.Physics.Shapes","Phaser.Physics.Shapes.Box","Phaser.Physics.Shapes.Box.constructor"],"mappings":";;;;;AAYA,IAAO,MAAM;AAgCZ,CAhCD,UAAO,MAAM;KAANA,UAAOA,OAAOA;QAZrBC,2CAA2CA;QAC3CA,sCAAsCA;QACtCA,mCAAmCA;QACnCA,iCAAiCA;QACjCA,gCAAgCA;QAEhCA;;;;UAIEA;SAEKA,UAAeA,MAAMA;YAExBC;;gBAGIC,kBADkBA;gBAClBA,SAHSA,GAAGA,CAGAA,CAACA,EAAEA,CAACA,EAAEA,KAAKA,EAAEA,MAAMA;oBAE3BC,OAAOA,CAACA,GAAGA,CAACA,QAAQA,EAAEA,CAACA,EAAEA,CAACA,EAAEA,KAAKA,EAAEA,MAAMA,CAACA;oBAE1CA,CAACA,GAAGA,eAAOA,CAACA,cAAcA,CAACA,CAACA,CAACA;oBAC7BA,CAACA,GAAGA,eAAOA,CAACA,cAAcA,CAACA,CAACA,CAACA;oBAC7BA,KAAKA,GAAGA,eAAOA,CAACA,cAAcA,CAACA,KAAKA,CAACA;oBACrCA,MAAMA,GAAGA,eAAOA,CAACA,cAAcA,CAACA,MAAMA,CAACA;oBAEvCA,OAAOA,CAACA,GAAGA,CAACA,OAAOA,EAAEA,CAACA,EAAEA,CAACA,EAAEA,KAAKA,EAAEA,MAAMA,CAACA;oBAE5CA,IAAIA,EAAEA,GAAGA,KAAKA,GAAGA,GAAGA,CAACA;oBACrBA,IAAIA,EAAEA,GAAGA,MAAMA,GAAGA,GAAGA,CAACA;oBAEnBA,OAAOA,CAACA,GAAGA,CAACA,QAAQA,EAAEA,EAAEA,EAAEA,EAAEA,CAACA;oBAEhCA,8BAAMA;gBACCA;oBAAEA,CAACA,EAAEA,CAACA,EAAEA,GAAGA,CAACA;oBAAEA,CAACA,EAAEA,CAACA,EAAEA,GAAGA,CAACA;iBAAEA;gBAC1BA;oBAAEA,CAACA,EAAEA,CAACA,EAAEA,GAAGA,CAACA;oBAAEA,CAACA,EAAEA,CAACA,EAAEA,GAAGA,CAACA;iBAAEA;gBAC1BA;oBAAEA,CAACA,EAAEA,CAACA,EAAEA,GAAGA,CAACA;oBAAEA,CAACA,EAAEA,CAACA,EAAEA,GAAGA,CAACA;iBAAEA;gBAC1BA;oBAAEA,CAACA,EAAEA,CAACA,EAAEA,GAAGA,CAACA;oBAAEA,CAACA,EAAEA,CAACA,EAAEA,GAAGA,CAACA;iBAAEA;aAChCA,CAILA;gBAFGA,CAACA;gBAELD;AAACA,YAADA,CAACA,EA5BwBD,MAAMA,CAACA,OAAOA,CAACA,MAAMA,CAACA,IAAIA,EA4BlDA;YA5BDA,iBA4BCA,YAAAA;QAELA,CAACA,2CAAAD;QAhCMA;AAgCNA,IAADA,CAACA,2CAAAD;IAhCMA;AAgCNA,CAAAA,2BAAA"} \ No newline at end of file diff --git a/Phaser/physics/shapes/Box.ts b/todo/physics/shapes/Box.ts similarity index 100% rename from Phaser/physics/shapes/Box.ts rename to todo/physics/shapes/Box.ts diff --git a/todo/physics/shapes/Circle.js b/todo/physics/shapes/Circle.js new file mode 100644 index 00000000..df298613 --- /dev/null +++ b/todo/physics/shapes/Circle.js @@ -0,0 +1,87 @@ +var __extends = this.__extends || function (d, b) { + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); +}; +var Phaser; +(function (Phaser) { + (function (Physics) { + /// + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Shape - Circle + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + (function (Shapes) { + var Circle = (function (_super) { + __extends(Circle, _super); + function Circle(radius, x, y) { + if (typeof x === "undefined") { x = 0; } + if (typeof y === "undefined") { y = 0; } + _super.call(this, Physics.AdvancedPhysics.SHAPE_TYPE_CIRCLE); + x = Physics.AdvancedPhysics.pixelsToMeters(x); + y = Physics.AdvancedPhysics.pixelsToMeters(y); + radius = Physics.AdvancedPhysics.pixelsToMeters(radius); + this.center = new Phaser.Vec2(x, y); + this.radius = radius; + this.tc = new Phaser.Vec2(); + this.finishVerts(); + } + Circle.prototype.finishVerts = function () { + this.radius = Math.abs(this.radius); + }; + Circle.prototype.duplicate = function () { + return new Circle(this.center.x, this.center.y, this.radius); + }; + Circle.prototype.recenter = function (c) { + this.center.subtract(c); + }; + Circle.prototype.transform = function (xf) { + Phaser.TransformUtils.transform(xf, this.center, this.center); + //this.center = xf.transform(this.center); + }; + Circle.prototype.untransform = function (xf) { + Phaser.TransformUtils.untransform(xf, this.center, this.center); + //this.center = xf.untransform(this.center); + }; + Circle.prototype.area = function () { + return Physics.AdvancedPhysics.areaForCircle(this.radius, 0); + }; + Circle.prototype.centroid = function () { + return Phaser.Vec2Utils.clone(this.center); + }; + Circle.prototype.inertia = function (mass) { + return Physics.AdvancedPhysics.inertiaForCircle(mass, this.center, this.radius, 0); + }; + Circle.prototype.cacheData = function (xf) { + 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); + }; + Circle.prototype.pointQuery = function (p) { + //return vec2.distsq(this.tc, p) < (this.r * this.r); + return Phaser.Vec2Utils.distanceSq(this.tc, p) < (this.radius * this.radius); + }; + Circle.prototype.findVertexByPoint = function (p, minDist) { + var dsq = minDist * minDist; + if(Phaser.Vec2Utils.distanceSq(this.tc, p) < dsq) { + return 0; + } + return -1; + }; + Circle.prototype.distanceOnPlane = function (n, d) { + Phaser.Vec2Utils.dot(n, this.tc) - this.radius - d; + }; + return Circle; + })(Phaser.Physics.Shape); + Shapes.Circle = Circle; + })(Physics.Shapes || (Physics.Shapes = {})); + var Shapes = Physics.Shapes; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); diff --git a/todo/physics/shapes/Circle.js.map b/todo/physics/shapes/Circle.js.map new file mode 100644 index 00000000..46921cb2 --- /dev/null +++ b/todo/physics/shapes/Circle.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Circle.js","sources":["Circle.ts"],"names":["Phaser","Phaser.Physics","Phaser.Physics.Shapes","Phaser.Physics.Shapes.Circle","Phaser.Physics.Shapes.Circle.constructor","Phaser.Physics.Shapes.Circle.finishVerts","Phaser.Physics.Shapes.Circle.duplicate","Phaser.Physics.Shapes.Circle.recenter","Phaser.Physics.Shapes.Circle.transform","Phaser.Physics.Shapes.Circle.untransform","Phaser.Physics.Shapes.Circle.area","Phaser.Physics.Shapes.Circle.centroid","Phaser.Physics.Shapes.Circle.inertia","Phaser.Physics.Shapes.Circle.cacheData","Phaser.Physics.Shapes.Circle.pointQuery","Phaser.Physics.Shapes.Circle.findVertexByPoint","Phaser.Physics.Shapes.Circle.distanceOnPlane"],"mappings":"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"} \ No newline at end of file diff --git a/Phaser/physics/shapes/Circle.ts b/todo/physics/shapes/Circle.ts similarity index 100% rename from Phaser/physics/shapes/Circle.ts rename to todo/physics/shapes/Circle.ts diff --git a/todo/physics/shapes/IShape.js b/todo/physics/shapes/IShape.js new file mode 100644 index 00000000..38c4f862 --- /dev/null +++ b/todo/physics/shapes/IShape.js @@ -0,0 +1,3 @@ +var Phaser; +(function (Phaser) { + })(Phaser || (Phaser = {})); diff --git a/todo/physics/shapes/IShape.js.map b/todo/physics/shapes/IShape.js.map new file mode 100644 index 00000000..b957e623 --- /dev/null +++ b/todo/physics/shapes/IShape.js.map @@ -0,0 +1 @@ +{"version":3,"file":"IShape.js","sources":["IShape.ts"],"names":["Phaser"],"mappings":"AAaA,IAAO,MAAM;AAgCZ,CAhCD,UAAO,MAAM;IAgCbA,CAACA,2BAAA"} \ No newline at end of file diff --git a/Phaser/physics/shapes/IShape.ts b/todo/physics/shapes/IShape.ts similarity index 100% rename from Phaser/physics/shapes/IShape.ts rename to todo/physics/shapes/IShape.ts diff --git a/todo/physics/shapes/Poly.js b/todo/physics/shapes/Poly.js new file mode 100644 index 00000000..95311d67 --- /dev/null +++ b/todo/physics/shapes/Poly.js @@ -0,0 +1,206 @@ +var __extends = this.__extends || function (d, b) { + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); +}; +var Phaser; +(function (Phaser) { + (function (Physics) { + /// + /// + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Shapes - Convex Polygon + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + (function (Shapes) { + var Poly = (function (_super) { + __extends(Poly, _super); + // Verts is an optional array of objects, the objects must have public x and y properties which will be used + // to seed this polygon (i.e. Vec2 objects, or just straight JS objects) and must wind COUNTER clockwise + function Poly(verts) { + _super.call(this, Physics.AdvancedPhysics.SHAPE_TYPE_POLY); + this.verts = []; + this.planes = []; + this.tverts = []; + this.tplanes = []; + if(verts) { + for(var i = 0; i < verts.length; i++) { + this.verts[i] = new Phaser.Vec2(verts[i].x, verts[i].y); + this.tverts[i] = this.verts[i]; + //this.tverts[i] = new Phaser.Vec2(verts[i].x, verts[i].y); + this.tplanes[i] = new Phaser.Physics.Plane(new Phaser.Vec2(), 0); + } + } + this.finishVerts(); + } + Poly.prototype.finishVerts = function () { + 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] = new Phaser.Physics.Plane(n, Phaser.Vec2Utils.dot(n, a)); + this.tverts[i] = Phaser.Vec2Utils.clone(this.verts[i])// reference??? + ; + //this.tverts[i] = this.verts[i]; // reference??? + this.tplanes[i] = new Phaser.Physics.Plane(new Phaser.Vec2(), 0); + } + for(var i = 0; i < this.verts.length; i++) { + //var b = this.verts[(i + 2) % this.verts.length]; + //var n = this.planes[i].normal; + //var d = this.planes[i].d; + if(Phaser.Vec2Utils.dot(this.planes[i].normal, this.verts[(i + 2) % this.verts.length]) - this.planes[i].d > 0) { + this.convexity = false; + } + } + }; + Poly.prototype.duplicate = function () { + return new Phaser.Physics.Shapes.Poly(this.verts); + }; + Poly.prototype.recenter = function (c) { + for(var i = 0; i < this.verts.length; i++) { + this.verts[i].subtract(c); + } + }; + Poly.prototype.transform = function (xf) { + for(var i = 0; i < this.verts.length; i++) { + this.verts[i] = Phaser.TransformUtils.transform(xf, this.verts[i]); + //this.verts[i] = xf.transform(this.verts[i]); + } + }; + Poly.prototype.untransform = function (xf) { + for(var i = 0; i < this.verts.length; i++) { + this.verts[i] = Phaser.TransformUtils.untransform(xf, this.verts[i]); + //this.verts[i] = xf.untransform(this.verts[i]); + } + }; + Poly.prototype.area = function () { + return Physics.AdvancedPhysics.areaForPoly(this.verts); + }; + Poly.prototype.centroid = function () { + return Physics.AdvancedPhysics.centroidForPoly(this.verts); + }; + Poly.prototype.inertia = function (mass) { + return Physics.AdvancedPhysics.inertiaForPoly(mass, this.verts, new Phaser.Vec2()); + }; + Poly.prototype.cacheData = function (xf) { + this.bounds.clear(); + var numVerts = this.verts.length; + Physics.AdvancedPhysics.write('----------- Poly cacheData = ' + numVerts); + if(numVerts == 0) { + return; + } + for(var i = 0; i < numVerts; i++) { + this.tverts[i] = Phaser.TransformUtils.transform(xf, this.verts[i]); + //this.tverts[i] = xf.transform(this.verts[i]); + Physics.AdvancedPhysics.write('tvert' + i + ' = ' + this.tverts[i].toString()); + } + 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))); + Physics.AdvancedPhysics.write('a = ' + a.toString()); + Physics.AdvancedPhysics.write('b = ' + b.toString()); + Physics.AdvancedPhysics.write('n = ' + n.toString()); + this.tplanes[i].normal = n; + this.tplanes[i].d = Phaser.Vec2Utils.dot(n, a); + Physics.AdvancedPhysics.write('tplanes' + i + ' n = ' + this.tplanes[i].normal.toString()); + Physics.AdvancedPhysics.write('tplanes' + i + ' d = ' + this.tplanes[i].d.toString()); + this.bounds.addPoint(a); + } + }; + Poly.prototype.pointQuery = function (p) { + if(!this.bounds.containPoint(p)) { + return false; + } + return this.containPoint(p); + }; + Poly.prototype.findVertexByPoint = function (p, minDist) { + 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; + }; + Poly.prototype.findEdgeByPoint = function (p, minDist) { + 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].normal; + 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; + }; + Poly.prototype.distanceOnPlane = function (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; + }; + Poly.prototype.containPoint = function (p) { + for(var i = 0; i < this.verts.length; i++) { + var plane = this.tplanes[i]; + if(Phaser.Vec2Utils.dot(plane.normal, p) - plane.d > 0) { + return false; + } + } + return true; + }; + Poly.prototype.containPointPartial = function (p, n) { + for(var i = 0; i < this.verts.length; i++) { + var plane = this.tplanes[i]; + if(Phaser.Vec2Utils.dot(plane.normal, n) < 0.0001) { + continue; + } + if(Phaser.Vec2Utils.dot(plane.normal, p) - plane.d > 0) { + return false; + } + } + return true; + }; + return Poly; + })(Phaser.Physics.Shape); + Shapes.Poly = Poly; + })(Physics.Shapes || (Physics.Shapes = {})); + var Shapes = Physics.Shapes; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); diff --git a/todo/physics/shapes/Poly.js.map b/todo/physics/shapes/Poly.js.map new file mode 100644 index 00000000..14f926d9 --- /dev/null +++ b/todo/physics/shapes/Poly.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Poly.js","sources":["Poly.ts"],"names":["Phaser","Phaser.Physics","Phaser.Physics.Shapes","Phaser.Physics.Shapes.Poly","Phaser.Physics.Shapes.Poly.constructor","Phaser.Physics.Shapes.Poly.finishVerts","Phaser.Physics.Shapes.Poly.duplicate","Phaser.Physics.Shapes.Poly.recenter","Phaser.Physics.Shapes.Poly.transform","Phaser.Physics.Shapes.Poly.untransform","Phaser.Physics.Shapes.Poly.area","Phaser.Physics.Shapes.Poly.centroid","Phaser.Physics.Shapes.Poly.inertia","Phaser.Physics.Shapes.Poly.cacheData","Phaser.Physics.Shapes.Poly.pointQuery","Phaser.Physics.Shapes.Poly.findVertexByPoint","Phaser.Physics.Shapes.Poly.findEdgeByPoint","Phaser.Physics.Shapes.Poly.distanceOnPlane","Phaser.Physics.Shapes.Poly.containPoint","Phaser.Physics.Shapes.Poly.containPointPartial"],"mappings":"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"} \ No newline at end of file diff --git a/Phaser/physics/shapes/Poly.ts b/todo/physics/shapes/Poly.ts similarity index 100% rename from Phaser/physics/shapes/Poly.ts rename to todo/physics/shapes/Poly.ts diff --git a/todo/physics/shapes/Segment.js b/todo/physics/shapes/Segment.js new file mode 100644 index 00000000..678f8047 --- /dev/null +++ b/todo/physics/shapes/Segment.js @@ -0,0 +1,141 @@ +var __extends = this.__extends || function (d, b) { + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); +}; +var Phaser; +(function (Phaser) { + (function (Physics) { + /// + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Shapes - Segment + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + (function (Shapes) { + var Segment = (function (_super) { + __extends(Segment, _super); + function Segment(a, b, radius) { + _super.call(this, Physics.AdvancedPhysics.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(); + } + Segment.prototype.finishVerts = function () { + this.normal = Phaser.Vec2Utils.perp(Phaser.Vec2Utils.subtract(this.b, this.a)); + this.normal.normalize(); + this.radius = Math.abs(this.radius); + }; + Segment.prototype.duplicate = function () { + return new Phaser.Physics.Shapes.Segment(this.a, this.b, this.radius); + }; + Segment.prototype.recenter = function (c) { + this.a.subtract(c); + this.b.subtract(c); + }; + Segment.prototype.transform = function (xf) { + 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); + }; + Segment.prototype.untransform = function (xf) { + 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); + }; + Segment.prototype.area = function () { + return Physics.AdvancedPhysics.areaForSegment(this.a, this.b, this.radius); + }; + Segment.prototype.centroid = function () { + return Physics.AdvancedPhysics.centroidForSegment(this.a, this.b); + }; + Segment.prototype.inertia = function (mass) { + return Physics.AdvancedPhysics.inertiaForSegment(mass, this.a, this.b); + }; + Segment.prototype.cacheData = function (xf) { + 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); + }; + Segment.prototype.pointQuery = function (p) { + 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; + }; + Segment.prototype.findVertexByPoint = function (p, minDist) { + 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; + }; + Segment.prototype.distanceOnPlane = function (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; + }; + return Segment; + })(Phaser.Physics.Shape); + Shapes.Segment = Segment; + })(Physics.Shapes || (Physics.Shapes = {})); + var Shapes = Physics.Shapes; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); diff --git a/todo/physics/shapes/Segment.js.map b/todo/physics/shapes/Segment.js.map new file mode 100644 index 00000000..d7f8512a --- /dev/null +++ b/todo/physics/shapes/Segment.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Segment.js","sources":["Segment.ts"],"names":["Phaser","Phaser.Physics","Phaser.Physics.Shapes","Phaser.Physics.Shapes.Segment","Phaser.Physics.Shapes.Segment.constructor","Phaser.Physics.Shapes.Segment.finishVerts","Phaser.Physics.Shapes.Segment.duplicate","Phaser.Physics.Shapes.Segment.recenter","Phaser.Physics.Shapes.Segment.transform","Phaser.Physics.Shapes.Segment.untransform","Phaser.Physics.Shapes.Segment.area","Phaser.Physics.Shapes.Segment.centroid","Phaser.Physics.Shapes.Segment.inertia","Phaser.Physics.Shapes.Segment.cacheData","Phaser.Physics.Shapes.Segment.pointQuery","Phaser.Physics.Shapes.Segment.findVertexByPoint","Phaser.Physics.Shapes.Segment.distanceOnPlane"],"mappings":"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"} \ No newline at end of file diff --git a/Phaser/physics/shapes/Segment.ts b/todo/physics/shapes/Segment.ts similarity index 100% rename from Phaser/physics/shapes/Segment.ts rename to todo/physics/shapes/Segment.ts diff --git a/todo/physics/shapes/Shape.js b/todo/physics/shapes/Shape.js new file mode 100644 index 00000000..12786dac --- /dev/null +++ b/todo/physics/shapes/Shape.js @@ -0,0 +1,33 @@ +var Phaser; +(function (Phaser) { + /// + /// + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Shape + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + (function (Physics) { + var Shape = (function () { + function Shape(type) { + this.id = Physics.AdvancedPhysics.shapeCounter++; + this.type = type; + this.elasticity = 0.0; + this.friction = 1.0; + this.density = 1; + this.bounds = new Physics.Bounds(); + } + Shape.prototype.findEdgeByPoint = // Over-ridden by ShapePoly + function (p, minDist) { + return -1; + }; + return Shape; + })(); + Physics.Shape = Shape; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); diff --git a/todo/physics/shapes/Shape.js.map b/todo/physics/shapes/Shape.js.map new file mode 100644 index 00000000..eef9473d --- /dev/null +++ b/todo/physics/shapes/Shape.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Shape.js","sources":["Shape.ts"],"names":["Phaser","Phaser.Physics","Phaser.Physics.Shape","Phaser.Physics.Shape.constructor","Phaser.Physics.Shape.findEdgeByPoint"],"mappings":"AAaA,IAAO,MAAM;AAgDZ,CAhDD,UAAO,MAAM;IAbbA,2CAA2CA;IAC3CA,gDAAgDA;IAChDA,sCAAsCA;IACtCA,mCAAmCA;IACnCA,qCAAqCA;IACrCA,kCAAkCA;IAElCA;;;;MAIEA;KAEKA,UAAOA,OAAOA;QAEjBC;YAEIC,SAFSA,KAAKA,CAEFA,IAAYA;gBAEpBC,IAAIA,CAACA,EAAEA,GAAGA,MAAMA,CAACA,OAAOA,CAACA,OAAOA,CAACA,YAAYA,EAAEA;gBAC/CA,IAAIA,CAACA,IAAIA,GAAGA,IAAIA;gBAEhBA,IAAIA,CAACA,UAAUA,GAAGA,GAAGA;gBACrBA,IAAIA,CAACA,QAAQA,GAAGA,GAAGA;gBACnBA,IAAIA,CAACA,OAAOA,GAAGA,CAACA;gBAEhBA,IAAIA,CAACA,MAAMA,GAAGA,IAAIA,MAAMA,EAAAA;YAE5BA,CAACA;YA2BDD,kCADAA,4BAA4BA;YAC5BA,UAAuBA,CAAcA,EAAEA,OAAeA;gBAClDE,OAAOA,CAACA,CAACA,CAACA;YACdA,CAACA;YAELF;AAACA,QAADA,CAACA,IAAAD;QA5CDA,sBA4CCA,QAAAA;IAELA,CAACA,2CAAAD;IAhDMA;AAgDNA,CAAAA,2BAAA"} \ No newline at end of file diff --git a/Phaser/physics/shapes/Shape.ts b/todo/physics/shapes/Shape.ts similarity index 100% rename from Phaser/physics/shapes/Shape.ts rename to todo/physics/shapes/Shape.ts diff --git a/todo/physics/shapes/Triangle.js b/todo/physics/shapes/Triangle.js new file mode 100644 index 00000000..2c8aea16 --- /dev/null +++ b/todo/physics/shapes/Triangle.js @@ -0,0 +1,51 @@ +var __extends = this.__extends || function (d, b) { + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); +}; +var Phaser; +(function (Phaser) { + (function (Physics) { + /// + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Shapes - Triangle + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + (function (Shapes) { + var Triangle = (function (_super) { + __extends(Triangle, _super); + function Triangle(x1, y1, x2, y2, x3, y3) { + x1 = Phaser.Physics.AdvancedPhysics.pixelsToMeters(x1); + y1 = Phaser.Physics.AdvancedPhysics.pixelsToMeters(y1); + x2 = Phaser.Physics.AdvancedPhysics.pixelsToMeters(x2); + y2 = Phaser.Physics.AdvancedPhysics.pixelsToMeters(y2); + x3 = Phaser.Physics.AdvancedPhysics.pixelsToMeters(x3); + y3 = Phaser.Physics.AdvancedPhysics.pixelsToMeters(y3); + _super.call(this, [ + { + x: x1, + y: y1 + }, + { + x: x2, + y: y2 + }, + { + x: x3, + y: y3 + } + ]); + } + return Triangle; + })(Phaser.Physics.Shapes.Poly); + Shapes.Triangle = Triangle; + })(Physics.Shapes || (Physics.Shapes = {})); + var Shapes = Physics.Shapes; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); diff --git a/todo/physics/shapes/Triangle.js.map b/todo/physics/shapes/Triangle.js.map new file mode 100644 index 00000000..c1b54ffa --- /dev/null +++ b/todo/physics/shapes/Triangle.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Triangle.js","sources":["Triangle.ts"],"names":["Phaser","Phaser.Physics","Phaser.Physics.Shapes","Phaser.Physics.Shapes.Triangle","Phaser.Physics.Shapes.Triangle.constructor"],"mappings":";;;;;AAYA,IAAO,MAAM;AAmBZ,CAnBD,UAAO,MAAM;KAANA,UAAOA,OAAOA;QAZrBC,2CAA2CA;QAC3CA,sCAAsCA;QACtCA,mCAAmCA;QACnCA,iCAAiCA;QACjCA,gCAAgCA;QAEhCA;;;;UAIEA;SAEKA,UAAeA,MAAMA;YAExBC;;gBAEIC,SAFSA,QAAQA,CAELA,EAAUA,EAAEA,EAAUA,EAAEA,EAAUA,EAAEA,EAAUA,EAAEA,EAAUA,EAAEA,EAAUA;oBAE9EC,EAAEA,GAAGA,eAAOA,CAACA,cAAcA,CAACA,EAAEA,CAACA;oBAC/BA,EAAEA,GAAGA,eAAOA,CAACA,cAAcA,CAACA,EAAEA,CAACA;oBAC/BA,EAAEA,GAAGA,eAAOA,CAACA,cAAcA,CAACA,EAAEA,CAACA;oBAC/BA,EAAEA,GAAGA,eAAOA,CAACA,cAAcA,CAACA,EAAEA,CAACA;oBAC/BA,EAAEA,GAAGA,eAAOA,CAACA,cAAcA,CAACA,EAAEA,CAACA;oBAC/BA,EAAEA,GAAGA,eAAOA,CAACA,cAAcA,CAACA,EAAEA,CAACA;oBAE/BA,8BAAMA;gBAACA;oBAAEA,CAACA,EAAEA,EAAEA;oBAAEA,CAACA,EAAEA,EAAEA;iBAAEA;gBAAEA;oBAAEA,CAACA,EAAEA,EAAEA;oBAAEA,CAACA,EAAEA,EAAEA;iBAAEA;gBAAEA;oBAAEA,CAACA,EAAEA,EAAEA;oBAAEA,CAACA,EAAEA,EAAEA;iBAAEA;aAACA,CAInEA;gBAFGA,CAACA;gBAELD;AAACA,YAADA,CAACA,EAf6BD,MAAMA,CAACA,OAAOA,CAACA,MAAMA,CAACA,IAAIA,EAevDA;YAfDA,2BAeCA,YAAAA;QAELA,CAACA,2CAAAD;QAnBMA;AAmBNA,IAADA,CAACA,2CAAAD;IAnBMA;AAmBNA,CAAAA,2BAAA"} \ No newline at end of file diff --git a/Phaser/physics/shapes/Triangle.ts b/todo/physics/shapes/Triangle.ts similarity index 100% rename from Phaser/physics/shapes/Triangle.ts rename to todo/physics/shapes/Triangle.ts