From 829a1b00e4bed722e3b62435a24316c0f2ee5d8e Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Tue, 18 Jun 2013 19:37:09 +0100 Subject: [PATCH 1/2] Brand new physics system finally (mostly) working. Some poly issues to resolve, but it's running well. --- Phaser/input/Input.ts | 25 ++ Phaser/physics/advanced/Body.ts | 77 +++++- Phaser/physics/advanced/Bounds.ts | 16 ++ Phaser/physics/advanced/Space.ts | 1 + Phaser/physics/advanced/shapes/Box.ts | 8 +- Phaser/physics/advanced/shapes/Circle.ts | 4 + Phaser/physics/advanced/shapes/Poly.ts | 9 +- Phaser/physics/advanced/shapes/Triangle.ts | 11 +- Tests/assets/sprites/cokecan.png | Bin 0 -> 1381 bytes Tests/phaser.js | 292 +++++++++++++++------ Tests/physics/body1.js | 62 ++++- Tests/physics/body1.ts | 49 ++-- build/phaser.d.ts | 70 +++-- build/phaser.js | 292 +++++++++++++++------ 14 files changed, 684 insertions(+), 232 deletions(-) create mode 100644 Tests/assets/sprites/cokecan.png diff --git a/Phaser/input/Input.ts b/Phaser/input/Input.ts index 32ed80cd..26231fee 100644 --- a/Phaser/input/Input.ts +++ b/Phaser/input/Input.ts @@ -53,6 +53,11 @@ module Phaser { this.activePointer = this.mousePointer; this.currentPointers = 0; + this.hitCanvas = document.createElement('canvas'); + this.hitCanvas.width = 1; + this.hitCanvas.height = 1; + this.hitContext = this.hitCanvas.getContext('2d'); + } /** @@ -60,6 +65,18 @@ module Phaser { */ private _game: Game; + /** + * A 1x1 sized canvas used for pixel-perfect checks + * @type {HTMLCanvasElement} + */ + public hitCanvas: HTMLCanvasElement; + + /** + * The context of the 1x1 pixel check canvas + * @type {CanvasRenderingContext2D} + */ + public hitContext: CanvasRenderingContext2D; + /** * A vector object representing the previous position of the Pointer. * @property vector @@ -961,6 +978,14 @@ module Phaser { return Vec2Utils.angle(pointer1.position, pointer2.position); } + public pixelPerfectCheck(sprite: Phaser.Sprite, pointer: Phaser.Pointer, alpha: number = 255): bool { + + this.hitContext.clearRect(0, 0, 1, 1); + + return true; + + } + } } \ No newline at end of file diff --git a/Phaser/physics/advanced/Body.ts b/Phaser/physics/advanced/Body.ts index a6cdf4c1..fff4d13e 100644 --- a/Phaser/physics/advanced/Body.ts +++ b/Phaser/physics/advanced/Body.ts @@ -8,6 +8,11 @@ /// /// /// +/// +/// +/// +/// +/// /** * Phaser - Advanced Physics - Body @@ -29,12 +34,12 @@ module Phaser.Physics.Advanced { { this.sprite = sprite; this.game = sprite.game; - this.position = new Phaser.Vec2(sprite.x, sprite.y); + this.position = new Phaser.Vec2(Phaser.Physics.Advanced.Manager.pixelsToMeters(sprite.x), Phaser.Physics.Advanced.Manager.pixelsToMeters(sprite.y)); this.angle = sprite.rotation; } else { - this.position = new Phaser.Vec2(x, y); + this.position = new Phaser.Vec2(Phaser.Physics.Advanced.Manager.pixelsToMeters(x), Phaser.Physics.Advanced.Manager.pixelsToMeters(y)); this.angle = 0; } @@ -64,6 +69,8 @@ module Phaser.Physics.Advanced { } + private _tempVec2: Phaser.Vec2 = new Phaser.Vec2; + /** * Reference to Phaser.Game */ @@ -139,6 +146,11 @@ module Phaser.Physics.Advanced { // Bounds of all shapes public bounds: Bounds; + public mass: number; + public massInverted: number; + public inertia: number; + public inertiaInverted: number; + public fixedRotation = false; public categoryBits = 0x0001; public maskBits = 0xFFFF; @@ -195,6 +207,62 @@ module Phaser.Physics.Advanced { } + public addPoly(verts, elasticity?: number = 1, friction?: number = 1, density?: number = 1): Phaser.Physics.Advanced.Shapes.Poly { + + var poly: Phaser.Physics.Advanced.Shapes.Poly = new Phaser.Physics.Advanced.Shapes.Poly(verts); + poly.elasticity = elasticity; + poly.friction = friction; + poly.density = density; + + this.addShape(poly); + this.resetMassData(); + + return poly; + + } + + public addTriangle(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, elasticity?: number = 1, friction?: number = 1, density?: number = 1): Phaser.Physics.Advanced.Shapes.Triangle { + + var tri: Phaser.Physics.Advanced.Shapes.Triangle = new Phaser.Physics.Advanced.Shapes.Triangle(x1, y1, x2, y2, x3, y3); + tri.elasticity = elasticity; + tri.friction = friction; + tri.density = density; + + this.addShape(tri); + this.resetMassData(); + + return tri; + + } + + public addBox(x: number, y: number, width: number, height: number, elasticity?: number = 1, friction?: number = 1, density?: number = 1): Phaser.Physics.Advanced.Shapes.Box { + + var box: Phaser.Physics.Advanced.Shapes.Box = new Phaser.Physics.Advanced.Shapes.Box(x, y, width, height); + box.elasticity = elasticity; + box.friction = friction; + box.density = density; + + this.addShape(box); + this.resetMassData(); + + return box; + + } + + public addCircle(radius: number, x?: number = 0, y?: number = 0, elasticity?: number = 1, friction?: number = 1, density?: number = 1): Phaser.Physics.Advanced.Shapes.Circle { + + var circle: Phaser.Physics.Advanced.Shapes.Circle = new Phaser.Physics.Advanced.Shapes.Circle(radius, x, y); + circle.elasticity = elasticity; + circle.friction = friction; + circle.density = density; + + this.addShape(circle); + this.resetMassData(); + + return circle; + + } + public addShape(shape) { // Check not already part of this body @@ -218,10 +286,6 @@ module Phaser.Physics.Advanced { } - public mass: number; - public massInverted: number; - public inertia: number; - public inertiaInverted: number; private setMass(mass) { @@ -381,7 +445,6 @@ module Phaser.Physics.Advanced { } - private _tempVec2: Phaser.Vec2 = new Phaser.Vec2; public updateVelocity(gravity, dt, damping) { diff --git a/Phaser/physics/advanced/Bounds.ts b/Phaser/physics/advanced/Bounds.ts index 6e7ce285..b5eb34f8 100644 --- a/Phaser/physics/advanced/Bounds.ts +++ b/Phaser/physics/advanced/Bounds.ts @@ -71,6 +71,22 @@ module Phaser.Physics.Advanced { } + public get x(): number { + return Phaser.Physics.Advanced.Manager.metersToPixels(this.mins.x); + } + + public get y(): number { + return Phaser.Physics.Advanced.Manager.metersToPixels(this.mins.y); + } + + public get width(): number { + return Phaser.Physics.Advanced.Manager.metersToPixels(this.maxs.x - this.mins.x); + } + + public get height(): number { + return Phaser.Physics.Advanced.Manager.metersToPixels(this.maxs.y - this.mins.y); + } + public isEmpty(): bool { return (this.mins.x > this.maxs.x || this.mins.y > this.maxs.y); } diff --git a/Phaser/physics/advanced/Space.ts b/Phaser/physics/advanced/Space.ts index 52e09a5c..5bab1961 100644 --- a/Phaser/physics/advanced/Space.ts +++ b/Phaser/physics/advanced/Space.ts @@ -560,6 +560,7 @@ module Phaser.Physics.Advanced { //stats.timeCollision = Date.now() - t0; return newContactSolverArr; + } public initSolver(dt, dt_inv, warmStarting) { diff --git a/Phaser/physics/advanced/shapes/Box.ts b/Phaser/physics/advanced/shapes/Box.ts index 3159e317..5cbf2d95 100644 --- a/Phaser/physics/advanced/shapes/Box.ts +++ b/Phaser/physics/advanced/shapes/Box.ts @@ -26,10 +26,10 @@ module Phaser.Physics.Advanced.Shapes { var hh = height * 0.5; super([ - new Phaser.Vec2(-hw + x, +hh + y), - new Phaser.Vec2(-hw + x, -hh + y), - new Phaser.Vec2(+hw + x, -hh + y), - new Phaser.Vec2(+hw + x, +hh + y) + { x: -hw + x, y: +hh + y }, + { x: -hw + x, y: -hh + y }, + { x: +hw + x, y: -hh + y }, + { x: +hw + x, y: +hh + y } ]); } diff --git a/Phaser/physics/advanced/shapes/Circle.ts b/Phaser/physics/advanced/shapes/Circle.ts index 6911f118..0f12673b 100644 --- a/Phaser/physics/advanced/shapes/Circle.ts +++ b/Phaser/physics/advanced/shapes/Circle.ts @@ -18,6 +18,10 @@ module Phaser.Physics.Advanced.Shapes { super(Manager.SHAPE_TYPE_CIRCLE); + x = Manager.pixelsToMeters(x); + y = Manager.pixelsToMeters(y); + radius = Manager.pixelsToMeters(radius); + this.center = new Phaser.Vec2(x, y); this.radius = radius; this.tc = new Phaser.Vec2; diff --git a/Phaser/physics/advanced/shapes/Poly.ts b/Phaser/physics/advanced/shapes/Poly.ts index f4d50699..f4c85523 100644 --- a/Phaser/physics/advanced/shapes/Poly.ts +++ b/Phaser/physics/advanced/shapes/Poly.ts @@ -14,7 +14,9 @@ module Phaser.Physics.Advanced.Shapes { export class Poly extends Phaser.Physics.Advanced.Shape implements IShape { - constructor(verts?:Phaser.Vec2[]) { + // 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 + constructor(verts?) { super(Manager.SHAPE_TYPE_POLY); @@ -28,7 +30,7 @@ module Phaser.Physics.Advanced.Shapes { { for (var i = 0; i < verts.length; i++) { - this.verts[i] = Phaser.Vec2Utils.clone(verts[i]); + this.verts[i] = new Phaser.Vec2(verts[i].x, verts[i].y); this.tverts[i] = this.verts[i]; this.tplanes[i] = {}; @@ -91,6 +93,7 @@ module Phaser.Physics.Advanced.Shapes { this.convexity = false; } } + } public duplicate() { @@ -138,7 +141,7 @@ module Phaser.Physics.Advanced.Shapes { var numVerts = this.verts.length; - //console.log('shapePoly cacheData', numVerts); + console.log('Poly cacheData', numVerts, this.body.name); if (numVerts == 0) { diff --git a/Phaser/physics/advanced/shapes/Triangle.ts b/Phaser/physics/advanced/shapes/Triangle.ts index 90147ca8..7b88e013 100644 --- a/Phaser/physics/advanced/shapes/Triangle.ts +++ b/Phaser/physics/advanced/shapes/Triangle.ts @@ -14,9 +14,16 @@ module Phaser.Physics.Advanced.Shapes { export class Triangle extends Phaser.Physics.Advanced.Shapes.Poly { - constructor(p1, p2, p3) { + constructor(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number) { - super( [ new Phaser.Vec2(p1.x, p1.y), new Phaser.Vec2(p2.x, p2.y), new Phaser.Vec2(p3.x, p3.y) ] ); + x1 = Manager.pixelsToMeters(x1); + y1 = Manager.pixelsToMeters(y1); + x2 = Manager.pixelsToMeters(x2); + y2 = Manager.pixelsToMeters(y2); + x3 = Manager.pixelsToMeters(x3); + y3 = Manager.pixelsToMeters(y3); + + super([{ x: x1, y: y1 }, { x: x2, y: y2 }, { x: x3, y: y3 }]); } diff --git a/Tests/assets/sprites/cokecan.png b/Tests/assets/sprites/cokecan.png new file mode 100644 index 0000000000000000000000000000000000000000..64ab2678c72f34c612bf991531daf64f48563505 GIT binary patch literal 1381 zcmV-r1)BPaP)wDuWols^`7FXrlg&2VA2YLRdtaJ<4FZ+0)Ce1CQBg!8Xf5(2(v+}g z6NW_fr^39%g)oQ5^X^YZ2}_BvS0#%hO$kedF!C~MMbfEjnG&`YVgDOhzFMY)Y4WWX zEGhe}+NFf0Mc7(Zfx+^8n-gFvvY~g15*8~C^VO~qNylT_SD(I^+Z+?d&$wx3e1-DBW=&CohOl7OJ4+SWz#j!M`<8`Z=9iNDAzK5}HMRZrjz z89>62Jch8=ld!X(VN%^s3HvBve=hFd4UBWltNk=7{oCaFz1eU24;8?a5|)aW9K~N$ zDJ|yXEh4Kko%4?N;co|hT)T*@4Xk|a2LJ1v_4PAlHp_+M%;(PcWvey)RR|ldY{AsD zg_=B(b?;$2OF#h`g7kf|lk?hKyOql+=r~07TXwqxeq293WN920Ez&1~Y%`lnQP1U0 zD^Rmyn?!UM8r!pXR)cY=QNp6+l7m~aj8~f0Ana+LcVT)a1&Z~gdh_eb=iX7KMy*h;zNtkLtw z3lmZQyng1iMk0&qXAMIzksYd$)ZWGIcP>tzH&ml>*i#5Q589H?YK^Z}4b={(8GD9c zi7d%`4}|U9QwFRk(=w2yaoE;`jR^`Ht4ejNnyIkvJ;~*AQ%<|6{xymUFtdTUQwe(( zVfmmf^Q09_j>i#3#%WooR*Hmy>3qq}b4f7l_wPep>eiDb5+psLhV4>4);B}AFl2|0 zN>akMCXBOpB#I-8(au)TKI`d?cW%GS{k-(uJ4q9U5x#HKHH_o()H11Fio~IpjyxMc z35%{_Uwyv_bQA-wT zmba$4<5r+qCFHILB`k5mFv8EJp8x3EIz5SOxd#I0^NY}Q-s-y%`MmgbV7bDvq; nEhLU3d81$TQ^F$IZvh4X4NiHgoGZRt00000NkvXXu0mjf`d62e literal 0 HcmV?d00001 diff --git a/Tests/phaser.js b/Tests/phaser.js index 0f9b2dab..70ddf6c5 100644 --- a/Tests/phaser.js +++ b/Tests/phaser.js @@ -16057,6 +16057,10 @@ var Phaser; this.camera = this._game.camera; this.activePointer = this.mousePointer; this.currentPointers = 0; + this.hitCanvas = document.createElement('canvas'); + this.hitCanvas.width = 1; + this.hitCanvas.height = 1; + this.hitContext = this.hitCanvas.getContext('2d'); } Input.MOUSE_OVERRIDES_TOUCH = 0; Input.TOUCH_OVERRIDES_MOUSE = 1; @@ -16495,7 +16499,16 @@ var Phaser; return Input; })(); Phaser.Input = Input; -})(Phaser || (Phaser = {})); + /* + public pixelPerfectCheck(sprite: Phaser.Sprite, pointer: Phaser.Pointer, alpha: number = 255): bool { + + this.hitContext.clearRect(0, 0, 1, 1); + + return true; + + } + */ + })(Phaser || (Phaser = {})); /// /// /// @@ -19387,6 +19400,34 @@ var Phaser; this.maxs.setTo(-999999, -999999); return this; }; + Object.defineProperty(Bounds.prototype, "x", { + get: function () { + return Phaser.Physics.Advanced.Manager.metersToPixels(this.mins.x); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Bounds.prototype, "y", { + get: function () { + return Phaser.Physics.Advanced.Manager.metersToPixels(this.mins.y); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Bounds.prototype, "width", { + get: function () { + return Phaser.Physics.Advanced.Manager.metersToPixels(this.maxs.x - this.mins.x); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Bounds.prototype, "height", { + get: function () { + return Phaser.Physics.Advanced.Manager.metersToPixels(this.maxs.y - this.mins.y); + }, + enumerable: true, + configurable: true + }); Bounds.prototype.isEmpty = function () { return (this.mins.x > this.maxs.x || this.mins.y > this.maxs.y); }; @@ -19845,6 +19886,9 @@ var Phaser; if (typeof x === "undefined") { x = 0; } if (typeof y === "undefined") { y = 0; } _super.call(this, Advanced.Manager.SHAPE_TYPE_CIRCLE); + x = Advanced.Manager.pixelsToMeters(x); + y = Advanced.Manager.pixelsToMeters(y); + radius = Advanced.Manager.pixelsToMeters(radius); this.center = new Phaser.Vec2(x, y); this.radius = radius; this.tc = new Phaser.Vec2(); @@ -19923,6 +19967,8 @@ var Phaser; (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, Advanced.Manager.SHAPE_TYPE_POLY); this.verts = []; @@ -19931,7 +19977,7 @@ var Phaser; this.tplanes = []; if(verts) { for(var i = 0; i < verts.length; i++) { - this.verts[i] = Phaser.Vec2Utils.clone(verts[i]); + this.verts[i] = new Phaser.Vec2(verts[i].x, verts[i].y); this.tverts[i] = this.verts[i]; this.tplanes[i] = { }; @@ -20004,7 +20050,7 @@ var Phaser; Poly.prototype.cacheData = function (xf) { this.bounds.clear(); var numVerts = this.verts.length; - //console.log('shapePoly cacheData', numVerts); + console.log('Poly cacheData', numVerts, this.body.name); if(numVerts == 0) { return; } @@ -21156,6 +21202,109 @@ var Phaser; var Physics = Phaser.Physics; })(Phaser || (Phaser = {})); var Phaser; +(function (Phaser) { + (function (Physics) { + (function (Advanced) { + /// + /// + /// + /// + /// + /** + * 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 = Advanced.Manager.pixelsToMeters(x1); + y1 = Advanced.Manager.pixelsToMeters(y1); + x2 = Advanced.Manager.pixelsToMeters(x2); + y2 = Advanced.Manager.pixelsToMeters(y2); + x3 = Advanced.Manager.pixelsToMeters(x3); + y3 = Advanced.Manager.pixelsToMeters(y3); + _super.call(this, [ + { + x: x1, + y: y1 + }, + { + x: x2, + y: y2 + }, + { + x: x3, + y: y3 + } + ]); + } + return Triangle; + })(Phaser.Physics.Advanced.Shapes.Poly); + Shapes.Triangle = Triangle; + })(Advanced.Shapes || (Advanced.Shapes = {})); + var Shapes = Advanced.Shapes; + })(Physics.Advanced || (Physics.Advanced = {})); + var Advanced = Physics.Advanced; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + (function (Physics) { + (function (Advanced) { + /// + /// + /// + /// + /// + /** + * 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) { + x = Advanced.Manager.pixelsToMeters(x); + y = Advanced.Manager.pixelsToMeters(y); + width = Advanced.Manager.pixelsToMeters(width); + height = Advanced.Manager.pixelsToMeters(height); + var hw = width * 0.5; + var hh = height * 0.5; + _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.Advanced.Shapes.Poly); + Shapes.Box = Box; + })(Advanced.Shapes || (Advanced.Shapes = {})); + var Shapes = Advanced.Shapes; + })(Physics.Advanced || (Physics.Advanced = {})); + var Advanced = Physics.Advanced; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); +var Phaser; (function (Phaser) { (function (Physics) { /// @@ -21168,6 +21317,11 @@ var Phaser; /// /// /// + /// + /// + /// + /// + /// /** * Phaser - Advanced Physics - Body * @@ -21178,6 +21332,7 @@ var Phaser; function Body(sprite, type, x, y) { if (typeof x === "undefined") { x = 0; } if (typeof y === "undefined") { y = 0; } + this._tempVec2 = new Phaser.Vec2(); // Shapes this.shapes = []; // Joints @@ -21188,17 +21343,16 @@ var Phaser; this.categoryBits = 0x0001; this.maskBits = 0xFFFF; this.stepCount = 0; - this._tempVec2 = new Phaser.Vec2(); this.id = Phaser.Physics.Advanced.Manager.bodyCounter++; this.name = 'body' + this.id; this.type = type; if(sprite) { this.sprite = sprite; this.game = sprite.game; - this.position = new Phaser.Vec2(sprite.x, sprite.y); + this.position = new Phaser.Vec2(Phaser.Physics.Advanced.Manager.pixelsToMeters(sprite.x), Phaser.Physics.Advanced.Manager.pixelsToMeters(sprite.y)); this.angle = sprite.rotation; } else { - this.position = new Phaser.Vec2(x, y); + this.position = new Phaser.Vec2(Phaser.Physics.Advanced.Manager.pixelsToMeters(x), Phaser.Physics.Advanced.Manager.pixelsToMeters(y)); this.angle = 0; } this.transform = new Phaser.Transform(this.position, this.angle); @@ -21270,6 +21424,56 @@ var Phaser; 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.Advanced.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.Advanced.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.Advanced.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.Advanced.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; @@ -21524,82 +21728,6 @@ var Phaser; })(Phaser.Physics || (Phaser.Physics = {})); var Physics = Phaser.Physics; })(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - (function (Physics) { - (function (Advanced) { - /// - /// - /// - /// - /// - /** - * 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) { - x = Advanced.Manager.pixelsToMeters(x); - y = Advanced.Manager.pixelsToMeters(y); - width = Advanced.Manager.pixelsToMeters(width); - height = Advanced.Manager.pixelsToMeters(height); - var hw = width * 0.5; - var hh = height * 0.5; - _super.call(this, [ - new Phaser.Vec2(-hw + x, +hh + y), - new Phaser.Vec2(-hw + x, -hh + y), - new Phaser.Vec2(+hw + x, -hh + y), - new Phaser.Vec2(+hw + x, +hh + y) - ]); - } - return Box; - })(Phaser.Physics.Advanced.Shapes.Poly); - Shapes.Box = Box; - })(Advanced.Shapes || (Advanced.Shapes = {})); - var Shapes = Advanced.Shapes; - })(Physics.Advanced || (Physics.Advanced = {})); - var Advanced = Physics.Advanced; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - (function (Physics) { - (function (Advanced) { - /// - /// - /// - /// - /// - /** - * 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(p1, p2, p3) { - _super.call(this, [ - new Phaser.Vec2(p1.x, p1.y), - new Phaser.Vec2(p2.x, p2.y), - new Phaser.Vec2(p3.x, p3.y) - ]); - } - return Triangle; - })(Phaser.Physics.Advanced.Shapes.Poly); - Shapes.Triangle = Triangle; - })(Advanced.Shapes || (Advanced.Shapes = {})); - var Shapes = Advanced.Shapes; - })(Physics.Advanced || (Physics.Advanced = {})); - var Advanced = Physics.Advanced; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); /// /// /// diff --git a/Tests/physics/body1.js b/Tests/physics/body1.js index f8f99706..1af4c4ea 100644 --- a/Tests/physics/body1.js +++ b/Tests/physics/body1.js @@ -15,32 +15,63 @@ var physics; var circle; var walls; - var ground; + var t; function create() { atari = game.add.sprite(200, 100, 'atari'); + // need to get the physics bounds around the sprite center, regardless of origin atari.transform.origin.setTo(0.5, 0.5); //card = game.add.sprite(500, 300, 'card'); physics = new Phaser.Physics.Advanced.Manager(game); - walls = new Phaser.Physics.Advanced.Body(null, Phaser.Types.BODY_STATIC); + walls = new Phaser.Physics.Advanced.Body(null, Phaser.Types.BODY_KINETIC); walls.game = game; + walls.addBox(500, 500, 500, 20); + walls.addBox(100, 250, 250, 20); + walls.transform.setRotation(game.math.degreesToRadians(3)); + //walls.fixedRotation = true; // position is in relation to the containing body! don't forget this - ground = walls.addShape(new Phaser.Physics.Advanced.Shapes.Box(400, 500, 500, 20)); + //ground = walls.addShape(new Phaser.Physics.Advanced.Shapes.Box(400, 500, 500, 20)); //walls.addShape(new Phaser.Physics.Advanced.ShapeBox(0, 0.2, 20.48, 0.4)); //walls.addShape(new Phaser.Physics.Advanced.ShapeBox(0, 15.16, 20.48, 0.4)); //walls.addShape(new Phaser.Physics.Advanced.ShapeBox(-10.04, 7.68, 0.4, 14.56)); //walls.addShape(new Phaser.Physics.Advanced.ShapeBox(10.04, 7.68, 0.4, 14.56)); - walls.resetMassData(); + //walls.resetMassData(); physics.space.addBody(walls); // Add a circle - circle = new Phaser.Physics.Advanced.Body(null, Phaser.Types.BODY_DYNAMIC, physics.pixelsToMeters(300), physics.pixelsToMeters(200)); + circle = new Phaser.Physics.Advanced.Body(null, Phaser.Types.BODY_DYNAMIC, 100, 200); circle.game = game; - var shape = new Phaser.Physics.Advanced.Shapes.Circle(0.4, 0, 0); - shape.elasticity = 0.8; - shape.friction = 1; - shape.density = 1; - circle.addShape(shape); - circle.resetMassData(); + circle.addCircle(32, 0, 0, 0.8); physics.space.addBody(circle); + t = new Phaser.Physics.Advanced.Body(null, Phaser.Types.BODY_KINETIC, 500, 400); + t.game = game; + //t.addCircle(32, 0, 0, 0.8); + //t.addTriangle(0, 0, 1, 1, 2, 2); + t.addPoly([ + { + x: -0.8, + y: 0.48 + }, + { + x: -0.8, + y: 0 + }, + { + x: 0.8, + y: 0 + }, + { + x: 0.8, + y: 0.32 + }, + { + x: 0, + y: 0.84 + }, + { + x: -0.56, + y: 0.84 + } + ], 0.5, 1, 6); + physics.space.addBody(t); } function update() { physics.update(); @@ -71,6 +102,10 @@ //console.log(circle.velocity.x, circle.velocity.y); //console.log('p', circle.position.x, circle.position.y); } + function renderBounds(body) { + game.stage.context.fillStyle = 'rgba(0,255,200,0.2)'; + game.stage.context.fillRect(body.bounds.x, body.bounds.y, body.bounds.width, body.bounds.height); + } function renderCircle(shape) { game.stage.context.beginPath(); game.stage.context.arc(shape.tc.x * 50, shape.tc.y * 50, shape.radius * 50, 0, Math.PI * 2, false); @@ -99,6 +134,11 @@ game.stage.context.fillText('x: ' + circle.position.x + ' y: ' + circle.position.y, 32, 32); game.stage.context.fillText('vx: ' + circle.velocity.x + ' vy: ' + circle.velocity.y, 32, 64); renderCircle(circle.shapes[0]); + renderBounds(circle); drawPolygon(game.stage.context, walls.shapes[0], 1, 'rgb(0,255,255)'); + drawPolygon(game.stage.context, walls.shapes[1], 1, 'rgb(0,255,255)'); + //renderCircle(t.shapes[0]); + drawPolygon(game.stage.context, t.shapes[0], 1, 'rgb(255,255,255)'); + renderBounds(t); } })(); diff --git a/Tests/physics/body1.ts b/Tests/physics/body1.ts index 2ab49637..6f43f4db 100644 --- a/Tests/physics/body1.ts +++ b/Tests/physics/body1.ts @@ -21,45 +21,50 @@ var physics: Phaser.Physics.Advanced.Manager; var circle: Phaser.Physics.Advanced.Body; var walls: Phaser.Physics.Advanced.Body; - - var ground: Phaser.Physics.Advanced.Shapes.Box; + var t: Phaser.Physics.Advanced.Body; function create() { atari = game.add.sprite(200, 100, 'atari'); + + // need to get the physics bounds around the sprite center, regardless of origin atari.transform.origin.setTo(0.5, 0.5); //card = game.add.sprite(500, 300, 'card'); physics = new Phaser.Physics.Advanced.Manager(game); - walls = new Phaser.Physics.Advanced.Body(null, Phaser.Types.BODY_STATIC); + walls = new Phaser.Physics.Advanced.Body(null, Phaser.Types.BODY_KINETIC); walls.game = game; + walls.addBox(500, 500, 500, 20); + walls.addBox(100, 250, 250, 20); + walls.transform.setRotation(game.math.degreesToRadians(3)); + //walls.fixedRotation = true; + // position is in relation to the containing body! don't forget this - ground = walls.addShape(new Phaser.Physics.Advanced.Shapes.Box(400, 500, 500, 20)); + //ground = walls.addShape(new Phaser.Physics.Advanced.Shapes.Box(400, 500, 500, 20)); //walls.addShape(new Phaser.Physics.Advanced.ShapeBox(0, 0.2, 20.48, 0.4)); //walls.addShape(new Phaser.Physics.Advanced.ShapeBox(0, 15.16, 20.48, 0.4)); //walls.addShape(new Phaser.Physics.Advanced.ShapeBox(-10.04, 7.68, 0.4, 14.56)); //walls.addShape(new Phaser.Physics.Advanced.ShapeBox(10.04, 7.68, 0.4, 14.56)); - walls.resetMassData(); + //walls.resetMassData(); physics.space.addBody(walls); // Add a circle - - circle = new Phaser.Physics.Advanced.Body(null, Phaser.Types.BODY_DYNAMIC, physics.pixelsToMeters(300), physics.pixelsToMeters(200)); + circle = new Phaser.Physics.Advanced.Body(null, Phaser.Types.BODY_DYNAMIC, 100, 200); circle.game = game; - - var shape = new Phaser.Physics.Advanced.Shapes.Circle(0.4, 0, 0); - shape.elasticity = 0.8; - shape.friction = 1; - shape.density = 1; - circle.addShape(shape); - circle.resetMassData(); - + circle.addCircle(32, 0, 0, 0.8); physics.space.addBody(circle); + t = new Phaser.Physics.Advanced.Body(null, Phaser.Types.BODY_KINETIC, 500, 400); + t.game = game; + //t.addCircle(32, 0, 0, 0.8); + //t.addTriangle(0, 0, 1, 1, 2, 2); + t.addPoly([{ x: -0.8, y: 0.48 }, { x: -0.8, y: 0 }, { x: 0.8, y: 0 }, { x: 0.8, y: 0.32 }, { x: 0, y: 0.84 }, { x: -0.56, y: 0.84 }], 0.5, 1, 6); + physics.space.addBody(t); + } function update() { @@ -106,6 +111,14 @@ //console.log('p', circle.position.x, circle.position.y); } + function renderBounds(body: Phaser.Physics.Advanced.Body) { + + game.stage.context.fillStyle = 'rgba(0,255,200,0.2)'; + + game.stage.context.fillRect(body.bounds.x, body.bounds.y, body.bounds.width, body.bounds.height); + + } + function renderCircle(shape) { game.stage.context.beginPath(); @@ -152,8 +165,14 @@ game.stage.context.fillText('vx: ' + circle.velocity.x + ' vy: ' + circle.velocity.y, 32, 64); renderCircle(circle.shapes[0]); + renderBounds(circle); drawPolygon(game.stage.context, walls.shapes[0], 1, 'rgb(0,255,255)'); + drawPolygon(game.stage.context, walls.shapes[1], 1, 'rgb(0,255,255)'); + + //renderCircle(t.shapes[0]); + drawPolygon(game.stage.context, t.shapes[0], 1, 'rgb(255,255,255)'); + renderBounds(t); } diff --git a/build/phaser.d.ts b/build/phaser.d.ts index 7a30e48a..c83cbfd5 100644 --- a/build/phaser.d.ts +++ b/build/phaser.d.ts @@ -8473,6 +8473,16 @@ module Phaser { */ private _game; /** + * A 1x1 sized canvas used for pixel-perfect checks + * @type {HTMLCanvasElement} + */ + public hitCanvas: HTMLCanvasElement; + /** + * The context of the 1x1 pixel check canvas + * @type {CanvasRenderingContext2D} + */ + public hitContext: CanvasRenderingContext2D; + /** * A vector object representing the previous position of the Pointer. * @property vector * @type {Vec2} @@ -9668,6 +9678,10 @@ module Phaser.Physics.Advanced { 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 isEmpty(): bool; public getPerimeter(): number; public addPoint(p: Vec2): Bounds; @@ -9792,7 +9806,7 @@ module Phaser.Physics.Advanced.Shapes { */ module Phaser.Physics.Advanced.Shapes { class Poly extends Shape implements IShape { - constructor(verts?: Vec2[]); + constructor(verts?); public verts: Vec2[]; public planes; public tverts; @@ -9938,6 +9952,26 @@ module Phaser.Physics.Advanced { } } /** +* Phaser - Advanced Physics - Shapes - Triangle +* +* Based on the work Ju Hyung Lee started in JS PhyRus. +*/ +module Phaser.Physics.Advanced.Shapes { + class Triangle extends Poly { + constructor(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.Advanced.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. @@ -9945,6 +9979,7 @@ module Phaser.Physics.Advanced { module Phaser.Physics.Advanced { class Body { constructor(sprite: Sprite, type: number, x?: number, y?: number); + private _tempVec2; /** * Reference to Phaser.Game */ @@ -9986,6 +10021,10 @@ module Phaser.Physics.Advanced { public joints: IJoint[]; public jointHash: {}; public bounds: Bounds; + public mass: number; + public massInverted: number; + public inertia: number; + public inertiaInverted: number; public fixedRotation: bool; public categoryBits: number; public maskBits: number; @@ -9997,12 +10036,12 @@ module Phaser.Physics.Advanced { 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; - public mass: number; - public massInverted: number; - public inertia: number; - public inertiaInverted: number; private setMass(mass); private setInertia(inertia); public setTransform(pos, angle): void; @@ -10015,7 +10054,6 @@ module Phaser.Physics.Advanced { public resetMassData(): void; public resetJointAnchors(): void; public cacheData(): void; - private _tempVec2; public updateVelocity(gravity, dt, damping): void; public updatePosition(dt): void; public resetForce(): void; @@ -10031,26 +10069,6 @@ module Phaser.Physics.Advanced { } } /** -* Phaser - Advanced Physics - Shapes - Box -* -* Based on the work Ju Hyung Lee started in JS PhyRus. -*/ -module Phaser.Physics.Advanced.Shapes { - class Box extends Poly { - constructor(x, y, width, height); - } -} -/** -* Phaser - Advanced Physics - Shapes - Triangle -* -* Based on the work Ju Hyung Lee started in JS PhyRus. -*/ -module Phaser.Physics.Advanced.Shapes { - class Triangle extends Poly { - constructor(p1, p2, p3); - } -} -/** * Phaser - PixelUtils * * A collection of methods useful for manipulating pixels. diff --git a/build/phaser.js b/build/phaser.js index 0f9b2dab..70ddf6c5 100644 --- a/build/phaser.js +++ b/build/phaser.js @@ -16057,6 +16057,10 @@ var Phaser; this.camera = this._game.camera; this.activePointer = this.mousePointer; this.currentPointers = 0; + this.hitCanvas = document.createElement('canvas'); + this.hitCanvas.width = 1; + this.hitCanvas.height = 1; + this.hitContext = this.hitCanvas.getContext('2d'); } Input.MOUSE_OVERRIDES_TOUCH = 0; Input.TOUCH_OVERRIDES_MOUSE = 1; @@ -16495,7 +16499,16 @@ var Phaser; return Input; })(); Phaser.Input = Input; -})(Phaser || (Phaser = {})); + /* + public pixelPerfectCheck(sprite: Phaser.Sprite, pointer: Phaser.Pointer, alpha: number = 255): bool { + + this.hitContext.clearRect(0, 0, 1, 1); + + return true; + + } + */ + })(Phaser || (Phaser = {})); /// /// /// @@ -19387,6 +19400,34 @@ var Phaser; this.maxs.setTo(-999999, -999999); return this; }; + Object.defineProperty(Bounds.prototype, "x", { + get: function () { + return Phaser.Physics.Advanced.Manager.metersToPixels(this.mins.x); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Bounds.prototype, "y", { + get: function () { + return Phaser.Physics.Advanced.Manager.metersToPixels(this.mins.y); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Bounds.prototype, "width", { + get: function () { + return Phaser.Physics.Advanced.Manager.metersToPixels(this.maxs.x - this.mins.x); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Bounds.prototype, "height", { + get: function () { + return Phaser.Physics.Advanced.Manager.metersToPixels(this.maxs.y - this.mins.y); + }, + enumerable: true, + configurable: true + }); Bounds.prototype.isEmpty = function () { return (this.mins.x > this.maxs.x || this.mins.y > this.maxs.y); }; @@ -19845,6 +19886,9 @@ var Phaser; if (typeof x === "undefined") { x = 0; } if (typeof y === "undefined") { y = 0; } _super.call(this, Advanced.Manager.SHAPE_TYPE_CIRCLE); + x = Advanced.Manager.pixelsToMeters(x); + y = Advanced.Manager.pixelsToMeters(y); + radius = Advanced.Manager.pixelsToMeters(radius); this.center = new Phaser.Vec2(x, y); this.radius = radius; this.tc = new Phaser.Vec2(); @@ -19923,6 +19967,8 @@ var Phaser; (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, Advanced.Manager.SHAPE_TYPE_POLY); this.verts = []; @@ -19931,7 +19977,7 @@ var Phaser; this.tplanes = []; if(verts) { for(var i = 0; i < verts.length; i++) { - this.verts[i] = Phaser.Vec2Utils.clone(verts[i]); + this.verts[i] = new Phaser.Vec2(verts[i].x, verts[i].y); this.tverts[i] = this.verts[i]; this.tplanes[i] = { }; @@ -20004,7 +20050,7 @@ var Phaser; Poly.prototype.cacheData = function (xf) { this.bounds.clear(); var numVerts = this.verts.length; - //console.log('shapePoly cacheData', numVerts); + console.log('Poly cacheData', numVerts, this.body.name); if(numVerts == 0) { return; } @@ -21156,6 +21202,109 @@ var Phaser; var Physics = Phaser.Physics; })(Phaser || (Phaser = {})); var Phaser; +(function (Phaser) { + (function (Physics) { + (function (Advanced) { + /// + /// + /// + /// + /// + /** + * 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 = Advanced.Manager.pixelsToMeters(x1); + y1 = Advanced.Manager.pixelsToMeters(y1); + x2 = Advanced.Manager.pixelsToMeters(x2); + y2 = Advanced.Manager.pixelsToMeters(y2); + x3 = Advanced.Manager.pixelsToMeters(x3); + y3 = Advanced.Manager.pixelsToMeters(y3); + _super.call(this, [ + { + x: x1, + y: y1 + }, + { + x: x2, + y: y2 + }, + { + x: x3, + y: y3 + } + ]); + } + return Triangle; + })(Phaser.Physics.Advanced.Shapes.Poly); + Shapes.Triangle = Triangle; + })(Advanced.Shapes || (Advanced.Shapes = {})); + var Shapes = Advanced.Shapes; + })(Physics.Advanced || (Physics.Advanced = {})); + var Advanced = Physics.Advanced; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + (function (Physics) { + (function (Advanced) { + /// + /// + /// + /// + /// + /** + * 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) { + x = Advanced.Manager.pixelsToMeters(x); + y = Advanced.Manager.pixelsToMeters(y); + width = Advanced.Manager.pixelsToMeters(width); + height = Advanced.Manager.pixelsToMeters(height); + var hw = width * 0.5; + var hh = height * 0.5; + _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.Advanced.Shapes.Poly); + Shapes.Box = Box; + })(Advanced.Shapes || (Advanced.Shapes = {})); + var Shapes = Advanced.Shapes; + })(Physics.Advanced || (Physics.Advanced = {})); + var Advanced = Physics.Advanced; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); +var Phaser; (function (Phaser) { (function (Physics) { /// @@ -21168,6 +21317,11 @@ var Phaser; /// /// /// + /// + /// + /// + /// + /// /** * Phaser - Advanced Physics - Body * @@ -21178,6 +21332,7 @@ var Phaser; function Body(sprite, type, x, y) { if (typeof x === "undefined") { x = 0; } if (typeof y === "undefined") { y = 0; } + this._tempVec2 = new Phaser.Vec2(); // Shapes this.shapes = []; // Joints @@ -21188,17 +21343,16 @@ var Phaser; this.categoryBits = 0x0001; this.maskBits = 0xFFFF; this.stepCount = 0; - this._tempVec2 = new Phaser.Vec2(); this.id = Phaser.Physics.Advanced.Manager.bodyCounter++; this.name = 'body' + this.id; this.type = type; if(sprite) { this.sprite = sprite; this.game = sprite.game; - this.position = new Phaser.Vec2(sprite.x, sprite.y); + this.position = new Phaser.Vec2(Phaser.Physics.Advanced.Manager.pixelsToMeters(sprite.x), Phaser.Physics.Advanced.Manager.pixelsToMeters(sprite.y)); this.angle = sprite.rotation; } else { - this.position = new Phaser.Vec2(x, y); + this.position = new Phaser.Vec2(Phaser.Physics.Advanced.Manager.pixelsToMeters(x), Phaser.Physics.Advanced.Manager.pixelsToMeters(y)); this.angle = 0; } this.transform = new Phaser.Transform(this.position, this.angle); @@ -21270,6 +21424,56 @@ var Phaser; 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.Advanced.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.Advanced.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.Advanced.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.Advanced.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; @@ -21524,82 +21728,6 @@ var Phaser; })(Phaser.Physics || (Phaser.Physics = {})); var Physics = Phaser.Physics; })(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - (function (Physics) { - (function (Advanced) { - /// - /// - /// - /// - /// - /** - * 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) { - x = Advanced.Manager.pixelsToMeters(x); - y = Advanced.Manager.pixelsToMeters(y); - width = Advanced.Manager.pixelsToMeters(width); - height = Advanced.Manager.pixelsToMeters(height); - var hw = width * 0.5; - var hh = height * 0.5; - _super.call(this, [ - new Phaser.Vec2(-hw + x, +hh + y), - new Phaser.Vec2(-hw + x, -hh + y), - new Phaser.Vec2(+hw + x, -hh + y), - new Phaser.Vec2(+hw + x, +hh + y) - ]); - } - return Box; - })(Phaser.Physics.Advanced.Shapes.Poly); - Shapes.Box = Box; - })(Advanced.Shapes || (Advanced.Shapes = {})); - var Shapes = Advanced.Shapes; - })(Physics.Advanced || (Physics.Advanced = {})); - var Advanced = Physics.Advanced; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - (function (Physics) { - (function (Advanced) { - /// - /// - /// - /// - /// - /** - * 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(p1, p2, p3) { - _super.call(this, [ - new Phaser.Vec2(p1.x, p1.y), - new Phaser.Vec2(p2.x, p2.y), - new Phaser.Vec2(p3.x, p3.y) - ]); - } - return Triangle; - })(Phaser.Physics.Advanced.Shapes.Poly); - Shapes.Triangle = Triangle; - })(Advanced.Shapes || (Advanced.Shapes = {})); - var Shapes = Advanced.Shapes; - })(Physics.Advanced || (Physics.Advanced = {})); - var Advanced = Physics.Advanced; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); /// /// /// From ec845155eb9a753e1fa5fe3481a687b5369c7a52 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Fri, 21 Jun 2013 23:39:29 +0100 Subject: [PATCH 2/2] After hours and hours of debugging, polygon to polygon collision is now working perfectly :) --- Phaser/Phaser.csproj | 4 + Phaser/math/Transform.ts | 18 +- Phaser/math/TransformUtils.ts | 4 + Phaser/math/Vec2.ts | 3 +- Phaser/physics/advanced/Body.ts | 96 ++-- Phaser/physics/advanced/Collision.ts | 32 +- Phaser/physics/advanced/ContactSolver.ts | 66 ++- Phaser/physics/advanced/Manager.ts | 103 +++-- Phaser/physics/advanced/Plane.ts | 28 ++ Phaser/physics/advanced/Space.ts | 205 ++++----- Phaser/physics/advanced/shapes/Box.ts | 8 +- Phaser/physics/advanced/shapes/IShape.ts | 6 + Phaser/physics/advanced/shapes/Poly.ts | 77 ++-- Phaser/physics/advanced/shapes/Shape.ts | 8 + Tests/phaser.js | 547 ++++++++++++++--------- Tests/physics/body1.js | 106 ++--- Tests/physics/body1.ts | 89 ++-- build/phaser.d.ts | 85 ++-- build/phaser.js | 547 ++++++++++++++--------- 19 files changed, 1269 insertions(+), 763 deletions(-) create mode 100644 Phaser/physics/advanced/Plane.ts diff --git a/Phaser/Phaser.csproj b/Phaser/Phaser.csproj index 13fa3315..0873a13b 100644 --- a/Phaser/Phaser.csproj +++ b/Phaser/Phaser.csproj @@ -213,6 +213,10 @@ + + + Plane.ts + Box.ts diff --git a/Phaser/math/Transform.ts b/Phaser/math/Transform.ts index 4b5f5926..6c451048 100644 --- a/Phaser/math/Transform.ts +++ b/Phaser/math/Transform.ts @@ -22,12 +22,20 @@ module Phaser { this.t = Phaser.Vec2Utils.clone(pos); this.c = Math.cos(angle); this.s = Math.sin(angle); + this.angle = angle; } public t: Phaser.Vec2; public c: number; public s: number; + public angle: number; + + public toString() { + + return 't=' + this.t.toString() + ' c=' + this.c + ' s=' + this.s + ' a=' + this.angle; + + } public setTo(pos:Phaser.Vec2, angle:number) { @@ -41,8 +49,13 @@ module Phaser { public setRotation(angle:number) { - this.c = Math.cos(angle); - this.s = Math.sin(angle); + if (angle !== this.angle) + { + this.c = Math.cos(angle); + this.s = Math.sin(angle); + this.angle = angle; + } + return this; } @@ -50,6 +63,7 @@ module Phaser { public setPosition(p:Phaser.Vec2) { this.t.copyFrom(p); + return this; } diff --git a/Phaser/math/TransformUtils.ts b/Phaser/math/TransformUtils.ts index 583911f2..1f199209 100644 --- a/Phaser/math/TransformUtils.ts +++ b/Phaser/math/TransformUtils.ts @@ -14,14 +14,17 @@ module Phaser { export class TransformUtils { public static rotate(t: Transform, v:Phaser.Vec2, out?: Vec2 = new Vec2):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); } public static unrotate(t: Transform, v:Phaser.Vec2, out?: Vec2 = new Vec2):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); } public static transform(t: Transform, v:Phaser.Vec2, out?: Vec2 = new Vec2):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); } @@ -30,6 +33,7 @@ module Phaser { 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); } diff --git a/Phaser/math/Vec2.ts b/Phaser/math/Vec2.ts index de216c88..14c451b3 100644 --- a/Phaser/math/Vec2.ts +++ b/Phaser/math/Vec2.ts @@ -288,7 +288,8 @@ module Phaser { * @return {string} a string representation of the object. **/ public toString(): string { - return "[{Vec2 (x=" + this.x + " y=" + this.y + ")}]"; + //return "[{Vec2 (x=" + this.x + " y=" + this.y + ")}]"; + return "x=" + this.x + " y=" + this.y; } } diff --git a/Phaser/physics/advanced/Body.ts b/Phaser/physics/advanced/Body.ts index fff4d13e..0de64724 100644 --- a/Phaser/physics/advanced/Body.ts +++ b/Phaser/physics/advanced/Body.ts @@ -69,6 +69,10 @@ module Phaser.Physics.Advanced { } + public toString(): string { + return "[{Body (name=" + this.name + " velocity=" + this.velocity.toString() + " angularVelocity: " + this.angularVelocity + ")}]"; + } + private _tempVec2: Phaser.Vec2 = new Phaser.Vec2; /** @@ -305,7 +309,10 @@ module Phaser.Physics.Advanced { this.transform.setTo(pos, angle); // inject the transform into this.position + 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; @@ -313,17 +320,17 @@ module Phaser.Physics.Advanced { public syncTransform() { + 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); - - //var rotc: Phaser.Vec2 = this.transform.rotate(this.centroid); - //var sub: Phaser.Vec2 = Phaser.Vec2Utils.subtract(this.position, rotc); - //this.transform.setPosition(sub); - - // this.transform.setPosition(vec2.sub(this.position, this.transform.rotate(this.centroid))); - //Phaser.Vec2Utils.subtract(this.position, this.transform.rotate(this.centroid), this.transform.t); - // OPTIMISE: Creating new vector Phaser.Vec2Utils.subtract(this.position, Phaser.TransformUtils.rotate(this.transform, this.centroid), this.transform.t); + Manager.write('--------------------'); + Manager.write('xf: ' + this.transform.toString()); + Manager.write('--------------------'); } @@ -332,17 +339,17 @@ module Phaser.Physics.Advanced { return Phaser.TransformUtils.transform(this.transform, p); } - public getWorldVector(v) { + public getWorldVector(v:Phaser.Vec2) { // OPTIMISE: Creating new vector return Phaser.TransformUtils.rotate(this.transform, v); } - public getLocalPoint(p) { + public getLocalPoint(p:Phaser.Vec2) { // OPTIMISE: Creating new vector return Phaser.TransformUtils.untransform(this.transform, p); } - public getLocalVector(v) { + public getLocalVector(v:Phaser.Vec2) { // OPTIMISE: Creating new vector return Phaser.TransformUtils.unrotate(this.transform, v); } @@ -430,21 +437,28 @@ module Phaser.Physics.Advanced { } } - public cacheData() { + public cacheData(source:string = '') { - //console.log('Body cacheData', this.name, 'len', this.shapes.length); + 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.shapes.length; i++) { - var shape = this.shapes[i]; + var shape: IShape = 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'); + + } public updateVelocity(gravity, dt, damping) { @@ -461,14 +475,44 @@ module Phaser.Physics.Advanced { // v2 = exp(-c * dt) * v1 // Taylor expansion: // v2 = (1.0f - c * dt) * v1 - this.velocity.scale(this.game.math.clamp(1 - dt * (damping + this.linearDamping), 0, 1)); - this.angularVelocity *= this.game.math.clamp(1 - dt * (damping + this.angularDamping), 0, 1); + this.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; } + public inContact(body2: Body): bool { + + 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; + + } + + public clamp(v, min, max) { + return v < min ? min : (v > max ? max : v); + } + public updatePosition(dt) { //console.log('body update pos', this.position.y); @@ -489,7 +533,7 @@ module Phaser.Physics.Advanced { this.torque = 0; } - public applyForce(force, p) { + public applyForce(force:Phaser.Vec2, p:Phaser.Vec2) { if (this.isDynamic == false) { @@ -511,7 +555,7 @@ module Phaser.Physics.Advanced { } - public applyForceToCenter(force) { + public applyForceToCenter(force:Phaser.Vec2) { if (this.isDynamic == false) { @@ -527,7 +571,7 @@ module Phaser.Physics.Advanced { } - public applyTorque(torque) { + public applyTorque(torque:number) { if (this.isDynamic == false) { @@ -543,7 +587,7 @@ module Phaser.Physics.Advanced { } - public applyLinearImpulse(impulse, p) { + public applyLinearImpulse(impulse:Phaser.Vec2, p:Phaser.Vec2) { if (this.isDynamic == false) { @@ -560,6 +604,7 @@ module Phaser.Physics.Advanced { // this.angularVelocity += vec2.cross(vec2.sub(p, this.position), impulse) * this.inertiaInverted; Phaser.Vec2Utils.subtract(p, this.position, this._tempVec2); + this.angularVelocity += Phaser.Vec2Utils.cross(this._tempVec2, impulse) * this.inertiaInverted; } @@ -611,7 +656,7 @@ module Phaser.Physics.Advanced { } - public isCollidable(other) { + public isCollidable(other:Body) { if (this == other) { @@ -632,12 +677,7 @@ module Phaser.Physics.Advanced { { var joint = this.joints[i]; - if (!joint) - { - continue; - } - - if (!joint.collideConnected && other.jointHash[joint.id] != undefined) + if (!this.joints[i] || (!this.joints[i].collideConnected && other.jointHash[this.joints[i].id] != undefined)) { return false; } diff --git a/Phaser/physics/advanced/Collision.ts b/Phaser/physics/advanced/Collision.ts index 419a7d29..465a1658 100644 --- a/Phaser/physics/advanced/Collision.ts +++ b/Phaser/physics/advanced/Collision.ts @@ -187,20 +187,20 @@ module Phaser.Physics.Advanced { for (var i = 0; i < poly.verts.length; i++) { var plane = poly.tplanes[i]; - var dist = Phaser.Vec2Utils.dot(circ.tc, plane.n) - plane.d - circ.radius; + 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].n; + 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); @@ -358,7 +358,7 @@ module Phaser.Physics.Advanced { for (var i = 0; i < poly.verts.length; i++) { var plane = poly.tplanes[i]; - var dist = seg.distanceOnPlane(plane.n, plane.d); + var dist = seg.distanceOnPlane(plane.normal, plane.d); if (dist > 0) { @@ -373,7 +373,7 @@ module Phaser.Physics.Advanced { } var poly_n: Phaser.Vec2 = new Phaser.Vec2; - Phaser.Vec2Utils.negative(poly.tplanes[poly_i].n, poly_n); + Phaser.Vec2Utils.negative(poly.tplanes[poly_i].normal, poly_n); //var poly_n = vec2.neg(poly.tplanes[poly_i].n); var va: Phaser.Vec2 = new Phaser.Vec2; @@ -397,6 +397,7 @@ module Phaser.Physics.Advanced { // 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) @@ -441,14 +442,14 @@ module Phaser.Physics.Advanced { } // Find the minimum separating axis for the given poly and plane list. - public findMSA(poly: Phaser.Physics.Advanced.Shapes.Poly, planes, num: number) { + public findMSA(poly: Phaser.Physics.Advanced.Shapes.Poly, planes: Phaser.Physics.Advanced.Plane[], num: number) { - var min_dist = -999999; - var min_index = -1; + var min_dist: number = -999999; + var min_index: number = -1; - for (var i = 0; i < num; i++) + for (var i: number = 0; i < num; i++) { - var dist = poly.distanceOnPlane(planes[i].n, planes[i].d); + var dist: number = poly.distanceOnPlane(planes[i].normal, planes[i].d); if (dist > 0) { @@ -456,7 +457,7 @@ module Phaser.Physics.Advanced { return { dist: 0, index: -1 }; } else if (dist > min_dist) - { + { min_dist = dist; min_index = i; } @@ -534,22 +535,25 @@ module Phaser.Physics.Advanced { 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 shoud be from poly1 to poly2 + // Penetration normal direction should be from poly1 to poly2 if (msa1.dist > msa2.dist) { - return this.findVerts(contactArr, poly1, poly2, poly1.tplanes[msa1.index].n, msa1.dist); + return this.findVerts(contactArr, poly1, poly2, poly1.tplanes[msa1.index].normal, msa1.dist); } - return this.findVerts(contactArr, poly1, poly2, Phaser.Vec2Utils.negative(poly2.tplanes[msa2.index].n), msa2.dist); + return this.findVerts(contactArr, poly1, poly2, Phaser.Vec2Utils.negative(poly2.tplanes[msa2.index].normal), msa2.dist); } diff --git a/Phaser/physics/advanced/ContactSolver.ts b/Phaser/physics/advanced/ContactSolver.ts index 965919a7..3e5244c9 100644 --- a/Phaser/physics/advanced/ContactSolver.ts +++ b/Phaser/physics/advanced/ContactSolver.ts @@ -38,8 +38,6 @@ module Phaser.Physics.Advanced { constructor(shape1, shape2) { - //console.log('ContactSolver super'); - this.shape1 = shape1; this.shape2 = shape2; @@ -160,7 +158,7 @@ module Phaser.Physics.Advanced { for (var i = 0; i < this.contacts.length; i++) { - var con = this.contacts[i]; + var con:Contact = this.contacts[i]; var n = con.normal; var lambda_n = con.lambdaNormal; var lambda_t = con.lambdaTangential; @@ -170,16 +168,18 @@ module Phaser.Physics.Advanced { //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.velocity.multiplyAddByScalar(impulse, body2.massInverted); //body2.v.mad(impulse, body2.m_inv); - body2.angularVelocity -= Phaser.Vec2Utils.cross(con.r2, impulse) * body2.inertiaInverted; + body2.angularVelocity += Phaser.Vec2Utils.cross(con.r2, impulse) * body2.inertiaInverted; //body2.w += vec2.cross(con.r2, impulse) * body2.i_inv; } @@ -190,15 +190,25 @@ module Phaser.Physics.Advanced { var body1: Body = this.shape1.body; var body2: Body = this.shape2.body; + Manager.write('solveVelocityConstraints. Body1: ' + body1.name + ' Body2: ' + body2.name); + 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; + Manager.write('m1_inv: ' + m1_inv); + Manager.write('i1_inv: ' + i1_inv); + Manager.write('m2_inv: ' + m2_inv); + Manager.write('i2_inv: ' + i2_inv); + for (var i = 0; i < this.contacts.length; i++) { - var con = this.contacts[i]; - var n = con.normal; + Manager.write('------------ solve con ' + i); + + var con: Contact = this.contacts[i]; + var n: Phaser.Vec2 = con.normal; var t = Phaser.Vec2Utils.perp(n); var r1 = con.r1; var r2 = con.r2; @@ -212,23 +222,34 @@ module Phaser.Physics.Advanced { Phaser.Vec2Utils.multiplyAdd(body1.velocity, Phaser.Vec2Utils.perp(r1), body1.angularVelocity, v1); //var v1 = vec2.mad(body1.v, vec2.perp(r1), body1.w); + 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); + 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); + 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); + 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; + 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); @@ -245,6 +266,7 @@ module Phaser.Physics.Advanced { //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); + Manager.write('impulse: ' + impulse.toString()); body1.velocity.multiplyAddByScalar(impulse, -m1_inv); //body1.v.mad(impulse, -m1_inv); @@ -255,9 +277,12 @@ module Phaser.Physics.Advanced { body2.velocity.multiplyAddByScalar(impulse, m2_inv); //body2.v.mad(impulse, m2_inv); - body1.angularVelocity += Phaser.Vec2Utils.cross(r2, impulse) * i2_inv; + body2.angularVelocity += Phaser.Vec2Utils.cross(r2, impulse) * i2_inv; //body2.w += vec2.cross(r2, impulse) * i2_inv; + Manager.write('body1: ' + body1.toString()); + Manager.write('body2: ' + body2.toString()); + } } @@ -267,6 +292,8 @@ module Phaser.Physics.Advanced { var body1: Body = this.shape1.body; var body2: Body = this.shape2.body; + Manager.write('solvePositionConstraints'); + var m1_inv = body1.massInverted; var i1_inv = body1.inertiaInverted; var m2_inv = body2.massInverted; @@ -277,8 +304,10 @@ module Phaser.Physics.Advanced { for (var i = 0; i < this.contacts.length; i++) { - var con = this.contacts[i]; - var n = con.normal; + Manager.write('------------- solvePositionConstraints ' + i); + + var con:Contact = this.contacts[i]; + var n:Phaser.Vec2 = con.normal; var r1 = new Phaser.Vec2; var r2 = new Phaser.Vec2; @@ -288,10 +317,14 @@ module Phaser.Physics.Advanced { Phaser.Vec2Utils.rotate(con.r1_local, body1.angle, r1); //var r1 = vec2.rotate(con.r1_local, body1.a); - Phaser.Vec2Utils.rotate(con.r2_local, body2.angle, r2); //var r2 = vec2.rotate(con.r2_local, body2.a); + Manager.write('r1_local.x = ' + con.r1_local.x + ' r1_local.y = ' + con.r1_local.y + ' angle: ' + body1.angle); + Manager.write('r1 rotated: r1.x = ' + r1.x + ' r1.y = ' + r1.y); + Manager.write('r2_local.x = ' + con.r2_local.x + ' r2_local.y = ' + con.r2_local.y + ' angle: ' + body2.angle); + 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; @@ -302,9 +335,12 @@ module Phaser.Physics.Advanced { Phaser.Vec2Utils.add(body2.position, r2, p2); //var p2 = vec2.add(body2.p, r2); + Manager.write('body1.pos.x=' + body1.position.x + ' y=' + body1.position.y); + 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); + Phaser.Vec2Utils.subtract(p2, p1, dp); //var dp = vec2.sub(p2, p1); // Position constraint @@ -343,8 +379,13 @@ module Phaser.Physics.Advanced { //body2.p.mad(impulse_dt, m2_inv); body2.angle += sn2 * lambda_dt * i2_inv; + + Manager.write('body1.pos.x=' + body1.position.x + ' y=' + body1.position.y); + Manager.write('body2.pos.x=' + body2.position.x + ' y=' + body2.position.y); } + Manager.write('max_penetration: ' + max_penetration); + return max_penetration <= Manager.CONTACT_SOLVER_COLLISION_SLOP * 3; } @@ -353,7 +394,6 @@ module Phaser.Physics.Advanced { return v < min ? min : (v > max ? max : v); } - } } diff --git a/Phaser/physics/advanced/Manager.ts b/Phaser/physics/advanced/Manager.ts index a83b7335..f7b3a6d0 100644 --- a/Phaser/physics/advanced/Manager.ts +++ b/Phaser/physics/advanced/Manager.ts @@ -28,6 +28,59 @@ module Phaser.Physics.Advanced { */ 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 static collision: Collision; public static SHAPE_TYPE_CIRCLE: number = 0; @@ -68,8 +121,12 @@ module Phaser.Physics.Advanced { public timeDelta: number = 0; public paused: bool = false; public step: bool = 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) public velocityIterations: number = 8; public positionIterations: number = 4; + //public velocityIterations: number = 1; + //public positionIterations: number = 1; public allowSleep: bool = true; public warmStarting: bool = true; @@ -91,6 +148,8 @@ module Phaser.Physics.Advanced { if (!this.paused || this.step) { + Manager.clear(); + var h = 1 / this.frameRateHz; this.timeDelta += frameTime; @@ -123,29 +182,6 @@ module Phaser.Physics.Advanced { } - - - - - - - - - - - - - - - - - - - - - - - public pixelsToMeters(value: number): number { return value * 0.02; } @@ -170,31 +206,32 @@ module Phaser.Physics.Advanced { return value * 50; } - public static areaForCircle(radius_outer, radius_inner): number { + public static areaForCircle(radius_outer: number, radius_inner: number): number { return Math.PI * (radius_outer * radius_outer - radius_inner * radius_inner); } - public static inertiaForCircle(mass, center, radius_outer, radius_inner): number { + public static inertiaForCircle(mass: number, center: Phaser.Vec2, radius_outer: number, radius_inner: number): number { return mass * ((radius_outer * radius_outer + radius_inner * radius_inner) * 0.5 + center.lengthSq()); } - public static areaForSegment(a, b, radius): number { + public static areaForSegment(a: Phaser.Vec2, b: Phaser.Vec2, radius: number): number { return radius * (Math.PI * radius + 2 * Phaser.Vec2Utils.distance(a, b)); } - public static centroidForSegment(a, b): Phaser.Vec2 { + public static centroidForSegment(a: Phaser.Vec2, b: Phaser.Vec2): Phaser.Vec2 { return Phaser.Vec2Utils.scale(Phaser.Vec2Utils.add(a, b), 0.5); } - public static inertiaForSegment(mass, a, b): number { + public static inertiaForSegment(mass: number, a: Phaser.Vec2, b: Phaser.Vec2): number { var distsq = Phaser.Vec2Utils.distanceSq(b, a); var offset: Phaser.Vec2 = Phaser.Vec2Utils.scale(Phaser.Vec2Utils.add(a, b), 0.5); return mass * (distsq / 12 + offset.lengthSq()); + } - public static areaForPoly(verts): number { + public static areaForPoly(verts: Phaser.Vec2[]): number { var area = 0; @@ -206,7 +243,7 @@ module Phaser.Physics.Advanced { return area / 2; } - public static centroidForPoly(verts): Phaser.Vec2 { + public static centroidForPoly(verts: Phaser.Vec2[]): Phaser.Vec2 { var area = 0; var vsum = new Phaser.Vec2; @@ -224,9 +261,10 @@ module Phaser.Physics.Advanced { } return Phaser.Vec2Utils.scale(vsum, 1 / (3 * area)); + } - public static inertiaForPoly(mass, verts, offset): number { + public static inertiaForPoly(mass: number, verts: Phaser.Vec2[], offset: Phaser.Vec2): number { var sum1 = 0; var sum2 = 0; @@ -244,9 +282,10 @@ module Phaser.Physics.Advanced { } return (mass * sum1) / (6 * sum2); + } - public static inertiaForBox(mass, w, h) { + public static inertiaForBox(mass: number, w: number, h: number) { return mass * (w * w + h * h) / 12; } diff --git a/Phaser/physics/advanced/Plane.ts b/Phaser/physics/advanced/Plane.ts new file mode 100644 index 00000000..965c5600 --- /dev/null +++ b/Phaser/physics/advanced/Plane.ts @@ -0,0 +1,28 @@ +/// +/// +/// +/// + +/** +* Phaser - Advanced Physics - Plane +* +* Based on the work Ju Hyung Lee started in JS PhyRus. +*/ + +module Phaser.Physics.Advanced { + + export class Plane { + + constructor(normal: Phaser.Vec2, d: number) { + + this.normal = normal; + this.d = d; + + } + + public normal: Phaser.Vec2; + public d: number; + + } + +} diff --git a/Phaser/physics/advanced/Space.ts b/Phaser/physics/advanced/Space.ts index 5bab1961..a83f17be 100644 --- a/Phaser/physics/advanced/Space.ts +++ b/Phaser/physics/advanced/Space.ts @@ -84,14 +84,12 @@ module Phaser.Physics.Advanced { return; } - //console.log('Body added to space', body.name); - var index = this.bodyArr.push(body) - 1; this.bodyHash[body.id] = index; body.awake(true); body.space = this; - body.cacheData(); + body.cacheData('addBody'); } @@ -433,6 +431,8 @@ module Phaser.Physics.Advanced { public findContactSolver(shape1, shape2) { + Manager.write('findContactSolver. Length: ' + this.contactSolvers.length); + for (var i = 0; i < this.contactSolvers.length; i++) { var contactSolver = this.contactSolvers[i]; @@ -448,20 +448,17 @@ module Phaser.Physics.Advanced { public genTemporalContactSolvers() { - //console.log('genTemporalContactSolvers'); - - //var t0 = Date.now(); + Manager.write('genTemporalContactSolvers'); var newContactSolverArr = []; + var bl: number = this.bodyArr.length; this.numContacts = 0; - for (var body1_index = 0; body1_index < this.bodyArr.length; body1_index++) + for (var body1_index = 0; body1_index < bl; body1_index++) { var body1: Body = this.bodyArr[body1_index]; - //console.log('body1', body1_index, body1.type); - if (!body1) { continue; @@ -469,47 +466,16 @@ module Phaser.Physics.Advanced { body1.stepCount = this.stepCount; - for (var body2_index = 0; body2_index < this.bodyArr.length; body2_index++) + for (var body2_index = 0; body2_index < bl; body2_index++) { var body2: Body = this.bodyArr[body2_index]; - //console.log('body2', body2_index, body2.type); - - if (!body2) + if (body1.inContact(body2) == false) { continue; } - if (body1.stepCount == body2.stepCount) - { - continue; - } - - //console.log('step'); - - var active1 = body1.isAwake && !body1.isStatic; - var active2 = body2.isAwake && !body2.isStatic; - - if (!active1 && !active2) - { - continue; - } - - //console.log('active'); - - if (!body1.isCollidable(body2)) - { - continue; - } - - //console.log('collideable'); - - if (!body1.bounds.intersectsBounds(body2.bounds)) - { - continue; - } - - //console.log('>>>>>>>>>> intersects'); + Manager.write('body1 and body2 intersect'); for (var i = 0; i < body1.shapes.length; i++) { @@ -536,6 +502,8 @@ module Phaser.Physics.Advanced { var contactSolver = this.findContactSolver(shape1, shape2); + Manager.write('findContactSolver result: ' + contactSolver); + if (contactSolver) { contactSolver.update(contactArr); @@ -543,6 +511,8 @@ module Phaser.Physics.Advanced { } else { + Manager.write('awake both bodies'); + body1.awake(true); body2.awake(true); @@ -551,20 +521,23 @@ module Phaser.Physics.Advanced { newContactSolver.elasticity = Math.max(shape1.elasticity, shape2.elasticity); newContactSolver.friction = Math.sqrt(shape1.friction * shape2.friction); newContactSolverArr.push(newContactSolver); + Manager.write('new contact solver'); + //console.log(newContactSolver); } } } } } - //stats.timeCollision = Date.now() - t0; - return newContactSolverArr; } public initSolver(dt, dt_inv, warmStarting) { + Manager.write('initSolver'); + Manager.write('contactSolvers.length: ' + this.contactSolvers.length); + //var t0 = Date.now(); // Initialize contact solvers @@ -596,6 +569,8 @@ module Phaser.Physics.Advanced { public velocitySolver(iteration) { + Manager.write('velocitySolver, iterations: ' + iteration + ' csa len: ' + this.contactSolvers.length); + //var t0 = Date.now(); for (var i = 0; i < iteration; i++) @@ -614,17 +589,12 @@ module Phaser.Physics.Advanced { } } - //stats.timeVelocitySolver = Date.now() - t0; } public positionSolver(iteration) { - //var t0 = Date.now(); - var positionSolved = false; - //stats.positionIterations = 0; - for (var i = 0; i < iteration; i++) { var contactsOk = true; @@ -651,47 +621,51 @@ module Phaser.Physics.Advanced { positionSolved = true; break; } - - //stats.positionIterations++; } - //stats.timePositionSolver = Date.now() - t0; - return positionSolved; } + + public step(dt, vel_iteration, pos_iteration, warmStarting, allowSleep) { - var dt_inv = 1 / dt; + Manager.clear(); + Manager.write('Space step ' + this.stepCount); + + var dt_inv: number = 1 / dt; + var bl: number = this.bodyArr.length; + var jl: number = this.jointArr.length; this.stepCount++; - // Generate contact & contactSolver + // 1) Generate Contact Solvers this.contactSolvers = this.genTemporalContactSolvers(); - // Initialize contacts & joints solver + Manager.dump("Contact Solvers", this.bodyArr[1]); + + // 2) Initialize the Contact Solvers this.initSolver(dt, dt_inv, warmStarting); - // Intergrate velocity - for (var i = 0; i < this.bodyArr.length; i++) + Manager.dump("Init Solver", this.bodyArr[1]); + + // 3) Intergrate velocity + for (var i = 0; i < bl; i++) { - var body = this.bodyArr[i]; - - if (!body) + if (this.bodyArr[i] && this.bodyArr[i].isDynamic && this.bodyArr[i].isAwake) { - continue; - } - - if (body.isDynamic && body.isAwake) - { - body.updateVelocity(this.gravity, dt, this.damping); + this.bodyArr[i].updateVelocity(this.gravity, dt, this.damping); } } - for (var i = 0; i < this.jointArr.length; i++) + Manager.dump("Update Velocity", this.bodyArr[1]); + + /* + // 4) Awaken bodies + for (var j = 0; i < jl; j++) { - var joint = this.jointArr[i]; + var joint = this.jointArr[j]; if (!joint) { @@ -717,85 +691,72 @@ module Phaser.Physics.Advanced { } } } + */ - // Iterative velocity constraints solver + // 5) Iterative velocity constraints solver this.velocitySolver(vel_iteration); - // Intergrate position - for (var i = 0; i < this.bodyArr.length; i++) + Manager.dump("Velocity Solvers", this.bodyArr[1]); + + // 6) Intergrate position + for (var i = 0; i < bl; i++) { - var body = this.bodyArr[i]; - - if (!body) + if (this.bodyArr[i] && this.bodyArr[i].isDynamic && this.bodyArr[i].isAwake) { - continue - } - - if (body.isDynamic && body.isAwake) - { - body.updatePosition(dt); + this.bodyArr[i].updatePosition(dt); } } - // Process breakable joint - for (var i = 0; i < this.jointArr.length; i++) + Manager.dump("Update Position", this.bodyArr[1]); + + // 7) Process breakable joint + for (var i = 0; i < jl; i++) { - var joint = this.jointArr[i]; - - if (!joint) + if (this.jointArr[i] && this.jointArr[i].breakable && (this.jointArr[i].getReactionForce(dt_inv).lengthSq() >= this.jointArr[i].maxForce * this.jointArr[i].maxForce)) { - continue; - } - - if (joint.breakable) - { - if (joint.getReactionForce(dt_inv).lengthsq() >= joint.maxForce * joint.maxForce) - { - this.removeJoint(joint); - } + this.removeJoint(this.jointArr[i]); } } - // Iterative position constraints solver + // 8) Iterative position constraints solver var positionSolved = this.positionSolver(pos_iteration); - for (var i = 0; i < this.bodyArr.length; i++) + Manager.dump("Position Solver", this.bodyArr[1]); + + // 9) Sync the Transforms + for (var i = 0; i < bl; i++) { - var body = this.bodyArr[i]; - - if (!body) + if (this.bodyArr[i]) { - continue; + this.bodyArr[i].syncTransform(); } - - body.syncTransform(); } - // Post solve collision callback + Manager.dump("Sync Transform", this.bodyArr[1]); + + // 10) Post solve collision callback for (var i = 0; i < this.contactSolvers.length; i++) { var arb = this.contactSolvers[i]; - // Re-enable this //this.postSolve(arb); } - for (var i = 0; i < this.bodyArr.length; i++) + // 11) Cache Body Data + for (var i = 0; i < bl; i++) { - var body = this.bodyArr[i]; - - if (!body) + if (this.bodyArr[i] && this.bodyArr[i].isDynamic && this.bodyArr[i].isAwake) { - continue; - } - - if (body.isDynamic && body.isAwake) - { - body.cacheData(); + this.bodyArr[i].cacheData('post solve collision callback'); } } - // Process sleeping + Manager.dump("Cache Data", this.bodyArr[1]); + + Manager.writeAll(); + + // 12) Process sleeping + /* if (allowSleep) { var minSleepTime = 999999; @@ -803,16 +764,11 @@ module Phaser.Physics.Advanced { var linTolSqr = Space.SLEEP_LINEAR_TOLERANCE * Space.SLEEP_LINEAR_TOLERANCE; var angTolSqr = Space.SLEEP_ANGULAR_TOLERANCE * Space.SLEEP_ANGULAR_TOLERANCE; - for (var i = 0; i < this.bodyArr.length; i++) + for (var i = 0; i < bl; i++) { var body = this.bodyArr[i]; - if (!body) - { - continue; - } - - if (!body.isDynamic) + if (!this.bodyArr[i] || this.bodyArr[i].isDynamic == false) { continue; } @@ -844,6 +800,7 @@ module Phaser.Physics.Advanced { } } } + */ } } diff --git a/Phaser/physics/advanced/shapes/Box.ts b/Phaser/physics/advanced/shapes/Box.ts index 5cbf2d95..c252a504 100644 --- a/Phaser/physics/advanced/shapes/Box.ts +++ b/Phaser/physics/advanced/shapes/Box.ts @@ -17,10 +17,10 @@ module Phaser.Physics.Advanced.Shapes { // Give in pixels constructor(x, y, width, height) { - x = Manager.pixelsToMeters(x); - y = Manager.pixelsToMeters(y); - width = Manager.pixelsToMeters(width); - height = Manager.pixelsToMeters(height); + //x = Manager.pixelsToMeters(x); + //y = Manager.pixelsToMeters(y); + //width = Manager.pixelsToMeters(width); + //height = Manager.pixelsToMeters(height); var hw = width * 0.5; var hh = height * 0.5; diff --git a/Phaser/physics/advanced/shapes/IShape.ts b/Phaser/physics/advanced/shapes/IShape.ts index 1fe6ef32..8ef1dbb5 100644 --- a/Phaser/physics/advanced/shapes/IShape.ts +++ b/Phaser/physics/advanced/shapes/IShape.ts @@ -33,6 +33,12 @@ module Phaser.Physics.Advanced { findEdgeByPoint(p: Phaser.Vec2, minDist: number): number; findVertexByPoint(p: Phaser.Vec2, minDist: number): number; + verts: Phaser.Vec2[]; + planes: Phaser.Physics.Advanced.Plane[]; + tverts: Phaser.Vec2[]; + tplanes: Phaser.Physics.Advanced.Plane[]; + convexity: bool; + } } diff --git a/Phaser/physics/advanced/shapes/Poly.ts b/Phaser/physics/advanced/shapes/Poly.ts index f4c85523..0a8e3f77 100644 --- a/Phaser/physics/advanced/shapes/Poly.ts +++ b/Phaser/physics/advanced/shapes/Poly.ts @@ -2,6 +2,7 @@ /// /// /// +/// /// /** @@ -22,7 +23,6 @@ module Phaser.Physics.Advanced.Shapes { this.verts = []; this.planes = []; - this.tverts = []; this.tplanes = []; @@ -32,10 +32,8 @@ module Phaser.Physics.Advanced.Shapes { { this.verts[i] = new Phaser.Vec2(verts[i].x, verts[i].y); this.tverts[i] = this.verts[i]; - - this.tplanes[i] = {}; - this.tplanes[i].n = new Phaser.Vec2; - this.tplanes[i].d = 0; + //this.tverts[i] = new Phaser.Vec2(verts[i].x, verts[i].y); + this.tplanes[i] = new Phaser.Physics.Advanced.Plane(new Phaser.Vec2, 0); } } @@ -43,13 +41,6 @@ module Phaser.Physics.Advanced.Shapes { } - public verts: Phaser.Vec2[]; - public planes; - - public tverts; - public tplanes; - - public convexity: bool; public finishVerts() { @@ -71,24 +62,21 @@ module Phaser.Physics.Advanced.Shapes { var b = this.verts[(i + 1) % this.verts.length]; var n = Phaser.Vec2Utils.normalize(Phaser.Vec2Utils.perp(Phaser.Vec2Utils.subtract(a, b))); - this.planes[i] = {}; - this.planes[i].n = n; - this.planes[i].d = Phaser.Vec2Utils.dot(n, a); + this.planes[i] = new Phaser.Physics.Advanced.Plane(n, Phaser.Vec2Utils.dot(n, a)); - this.tverts[i] = this.verts[i]; + this.tverts[i] = Phaser.Vec2Utils.clone(this.verts[i]); // reference??? + //this.tverts[i] = this.verts[i]; // reference??? - this.tplanes[i] = {}; - this.tplanes[i].n = new Phaser.Vec2; - this.tplanes[i].d = 0; + this.tplanes[i] = new Phaser.Physics.Advanced.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].n; - var d = this.planes[i].d; + //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(n, b) - d > 0) + if (Phaser.Vec2Utils.dot(this.planes[i].normal, this.verts[(i + 2) % this.verts.length]) - this.planes[i].d > 0) { this.convexity = false; } @@ -109,18 +97,23 @@ module Phaser.Physics.Advanced.Shapes { } - public transform(xf) { + public transform(xf:Phaser.Transform) { + for (var i = 0; i < this.verts.length; i++) { - this.verts[i] = xf.transform(this.verts[i]); + this.verts[i] = Phaser.TransformUtils.transform(xf, this.verts[i]); + //this.verts[i] = xf.transform(this.verts[i]); } } - public untransform(xf) { + public untransform(xf:Phaser.Transform) { + for (var i = 0; i < this.verts.length; i++) { - this.verts[i] = xf.untransform(this.verts[i]); + this.verts[i] = Phaser.TransformUtils.untransform(xf, this.verts[i]); + //this.verts[i] = xf.untransform(this.verts[i]); } + } public area(): number { @@ -141,7 +134,7 @@ module Phaser.Physics.Advanced.Shapes { var numVerts = this.verts.length; - console.log('Poly cacheData', numVerts, this.body.name); + Manager.write('----------- Poly cacheData = ' + numVerts); if (numVerts == 0) { @@ -150,8 +143,9 @@ module Phaser.Physics.Advanced.Shapes { for (var i = 0; i < numVerts; i++) { - Phaser.TransformUtils.transform(xf, this.tverts[i], this.tverts[i]); + this.tverts[i] = Phaser.TransformUtils.transform(xf, this.verts[i]); //this.tverts[i] = xf.transform(this.verts[i]); + Manager.write('tvert' + i + ' = ' + this.tverts[i].toString()); } if (numVerts < 2) @@ -164,13 +158,20 @@ module Phaser.Physics.Advanced.Shapes { { var a = this.tverts[i]; var b = this.tverts[(i + 1) % numVerts]; - var n = Phaser.Vec2Utils.normalize(Phaser.Vec2Utils.perp(Phaser.Vec2Utils.subtract(a, b))); - this.tplanes[i].n = n; + Manager.write('a = ' + a.toString()); + Manager.write('b = ' + b.toString()); + Manager.write('n = ' + n.toString()); + + this.tplanes[i].normal = n; this.tplanes[i].d = Phaser.Vec2Utils.dot(n, a); + Manager.write('tplanes' + i + ' n = ' + this.tplanes[i].normal.toString()); + Manager.write('tplanes' + i + ' d = ' + this.tplanes[i].d.toString()); + this.bounds.addPoint(a); + } } @@ -209,7 +210,7 @@ module Phaser.Physics.Advanced.Shapes { { var v1 = this.tverts[i]; var v2 = this.tverts[(i + 1) % numVerts]; - var n = this.tplanes[i].n; + var n = this.tplanes[i].normal; var dtv1 = Phaser.Vec2Utils.cross(v1, n); var dtv2 = Phaser.Vec2Utils.cross(v2, n); @@ -244,9 +245,9 @@ module Phaser.Physics.Advanced.Shapes { } - public distanceOnPlane(n, d) { + public distanceOnPlane(n: Phaser.Vec2, d:number) { - var min = 999999; + var min: number = 999999; for (var i = 0; i < this.verts.length; i++) { @@ -257,13 +258,13 @@ module Phaser.Physics.Advanced.Shapes { } - public containPoint(p) { + public containPoint(p: Phaser.Vec2) { for (var i = 0; i < this.verts.length; i++) { var plane = this.tplanes[i]; - if (Phaser.Vec2Utils.dot(plane.n, p) - plane.d > 0) + if (Phaser.Vec2Utils.dot(plane.normal, p) - plane.d > 0) { return false; } @@ -279,12 +280,12 @@ module Phaser.Physics.Advanced.Shapes { { var plane = this.tplanes[i]; - if (Phaser.Vec2Utils.dot(plane.n, n) < 0.0001) + if (Phaser.Vec2Utils.dot(plane.normal, n) < 0.0001) { continue; } - if (Phaser.Vec2Utils.dot(plane.n, p) - plane.d > 0) + if (Phaser.Vec2Utils.dot(plane.normal, p) - plane.d > 0) { return false; } diff --git a/Phaser/physics/advanced/shapes/Shape.ts b/Phaser/physics/advanced/shapes/Shape.ts index e1260c88..c1d81c2c 100644 --- a/Phaser/physics/advanced/shapes/Shape.ts +++ b/Phaser/physics/advanced/shapes/Shape.ts @@ -32,6 +32,14 @@ module Phaser.Physics.Advanced { public type: number; public body: Body; + public verts: Phaser.Vec2[]; + public planes: Phaser.Physics.Advanced.Plane[]; + + public tverts: Phaser.Vec2[]; + public tplanes: Phaser.Physics.Advanced.Plane[]; + + public convexity: bool; + // Coefficient of restitution (elasticity) public elasticity: number; diff --git a/Tests/phaser.js b/Tests/phaser.js index 70ddf6c5..ae3e1c09 100644 --- a/Tests/phaser.js +++ b/Tests/phaser.js @@ -955,7 +955,8 @@ var Phaser; * @return {string} a string representation of the object. **/ function () { - return "[{Vec2 (x=" + this.x + " y=" + this.y + ")}]"; + //return "[{Vec2 (x=" + this.x + " y=" + this.y + ")}]"; + return "x=" + this.x + " y=" + this.y; }; return Vec2; })(); @@ -16496,19 +16497,15 @@ var Phaser; function (pointer1, pointer2) { return Phaser.Vec2Utils.angle(pointer1.position, pointer2.position); }; + Input.prototype.pixelPerfectCheck = function (sprite, pointer, alpha) { + if (typeof alpha === "undefined") { alpha = 255; } + this.hitContext.clearRect(0, 0, 1, 1); + return true; + }; return Input; })(); Phaser.Input = Input; - /* - public pixelPerfectCheck(sprite: Phaser.Sprite, pointer: Phaser.Pointer, alpha: number = 255): bool { - - this.hitContext.clearRect(0, 0, 1, 1); - - return true; - - } - */ - })(Phaser || (Phaser = {})); +})(Phaser || (Phaser = {})); /// /// /// @@ -18073,7 +18070,11 @@ var Phaser; 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); @@ -18081,8 +18082,11 @@ var Phaser; return this; }; Transform.prototype.setRotation = function (angle) { - this.c = Math.cos(angle); - this.s = Math.sin(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) { @@ -18114,20 +18118,24 @@ var Phaser; 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; @@ -19150,14 +19158,58 @@ var Phaser; 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; + //public velocityIterations: number = 1; + //public positionIterations: number = 1; this.allowSleep = true; this.warmStarting = true; this.game = game; this.space = new Advanced.Space(); Manager.collision = new Advanced.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; @@ -19197,6 +19249,7 @@ var Phaser; // //domCanvas.style.cursor = body ? "pointer" : "default"; //} if(!this.paused || this.step) { + Manager.clear(); var h = 1 / this.frameRateHz; this.timeDelta += frameTime; if(this.step) { @@ -19649,7 +19702,6 @@ var Phaser; (function (Advanced) { var ContactSolver = (function () { function ContactSolver(shape1, shape2) { - //console.log('ContactSolver super'); this.shape1 = shape1; this.shape2 = shape2; this.contacts = []; @@ -19733,24 +19785,32 @@ var Phaser; //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.velocity.multiplyAddByScalar(impulse, body2.massInverted); //body2.v.mad(impulse, body2.m_inv); - body2.angularVelocity -= Phaser.Vec2Utils.cross(con.r2, impulse) * body2.inertiaInverted; + 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; + Advanced.Manager.write('solveVelocityConstraints. Body1: ' + body1.name + ' Body2: ' + body2.name); + Advanced.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; + Advanced.Manager.write('m1_inv: ' + m1_inv); + Advanced.Manager.write('i1_inv: ' + i1_inv); + Advanced.Manager.write('m2_inv: ' + m2_inv); + Advanced.Manager.write('i2_inv: ' + i2_inv); for(var i = 0; i < this.contacts.length; i++) { + Advanced.Manager.write('------------ solve con ' + i); var con = this.contacts[i]; var n = con.normal; var t = Phaser.Vec2Utils.perp(n); @@ -19762,19 +19822,25 @@ var Phaser; 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); + Advanced.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); + Advanced.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); + Advanced.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); + Advanced.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; + Advanced.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); @@ -19787,19 +19853,23 @@ var Phaser; // 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); + Advanced.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); - body1.angularVelocity += Phaser.Vec2Utils.cross(r2, impulse) * i2_inv; + body2.angularVelocity += Phaser.Vec2Utils.cross(r2, impulse) * i2_inv; //body2.w += vec2.cross(r2, impulse) * i2_inv; - } + Advanced.Manager.write('body1: ' + body1.toString()); + Advanced.Manager.write('body2: ' + body2.toString()); + } }; ContactSolver.prototype.solvePositionConstraints = function () { var body1 = this.shape1.body; var body2 = this.shape2.body; + Advanced.Manager.write('solvePositionConstraints'); var m1_inv = body1.massInverted; var i1_inv = body1.inertiaInverted; var m2_inv = body2.massInverted; @@ -19807,6 +19877,7 @@ var Phaser; var sum_m_inv = m1_inv + m2_inv; var max_penetration = 0; for(var i = 0; i < this.contacts.length; i++) { + Advanced.Manager.write('------------- solvePositionConstraints ' + i); var con = this.contacts[i]; var n = con.normal; var r1 = new Phaser.Vec2(); @@ -19816,6 +19887,10 @@ var Phaser; //var r1 = vec2.rotate(con.r1_local, body1.a); Phaser.Vec2Utils.rotate(con.r2_local, body2.angle, r2); //var r2 = vec2.rotate(con.r2_local, body2.a); + Advanced.Manager.write('r1_local.x = ' + con.r1_local.x + ' r1_local.y = ' + con.r1_local.y + ' angle: ' + body1.angle); + Advanced.Manager.write('r1 rotated: r1.x = ' + r1.x + ' r1.y = ' + r1.y); + Advanced.Manager.write('r2_local.x = ' + con.r2_local.x + ' r2_local.y = ' + con.r2_local.y + ' angle: ' + body2.angle); + Advanced.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(); @@ -19823,9 +19898,11 @@ var Phaser; //var p1 = vec2.add(body1.p, r1); Phaser.Vec2Utils.add(body2.position, r2, p2); //var p2 = vec2.add(body2.p, r2); + Advanced.Manager.write('body1.pos.x=' + body1.position.x + ' y=' + body1.position.y); + Advanced.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); + Phaser.Vec2Utils.subtract(p2, p1, dp); //var dp = vec2.sub(p2, p1); // Position constraint var c = Phaser.Vec2Utils.dot(dp, n) + con.depth; @@ -19851,7 +19928,10 @@ var Phaser; body2.position.multiplyAddByScalar(impulse_dt, m2_inv); //body2.p.mad(impulse_dt, m2_inv); body2.angle += sn2 * lambda_dt * i2_inv; + Advanced.Manager.write('body1.pos.x=' + body1.position.x + ' y=' + body1.position.y); + Advanced.Manager.write('body2.pos.x=' + body2.position.x + ' y=' + body2.position.y); } + Advanced.Manager.write('max_penetration: ' + max_penetration); return max_penetration <= Advanced.Manager.CONTACT_SOLVER_COLLISION_SLOP * 3; }; ContactSolver.prototype.clamp = function (v, min, max) { @@ -19951,6 +20031,32 @@ var Phaser; var Physics = Phaser.Physics; })(Phaser || (Phaser = {})); var Phaser; +(function (Phaser) { + (function (Physics) { + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Plane + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + (function (Advanced) { + var Plane = (function () { + function Plane(normal, d) { + this.normal = normal; + this.d = d; + } + return Plane; + })(); + Advanced.Plane = Plane; + })(Physics.Advanced || (Physics.Advanced = {})); + var Advanced = Physics.Advanced; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); +var Phaser; (function (Phaser) { (function (Physics) { (function (Advanced) { @@ -19958,6 +20064,7 @@ var Phaser; /// /// /// + /// /// /** * Phaser - Advanced Physics - Shapes - Convex Polygon @@ -19979,10 +20086,8 @@ var Phaser; 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.tplanes[i] = { - }; - this.tplanes[i].n = new Phaser.Vec2(); - this.tplanes[i].d = 0; + //this.tverts[i] = new Phaser.Vec2(verts[i].x, verts[i].y); + this.tplanes[i] = new Phaser.Physics.Advanced.Plane(new Phaser.Vec2(), 0); } } this.finishVerts(); @@ -20001,21 +20106,17 @@ var Phaser; var a = this.verts[i]; var b = this.verts[(i + 1) % this.verts.length]; var n = Phaser.Vec2Utils.normalize(Phaser.Vec2Utils.perp(Phaser.Vec2Utils.subtract(a, b))); - this.planes[i] = { - }; - this.planes[i].n = n; - this.planes[i].d = Phaser.Vec2Utils.dot(n, a); - this.tverts[i] = this.verts[i]; - this.tplanes[i] = { - }; - this.tplanes[i].n = new Phaser.Vec2(); - this.tplanes[i].d = 0; + this.planes[i] = new Phaser.Physics.Advanced.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.Advanced.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].n; - var d = this.planes[i].d; - if(Phaser.Vec2Utils.dot(n, b) - d > 0) { + //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; } } @@ -20030,13 +20131,15 @@ var Phaser; }; Poly.prototype.transform = function (xf) { for(var i = 0; i < this.verts.length; i++) { - this.verts[i] = xf.transform(this.verts[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] = xf.untransform(this.verts[i]); - } + this.verts[i] = Phaser.TransformUtils.untransform(xf, this.verts[i]); + //this.verts[i] = xf.untransform(this.verts[i]); + } }; Poly.prototype.area = function () { return Advanced.Manager.areaForPoly(this.verts); @@ -20050,14 +20153,15 @@ var Phaser; Poly.prototype.cacheData = function (xf) { this.bounds.clear(); var numVerts = this.verts.length; - console.log('Poly cacheData', numVerts, this.body.name); + Advanced.Manager.write('----------- Poly cacheData = ' + numVerts); if(numVerts == 0) { return; } for(var i = 0; i < numVerts; i++) { - Phaser.TransformUtils.transform(xf, this.tverts[i], this.tverts[i]); + this.tverts[i] = Phaser.TransformUtils.transform(xf, this.verts[i]); //this.tverts[i] = xf.transform(this.verts[i]); - } + Advanced.Manager.write('tvert' + i + ' = ' + this.tverts[i].toString()); + } if(numVerts < 2) { this.bounds.addPoint(this.tverts[0]); return; @@ -20066,8 +20170,13 @@ var Phaser; var a = this.tverts[i]; var b = this.tverts[(i + 1) % numVerts]; var n = Phaser.Vec2Utils.normalize(Phaser.Vec2Utils.perp(Phaser.Vec2Utils.subtract(a, b))); - this.tplanes[i].n = n; + Advanced.Manager.write('a = ' + a.toString()); + Advanced.Manager.write('b = ' + b.toString()); + Advanced.Manager.write('n = ' + n.toString()); + this.tplanes[i].normal = n; this.tplanes[i].d = Phaser.Vec2Utils.dot(n, a); + Advanced.Manager.write('tplanes' + i + ' n = ' + this.tplanes[i].normal.toString()); + Advanced.Manager.write('tplanes' + i + ' d = ' + this.tplanes[i].d.toString()); this.bounds.addPoint(a); } }; @@ -20092,7 +20201,7 @@ var Phaser; for(var i = 0; i < this.tverts.length; i++) { var v1 = this.tverts[i]; var v2 = this.tverts[(i + 1) % numVerts]; - var n = this.tplanes[i].n; + var 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); @@ -20123,7 +20232,7 @@ var Phaser; Poly.prototype.containPoint = function (p) { for(var i = 0; i < this.verts.length; i++) { var plane = this.tplanes[i]; - if(Phaser.Vec2Utils.dot(plane.n, p) - plane.d > 0) { + if(Phaser.Vec2Utils.dot(plane.normal, p) - plane.d > 0) { return false; } } @@ -20132,10 +20241,10 @@ var Phaser; 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.n, n) < 0.0001) { + if(Phaser.Vec2Utils.dot(plane.normal, n) < 0.0001) { continue; } - if(Phaser.Vec2Utils.dot(plane.n, p) - plane.d > 0) { + if(Phaser.Vec2Utils.dot(plane.normal, p) - plane.d > 0) { return false; } } @@ -20412,7 +20521,7 @@ var Phaser; var minIdx = -1; for(var i = 0; i < poly.verts.length; i++) { var plane = poly.tplanes[i]; - var dist = Phaser.Vec2Utils.dot(circ.tc, plane.n) - plane.d - circ.radius; + var dist = Phaser.Vec2Utils.dot(circ.tc, plane.normal) - plane.d - circ.radius; if(dist > 0) { return 0; } else if(dist > minDist) { @@ -20420,7 +20529,7 @@ var Phaser; minIdx = i; } } - var n = poly.tplanes[minIdx].n; + 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); @@ -20529,7 +20638,7 @@ var Phaser; var poly_i = -1; for(var i = 0; i < poly.verts.length; i++) { var plane = poly.tplanes[i]; - var dist = seg.distanceOnPlane(plane.n, plane.d); + var dist = seg.distanceOnPlane(plane.normal, plane.d); if(dist > 0) { return 0; } @@ -20539,7 +20648,7 @@ var Phaser; } } var poly_n = new Phaser.Vec2(); - Phaser.Vec2Utils.negative(poly.tplanes[poly_i].n, poly_n); + 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); @@ -20587,7 +20696,7 @@ var Phaser; var min_dist = -999999; var min_index = -1; for(var i = 0; i < num; i++) { - var dist = poly.distanceOnPlane(planes[i].n, planes[i].d); + var dist = poly.distanceOnPlane(planes[i].normal, planes[i].d); if(dist > 0) { // no collision return { @@ -20645,17 +20754,19 @@ var Phaser; 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 shoud be from poly1 to poly2 + // Penetration normal direction should be from poly1 to poly2 if(msa1.dist > msa2.dist) { - return this.findVerts(contactArr, poly1, poly2, poly1.tplanes[msa1.index].n, msa1.dist); + return this.findVerts(contactArr, poly1, poly2, poly1.tplanes[msa1.index].normal, msa1.dist); } - return this.findVerts(contactArr, poly1, poly2, Phaser.Vec2Utils.negative(poly2.tplanes[msa2.index].n), msa2.dist); + return this.findVerts(contactArr, poly1, poly2, Phaser.Vec2Utils.negative(poly2.tplanes[msa2.index].normal), msa2.dist); }; return Collision; })(); @@ -20729,12 +20840,11 @@ var Phaser; if(this.bodyHash[body.id] != undefined) { return; } - //console.log('Body added to space', body.name); var index = this.bodyArr.push(body) - 1; this.bodyHash[body.id] = index; body.awake(true); body.space = this; - body.cacheData(); + body.cacheData('addBody'); }; Space.prototype.removeBody = function (body) { if(this.bodyHash[body.id] == undefined) { @@ -20939,6 +21049,7 @@ var Phaser; return firstJointId; }; Space.prototype.findContactSolver = function (shape1, shape2) { + Advanced.Manager.write('findContactSolver. Length: ' + this.contactSolvers.length); for(var i = 0; i < this.contactSolvers.length; i++) { var contactSolver = this.contactSolvers[i]; if(shape1 == contactSolver.shape1 && shape2 == contactSolver.shape2) { @@ -20948,41 +21059,22 @@ var Phaser; return null; }; Space.prototype.genTemporalContactSolvers = function () { - //console.log('genTemporalContactSolvers'); - //var t0 = Date.now(); + Advanced.Manager.write('genTemporalContactSolvers'); var newContactSolverArr = []; + var bl = this.bodyArr.length; this.numContacts = 0; - for(var body1_index = 0; body1_index < this.bodyArr.length; body1_index++) { + for(var body1_index = 0; body1_index < bl; body1_index++) { var body1 = this.bodyArr[body1_index]; - //console.log('body1', body1_index, body1.type); if(!body1) { continue; } body1.stepCount = this.stepCount; - for(var body2_index = 0; body2_index < this.bodyArr.length; body2_index++) { + for(var body2_index = 0; body2_index < bl; body2_index++) { var body2 = this.bodyArr[body2_index]; - //console.log('body2', body2_index, body2.type); - if(!body2) { + if(body1.inContact(body2) == false) { continue; } - if(body1.stepCount == body2.stepCount) { - continue; - } - //console.log('step'); - var active1 = body1.isAwake && !body1.isStatic; - var active2 = body2.isAwake && !body2.isStatic; - if(!active1 && !active2) { - continue; - } - //console.log('active'); - if(!body1.isCollidable(body2)) { - continue; - } - //console.log('collideable'); - if(!body1.bounds.intersectsBounds(body2.bounds)) { - continue; - } - //console.log('>>>>>>>>>> intersects'); + Advanced.Manager.write('body1 and body2 intersect'); for(var i = 0; i < body1.shapes.length; i++) { for(var j = 0; j < body2.shapes.length; j++) { var shape1 = body1.shapes[i]; @@ -20998,10 +21090,12 @@ var Phaser; } this.numContacts += contactArr.length; var contactSolver = this.findContactSolver(shape1, shape2); + Advanced.Manager.write('findContactSolver result: ' + contactSolver); if(contactSolver) { contactSolver.update(contactArr); newContactSolverArr.push(contactSolver); } else { + Advanced.Manager.write('awake both bodies'); body1.awake(true); body2.awake(true); var newContactSolver = new Advanced.ContactSolver(shape1, shape2); @@ -21009,15 +21103,18 @@ var Phaser; newContactSolver.elasticity = Math.max(shape1.elasticity, shape2.elasticity); newContactSolver.friction = Math.sqrt(shape1.friction * shape2.friction); newContactSolverArr.push(newContactSolver); - } + Advanced.Manager.write('new contact solver'); + //console.log(newContactSolver); + } } } } } - //stats.timeCollision = Date.now() - t0; return newContactSolverArr; }; Space.prototype.initSolver = function (dt, dt_inv, warmStarting) { + Advanced.Manager.write('initSolver'); + Advanced.Manager.write('contactSolvers.length: ' + this.contactSolvers.length); //var t0 = Date.now(); // Initialize contact solvers for(var i = 0; i < this.contactSolvers.length; i++) { @@ -21038,6 +21135,7 @@ var Phaser; //stats.timeInitSolver = Date.now() - t0; }; Space.prototype.velocitySolver = function (iteration) { + Advanced.Manager.write('velocitySolver, iterations: ' + iteration + ' csa len: ' + this.contactSolvers.length); //var t0 = Date.now(); for(var i = 0; i < iteration; i++) { for(var j = 0; j < this.jointArr.length; j++) { @@ -21049,12 +21147,9 @@ var Phaser; this.contactSolvers[j].solveVelocityConstraints(); } } - //stats.timeVelocitySolver = Date.now() - t0; - }; + }; Space.prototype.positionSolver = function (iteration) { - //var t0 = Date.now(); var positionSolved = false; - //stats.positionIterations = 0; for(var i = 0; i < iteration; i++) { var contactsOk = true; var jointsOk = true; @@ -21073,126 +21168,147 @@ var Phaser; positionSolved = true; break; } - //stats.positionIterations++; - } - //stats.timePositionSolver = Date.now() - t0; + } return positionSolved; }; Space.prototype.step = function (dt, vel_iteration, pos_iteration, warmStarting, allowSleep) { + Advanced.Manager.clear(); + Advanced.Manager.write('Space step ' + this.stepCount); var dt_inv = 1 / dt; + var bl = this.bodyArr.length; + var jl = this.jointArr.length; this.stepCount++; - // Generate contact & contactSolver + // 1) Generate Contact Solvers this.contactSolvers = this.genTemporalContactSolvers(); - // Initialize contacts & joints solver + Advanced.Manager.dump("Contact Solvers", this.bodyArr[1]); + // 2) Initialize the Contact Solvers this.initSolver(dt, dt_inv, warmStarting); - // Intergrate velocity - for(var i = 0; i < this.bodyArr.length; i++) { - var body = this.bodyArr[i]; - if(!body) { - continue; - } - if(body.isDynamic && body.isAwake) { - body.updateVelocity(this.gravity, dt, this.damping); + Advanced.Manager.dump("Init Solver", this.bodyArr[1]); + // 3) Intergrate velocity + for(var i = 0; i < bl; i++) { + if(this.bodyArr[i] && this.bodyArr[i].isDynamic && this.bodyArr[i].isAwake) { + this.bodyArr[i].updateVelocity(this.gravity, dt, this.damping); } } - for(var i = 0; i < this.jointArr.length; i++) { - var joint = this.jointArr[i]; - if(!joint) { - continue; - } - var body1 = joint.body1; - var body2 = joint.body2; - var awake1 = body1.isAwake && !body1.isStatic; - var awake2 = body2.isAwake && !body2.isStatic; - if(awake1 ^ awake2) { - if(!awake1) { - body1.awake(true); - } - if(!awake2) { - body2.awake(true); - } - } + Advanced.Manager.dump("Update Velocity", this.bodyArr[1]); + /* + // 4) Awaken bodies + for (var j = 0; i < jl; j++) + { + var joint = this.jointArr[j]; + + if (!joint) + { + continue; } - // Iterative velocity constraints solver + + var body1 = joint.body1; + var body2 = joint.body2; + + var awake1 = body1.isAwake && !body1.isStatic; + var awake2 = body2.isAwake && !body2.isStatic; + + if (awake1 ^ awake2) + { + if (!awake1) + { + body1.awake(true); + } + + if (!awake2) + { + body2.awake(true); + } + } + } + */ + // 5) Iterative velocity constraints solver this.velocitySolver(vel_iteration); - // Intergrate position - for(var i = 0; i < this.bodyArr.length; i++) { - var body = this.bodyArr[i]; - if(!body) { - continue; - } - if(body.isDynamic && body.isAwake) { - body.updatePosition(dt); + Advanced.Manager.dump("Velocity Solvers", this.bodyArr[1]); + // 6) Intergrate position + for(var i = 0; i < bl; i++) { + if(this.bodyArr[i] && this.bodyArr[i].isDynamic && this.bodyArr[i].isAwake) { + this.bodyArr[i].updatePosition(dt); } } - // Process breakable joint - for(var i = 0; i < this.jointArr.length; i++) { - var joint = this.jointArr[i]; - if(!joint) { - continue; - } - if(joint.breakable) { - if(joint.getReactionForce(dt_inv).lengthsq() >= joint.maxForce * joint.maxForce) { - this.removeJoint(joint); - } + Advanced.Manager.dump("Update Position", this.bodyArr[1]); + // 7) Process breakable joint + for(var i = 0; i < jl; i++) { + if(this.jointArr[i] && this.jointArr[i].breakable && (this.jointArr[i].getReactionForce(dt_inv).lengthSq() >= this.jointArr[i].maxForce * this.jointArr[i].maxForce)) { + this.removeJoint(this.jointArr[i]); } } - // Iterative position constraints solver + // 8) Iterative position constraints solver var positionSolved = this.positionSolver(pos_iteration); - for(var i = 0; i < this.bodyArr.length; i++) { - var body = this.bodyArr[i]; - if(!body) { - continue; + Advanced.Manager.dump("Position Solver", this.bodyArr[1]); + // 9) Sync the Transforms + for(var i = 0; i < bl; i++) { + if(this.bodyArr[i]) { + this.bodyArr[i].syncTransform(); } - body.syncTransform(); } - // Post solve collision callback + Advanced.Manager.dump("Sync Transform", this.bodyArr[1]); + // 10) Post solve collision callback for(var i = 0; i < this.contactSolvers.length; i++) { var arb = this.contactSolvers[i]; // Re-enable this //this.postSolve(arb); } - for(var i = 0; i < this.bodyArr.length; i++) { - var body = this.bodyArr[i]; - if(!body) { - continue; - } - if(body.isDynamic && body.isAwake) { - body.cacheData(); + // 11) Cache Body Data + for(var i = 0; i < bl; i++) { + if(this.bodyArr[i] && this.bodyArr[i].isDynamic && this.bodyArr[i].isAwake) { + this.bodyArr[i].cacheData('post solve collision callback'); } } - // Process sleeping - if(allowSleep) { - var minSleepTime = 999999; - var linTolSqr = Space.SLEEP_LINEAR_TOLERANCE * Space.SLEEP_LINEAR_TOLERANCE; - var angTolSqr = Space.SLEEP_ANGULAR_TOLERANCE * Space.SLEEP_ANGULAR_TOLERANCE; - for(var i = 0; i < this.bodyArr.length; i++) { - var body = this.bodyArr[i]; - if(!body) { - continue; - } - if(!body.isDynamic) { - continue; - } - if(body.angularVelocity * body.angularVelocity > angTolSqr || body.velocity.dot(body.velocity) > linTolSqr) { - body.sleepTime = 0; - minSleepTime = 0; - } else { - body.sleepTime += dt; - minSleepTime = Math.min(minSleepTime, body.sleepTime); - } - } - if(positionSolved && minSleepTime >= Space.TIME_TO_SLEEP) { - for(var i = 0; i < this.bodyArr.length; i++) { - var body = this.bodyArr[i]; - if(!body) { - continue; - } - body.awake(false); - } - } + Advanced.Manager.dump("Cache Data", this.bodyArr[1]); + Advanced.Manager.writeAll(); + // 12) Process sleeping + /* + if (allowSleep) + { + var minSleepTime = 999999; + + var linTolSqr = Space.SLEEP_LINEAR_TOLERANCE * Space.SLEEP_LINEAR_TOLERANCE; + var angTolSqr = Space.SLEEP_ANGULAR_TOLERANCE * Space.SLEEP_ANGULAR_TOLERANCE; + + for (var i = 0; i < bl; i++) + { + var body = this.bodyArr[i]; + + if (!this.bodyArr[i] || this.bodyArr[i].isDynamic == false) + { + continue; } - }; + + if (body.angularVelocity * body.angularVelocity > angTolSqr || body.velocity.dot(body.velocity) > linTolSqr) + { + body.sleepTime = 0; + minSleepTime = 0; + } + else + { + body.sleepTime += dt; + minSleepTime = Math.min(minSleepTime, body.sleepTime); + } + } + + if (positionSolved && minSleepTime >= Space.TIME_TO_SLEEP) + { + for (var i = 0; i < this.bodyArr.length; i++) + { + var body = this.bodyArr[i]; + + if (!body) + { + continue; + } + + body.awake(false); + } + } + } + */ + }; return Space; })(); Advanced.Space = Space; @@ -21269,10 +21385,10 @@ var Phaser; __extends(Box, _super); // Give in pixels function Box(x, y, width, height) { - x = Advanced.Manager.pixelsToMeters(x); - y = Advanced.Manager.pixelsToMeters(y); - width = Advanced.Manager.pixelsToMeters(width); - height = Advanced.Manager.pixelsToMeters(height); + //x = Manager.pixelsToMeters(x); + //y = Manager.pixelsToMeters(y); + //width = Manager.pixelsToMeters(width); + //height = Manager.pixelsToMeters(height); var hw = width * 0.5; var hh = height * 0.5; _super.call(this, [ @@ -21375,6 +21491,9 @@ var Phaser; this.maskBits = 0xFFFF; this.stepCount = 0; } + Body.prototype.toString = function () { + return "[{Body (name=" + this.name + " velocity=" + this.velocity.toString() + " angularVelocity: " + this.angularVelocity + ")}]"; + }; Body.prototype.duplicate = function () { //console.log('body duplicate called'); //var body = new Body(this.type, this.transform.t, this.angle); @@ -21498,19 +21617,25 @@ var Phaser; Body.prototype.setTransform = function (pos, angle) { this.transform.setTo(pos, angle); // inject the transform into this.position + Advanced.Manager.write('setTransform: ' + this.position.toString()); + Advanced.Manager.write('centroid: ' + this.centroid.toString()); Phaser.TransformUtils.transform(this.transform, this.centroid, this.position); + Advanced.Manager.write('post setTransform: ' + this.position.toString()); //this.position.copyFrom(this.transform.transform(this.centroid)); this.angle = angle; }; Body.prototype.syncTransform = function () { + Advanced.Manager.write('syncTransform:'); + Advanced.Manager.write('p: ' + this.position.toString()); + Advanced.Manager.write('centroid: ' + this.centroid.toString()); + Advanced.Manager.write('xf: ' + this.transform.toString()); + Advanced.Manager.write('a: ' + this.angle); this.transform.setRotation(this.angle); - //var rotc: Phaser.Vec2 = this.transform.rotate(this.centroid); - //var sub: Phaser.Vec2 = Phaser.Vec2Utils.subtract(this.position, rotc); - //this.transform.setPosition(sub); - // this.transform.setPosition(vec2.sub(this.position, this.transform.rotate(this.centroid))); - //Phaser.Vec2Utils.subtract(this.position, this.transform.rotate(this.centroid), this.transform.t); // OPTIMISE: Creating new vector Phaser.Vec2Utils.subtract(this.position, Phaser.TransformUtils.rotate(this.transform, this.centroid), this.transform.t); + Advanced.Manager.write('--------------------'); + Advanced.Manager.write('xf: ' + this.transform.toString()); + Advanced.Manager.write('--------------------'); }; Body.prototype.getWorldPoint = function (p) { // OPTIMISE: Creating new vector @@ -21585,14 +21710,21 @@ var Phaser; joint.setWorldAnchor2(anchor2); } }; - Body.prototype.cacheData = function () { - //console.log('Body cacheData', this.name, 'len', this.shapes.length); + Body.prototype.cacheData = function (source) { + if (typeof source === "undefined") { source = ''; } + Advanced.Manager.write('cacheData -- start'); + Advanced.Manager.write('p: ' + this.position.toString()); + Advanced.Manager.write('xf: ' + this.transform.toString()); this.bounds.clear(); for(var i = 0; i < this.shapes.length; i++) { var shape = this.shapes[i]; shape.cacheData(this.transform); this.bounds.addBounds(shape.bounds); } + Advanced.Manager.write('bounds: ' + this.bounds.toString()); + Advanced.Manager.write('p: ' + this.position.toString()); + Advanced.Manager.write('xf: ' + this.transform.toString()); + Advanced.Manager.write('cacheData -- stop'); }; Body.prototype.updateVelocity = function (gravity, dt, damping) { // this.velocity = vec2.mad(this.velocity, vec2.mad(gravity, this.force, this.massInverted), dt); @@ -21606,11 +21738,29 @@ var Phaser; // v2 = exp(-c * dt) * v1 // Taylor expansion: // v2 = (1.0f - c * dt) * v1 - this.velocity.scale(this.game.math.clamp(1 - dt * (damping + this.linearDamping), 0, 1)); - this.angularVelocity *= this.game.math.clamp(1 - dt * (damping + this.angularDamping), 0, 1); + this.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) { //console.log('body update pos', this.position.y); //console.log('pre add temp', this._tempVec2.y); @@ -21711,10 +21861,7 @@ var Phaser; } for(var i = 0; i < this.joints.length; i++) { var joint = this.joints[i]; - if(!joint) { - continue; - } - if(!joint.collideConnected && other.jointHash[joint.id] != undefined) { + if(!this.joints[i] || (!this.joints[i].collideConnected && other.jointHash[this.joints[i].id] != undefined)) { return false; } } diff --git a/Tests/physics/body1.js b/Tests/physics/body1.js index 1af4c4ea..53aebce0 100644 --- a/Tests/physics/body1.js +++ b/Tests/physics/body1.js @@ -10,6 +10,7 @@ game.load.image('atari', 'assets/sprites/shinyball.png'); game.load.start(); } + var debug; var atari; var card; var physics; @@ -17,16 +18,27 @@ var walls; var t; function create() { - atari = game.add.sprite(200, 100, 'atari'); + //debug = document.createElement('textarea'); + //debug.style.position = 'absolute'; + //debug.style.left = '850px'; + //debug.style.top = '32px'; + //debug.style.width = '600px'; + //debug.style.height = '600px'; + //document.body.appendChild(debug); + //atari = game.add.sprite(200, 100, 'atari'); // need to get the physics bounds around the sprite center, regardless of origin - atari.transform.origin.setTo(0.5, 0.5); + //atari.transform.origin.setTo(0.5, 0.5); //card = game.add.sprite(500, 300, 'card'); physics = new Phaser.Physics.Advanced.Manager(game); - walls = new Phaser.Physics.Advanced.Body(null, Phaser.Types.BODY_KINETIC); + //Phaser.Physics.Advanced.Manager.debug = debug; + walls = new Phaser.Physics.Advanced.Body(null, Phaser.Types.BODY_STATIC, 0, 0); walls.game = game; - walls.addBox(500, 500, 500, 20); - walls.addBox(100, 250, 250, 20); - walls.transform.setRotation(game.math.degreesToRadians(3)); + //walls.addBox(250, 200, 500, 20, 0, 1, 1); + //staticBody.addShape(new ShapeBox(0, 0.2, 20.48, 0.4)); + // * 0.02 p2m + // * 50 m2p + walls.addBox(0, 500, 1024, 20, 0, 1, 1); + //walls.transform.setRotation(game.math.degreesToRadians(4)); //walls.fixedRotation = true; // position is in relation to the containing body! don't forget this //ground = walls.addShape(new Phaser.Physics.Advanced.Shapes.Box(400, 500, 500, 20)); @@ -37,47 +49,34 @@ //walls.resetMassData(); physics.space.addBody(walls); // Add a circle - circle = new Phaser.Physics.Advanced.Body(null, Phaser.Types.BODY_DYNAMIC, 100, 200); - circle.game = game; - circle.addCircle(32, 0, 0, 0.8); - physics.space.addBody(circle); - t = new Phaser.Physics.Advanced.Body(null, Phaser.Types.BODY_KINETIC, 500, 400); + //circle = new Phaser.Physics.Advanced.Body(null, Phaser.Types.BODY_DYNAMIC, 200, 100); + //circle.game = game; + //circle.addCircle(32, 0, 0, 0.5); + //physics.space.addBody(circle); + t = new Phaser.Physics.Advanced.Body(null, Phaser.Types.BODY_DYNAMIC, 300, 100); + //t.fixedRotation = true; t.game = game; + t.addBox(0, 0, 20, 20, 0.5, 1, 1); //t.addCircle(32, 0, 0, 0.8); //t.addTriangle(0, 0, 1, 1, 2, 2); - t.addPoly([ - { - x: -0.8, - y: 0.48 - }, - { - x: -0.8, - y: 0 - }, - { - x: 0.8, - y: 0 - }, - { - x: 0.8, - y: 0.32 - }, - { - x: 0, - y: 0.84 - }, - { - x: -0.56, - y: 0.84 - } - ], 0.5, 1, 6); + //t.addPoly([{ x: -0.8, y: 0.48 }, { x: -0.8, y: 0 }, { x: 0.8, y: 0 }, { x: 0.8, y: 0.32 }, { x: 0, y: 0.84 }, { x: -0.56, y: 0.84 }], 1, 1, 6); + //t.addPoly([{ x: -0.8, y: 0.48 }, { x: -0.8, y: 0 }, { x: 0.8, y: 0 }, { x: 0.8, y: 0.32 }, { x: 0, y: 0.84 }, { x: -0.56, y: 0.84 }], 0.5, 1, 1); + //t.transform.setRotation(game.math.degreesToRadians(45)); + //t.fixedRotation = true; physics.space.addBody(t); + game.input.onTap.add(step, this); + } + function step() { + physics.update(); } function update() { + //if (physics.space.stepCount < 90) + //{ physics.update(); - atari.x = physics.metersToPixels(circle.position.x); - atari.y = physics.metersToPixels(circle.position.y); - atari.rotation = physics.metersToPixels(circle.angle); + //} + //atari.x = physics.metersToPixels(circle.position.x); + //atari.y = physics.metersToPixels(circle.position.y); + //atari.rotation = physics.metersToPixels(circle.angle); // force moves without rotating if(game.input.keyboard.isDown(Phaser.Keyboard.LEFT)) { circle.applyAngularImpulse(-0.02); @@ -118,27 +117,30 @@ game.stage.context.closePath(); } function drawPolygon(ctx, shape, lineWidth, fillStyle) { - var verts = shape.verts; + var verts = shape.tverts; + var body = shape.body; ctx.beginPath(); - ctx.moveTo(verts[0].x * 50, verts[0].y * 50); + ctx.moveTo(body.position.x + verts[0].x * 50, body.position.y + verts[0].y * 50); for(var i = 0; i < verts.length; i++) { - ctx.lineTo(verts[i].x * 50, verts[i].y * 50); + ctx.lineTo(body.position.x + verts[i].x * 50, body.position.y + verts[i].y * 50); } - ctx.lineTo(verts[verts.length - 1].x * 50, verts[verts.length - 1].y * 50); + ctx.lineTo(body.position.x + verts[verts.length - 1].x * 50, body.position.y + verts[verts.length - 1].y * 50); ctx.closePath(); ctx.fillStyle = fillStyle; ctx.fill(); } function render() { - game.stage.context.fillStyle = 'rgb(255,255,0)'; - game.stage.context.fillText('x: ' + circle.position.x + ' y: ' + circle.position.y, 32, 32); - game.stage.context.fillText('vx: ' + circle.velocity.x + ' vy: ' + circle.velocity.y, 32, 64); - renderCircle(circle.shapes[0]); - renderBounds(circle); + //game.stage.context.fillStyle = 'rgb(255,255,0)'; + //game.stage.context.fillText('x: ' + t.position.x + ' y: ' + t.position.y, 32, 32); + //game.stage.context.fillText('vx: ' + t.velocity.x + ' vy: ' + t.velocity.y, 32, 64); + //game.stage.context.fillText('x: ' + t.bounds.x + ' y: ' + t.bounds.y, 32, 32); + //game.stage.context.fillText('vx: ' + t.velocity.x + ' vy: ' + t.velocity.y, 32, 64); + //renderCircle(circle.shapes[0]); + //renderBounds(circle); drawPolygon(game.stage.context, walls.shapes[0], 1, 'rgb(0,255,255)'); - drawPolygon(game.stage.context, walls.shapes[1], 1, 'rgb(0,255,255)'); + //drawPolygon(game.stage.context, walls.shapes[1], 1, 'rgb(0,255,255)'); //renderCircle(t.shapes[0]); drawPolygon(game.stage.context, t.shapes[0], 1, 'rgb(255,255,255)'); - renderBounds(t); - } + //renderBounds(t); + } })(); diff --git a/Tests/physics/body1.ts b/Tests/physics/body1.ts index 6f43f4db..6e87f57d 100644 --- a/Tests/physics/body1.ts +++ b/Tests/physics/body1.ts @@ -16,6 +16,7 @@ } + var debug: HTMLTextAreaElement; var atari: Phaser.Sprite; var card: Phaser.Sprite; var physics: Phaser.Physics.Advanced.Manager; @@ -25,20 +26,36 @@ function create() { - atari = game.add.sprite(200, 100, 'atari'); + //debug = document.createElement('textarea'); + //debug.style.position = 'absolute'; + //debug.style.left = '850px'; + //debug.style.top = '32px'; + //debug.style.width = '600px'; + //debug.style.height = '600px'; + //document.body.appendChild(debug); + + //atari = game.add.sprite(200, 100, 'atari'); // need to get the physics bounds around the sprite center, regardless of origin - atari.transform.origin.setTo(0.5, 0.5); + //atari.transform.origin.setTo(0.5, 0.5); //card = game.add.sprite(500, 300, 'card'); physics = new Phaser.Physics.Advanced.Manager(game); + //Phaser.Physics.Advanced.Manager.debug = debug; - walls = new Phaser.Physics.Advanced.Body(null, Phaser.Types.BODY_KINETIC); + walls = new Phaser.Physics.Advanced.Body(null, Phaser.Types.BODY_STATIC, 0, 0); walls.game = game; - walls.addBox(500, 500, 500, 20); - walls.addBox(100, 250, 250, 20); - walls.transform.setRotation(game.math.degreesToRadians(3)); + //walls.addBox(250, 200, 500, 20, 0, 1, 1); + + //staticBody.addShape(new ShapeBox(0, 0.2, 20.48, 0.4)); + + // * 0.02 p2m + // * 50 m2p + + walls.addBox(0, 500, 1024, 20, 0, 1, 1); + + //walls.transform.setRotation(game.math.degreesToRadians(4)); //walls.fixedRotation = true; // position is in relation to the containing body! don't forget this @@ -53,27 +70,42 @@ physics.space.addBody(walls); // Add a circle - circle = new Phaser.Physics.Advanced.Body(null, Phaser.Types.BODY_DYNAMIC, 100, 200); - circle.game = game; - circle.addCircle(32, 0, 0, 0.8); - physics.space.addBody(circle); + //circle = new Phaser.Physics.Advanced.Body(null, Phaser.Types.BODY_DYNAMIC, 200, 100); + //circle.game = game; + //circle.addCircle(32, 0, 0, 0.5); + //physics.space.addBody(circle); - t = new Phaser.Physics.Advanced.Body(null, Phaser.Types.BODY_KINETIC, 500, 400); + t = new Phaser.Physics.Advanced.Body(null, Phaser.Types.BODY_DYNAMIC, 300, 100); + //t.fixedRotation = true; t.game = game; + t.addBox(0, 0, 20, 20, 0.5, 1, 1); //t.addCircle(32, 0, 0, 0.8); //t.addTriangle(0, 0, 1, 1, 2, 2); - t.addPoly([{ x: -0.8, y: 0.48 }, { x: -0.8, y: 0 }, { x: 0.8, y: 0 }, { x: 0.8, y: 0.32 }, { x: 0, y: 0.84 }, { x: -0.56, y: 0.84 }], 0.5, 1, 6); + //t.addPoly([{ x: -0.8, y: 0.48 }, { x: -0.8, y: 0 }, { x: 0.8, y: 0 }, { x: 0.8, y: 0.32 }, { x: 0, y: 0.84 }, { x: -0.56, y: 0.84 }], 1, 1, 6); + //t.addPoly([{ x: -0.8, y: 0.48 }, { x: -0.8, y: 0 }, { x: 0.8, y: 0 }, { x: 0.8, y: 0.32 }, { x: 0, y: 0.84 }, { x: -0.56, y: 0.84 }], 0.5, 1, 1); + //t.transform.setRotation(game.math.degreesToRadians(45)); + //t.fixedRotation = true; physics.space.addBody(t); + game.input.onTap.add(step, this); + + } + + function step() { + + physics.update(); } function update() { - physics.update(); + //if (physics.space.stepCount < 90) + //{ + physics.update(); + //} - atari.x = physics.metersToPixels(circle.position.x); - atari.y = physics.metersToPixels(circle.position.y); - atari.rotation = physics.metersToPixels(circle.angle); + //atari.x = physics.metersToPixels(circle.position.x); + //atari.y = physics.metersToPixels(circle.position.y); + //atari.rotation = physics.metersToPixels(circle.angle); // force moves without rotating @@ -140,16 +172,17 @@ function drawPolygon(ctx, shape, lineWidth, fillStyle) { - var verts = shape.verts; + var verts = shape.tverts; + var body = shape.body; ctx.beginPath(); - ctx.moveTo(verts[0].x * 50, verts[0].y * 50); + ctx.moveTo(body.position.x + verts[0].x * 50, body.position.y + verts[0].y * 50); for (var i = 0; i < verts.length; i++) { - ctx.lineTo(verts[i].x * 50, verts[i].y * 50); + ctx.lineTo(body.position.x + verts[i].x * 50, body.position.y + verts[i].y * 50); } - ctx.lineTo(verts[verts.length - 1].x * 50, verts[verts.length - 1].y * 50); + ctx.lineTo(body.position.x + verts[verts.length - 1].x * 50, body.position.y + verts[verts.length - 1].y * 50); ctx.closePath(); @@ -160,19 +193,21 @@ function render() { - game.stage.context.fillStyle = 'rgb(255,255,0)'; - game.stage.context.fillText('x: ' + circle.position.x + ' y: ' + circle.position.y, 32, 32); - game.stage.context.fillText('vx: ' + circle.velocity.x + ' vy: ' + circle.velocity.y, 32, 64); + //game.stage.context.fillStyle = 'rgb(255,255,0)'; + //game.stage.context.fillText('x: ' + t.position.x + ' y: ' + t.position.y, 32, 32); + //game.stage.context.fillText('vx: ' + t.velocity.x + ' vy: ' + t.velocity.y, 32, 64); + //game.stage.context.fillText('x: ' + t.bounds.x + ' y: ' + t.bounds.y, 32, 32); + //game.stage.context.fillText('vx: ' + t.velocity.x + ' vy: ' + t.velocity.y, 32, 64); - renderCircle(circle.shapes[0]); - renderBounds(circle); + //renderCircle(circle.shapes[0]); + //renderBounds(circle); drawPolygon(game.stage.context, walls.shapes[0], 1, 'rgb(0,255,255)'); - drawPolygon(game.stage.context, walls.shapes[1], 1, 'rgb(0,255,255)'); + //drawPolygon(game.stage.context, walls.shapes[1], 1, 'rgb(0,255,255)'); //renderCircle(t.shapes[0]); drawPolygon(game.stage.context, t.shapes[0], 1, 'rgb(255,255,255)'); - renderBounds(t); + //renderBounds(t); } diff --git a/build/phaser.d.ts b/build/phaser.d.ts index c83cbfd5..ee5d593d 100644 --- a/build/phaser.d.ts +++ b/build/phaser.d.ts @@ -8862,6 +8862,7 @@ module Phaser { * @param {Pointer} pointer2 **/ public getAngle(pointer1: Pointer, pointer2: Pointer): number; + public pixelPerfectCheck(sprite: Sprite, pointer: Pointer, alpha?: number): bool; } } module Phaser { @@ -9439,6 +9440,8 @@ module Phaser { 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; @@ -9602,6 +9605,12 @@ module Phaser.Physics.Advanced { * Local 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; @@ -9646,15 +9655,15 @@ module Phaser.Physics.Advanced { static metersToPixels(value: number): number; static p2m(value: number): number; static m2p(value: number): number; - static areaForCircle(radius_outer, radius_inner): number; - static inertiaForCircle(mass, center, radius_outer, radius_inner): number; - static areaForSegment(a, b, radius): number; - static centroidForSegment(a, b): Vec2; - static inertiaForSegment(mass, a, b): number; - static areaForPoly(verts): number; - static centroidForPoly(verts): Vec2; - static inertiaForPoly(mass, verts, offset): number; - static inertiaForBox(mass, w, h): number; + static 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[]; } } @@ -9715,6 +9724,11 @@ module Phaser.Physics.Advanced { 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; } } /** @@ -9728,6 +9742,11 @@ module Phaser.Physics.Advanced { 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; @@ -9800,6 +9819,18 @@ module Phaser.Physics.Advanced.Shapes { } } /** +* Phaser - Advanced Physics - Plane +* +* Based on the work Ju Hyung Lee started in JS PhyRus. +*/ +module Phaser.Physics.Advanced { + 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. @@ -9807,16 +9838,11 @@ module Phaser.Physics.Advanced.Shapes { module Phaser.Physics.Advanced.Shapes { class Poly extends Shape implements IShape { constructor(verts?); - public verts: Vec2[]; - public planes; - public tverts; - public tplanes; - public convexity: bool; public finishVerts(): void; public duplicate(): Poly; public recenter(c): void; - public transform(xf): void; - public untransform(xf): void; + public transform(xf: Transform): void; + public untransform(xf: Transform): void; public area(): number; public centroid(): Vec2; public inertia(mass: number): number; @@ -9824,8 +9850,8 @@ module Phaser.Physics.Advanced.Shapes { public pointQuery(p: Vec2): bool; public findVertexByPoint(p: Vec2, minDist: number): number; public findEdgeByPoint(p: Vec2, minDist: number): number; - public distanceOnPlane(n, d): number; - public containPoint(p): bool; + public distanceOnPlane(n: Vec2, d: number): number; + public containPoint(p: Vec2): bool; public containPointPartial(p, n): bool; } } @@ -9875,7 +9901,7 @@ module Phaser.Physics.Advanced { public segment2Segment(seg1: Shapes.Segment, seg2: Shapes.Segment, contactArr: Contact[]): number; public findPointsBehindSeg(contactArr: Contact[], seg: Shapes.Segment, poly: Shapes.Poly, dist: number, coef: number): void; public segment2Poly(seg: Shapes.Segment, poly: Shapes.Poly, contactArr: Contact[]): number; - public findMSA(poly: Shapes.Poly, planes, num: number): { + public findMSA(poly: Shapes.Poly, planes: Plane[], num: number): { dist: number; index: number; }; @@ -9979,6 +10005,7 @@ module Phaser.Physics.Advanced.Shapes { module Phaser.Physics.Advanced { class Body { constructor(sprite: Sprite, type: number, x?: number, y?: number); + public toString(): string; private _tempVec2; /** * Reference to Phaser.Game @@ -10047,25 +10074,27 @@ module Phaser.Physics.Advanced { public setTransform(pos, angle): void; public syncTransform(): void; public getWorldPoint(p: Vec2): Vec2; - public getWorldVector(v): Vec2; - public getLocalPoint(p): Vec2; - public getLocalVector(v): Vec2; + public getWorldVector(v: Vec2): Vec2; + public getLocalPoint(p: Vec2): Vec2; + public getLocalVector(v: Vec2): Vec2; public setFixedRotation(flag): void; public resetMassData(): void; public resetJointAnchors(): void; - public cacheData(): 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): void; public resetForce(): void; - public applyForce(force, p): void; - public applyForceToCenter(force): void; - public applyTorque(torque): void; - public applyLinearImpulse(impulse, p): 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): bool; + public isCollidable(other: Body): bool; } } /** diff --git a/build/phaser.js b/build/phaser.js index 70ddf6c5..ae3e1c09 100644 --- a/build/phaser.js +++ b/build/phaser.js @@ -955,7 +955,8 @@ var Phaser; * @return {string} a string representation of the object. **/ function () { - return "[{Vec2 (x=" + this.x + " y=" + this.y + ")}]"; + //return "[{Vec2 (x=" + this.x + " y=" + this.y + ")}]"; + return "x=" + this.x + " y=" + this.y; }; return Vec2; })(); @@ -16496,19 +16497,15 @@ var Phaser; function (pointer1, pointer2) { return Phaser.Vec2Utils.angle(pointer1.position, pointer2.position); }; + Input.prototype.pixelPerfectCheck = function (sprite, pointer, alpha) { + if (typeof alpha === "undefined") { alpha = 255; } + this.hitContext.clearRect(0, 0, 1, 1); + return true; + }; return Input; })(); Phaser.Input = Input; - /* - public pixelPerfectCheck(sprite: Phaser.Sprite, pointer: Phaser.Pointer, alpha: number = 255): bool { - - this.hitContext.clearRect(0, 0, 1, 1); - - return true; - - } - */ - })(Phaser || (Phaser = {})); +})(Phaser || (Phaser = {})); /// /// /// @@ -18073,7 +18070,11 @@ var Phaser; 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); @@ -18081,8 +18082,11 @@ var Phaser; return this; }; Transform.prototype.setRotation = function (angle) { - this.c = Math.cos(angle); - this.s = Math.sin(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) { @@ -18114,20 +18118,24 @@ var Phaser; 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; @@ -19150,14 +19158,58 @@ var Phaser; 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; + //public velocityIterations: number = 1; + //public positionIterations: number = 1; this.allowSleep = true; this.warmStarting = true; this.game = game; this.space = new Advanced.Space(); Manager.collision = new Advanced.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; @@ -19197,6 +19249,7 @@ var Phaser; // //domCanvas.style.cursor = body ? "pointer" : "default"; //} if(!this.paused || this.step) { + Manager.clear(); var h = 1 / this.frameRateHz; this.timeDelta += frameTime; if(this.step) { @@ -19649,7 +19702,6 @@ var Phaser; (function (Advanced) { var ContactSolver = (function () { function ContactSolver(shape1, shape2) { - //console.log('ContactSolver super'); this.shape1 = shape1; this.shape2 = shape2; this.contacts = []; @@ -19733,24 +19785,32 @@ var Phaser; //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.velocity.multiplyAddByScalar(impulse, body2.massInverted); //body2.v.mad(impulse, body2.m_inv); - body2.angularVelocity -= Phaser.Vec2Utils.cross(con.r2, impulse) * body2.inertiaInverted; + 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; + Advanced.Manager.write('solveVelocityConstraints. Body1: ' + body1.name + ' Body2: ' + body2.name); + Advanced.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; + Advanced.Manager.write('m1_inv: ' + m1_inv); + Advanced.Manager.write('i1_inv: ' + i1_inv); + Advanced.Manager.write('m2_inv: ' + m2_inv); + Advanced.Manager.write('i2_inv: ' + i2_inv); for(var i = 0; i < this.contacts.length; i++) { + Advanced.Manager.write('------------ solve con ' + i); var con = this.contacts[i]; var n = con.normal; var t = Phaser.Vec2Utils.perp(n); @@ -19762,19 +19822,25 @@ var Phaser; 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); + Advanced.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); + Advanced.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); + Advanced.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); + Advanced.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; + Advanced.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); @@ -19787,19 +19853,23 @@ var Phaser; // 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); + Advanced.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); - body1.angularVelocity += Phaser.Vec2Utils.cross(r2, impulse) * i2_inv; + body2.angularVelocity += Phaser.Vec2Utils.cross(r2, impulse) * i2_inv; //body2.w += vec2.cross(r2, impulse) * i2_inv; - } + Advanced.Manager.write('body1: ' + body1.toString()); + Advanced.Manager.write('body2: ' + body2.toString()); + } }; ContactSolver.prototype.solvePositionConstraints = function () { var body1 = this.shape1.body; var body2 = this.shape2.body; + Advanced.Manager.write('solvePositionConstraints'); var m1_inv = body1.massInverted; var i1_inv = body1.inertiaInverted; var m2_inv = body2.massInverted; @@ -19807,6 +19877,7 @@ var Phaser; var sum_m_inv = m1_inv + m2_inv; var max_penetration = 0; for(var i = 0; i < this.contacts.length; i++) { + Advanced.Manager.write('------------- solvePositionConstraints ' + i); var con = this.contacts[i]; var n = con.normal; var r1 = new Phaser.Vec2(); @@ -19816,6 +19887,10 @@ var Phaser; //var r1 = vec2.rotate(con.r1_local, body1.a); Phaser.Vec2Utils.rotate(con.r2_local, body2.angle, r2); //var r2 = vec2.rotate(con.r2_local, body2.a); + Advanced.Manager.write('r1_local.x = ' + con.r1_local.x + ' r1_local.y = ' + con.r1_local.y + ' angle: ' + body1.angle); + Advanced.Manager.write('r1 rotated: r1.x = ' + r1.x + ' r1.y = ' + r1.y); + Advanced.Manager.write('r2_local.x = ' + con.r2_local.x + ' r2_local.y = ' + con.r2_local.y + ' angle: ' + body2.angle); + Advanced.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(); @@ -19823,9 +19898,11 @@ var Phaser; //var p1 = vec2.add(body1.p, r1); Phaser.Vec2Utils.add(body2.position, r2, p2); //var p2 = vec2.add(body2.p, r2); + Advanced.Manager.write('body1.pos.x=' + body1.position.x + ' y=' + body1.position.y); + Advanced.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); + Phaser.Vec2Utils.subtract(p2, p1, dp); //var dp = vec2.sub(p2, p1); // Position constraint var c = Phaser.Vec2Utils.dot(dp, n) + con.depth; @@ -19851,7 +19928,10 @@ var Phaser; body2.position.multiplyAddByScalar(impulse_dt, m2_inv); //body2.p.mad(impulse_dt, m2_inv); body2.angle += sn2 * lambda_dt * i2_inv; + Advanced.Manager.write('body1.pos.x=' + body1.position.x + ' y=' + body1.position.y); + Advanced.Manager.write('body2.pos.x=' + body2.position.x + ' y=' + body2.position.y); } + Advanced.Manager.write('max_penetration: ' + max_penetration); return max_penetration <= Advanced.Manager.CONTACT_SOLVER_COLLISION_SLOP * 3; }; ContactSolver.prototype.clamp = function (v, min, max) { @@ -19951,6 +20031,32 @@ var Phaser; var Physics = Phaser.Physics; })(Phaser || (Phaser = {})); var Phaser; +(function (Phaser) { + (function (Physics) { + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Plane + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + (function (Advanced) { + var Plane = (function () { + function Plane(normal, d) { + this.normal = normal; + this.d = d; + } + return Plane; + })(); + Advanced.Plane = Plane; + })(Physics.Advanced || (Physics.Advanced = {})); + var Advanced = Physics.Advanced; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); +var Phaser; (function (Phaser) { (function (Physics) { (function (Advanced) { @@ -19958,6 +20064,7 @@ var Phaser; /// /// /// + /// /// /** * Phaser - Advanced Physics - Shapes - Convex Polygon @@ -19979,10 +20086,8 @@ var Phaser; 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.tplanes[i] = { - }; - this.tplanes[i].n = new Phaser.Vec2(); - this.tplanes[i].d = 0; + //this.tverts[i] = new Phaser.Vec2(verts[i].x, verts[i].y); + this.tplanes[i] = new Phaser.Physics.Advanced.Plane(new Phaser.Vec2(), 0); } } this.finishVerts(); @@ -20001,21 +20106,17 @@ var Phaser; var a = this.verts[i]; var b = this.verts[(i + 1) % this.verts.length]; var n = Phaser.Vec2Utils.normalize(Phaser.Vec2Utils.perp(Phaser.Vec2Utils.subtract(a, b))); - this.planes[i] = { - }; - this.planes[i].n = n; - this.planes[i].d = Phaser.Vec2Utils.dot(n, a); - this.tverts[i] = this.verts[i]; - this.tplanes[i] = { - }; - this.tplanes[i].n = new Phaser.Vec2(); - this.tplanes[i].d = 0; + this.planes[i] = new Phaser.Physics.Advanced.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.Advanced.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].n; - var d = this.planes[i].d; - if(Phaser.Vec2Utils.dot(n, b) - d > 0) { + //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; } } @@ -20030,13 +20131,15 @@ var Phaser; }; Poly.prototype.transform = function (xf) { for(var i = 0; i < this.verts.length; i++) { - this.verts[i] = xf.transform(this.verts[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] = xf.untransform(this.verts[i]); - } + this.verts[i] = Phaser.TransformUtils.untransform(xf, this.verts[i]); + //this.verts[i] = xf.untransform(this.verts[i]); + } }; Poly.prototype.area = function () { return Advanced.Manager.areaForPoly(this.verts); @@ -20050,14 +20153,15 @@ var Phaser; Poly.prototype.cacheData = function (xf) { this.bounds.clear(); var numVerts = this.verts.length; - console.log('Poly cacheData', numVerts, this.body.name); + Advanced.Manager.write('----------- Poly cacheData = ' + numVerts); if(numVerts == 0) { return; } for(var i = 0; i < numVerts; i++) { - Phaser.TransformUtils.transform(xf, this.tverts[i], this.tverts[i]); + this.tverts[i] = Phaser.TransformUtils.transform(xf, this.verts[i]); //this.tverts[i] = xf.transform(this.verts[i]); - } + Advanced.Manager.write('tvert' + i + ' = ' + this.tverts[i].toString()); + } if(numVerts < 2) { this.bounds.addPoint(this.tverts[0]); return; @@ -20066,8 +20170,13 @@ var Phaser; var a = this.tverts[i]; var b = this.tverts[(i + 1) % numVerts]; var n = Phaser.Vec2Utils.normalize(Phaser.Vec2Utils.perp(Phaser.Vec2Utils.subtract(a, b))); - this.tplanes[i].n = n; + Advanced.Manager.write('a = ' + a.toString()); + Advanced.Manager.write('b = ' + b.toString()); + Advanced.Manager.write('n = ' + n.toString()); + this.tplanes[i].normal = n; this.tplanes[i].d = Phaser.Vec2Utils.dot(n, a); + Advanced.Manager.write('tplanes' + i + ' n = ' + this.tplanes[i].normal.toString()); + Advanced.Manager.write('tplanes' + i + ' d = ' + this.tplanes[i].d.toString()); this.bounds.addPoint(a); } }; @@ -20092,7 +20201,7 @@ var Phaser; for(var i = 0; i < this.tverts.length; i++) { var v1 = this.tverts[i]; var v2 = this.tverts[(i + 1) % numVerts]; - var n = this.tplanes[i].n; + var 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); @@ -20123,7 +20232,7 @@ var Phaser; Poly.prototype.containPoint = function (p) { for(var i = 0; i < this.verts.length; i++) { var plane = this.tplanes[i]; - if(Phaser.Vec2Utils.dot(plane.n, p) - plane.d > 0) { + if(Phaser.Vec2Utils.dot(plane.normal, p) - plane.d > 0) { return false; } } @@ -20132,10 +20241,10 @@ var Phaser; 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.n, n) < 0.0001) { + if(Phaser.Vec2Utils.dot(plane.normal, n) < 0.0001) { continue; } - if(Phaser.Vec2Utils.dot(plane.n, p) - plane.d > 0) { + if(Phaser.Vec2Utils.dot(plane.normal, p) - plane.d > 0) { return false; } } @@ -20412,7 +20521,7 @@ var Phaser; var minIdx = -1; for(var i = 0; i < poly.verts.length; i++) { var plane = poly.tplanes[i]; - var dist = Phaser.Vec2Utils.dot(circ.tc, plane.n) - plane.d - circ.radius; + var dist = Phaser.Vec2Utils.dot(circ.tc, plane.normal) - plane.d - circ.radius; if(dist > 0) { return 0; } else if(dist > minDist) { @@ -20420,7 +20529,7 @@ var Phaser; minIdx = i; } } - var n = poly.tplanes[minIdx].n; + 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); @@ -20529,7 +20638,7 @@ var Phaser; var poly_i = -1; for(var i = 0; i < poly.verts.length; i++) { var plane = poly.tplanes[i]; - var dist = seg.distanceOnPlane(plane.n, plane.d); + var dist = seg.distanceOnPlane(plane.normal, plane.d); if(dist > 0) { return 0; } @@ -20539,7 +20648,7 @@ var Phaser; } } var poly_n = new Phaser.Vec2(); - Phaser.Vec2Utils.negative(poly.tplanes[poly_i].n, poly_n); + 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); @@ -20587,7 +20696,7 @@ var Phaser; var min_dist = -999999; var min_index = -1; for(var i = 0; i < num; i++) { - var dist = poly.distanceOnPlane(planes[i].n, planes[i].d); + var dist = poly.distanceOnPlane(planes[i].normal, planes[i].d); if(dist > 0) { // no collision return { @@ -20645,17 +20754,19 @@ var Phaser; 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 shoud be from poly1 to poly2 + // Penetration normal direction should be from poly1 to poly2 if(msa1.dist > msa2.dist) { - return this.findVerts(contactArr, poly1, poly2, poly1.tplanes[msa1.index].n, msa1.dist); + return this.findVerts(contactArr, poly1, poly2, poly1.tplanes[msa1.index].normal, msa1.dist); } - return this.findVerts(contactArr, poly1, poly2, Phaser.Vec2Utils.negative(poly2.tplanes[msa2.index].n), msa2.dist); + return this.findVerts(contactArr, poly1, poly2, Phaser.Vec2Utils.negative(poly2.tplanes[msa2.index].normal), msa2.dist); }; return Collision; })(); @@ -20729,12 +20840,11 @@ var Phaser; if(this.bodyHash[body.id] != undefined) { return; } - //console.log('Body added to space', body.name); var index = this.bodyArr.push(body) - 1; this.bodyHash[body.id] = index; body.awake(true); body.space = this; - body.cacheData(); + body.cacheData('addBody'); }; Space.prototype.removeBody = function (body) { if(this.bodyHash[body.id] == undefined) { @@ -20939,6 +21049,7 @@ var Phaser; return firstJointId; }; Space.prototype.findContactSolver = function (shape1, shape2) { + Advanced.Manager.write('findContactSolver. Length: ' + this.contactSolvers.length); for(var i = 0; i < this.contactSolvers.length; i++) { var contactSolver = this.contactSolvers[i]; if(shape1 == contactSolver.shape1 && shape2 == contactSolver.shape2) { @@ -20948,41 +21059,22 @@ var Phaser; return null; }; Space.prototype.genTemporalContactSolvers = function () { - //console.log('genTemporalContactSolvers'); - //var t0 = Date.now(); + Advanced.Manager.write('genTemporalContactSolvers'); var newContactSolverArr = []; + var bl = this.bodyArr.length; this.numContacts = 0; - for(var body1_index = 0; body1_index < this.bodyArr.length; body1_index++) { + for(var body1_index = 0; body1_index < bl; body1_index++) { var body1 = this.bodyArr[body1_index]; - //console.log('body1', body1_index, body1.type); if(!body1) { continue; } body1.stepCount = this.stepCount; - for(var body2_index = 0; body2_index < this.bodyArr.length; body2_index++) { + for(var body2_index = 0; body2_index < bl; body2_index++) { var body2 = this.bodyArr[body2_index]; - //console.log('body2', body2_index, body2.type); - if(!body2) { + if(body1.inContact(body2) == false) { continue; } - if(body1.stepCount == body2.stepCount) { - continue; - } - //console.log('step'); - var active1 = body1.isAwake && !body1.isStatic; - var active2 = body2.isAwake && !body2.isStatic; - if(!active1 && !active2) { - continue; - } - //console.log('active'); - if(!body1.isCollidable(body2)) { - continue; - } - //console.log('collideable'); - if(!body1.bounds.intersectsBounds(body2.bounds)) { - continue; - } - //console.log('>>>>>>>>>> intersects'); + Advanced.Manager.write('body1 and body2 intersect'); for(var i = 0; i < body1.shapes.length; i++) { for(var j = 0; j < body2.shapes.length; j++) { var shape1 = body1.shapes[i]; @@ -20998,10 +21090,12 @@ var Phaser; } this.numContacts += contactArr.length; var contactSolver = this.findContactSolver(shape1, shape2); + Advanced.Manager.write('findContactSolver result: ' + contactSolver); if(contactSolver) { contactSolver.update(contactArr); newContactSolverArr.push(contactSolver); } else { + Advanced.Manager.write('awake both bodies'); body1.awake(true); body2.awake(true); var newContactSolver = new Advanced.ContactSolver(shape1, shape2); @@ -21009,15 +21103,18 @@ var Phaser; newContactSolver.elasticity = Math.max(shape1.elasticity, shape2.elasticity); newContactSolver.friction = Math.sqrt(shape1.friction * shape2.friction); newContactSolverArr.push(newContactSolver); - } + Advanced.Manager.write('new contact solver'); + //console.log(newContactSolver); + } } } } } - //stats.timeCollision = Date.now() - t0; return newContactSolverArr; }; Space.prototype.initSolver = function (dt, dt_inv, warmStarting) { + Advanced.Manager.write('initSolver'); + Advanced.Manager.write('contactSolvers.length: ' + this.contactSolvers.length); //var t0 = Date.now(); // Initialize contact solvers for(var i = 0; i < this.contactSolvers.length; i++) { @@ -21038,6 +21135,7 @@ var Phaser; //stats.timeInitSolver = Date.now() - t0; }; Space.prototype.velocitySolver = function (iteration) { + Advanced.Manager.write('velocitySolver, iterations: ' + iteration + ' csa len: ' + this.contactSolvers.length); //var t0 = Date.now(); for(var i = 0; i < iteration; i++) { for(var j = 0; j < this.jointArr.length; j++) { @@ -21049,12 +21147,9 @@ var Phaser; this.contactSolvers[j].solveVelocityConstraints(); } } - //stats.timeVelocitySolver = Date.now() - t0; - }; + }; Space.prototype.positionSolver = function (iteration) { - //var t0 = Date.now(); var positionSolved = false; - //stats.positionIterations = 0; for(var i = 0; i < iteration; i++) { var contactsOk = true; var jointsOk = true; @@ -21073,126 +21168,147 @@ var Phaser; positionSolved = true; break; } - //stats.positionIterations++; - } - //stats.timePositionSolver = Date.now() - t0; + } return positionSolved; }; Space.prototype.step = function (dt, vel_iteration, pos_iteration, warmStarting, allowSleep) { + Advanced.Manager.clear(); + Advanced.Manager.write('Space step ' + this.stepCount); var dt_inv = 1 / dt; + var bl = this.bodyArr.length; + var jl = this.jointArr.length; this.stepCount++; - // Generate contact & contactSolver + // 1) Generate Contact Solvers this.contactSolvers = this.genTemporalContactSolvers(); - // Initialize contacts & joints solver + Advanced.Manager.dump("Contact Solvers", this.bodyArr[1]); + // 2) Initialize the Contact Solvers this.initSolver(dt, dt_inv, warmStarting); - // Intergrate velocity - for(var i = 0; i < this.bodyArr.length; i++) { - var body = this.bodyArr[i]; - if(!body) { - continue; - } - if(body.isDynamic && body.isAwake) { - body.updateVelocity(this.gravity, dt, this.damping); + Advanced.Manager.dump("Init Solver", this.bodyArr[1]); + // 3) Intergrate velocity + for(var i = 0; i < bl; i++) { + if(this.bodyArr[i] && this.bodyArr[i].isDynamic && this.bodyArr[i].isAwake) { + this.bodyArr[i].updateVelocity(this.gravity, dt, this.damping); } } - for(var i = 0; i < this.jointArr.length; i++) { - var joint = this.jointArr[i]; - if(!joint) { - continue; - } - var body1 = joint.body1; - var body2 = joint.body2; - var awake1 = body1.isAwake && !body1.isStatic; - var awake2 = body2.isAwake && !body2.isStatic; - if(awake1 ^ awake2) { - if(!awake1) { - body1.awake(true); - } - if(!awake2) { - body2.awake(true); - } - } + Advanced.Manager.dump("Update Velocity", this.bodyArr[1]); + /* + // 4) Awaken bodies + for (var j = 0; i < jl; j++) + { + var joint = this.jointArr[j]; + + if (!joint) + { + continue; } - // Iterative velocity constraints solver + + var body1 = joint.body1; + var body2 = joint.body2; + + var awake1 = body1.isAwake && !body1.isStatic; + var awake2 = body2.isAwake && !body2.isStatic; + + if (awake1 ^ awake2) + { + if (!awake1) + { + body1.awake(true); + } + + if (!awake2) + { + body2.awake(true); + } + } + } + */ + // 5) Iterative velocity constraints solver this.velocitySolver(vel_iteration); - // Intergrate position - for(var i = 0; i < this.bodyArr.length; i++) { - var body = this.bodyArr[i]; - if(!body) { - continue; - } - if(body.isDynamic && body.isAwake) { - body.updatePosition(dt); + Advanced.Manager.dump("Velocity Solvers", this.bodyArr[1]); + // 6) Intergrate position + for(var i = 0; i < bl; i++) { + if(this.bodyArr[i] && this.bodyArr[i].isDynamic && this.bodyArr[i].isAwake) { + this.bodyArr[i].updatePosition(dt); } } - // Process breakable joint - for(var i = 0; i < this.jointArr.length; i++) { - var joint = this.jointArr[i]; - if(!joint) { - continue; - } - if(joint.breakable) { - if(joint.getReactionForce(dt_inv).lengthsq() >= joint.maxForce * joint.maxForce) { - this.removeJoint(joint); - } + Advanced.Manager.dump("Update Position", this.bodyArr[1]); + // 7) Process breakable joint + for(var i = 0; i < jl; i++) { + if(this.jointArr[i] && this.jointArr[i].breakable && (this.jointArr[i].getReactionForce(dt_inv).lengthSq() >= this.jointArr[i].maxForce * this.jointArr[i].maxForce)) { + this.removeJoint(this.jointArr[i]); } } - // Iterative position constraints solver + // 8) Iterative position constraints solver var positionSolved = this.positionSolver(pos_iteration); - for(var i = 0; i < this.bodyArr.length; i++) { - var body = this.bodyArr[i]; - if(!body) { - continue; + Advanced.Manager.dump("Position Solver", this.bodyArr[1]); + // 9) Sync the Transforms + for(var i = 0; i < bl; i++) { + if(this.bodyArr[i]) { + this.bodyArr[i].syncTransform(); } - body.syncTransform(); } - // Post solve collision callback + Advanced.Manager.dump("Sync Transform", this.bodyArr[1]); + // 10) Post solve collision callback for(var i = 0; i < this.contactSolvers.length; i++) { var arb = this.contactSolvers[i]; // Re-enable this //this.postSolve(arb); } - for(var i = 0; i < this.bodyArr.length; i++) { - var body = this.bodyArr[i]; - if(!body) { - continue; - } - if(body.isDynamic && body.isAwake) { - body.cacheData(); + // 11) Cache Body Data + for(var i = 0; i < bl; i++) { + if(this.bodyArr[i] && this.bodyArr[i].isDynamic && this.bodyArr[i].isAwake) { + this.bodyArr[i].cacheData('post solve collision callback'); } } - // Process sleeping - if(allowSleep) { - var minSleepTime = 999999; - var linTolSqr = Space.SLEEP_LINEAR_TOLERANCE * Space.SLEEP_LINEAR_TOLERANCE; - var angTolSqr = Space.SLEEP_ANGULAR_TOLERANCE * Space.SLEEP_ANGULAR_TOLERANCE; - for(var i = 0; i < this.bodyArr.length; i++) { - var body = this.bodyArr[i]; - if(!body) { - continue; - } - if(!body.isDynamic) { - continue; - } - if(body.angularVelocity * body.angularVelocity > angTolSqr || body.velocity.dot(body.velocity) > linTolSqr) { - body.sleepTime = 0; - minSleepTime = 0; - } else { - body.sleepTime += dt; - minSleepTime = Math.min(minSleepTime, body.sleepTime); - } - } - if(positionSolved && minSleepTime >= Space.TIME_TO_SLEEP) { - for(var i = 0; i < this.bodyArr.length; i++) { - var body = this.bodyArr[i]; - if(!body) { - continue; - } - body.awake(false); - } - } + Advanced.Manager.dump("Cache Data", this.bodyArr[1]); + Advanced.Manager.writeAll(); + // 12) Process sleeping + /* + if (allowSleep) + { + var minSleepTime = 999999; + + var linTolSqr = Space.SLEEP_LINEAR_TOLERANCE * Space.SLEEP_LINEAR_TOLERANCE; + var angTolSqr = Space.SLEEP_ANGULAR_TOLERANCE * Space.SLEEP_ANGULAR_TOLERANCE; + + for (var i = 0; i < bl; i++) + { + var body = this.bodyArr[i]; + + if (!this.bodyArr[i] || this.bodyArr[i].isDynamic == false) + { + continue; } - }; + + if (body.angularVelocity * body.angularVelocity > angTolSqr || body.velocity.dot(body.velocity) > linTolSqr) + { + body.sleepTime = 0; + minSleepTime = 0; + } + else + { + body.sleepTime += dt; + minSleepTime = Math.min(minSleepTime, body.sleepTime); + } + } + + if (positionSolved && minSleepTime >= Space.TIME_TO_SLEEP) + { + for (var i = 0; i < this.bodyArr.length; i++) + { + var body = this.bodyArr[i]; + + if (!body) + { + continue; + } + + body.awake(false); + } + } + } + */ + }; return Space; })(); Advanced.Space = Space; @@ -21269,10 +21385,10 @@ var Phaser; __extends(Box, _super); // Give in pixels function Box(x, y, width, height) { - x = Advanced.Manager.pixelsToMeters(x); - y = Advanced.Manager.pixelsToMeters(y); - width = Advanced.Manager.pixelsToMeters(width); - height = Advanced.Manager.pixelsToMeters(height); + //x = Manager.pixelsToMeters(x); + //y = Manager.pixelsToMeters(y); + //width = Manager.pixelsToMeters(width); + //height = Manager.pixelsToMeters(height); var hw = width * 0.5; var hh = height * 0.5; _super.call(this, [ @@ -21375,6 +21491,9 @@ var Phaser; this.maskBits = 0xFFFF; this.stepCount = 0; } + Body.prototype.toString = function () { + return "[{Body (name=" + this.name + " velocity=" + this.velocity.toString() + " angularVelocity: " + this.angularVelocity + ")}]"; + }; Body.prototype.duplicate = function () { //console.log('body duplicate called'); //var body = new Body(this.type, this.transform.t, this.angle); @@ -21498,19 +21617,25 @@ var Phaser; Body.prototype.setTransform = function (pos, angle) { this.transform.setTo(pos, angle); // inject the transform into this.position + Advanced.Manager.write('setTransform: ' + this.position.toString()); + Advanced.Manager.write('centroid: ' + this.centroid.toString()); Phaser.TransformUtils.transform(this.transform, this.centroid, this.position); + Advanced.Manager.write('post setTransform: ' + this.position.toString()); //this.position.copyFrom(this.transform.transform(this.centroid)); this.angle = angle; }; Body.prototype.syncTransform = function () { + Advanced.Manager.write('syncTransform:'); + Advanced.Manager.write('p: ' + this.position.toString()); + Advanced.Manager.write('centroid: ' + this.centroid.toString()); + Advanced.Manager.write('xf: ' + this.transform.toString()); + Advanced.Manager.write('a: ' + this.angle); this.transform.setRotation(this.angle); - //var rotc: Phaser.Vec2 = this.transform.rotate(this.centroid); - //var sub: Phaser.Vec2 = Phaser.Vec2Utils.subtract(this.position, rotc); - //this.transform.setPosition(sub); - // this.transform.setPosition(vec2.sub(this.position, this.transform.rotate(this.centroid))); - //Phaser.Vec2Utils.subtract(this.position, this.transform.rotate(this.centroid), this.transform.t); // OPTIMISE: Creating new vector Phaser.Vec2Utils.subtract(this.position, Phaser.TransformUtils.rotate(this.transform, this.centroid), this.transform.t); + Advanced.Manager.write('--------------------'); + Advanced.Manager.write('xf: ' + this.transform.toString()); + Advanced.Manager.write('--------------------'); }; Body.prototype.getWorldPoint = function (p) { // OPTIMISE: Creating new vector @@ -21585,14 +21710,21 @@ var Phaser; joint.setWorldAnchor2(anchor2); } }; - Body.prototype.cacheData = function () { - //console.log('Body cacheData', this.name, 'len', this.shapes.length); + Body.prototype.cacheData = function (source) { + if (typeof source === "undefined") { source = ''; } + Advanced.Manager.write('cacheData -- start'); + Advanced.Manager.write('p: ' + this.position.toString()); + Advanced.Manager.write('xf: ' + this.transform.toString()); this.bounds.clear(); for(var i = 0; i < this.shapes.length; i++) { var shape = this.shapes[i]; shape.cacheData(this.transform); this.bounds.addBounds(shape.bounds); } + Advanced.Manager.write('bounds: ' + this.bounds.toString()); + Advanced.Manager.write('p: ' + this.position.toString()); + Advanced.Manager.write('xf: ' + this.transform.toString()); + Advanced.Manager.write('cacheData -- stop'); }; Body.prototype.updateVelocity = function (gravity, dt, damping) { // this.velocity = vec2.mad(this.velocity, vec2.mad(gravity, this.force, this.massInverted), dt); @@ -21606,11 +21738,29 @@ var Phaser; // v2 = exp(-c * dt) * v1 // Taylor expansion: // v2 = (1.0f - c * dt) * v1 - this.velocity.scale(this.game.math.clamp(1 - dt * (damping + this.linearDamping), 0, 1)); - this.angularVelocity *= this.game.math.clamp(1 - dt * (damping + this.angularDamping), 0, 1); + this.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) { //console.log('body update pos', this.position.y); //console.log('pre add temp', this._tempVec2.y); @@ -21711,10 +21861,7 @@ var Phaser; } for(var i = 0; i < this.joints.length; i++) { var joint = this.joints[i]; - if(!joint) { - continue; - } - if(!joint.collideConnected && other.jointHash[joint.id] != undefined) { + if(!this.joints[i] || (!this.joints[i].collideConnected && other.jointHash[this.joints[i].id] != undefined)) { return false; } }