From 0591c7f2bdc4fa42c05d1d3ad6ad2c70f1647bee Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Tue, 25 Jun 2013 15:35:45 +0100 Subject: [PATCH 1/3] Doing one final commit before the task of merging physics with core. --- Phaser/components/animation/FrameData.ts | 7 +- Phaser/components/sprite/Input.ts | 5 +- Phaser/core/Group.ts | 6 +- Phaser/gameobjects/Tilemap.ts | 6 + Phaser/input/Input.ts | 1 + Phaser/physics/advanced/Body.ts | 34 +- Phaser/physics/advanced/Manager.ts | 14 +- Phaser/physics/advanced/Space.ts | 377 ++++++++++---------- README.md | 7 + Tests/phaser.js | 424 +++++++++++------------ build/phaser.d.ts | 36 +- build/phaser.js | 424 +++++++++++------------ 12 files changed, 659 insertions(+), 682 deletions(-) diff --git a/Phaser/components/animation/FrameData.ts b/Phaser/components/animation/FrameData.ts index e54c8a7e..5594fe12 100644 --- a/Phaser/components/animation/FrameData.ts +++ b/Phaser/components/animation/FrameData.ts @@ -93,12 +93,13 @@ module Phaser { */ public checkFrameName(name: string): bool { - if (this._frameNames[name]) + + if (this._frameNames[name] == null) { - return true; + return false; } - return false; + return true; } diff --git a/Phaser/components/sprite/Input.ts b/Phaser/components/sprite/Input.ts index 16d87575..c6e0a0b9 100644 --- a/Phaser/components/sprite/Input.ts +++ b/Phaser/components/sprite/Input.ts @@ -263,6 +263,7 @@ module Phaser.Components.Sprite { if (this.enabled) { + this.enabled = false; this.game.input.removeGameObject(this.indexID); } @@ -578,7 +579,9 @@ module Phaser.Components.Sprite { if (this.dragFromCenter) { // Move the sprite to the middle of the pointer - this._dragPoint.setTo(-this.sprite.worldView.halfWidth, -this.sprite.worldView.halfHeight); + //this._dragPoint.setTo(-this.sprite.worldView.halfWidth, -this.sprite.worldView.halfHeight); + //this._dragPoint.setTo(this.sprite.transform.center.x, this.sprite.transform.center.y); + this._dragPoint.setTo(this.sprite.x - pointer.x, this.sprite.y - pointer.y); } else { diff --git a/Phaser/core/Group.ts b/Phaser/core/Group.ts index 252962bb..8d1633ce 100644 --- a/Phaser/core/Group.ts +++ b/Phaser/core/Group.ts @@ -527,6 +527,8 @@ module Phaser { */ public remove(object, splice: bool = false) { + console.log('removing from group'); + this._i = this.members.indexOf(object); if (this._i < 0 || (this._i >= this.members.length)) @@ -544,6 +546,8 @@ module Phaser { this.members[this._i] = null; } + console.log('nulled'); + if (object['events']) { object['events'].onRemovedFromGroup.dispatch(object, this); @@ -615,7 +619,7 @@ module Phaser { public bringToTop(child): bool { // If child not in this group, or is already at the top of the group, return false - if (child.group.ID != this.ID || child.z == this._zCounter) + if (!child || child.group == null || child.group.ID != this.ID || child.z == this._zCounter) { return false; } diff --git a/Phaser/gameobjects/Tilemap.ts b/Phaser/gameobjects/Tilemap.ts index f7d2bc4c..14408fb6 100644 --- a/Phaser/gameobjects/Tilemap.ts +++ b/Phaser/gameobjects/Tilemap.ts @@ -229,6 +229,12 @@ module Phaser { { var layer: TilemapLayer = new TilemapLayer(this.game, this, key, Tilemap.FORMAT_TILED_JSON, json.layers[i].name, json.tilewidth, json.tileheight); + // Check it's a data layer + if (!json.layers[i].data) + { + continue; + } + layer.alpha = json.layers[i].opacity; layer.visible = json.layers[i].visible; layer.tileMargin = json.tilesets[0].margin; diff --git a/Phaser/input/Input.ts b/Phaser/input/Input.ts index 26231fee..6702aad9 100644 --- a/Phaser/input/Input.ts +++ b/Phaser/input/Input.ts @@ -507,6 +507,7 @@ module Phaser { if (this.inputObjects[index]) { + console.log('object removed from the input manager', index); this.inputObjects[index] = null; } diff --git a/Phaser/physics/advanced/Body.ts b/Phaser/physics/advanced/Body.ts index 0de64724..41bd828a 100644 --- a/Phaser/physics/advanced/Body.ts +++ b/Phaser/physics/advanced/Body.ts @@ -143,6 +143,9 @@ module Phaser.Physics.Advanced { // Shapes public shapes: IShape[] = []; + // Length of the shapes array + public shapesLength: number; + // Joints public joints: IJoint[] = []; public jointHash = {}; @@ -163,7 +166,7 @@ module Phaser.Physics.Advanced { public duplicate() { - //console.log('body duplicate called'); + console.log('body duplicate called'); //var body = new Body(this.type, this.transform.t, this.angle); @@ -274,6 +277,8 @@ module Phaser.Physics.Advanced { this.shapes.push(shape); + this.shapesLength = this.shapes.length; + return shape; } @@ -288,8 +293,9 @@ module Phaser.Physics.Advanced { shape.body = undefined; } - } + this.shapesLength = this.shapes.length; + } private setMass(mass) { @@ -307,8 +313,8 @@ module Phaser.Physics.Advanced { public setTransform(pos, angle) { - this.transform.setTo(pos, angle); // inject the transform into this.position + this.transform.setTo(pos, angle); Manager.write('setTransform: ' + this.position.toString()); Manager.write('centroid: ' + this.centroid.toString()); Phaser.TransformUtils.transform(this.transform, this.centroid, this.position); @@ -399,20 +405,14 @@ module Phaser.Physics.Advanced { if (!this.fixedRotation) { - //this.setInertia(totalInertia - totalMass * vec2.dot(this.centroid, this.centroid)); this.setInertia(totalInertia - totalMass * Phaser.Vec2Utils.dot(this.centroid, this.centroid)); } - //console.log("mass = " + this.m + " inertia = " + this.i); - // Move center of mass var oldPosition: Phaser.Vec2 = Phaser.Vec2Utils.clone(this.position); - //this.position.copyFrom(this.transform.transform(this.centroid)); Phaser.TransformUtils.transform(this.transform, this.centroid, this.position); // Update center of mass velocity - - //this.velocity.mad(vec2.perp(vec2.sub(this.position, old_p)), this.angularVelocity); oldPosition.subtract(this.position); this.velocity.multiplyAddByScalar(Phaser.Vec2Utils.perp(oldPosition, oldPosition), this.angularVelocity); @@ -462,7 +462,6 @@ module Phaser.Physics.Advanced { public updateVelocity(gravity, dt, damping) { - // this.velocity = vec2.mad(this.velocity, vec2.mad(gravity, this.force, this.massInverted), dt); Phaser.Vec2Utils.multiplyAdd(gravity, this.force, this.massInverted, this._tempVec2); Phaser.Vec2Utils.multiplyAdd(this.velocity, this._tempVec2, dt, this.velocity); @@ -513,17 +512,10 @@ module Phaser.Physics.Advanced { return v < min ? min : (v > max ? max : v); } - public updatePosition(dt) { + public updatePosition(dt:number) { - //console.log('body update pos', this.position.y); - //console.log('pre add temp', this._tempVec2.y); - - //this.position.addself(vec2.scale(this.velocity, dt)); this.position.add(Phaser.Vec2Utils.scale(this.velocity, dt, this._tempVec2)); - //console.log('post add temp', this._tempVec2.y); - //console.log('post add', this.position.y); - this.angle += this.angularVelocity * dt; } @@ -547,10 +539,8 @@ module Phaser.Physics.Advanced { this.force.add(force); - // this.f.addself(force); - // this.torque += vec2.cross(vec2.sub(p, this.p), force); - Phaser.Vec2Utils.subtract(p, this.position, this._tempVec2); + this.torque += Phaser.Vec2Utils.cross(this._tempVec2, force); } @@ -601,8 +591,6 @@ module Phaser.Physics.Advanced { this.velocity.multiplyAddByScalar(impulse, this.massInverted); - // this.angularVelocity += vec2.cross(vec2.sub(p, this.position), impulse) * this.inertiaInverted; - Phaser.Vec2Utils.subtract(p, this.position, this._tempVec2); this.angularVelocity += Phaser.Vec2Utils.cross(this._tempVec2, impulse) * this.inertiaInverted; diff --git a/Phaser/physics/advanced/Manager.ts b/Phaser/physics/advanced/Manager.ts index f7b3a6d0..7fa322d8 100644 --- a/Phaser/physics/advanced/Manager.ts +++ b/Phaser/physics/advanced/Manager.ts @@ -36,7 +36,7 @@ module Phaser.Physics.Advanced { } public static write(s: string) { - //Manager.debug.textContent += s + "\n"; + Manager.debug.textContent += s + "\n"; } public static writeAll() { @@ -119,10 +119,10 @@ module Phaser.Physics.Advanced { public lastTime: number = Date.now(); public frameRateHz: number = 60; public timeDelta: number = 0; - public paused: bool = false; - public step: bool = false; // step through the simulation (i.e. per click) - //public paused: bool = true; + //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; @@ -170,12 +170,6 @@ module Phaser.Physics.Advanced { { this.timeDelta = 0; } - - //if (sceneIndex < demoArr.length) - //{ - // demo = demoArr[sceneIndex]; - // demo.runFrame(); - //} } //frameCount++; diff --git a/Phaser/physics/advanced/Space.ts b/Phaser/physics/advanced/Space.ts index a83f17be..4eecf70e 100644 --- a/Phaser/physics/advanced/Space.ts +++ b/Phaser/physics/advanced/Space.ts @@ -20,33 +20,61 @@ module Phaser.Physics.Advanced { constructor() { - this.bodyArr = []; + this.bodies = []; this.bodyHash = {}; - this.jointArr = []; + this.joints = []; this.jointHash = {}; this.numContacts = 0; this.contactSolvers = []; - //this.postSolve(arb) { }; - this.gravity = new Phaser.Vec2(0, 10); this.damping = 0; + this._linTolSqr = Space.SLEEP_LINEAR_TOLERANCE * Space.SLEEP_LINEAR_TOLERANCE; + this._angTolSqr = Space.SLEEP_ANGULAR_TOLERANCE * Space.SLEEP_ANGULAR_TOLERANCE; + } + // Delta Timer + private _delta: number; + private _deltaInv: number; + + // Body array length + private _bl: number; + + // Joints array length + private _jl: number; + + // Contact Solvers array length + private _cl: number; + + private _linTolSqr: number; + private _angTolSqr: number; + + // Minimum sleep time (used in the sleep process solver) + private _minSleepTime: number; + + private _positionSolved: bool; + + private _shape1: IShape; + private _shape2: IShape; + private _contactsOk: bool; + private _jointsOk: bool; + + private bodyHash; + private jointHash; + public static TIME_TO_SLEEP = 0.5; public static SLEEP_LINEAR_TOLERANCE = 0.5; public static SLEEP_ANGULAR_TOLERANCE = 2 * Phaser.GameMath.DEG_TO_RAD; - public bodyArr: Body[]; - public bodyHash; - public jointArr: IJoint[]; - public jointHash; + public bodies: Body[]; + public joints: IJoint[]; public numContacts: number; public contactSolvers: ContactSolver[]; - public postSolve; + public postSolve = null; public gravity: Phaser.Vec2; public damping: number; public stepCount: number = 0; @@ -57,18 +85,18 @@ module Phaser.Physics.Advanced { Manager.bodyCounter = 0; Manager.jointCounter = 0; - for (var i = 0; i < this.bodyArr.length; i++) + for (var i = 0; i < this.bodies.length; i++) { - if (this.bodyArr[i]) + if (this.bodies[i]) { - this.removeBody(this.bodyArr[i]); + this.removeBody(this.bodies[i]); } } - this.bodyArr = []; + this.bodies = []; this.bodyHash = {}; - this.jointArr = []; + this.joints = []; this.jointHash = {}; this.contactSolvers = []; @@ -84,7 +112,7 @@ module Phaser.Physics.Advanced { return; } - var index = this.bodyArr.push(body) - 1; + var index = this.bodies.push(body) - 1; this.bodyHash[body.id] = index; body.awake(true); @@ -100,7 +128,7 @@ module Phaser.Physics.Advanced { return; } - // Remove linked joint + // Remove linked joints for (var i = 0; i < body.joints.length; i++) { if (body.joints[i]) @@ -113,7 +141,7 @@ module Phaser.Physics.Advanced { var index = this.bodyHash[body.id]; delete this.bodyHash[body.id]; - delete this.bodyArr[index]; + delete this.bodies[index]; } @@ -127,7 +155,7 @@ module Phaser.Physics.Advanced { joint.body1.awake(true); joint.body2.awake(true); - var index = this.jointArr.push(joint) - 1; + var index = this.joints.push(joint) - 1; this.jointHash[joint.id] = index; var index = joint.body1.joints.push(joint) - 1; @@ -158,7 +186,7 @@ module Phaser.Physics.Advanced { var index = this.jointHash[joint.id]; delete this.jointHash[joint.id]; - delete this.jointArr[index]; + delete this.joints[index]; } @@ -166,9 +194,9 @@ module Phaser.Physics.Advanced { var firstShape; - for (var i = 0; i < this.bodyArr.length; i++) + for (var i = 0; i < this.bodies.length; i++) { - var body = this.bodyArr[i]; + var body = this.bodies[i]; if (!body) { @@ -206,9 +234,9 @@ module Phaser.Physics.Advanced { var firstBody; - for (var i = 0; i < this.bodyArr.length; i++) + for (var i = 0; i < this.bodies.length; i++) { - var body = this.bodyArr[i]; + var body = this.bodies[i]; if (!body) { @@ -245,14 +273,14 @@ module Phaser.Physics.Advanced { } - // TODO: Replace this function to shape hashing public shapeById(id) { var shape; - for (var i = 0; i < this.bodyArr.length; i++) + for (var i = 0; i < this.bodies.length; i++) { - var body = this.bodyArr[i]; + var body: Body = this.bodies[i]; + if (!body) { continue; @@ -276,7 +304,7 @@ module Phaser.Physics.Advanced { if (index != undefined) { - return this.jointArr[index]; + return this.joints[index]; } return null; @@ -288,9 +316,9 @@ module Phaser.Physics.Advanced { refVertexId = refVertexId || -1; - for (var i = 0; i < this.bodyArr.length; i++) + for (var i = 0; i < this.bodies.length; i++) { - var body = this.bodyArr[i]; + var body = this.bodies[i]; if (!body) { @@ -334,9 +362,9 @@ module Phaser.Physics.Advanced { refEdgeId = refEdgeId || -1; - for (var i = 0; i < this.bodyArr.length; i++) + for (var i = 0; i < this.bodies.length; i++) { - var body = this.bodyArr[i]; + var body = this.bodies[i]; if (!body) { @@ -387,9 +415,9 @@ module Phaser.Physics.Advanced { refJointId = refJointId || -1; - for (var i = 0; i < this.jointArr.length; i++) + for (var i = 0; i < this.joints.length; i++) { - var joint = this.jointArr[i]; + var joint = this.joints[i]; if (!joint) { @@ -429,13 +457,13 @@ module Phaser.Physics.Advanced { return firstJointId; } - public findContactSolver(shape1, shape2) { + private findContactSolver(shape1:IShape, shape2:IShape):ContactSolver { - Manager.write('findContactSolver. Length: ' + this.contactSolvers.length); + Manager.write('findContactSolver. Length: ' + this._cl); - for (var i = 0; i < this.contactSolvers.length; i++) + for (var i = 0; i < this._cl; i++) { - var contactSolver = this.contactSolvers[i]; + var contactSolver: ContactSolver = this.contactSolvers[i]; if (shape1 == contactSolver.shape1 && shape2 == contactSolver.shape2) { @@ -444,363 +472,346 @@ module Phaser.Physics.Advanced { } return null; + } - public genTemporalContactSolvers() { + private genTemporalContactSolvers() { Manager.write('genTemporalContactSolvers'); - var newContactSolverArr = []; - var bl: number = this.bodyArr.length; - + this._cl = 0; + this.contactSolvers.length = 0; this.numContacts = 0; - for (var body1_index = 0; body1_index < bl; body1_index++) + for (var body1Index = 0; body1Index < this._bl; body1Index++) { - var body1: Body = this.bodyArr[body1_index]; - - if (!body1) + if (!this.bodies[body1Index]) { continue; } - body1.stepCount = this.stepCount; + this.bodies[body1Index].stepCount = this.stepCount; - for (var body2_index = 0; body2_index < bl; body2_index++) + for (var body2Index = 0; body2Index < this._bl; body2Index++) { - var body2: Body = this.bodyArr[body2_index]; - - if (body1.inContact(body2) == false) + if (this.bodies[body1Index].inContact(this.bodies[body2Index]) == false) { continue; } Manager.write('body1 and body2 intersect'); - for (var i = 0; i < body1.shapes.length; i++) + for (var i = 0; i < this.bodies[body1Index].shapesLength; i++) { - for (var j = 0; j < body2.shapes.length; j++) + for (var j = 0; j < this.bodies[body2Index].shapesLength; j++) { - var shape1 = body1.shapes[i]; - var shape2 = body2.shapes[j]; + this._shape1 = this.bodies[body1Index].shapes[i]; + this._shape2 = this.bodies[body2Index].shapes[j]; var contactArr = []; - if (!Manager.collision.collide(shape1, shape2, contactArr)) + if (!Manager.collision.collide(this._shape1, this._shape2, contactArr)) { continue; } - if (shape1.type > shape2.type) + if (this._shape1.type > this._shape2.type) { - var temp = shape1; - shape1 = shape2; - shape2 = temp; + var temp = this._shape1; + this._shape1 = this._shape2; + this._shape2 = temp; } this.numContacts += contactArr.length; - var contactSolver = this.findContactSolver(shape1, shape2); + // Result stored in this._contactSolver (see what we can do about generating some re-usable solvers) + var contactSolver: ContactSolver = this.findContactSolver(this._shape1, this._shape2); Manager.write('findContactSolver result: ' + contactSolver); if (contactSolver) { contactSolver.update(contactArr); - newContactSolverArr.push(contactSolver); + this.contactSolvers.push(contactSolver); } else { Manager.write('awake both bodies'); - body1.awake(true); - body2.awake(true); + this.bodies[body1Index].awake(true); + this.bodies[body2Index].awake(true); - var newContactSolver = new ContactSolver(shape1, shape2); + var newContactSolver = new ContactSolver(this._shape1, this._shape2); newContactSolver.contacts = contactArr; - newContactSolver.elasticity = Math.max(shape1.elasticity, shape2.elasticity); - newContactSolver.friction = Math.sqrt(shape1.friction * shape2.friction); - newContactSolverArr.push(newContactSolver); + newContactSolver.elasticity = Math.max(this._shape1.elasticity, this._shape2.elasticity); + newContactSolver.friction = Math.sqrt(this._shape1.friction * this._shape2.friction); + + this.contactSolvers.push(newContactSolver); Manager.write('new contact solver'); - //console.log(newContactSolver); } } } } } - return newContactSolverArr; + this._cl = this.contactSolvers.length; } - public initSolver(dt, dt_inv, warmStarting) { + private initSolver(warmStarting) { Manager.write('initSolver'); - Manager.write('contactSolvers.length: ' + this.contactSolvers.length); - - //var t0 = Date.now(); + Manager.write('contactSolvers.length: ' + this._cl); // Initialize contact solvers - for (var i = 0; i < this.contactSolvers.length; i++) + for (var c = 0; c < this._cl; c++) { - this.contactSolvers[i].initSolver(dt_inv); + this.contactSolvers[c].initSolver(this._deltaInv); + + // Warm starting (apply cached impulse) + if (warmStarting) + { + this.contactSolvers[c].warmStart(); + } + } // Initialize joint solver - for (var i = 0; i < this.jointArr.length; i++) + for (var j = 0; j < this.joints.length; j++) { - if (this.jointArr[i]) + if (this.joints[j]) { - this.jointArr[i].initSolver(dt, warmStarting); + this.joints[j].initSolver(this._delta, warmStarting); } } // Warm starting (apply cached impulse) + /* if (warmStarting) { - for (var i = 0; i < this.contactSolvers.length; i++) + for (var c = 0; c < this._cl; c++) { - this.contactSolvers[i].warmStart(); + this.contactSolvers[c].warmStart(); } } + */ - //stats.timeInitSolver = Date.now() - t0; } - public velocitySolver(iteration) { + private velocitySolver(iterations:number) { - Manager.write('velocitySolver, iterations: ' + iteration + ' csa len: ' + this.contactSolvers.length); + Manager.write('velocitySolver, iterations: ' + iterations + ' csa len: ' + this._cl); - //var t0 = Date.now(); - - for (var i = 0; i < iteration; i++) + for (var i = 0; i < iterations; i++) { - for (var j = 0; j < this.jointArr.length; j++) + for (var j = 0; j < this._jl; j++) { - if (this.jointArr[j]) + if (this.joints[j]) { - this.jointArr[j].solveVelocityConstraints(); + this.joints[j].solveVelocityConstraints(); } } - for (var j = 0; j < this.contactSolvers.length; j++) + for (var c = 0; c < this._cl; c++) { - this.contactSolvers[j].solveVelocityConstraints(); + this.contactSolvers[c].solveVelocityConstraints(); } } } - public positionSolver(iteration) { + private positionSolver(iterations:number):bool { - var positionSolved = false; + this._positionSolved = false; - for (var i = 0; i < iteration; i++) + for (var i = 0; i < iterations; i++) { - var contactsOk = true; - var jointsOk = true; + this._contactsOk = true; + this._jointsOk = true; - for (var j = 0; j < this.contactSolvers.length; j++) + for (var c = 0; c < this._cl; c++) { - var contactOk = this.contactSolvers[j].solvePositionConstraints(); - contactsOk = contactOk && contactsOk; + this._contactsOk = this.contactSolvers[c].solvePositionConstraints() && this._contactsOk; } - for (var j = 0; j < this.jointArr.length; j++) + for (var j = 0; j < this._jl; j++) { - if (this.jointArr[j]) + if (this.joints[j]) { - var jointOk = this.jointArr[j].solvePositionConstraints(); - jointsOk = jointOk && jointsOk; + this._jointsOk = this.joints[j].solvePositionConstraints() && this._jointsOk; } } - if (contactsOk && jointsOk) + if (this._contactsOk && this._jointsOk) { // exit early if the position errors are small - positionSolved = true; + this._positionSolved = true; break; } } - return positionSolved; + return this._positionSolved; } - - - public step(dt, vel_iteration, pos_iteration, warmStarting, allowSleep) { + // Step through the physics simulation + public step(dt: number, velocityIterations: number, positionIterations: number, warmStarting: bool, allowSleep: bool) { 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._delta = dt; + this._deltaInv = 1 / dt; + this._bl = this.bodies.length; + this._jl = this.joints.length; this.stepCount++; - // 1) Generate Contact Solvers - this.contactSolvers = this.genTemporalContactSolvers(); + // 1) Generate Contact Solvers (into the this.contactSolvers array) + this.genTemporalContactSolvers(); - Manager.dump("Contact Solvers", this.bodyArr[1]); + Manager.dump("Contact Solvers", this.bodies[1]); // 2) Initialize the Contact Solvers - this.initSolver(dt, dt_inv, warmStarting); + this.initSolver(warmStarting); - Manager.dump("Init Solver", this.bodyArr[1]); + Manager.dump("Init Solver", this.bodies[1]); // 3) Intergrate velocity - for (var i = 0; i < bl; i++) + for (var i = 0; i < this._bl; i++) { - if (this.bodyArr[i] && this.bodyArr[i].isDynamic && this.bodyArr[i].isAwake) + if (this.bodies[i] && this.bodies[i].isDynamic && this.bodies[i].isAwake) { - this.bodyArr[i].updateVelocity(this.gravity, dt, this.damping); + this.bodies[i].updateVelocity(this.gravity, this._delta, this.damping); } } - Manager.dump("Update Velocity", this.bodyArr[1]); + Manager.dump("Update Velocity", this.bodies[1]); - /* - // 4) Awaken bodies - for (var j = 0; i < jl; j++) + // 4) Awaken bodies via joints + for (var j = 0; i < this._jl; j++) { - var joint = this.jointArr[j]; - - if (!joint) + if (!this.joints[j]) { continue; } - var body1 = joint.body1; - var body2 = joint.body2; - - var awake1 = body1.isAwake && !body1.isStatic; - var awake2 = body2.isAwake && !body2.isStatic; + // combine + var awake1 = this.joints[j].body1.isAwake && !this.joints[j].body1.isStatic; + var awake2 = this.joints[j].body2.isAwake && !this.joints[j].body2.isStatic; if (awake1 ^ awake2) { if (!awake1) { - body1.awake(true); + this.joints[j].body1.awake(true); } - + if (!awake2) { - body2.awake(true); + this.joints[j].body2.awake(true); } } } - */ // 5) Iterative velocity constraints solver - this.velocitySolver(vel_iteration); + this.velocitySolver(velocityIterations); - Manager.dump("Velocity Solvers", this.bodyArr[1]); + Manager.dump("Velocity Solvers", this.bodies[1]); // 6) Intergrate position - for (var i = 0; i < bl; i++) + for (var i = 0; i < this._bl; i++) { - if (this.bodyArr[i] && this.bodyArr[i].isDynamic && this.bodyArr[i].isAwake) + if (this.bodies[i] && this.bodies[i].isDynamic && this.bodies[i].isAwake) { - this.bodyArr[i].updatePosition(dt); + this.bodies[i].updatePosition(this._delta); } } - Manager.dump("Update Position", this.bodyArr[1]); + Manager.dump("Update Position", this.bodies[1]); // 7) Process breakable joint - for (var i = 0; i < jl; i++) + for (var i = 0; i < this._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)) + if (this.joints[i] && this.joints[i].breakable && (this.joints[i].getReactionForce(this._deltaInv).lengthSq() >= this.joints[i].maxForce * this.joints[i].maxForce)) { - this.removeJoint(this.jointArr[i]); + this.removeJoint(this.joints[i]); } } - // 8) Iterative position constraints solver - var positionSolved = this.positionSolver(pos_iteration); + // 8) Iterative position constraints solver (result stored in this._positionSolved) + this.positionSolver(positionIterations); - Manager.dump("Position Solver", this.bodyArr[1]); + Manager.dump("Position Solver", this.bodies[1]); // 9) Sync the Transforms - for (var i = 0; i < bl; i++) + for (var i = 0; i < this._bl; i++) { - if (this.bodyArr[i]) + if (this.bodies[i]) { - this.bodyArr[i].syncTransform(); + this.bodies[i].syncTransform(); } } - Manager.dump("Sync Transform", this.bodyArr[1]); + Manager.dump("Sync Transform", this.bodies[1]); // 10) Post solve collision callback - for (var i = 0; i < this.contactSolvers.length; i++) + if (this.postSolve) { - var arb = this.contactSolvers[i]; - // Re-enable this - //this.postSolve(arb); + for (var i = 0; i < this._cl; i++) + { + this.postSolve(this.contactSolvers[i]); + } } // 11) Cache Body Data - for (var i = 0; i < bl; i++) + for (var i = 0; i < this._bl; i++) { - if (this.bodyArr[i] && this.bodyArr[i].isDynamic && this.bodyArr[i].isAwake) + if (this.bodies[i] && this.bodies[i].isDynamic && this.bodies[i].isAwake) { - this.bodyArr[i].cacheData('post solve collision callback'); + this.bodies[i].cacheData('post solve collision callback'); } } - Manager.dump("Cache Data", this.bodyArr[1]); + Manager.dump("Cache Data", this.bodies[1]); Manager.writeAll(); // 12) Process sleeping - /* if (allowSleep) { - var minSleepTime = 999999; + this._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++) + for (var i = 0; i < this._bl; i++) { - var body = this.bodyArr[i]; - - if (!this.bodyArr[i] || this.bodyArr[i].isDynamic == false) + if (!this.bodies[i] || this.bodies[i].isDynamic == false) { continue; } - if (body.angularVelocity * body.angularVelocity > angTolSqr || body.velocity.dot(body.velocity) > linTolSqr) + if (this.bodies[i].angularVelocity * this.bodies[i].angularVelocity > this._angTolSqr || this.bodies[i].velocity.dot(this.bodies[i].velocity) > this._linTolSqr) { - body.sleepTime = 0; - minSleepTime = 0; + this.bodies[i].sleepTime = 0; + this._minSleepTime = 0; } else { - body.sleepTime += dt; - minSleepTime = Math.min(minSleepTime, body.sleepTime); + this.bodies[i].sleepTime += this._delta; + this._minSleepTime = Math.min(this._minSleepTime, this.bodies[i].sleepTime); } } - if (positionSolved && minSleepTime >= Space.TIME_TO_SLEEP) + if (this._positionSolved && this._minSleepTime >= Space.TIME_TO_SLEEP) { - for (var i = 0; i < this.bodyArr.length; i++) + for (var i = 0; i < this._bl; i++) { - var body = this.bodyArr[i]; - - if (!body) + if (this.bodies[i]) { - continue; + this.bodies[i].awake(false); } - - body.awake(false); } } } - */ } } diff --git a/README.md b/README.md index 6d5fe091..bd59ca53 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,10 @@ TODO: * Add clip support + shape options to Texture Component. * Make sure I'm using Point and not Vec2 when it's not a directional vector I need * Bug with setting scale or anything on a Sprite inside a Group, or maybe group.addNewSprite issue +* Drag Sprite with "snap to center" uses local coords not world, so fails on scrolling world (no center lock works fine) +* Need to be able to set the current tilemap layer, then the getTileXY default layer uses that one if no other given +* Pointer worldX/Y don't appear to be correct for some reason + * Sprite collision events * See which functions in the input component can move elsewhere (utils) @@ -117,6 +121,9 @@ V1.0.0 * Added Cache.getImageKeys (and similar) to return an array of all the keys for all currently cached objects. * Added Group.bringToTop feature. Will sort the Group, move the given sprites z-index to the top and shift the rest down by one. * Brand new Advanced Physics system added and working! Woohoo :) +* Fixed issue in Tilemap.parseTiledJSON where it would accidentally think image and object layers were map data. +* Fixed bug in Group.bringToTop if the child didn't have a group property yet. +* Fixed bug in FrameData.checkFrameName where the first index of the _frameNames array would be skipped. diff --git a/Tests/phaser.js b/Tests/phaser.js index ae3e1c09..96d3a9b8 100644 --- a/Tests/phaser.js +++ b/Tests/phaser.js @@ -2539,10 +2539,10 @@ var Phaser; * @return {boolean} True if frame with given name found, otherwise return false. */ function (name) { - if(this._frameNames[name]) { - return true; + if(this._frameNames[name] == null) { + return false; } - return false; + return true; }; FrameData.prototype.getFrameRange = /** * Get ranges of frames in an array. @@ -3534,6 +3534,7 @@ var Phaser; */ function () { if(this.enabled) { + this.enabled = false; this.game.input.removeGameObject(this.indexID); } }; @@ -3766,7 +3767,9 @@ var Phaser; this._pointerData[pointer.id].isDragged = true; if(this.dragFromCenter) { // Move the sprite to the middle of the pointer - this._dragPoint.setTo(-this.sprite.worldView.halfWidth, -this.sprite.worldView.halfHeight); + //this._dragPoint.setTo(-this.sprite.worldView.halfWidth, -this.sprite.worldView.halfHeight); + //this._dragPoint.setTo(this.sprite.transform.center.x, this.sprite.transform.center.y); + this._dragPoint.setTo(this.sprite.x - pointer.x, this.sprite.y - pointer.y); } else { this._dragPoint.setTo(this.sprite.x - pointer.x, this.sprite.y - pointer.y); } @@ -5516,6 +5519,7 @@ var Phaser; */ function (object, splice) { if (typeof splice === "undefined") { splice = false; } + console.log('removing from group'); this._i = this.members.indexOf(object); if(this._i < 0 || (this._i >= this.members.length)) { return null; @@ -5526,6 +5530,7 @@ var Phaser; } else { this.members[this._i] = null; } + console.log('nulled'); if(object['events']) { object['events'].onRemovedFromGroup.dispatch(object, this); } @@ -5575,7 +5580,7 @@ var Phaser; }; Group.prototype.bringToTop = function (child) { // If child not in this group, or is already at the top of the group, return false - if(child.group.ID != this.ID || child.z == this._zCounter) { + if(!child || child.group == null || child.group.ID != this.ID || child.z == this._zCounter) { return false; } this.sort(); @@ -10716,6 +10721,10 @@ var Phaser; var json = JSON.parse(data); for(var i = 0; i < json.layers.length; i++) { var layer = new Phaser.TilemapLayer(this.game, this, key, Tilemap.FORMAT_TILED_JSON, json.layers[i].name, json.tilewidth, json.tileheight); + // Check it's a data layer + if(!json.layers[i].data) { + continue; + } layer.alpha = json.layers[i].opacity; layer.visible = json.layers[i].visible; layer.tileMargin = json.tilesets[0].margin; @@ -16166,6 +16175,7 @@ var Phaser; **/ function (index) { if(this.inputObjects[index]) { + console.log('object removed from the input manager', index); this.inputObjects[index] = null; } }; @@ -19155,11 +19165,11 @@ var Phaser; this.lastTime = Date.now(); this.frameRateHz = 60; this.timeDelta = 0; - this.paused = false; + //public paused: bool = false; + //public step: bool = false; // step through the simulation (i.e. per click) + this.paused = true; 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; @@ -19175,8 +19185,8 @@ var Phaser; Manager.log = []; }; Manager.write = function write(s) { - //Manager.debug.textContent += s + "\n"; - }; + Manager.debug.textContent += s + "\n"; + }; Manager.writeAll = function writeAll() { for(var i = 0; i < Manager.log.length; i++) { //Manager.debug.textContent += Manager.log[i]; @@ -19263,12 +19273,7 @@ var Phaser; if(this.timeDelta > h) { this.timeDelta = 0; } - //if (sceneIndex < demoArr.length) - //{ - // demo = demoArr[sceneIndex]; - // demo.runFrame(); - //} - } + } //frameCount++; }; Manager.prototype.pixelsToMeters = function (value) { @@ -20803,10 +20808,10 @@ var Phaser; var Space = (function () { function Space() { this.stepCount = 0; - this.bodyArr = []; + this.bodies = []; this.bodyHash = { }; - this.jointArr = []; + this.joints = []; this.jointHash = { }; this.numContacts = 0; @@ -20814,6 +20819,8 @@ var Phaser; //this.postSolve(arb) { }; this.gravity = new Phaser.Vec2(0, 10); this.damping = 0; + this._linTolSqr = Space.SLEEP_LINEAR_TOLERANCE * Space.SLEEP_LINEAR_TOLERANCE; + this._angTolSqr = Space.SLEEP_ANGULAR_TOLERANCE * Space.SLEEP_ANGULAR_TOLERANCE; } Space.TIME_TO_SLEEP = 0.5; Space.SLEEP_LINEAR_TOLERANCE = 0.5; @@ -20822,15 +20829,15 @@ var Phaser; Advanced.Manager.shapeCounter = 0; Advanced.Manager.bodyCounter = 0; Advanced.Manager.jointCounter = 0; - for(var i = 0; i < this.bodyArr.length; i++) { - if(this.bodyArr[i]) { - this.removeBody(this.bodyArr[i]); + for(var i = 0; i < this.bodies.length; i++) { + if(this.bodies[i]) { + this.removeBody(this.bodies[i]); } } - this.bodyArr = []; + this.bodies = []; this.bodyHash = { }; - this.jointArr = []; + this.joints = []; this.jointHash = { }; this.contactSolvers = []; @@ -20840,7 +20847,7 @@ var Phaser; if(this.bodyHash[body.id] != undefined) { return; } - var index = this.bodyArr.push(body) - 1; + var index = this.bodies.push(body) - 1; this.bodyHash[body.id] = index; body.awake(true); body.space = this; @@ -20850,7 +20857,7 @@ var Phaser; if(this.bodyHash[body.id] == undefined) { return; } - // Remove linked joint + // Remove linked joints for(var i = 0; i < body.joints.length; i++) { if(body.joints[i]) { this.removeJoint(body.joints[i]); @@ -20859,7 +20866,7 @@ var Phaser; body.space = null; var index = this.bodyHash[body.id]; delete this.bodyHash[body.id]; - delete this.bodyArr[index]; + delete this.bodies[index]; }; Space.prototype.addJoint = function (joint) { if(this.jointHash[joint.id] != undefined) { @@ -20867,7 +20874,7 @@ var Phaser; } joint.body1.awake(true); joint.body2.awake(true); - var index = this.jointArr.push(joint) - 1; + var index = this.joints.push(joint) - 1; this.jointHash[joint.id] = index; var index = joint.body1.joints.push(joint) - 1; joint.body1.jointHash[joint.id] = index; @@ -20888,12 +20895,12 @@ var Phaser; delete joint.body2.joints[index]; var index = this.jointHash[joint.id]; delete this.jointHash[joint.id]; - delete this.jointArr[index]; + delete this.joints[index]; }; Space.prototype.findShapeByPoint = function (p, refShape) { var firstShape; - for(var i = 0; i < this.bodyArr.length; i++) { - var body = this.bodyArr[i]; + for(var i = 0; i < this.bodies.length; i++) { + var body = this.bodies[i]; if(!body) { continue; } @@ -20916,8 +20923,8 @@ var Phaser; }; Space.prototype.findBodyByPoint = function (p, refBody) { var firstBody; - for(var i = 0; i < this.bodyArr.length; i++) { - var body = this.bodyArr[i]; + for(var i = 0; i < this.bodies.length; i++) { + var body = this.bodies[i]; if(!body) { continue; } @@ -20939,11 +20946,10 @@ var Phaser; } return firstBody; }; - Space.prototype.shapeById = // TODO: Replace this function to shape hashing - function (id) { + Space.prototype.shapeById = function (id) { var shape; - for(var i = 0; i < this.bodyArr.length; i++) { - var body = this.bodyArr[i]; + for(var i = 0; i < this.bodies.length; i++) { + var body = this.bodies[i]; if(!body) { continue; } @@ -20958,15 +20964,15 @@ var Phaser; Space.prototype.jointById = function (id) { var index = this.jointHash[id]; if(index != undefined) { - return this.jointArr[index]; + return this.joints[index]; } return null; }; Space.prototype.findVertexByPoint = function (p, minDist, refVertexId) { var firstVertexId = -1; refVertexId = refVertexId || -1; - for(var i = 0; i < this.bodyArr.length; i++) { - var body = this.bodyArr[i]; + for(var i = 0; i < this.bodies.length; i++) { + var body = this.bodies[i]; if(!body) { continue; } @@ -20992,8 +20998,8 @@ var Phaser; Space.prototype.findEdgeByPoint = function (p, minDist, refEdgeId) { var firstEdgeId = -1; refEdgeId = refEdgeId || -1; - for(var i = 0; i < this.bodyArr.length; i++) { - var body = this.bodyArr[i]; + for(var i = 0; i < this.bodies.length; i++) { + var body = this.bodies[i]; if(!body) { continue; } @@ -21023,8 +21029,8 @@ var Phaser; var firstJointId = -1; var dsq = minDist * minDist; refJointId = refJointId || -1; - for(var i = 0; i < this.jointArr.length; i++) { - var joint = this.jointArr[i]; + for(var i = 0; i < this.joints.length; i++) { + var joint = this.joints[i]; if(!joint) { continue; } @@ -21049,8 +21055,8 @@ 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++) { + Advanced.Manager.write('findContactSolver. Length: ' + this._cl); + for(var i = 0; i < this._cl; i++) { var contactSolver = this.contactSolvers[i]; if(shape1 == contactSolver.shape1 && shape2 == contactSolver.shape2) { return contactSolver; @@ -21060,255 +21066,221 @@ var Phaser; }; Space.prototype.genTemporalContactSolvers = function () { Advanced.Manager.write('genTemporalContactSolvers'); - var newContactSolverArr = []; - var bl = this.bodyArr.length; + this._cl = 0; + this.contactSolvers.length = 0; this.numContacts = 0; - for(var body1_index = 0; body1_index < bl; body1_index++) { - var body1 = this.bodyArr[body1_index]; - if(!body1) { + for(var body1Index = 0; body1Index < this._bl; body1Index++) { + if(!this.bodies[body1Index]) { continue; } - body1.stepCount = this.stepCount; - for(var body2_index = 0; body2_index < bl; body2_index++) { - var body2 = this.bodyArr[body2_index]; - if(body1.inContact(body2) == false) { + this.bodies[body1Index].stepCount = this.stepCount; + for(var body2Index = 0; body2Index < this._bl; body2Index++) { + if(this.bodies[body1Index].inContact(this.bodies[body2Index]) == false) { continue; } 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]; - var shape2 = body2.shapes[j]; + for(var i = 0; i < this.bodies[body1Index].shapesLength; i++) { + for(var j = 0; j < this.bodies[body2Index].shapesLength; j++) { + this._shape1 = this.bodies[body1Index].shapes[i]; + this._shape2 = this.bodies[body2Index].shapes[j]; var contactArr = []; - if(!Advanced.Manager.collision.collide(shape1, shape2, contactArr)) { + if(!Advanced.Manager.collision.collide(this._shape1, this._shape2, contactArr)) { continue; } - if(shape1.type > shape2.type) { - var temp = shape1; - shape1 = shape2; - shape2 = temp; + if(this._shape1.type > this._shape2.type) { + var temp = this._shape1; + this._shape1 = this._shape2; + this._shape2 = temp; } this.numContacts += contactArr.length; - var contactSolver = this.findContactSolver(shape1, shape2); + // Result stored in this._contactSolver (see what we can do about generating some re-usable solvers) + var contactSolver = this.findContactSolver(this._shape1, this._shape2); Advanced.Manager.write('findContactSolver result: ' + contactSolver); if(contactSolver) { contactSolver.update(contactArr); - newContactSolverArr.push(contactSolver); + this.contactSolvers.push(contactSolver); } else { Advanced.Manager.write('awake both bodies'); - body1.awake(true); - body2.awake(true); - var newContactSolver = new Advanced.ContactSolver(shape1, shape2); + this.bodies[body1Index].awake(true); + this.bodies[body2Index].awake(true); + var newContactSolver = new Advanced.ContactSolver(this._shape1, this._shape2); newContactSolver.contacts = contactArr; - newContactSolver.elasticity = Math.max(shape1.elasticity, shape2.elasticity); - newContactSolver.friction = Math.sqrt(shape1.friction * shape2.friction); - newContactSolverArr.push(newContactSolver); + newContactSolver.elasticity = Math.max(this._shape1.elasticity, this._shape2.elasticity); + newContactSolver.friction = Math.sqrt(this._shape1.friction * this._shape2.friction); + this.contactSolvers.push(newContactSolver); Advanced.Manager.write('new contact solver'); - //console.log(newContactSolver); - } + } } } } } - return newContactSolverArr; + this._cl = this.contactSolvers.length; }; - Space.prototype.initSolver = function (dt, dt_inv, warmStarting) { + Space.prototype.initSolver = function (warmStarting) { Advanced.Manager.write('initSolver'); - Advanced.Manager.write('contactSolvers.length: ' + this.contactSolvers.length); - //var t0 = Date.now(); + Advanced.Manager.write('contactSolvers.length: ' + this._cl); // Initialize contact solvers - for(var i = 0; i < this.contactSolvers.length; i++) { - this.contactSolvers[i].initSolver(dt_inv); + for(var c = 0; c < this._cl; c++) { + this.contactSolvers[c].initSolver(this._deltaInv); + // Warm starting (apply cached impulse) + if(warmStarting) { + this.contactSolvers[c].warmStart(); + } } // Initialize joint solver - for(var i = 0; i < this.jointArr.length; i++) { - if(this.jointArr[i]) { - this.jointArr[i].initSolver(dt, warmStarting); + for(var j = 0; j < this.joints.length; j++) { + if(this.joints[j]) { + this.joints[j].initSolver(this._delta, warmStarting); } } // Warm starting (apply cached impulse) - if(warmStarting) { - for(var i = 0; i < this.contactSolvers.length; i++) { - this.contactSolvers[i].warmStart(); - } + /* + if (warmStarting) + { + for (var c = 0; c < this._cl; c++) + { + this.contactSolvers[c].warmStart(); } - //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++) { - if(this.jointArr[j]) { - this.jointArr[j].solveVelocityConstraints(); + Space.prototype.velocitySolver = function (iterations) { + Advanced.Manager.write('velocitySolver, iterations: ' + iterations + ' csa len: ' + this._cl); + for(var i = 0; i < iterations; i++) { + for(var j = 0; j < this._jl; j++) { + if(this.joints[j]) { + this.joints[j].solveVelocityConstraints(); } } - for(var j = 0; j < this.contactSolvers.length; j++) { - this.contactSolvers[j].solveVelocityConstraints(); + for(var c = 0; c < this._cl; c++) { + this.contactSolvers[c].solveVelocityConstraints(); } } }; - Space.prototype.positionSolver = function (iteration) { - var positionSolved = false; - for(var i = 0; i < iteration; i++) { - var contactsOk = true; - var jointsOk = true; - for(var j = 0; j < this.contactSolvers.length; j++) { - var contactOk = this.contactSolvers[j].solvePositionConstraints(); - contactsOk = contactOk && contactsOk; + Space.prototype.positionSolver = function (iterations) { + this._positionSolved = false; + for(var i = 0; i < iterations; i++) { + this._contactsOk = true; + this._jointsOk = true; + for(var c = 0; c < this._cl; c++) { + this._contactsOk = this.contactSolvers[c].solvePositionConstraints() && this._contactsOk; } - for(var j = 0; j < this.jointArr.length; j++) { - if(this.jointArr[j]) { - var jointOk = this.jointArr[j].solvePositionConstraints(); - jointsOk = jointOk && jointsOk; + for(var j = 0; j < this._jl; j++) { + if(this.joints[j]) { + this._jointsOk = this.joints[j].solvePositionConstraints() && this._jointsOk; } } - if(contactsOk && jointsOk) { + if(this._contactsOk && this._jointsOk) { // exit early if the position errors are small - positionSolved = true; + this._positionSolved = true; break; } } - return positionSolved; + return this._positionSolved; }; - Space.prototype.step = function (dt, vel_iteration, pos_iteration, warmStarting, allowSleep) { + Space.prototype.step = // Step through the physics simulation + function (dt, velocityIterations, positionIterations, 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._delta = dt; + this._deltaInv = 1 / dt; + this._bl = this.bodies.length; + this._jl = this.joints.length; this.stepCount++; - // 1) Generate Contact Solvers - this.contactSolvers = this.genTemporalContactSolvers(); - Advanced.Manager.dump("Contact Solvers", this.bodyArr[1]); + // 1) Generate Contact Solvers (into the this.contactSolvers array) + this.genTemporalContactSolvers(); + Advanced.Manager.dump("Contact Solvers", this.bodies[1]); // 2) Initialize the Contact Solvers - this.initSolver(dt, dt_inv, warmStarting); - Advanced.Manager.dump("Init Solver", this.bodyArr[1]); + this.initSolver(warmStarting); + Advanced.Manager.dump("Init Solver", this.bodies[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._bl; i++) { + if(this.bodies[i] && this.bodies[i].isDynamic && this.bodies[i].isAwake) { + this.bodies[i].updateVelocity(this.gravity, this._delta, this.damping); } } - 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; + Advanced.Manager.dump("Update Velocity", this.bodies[1]); + // 4) Awaken bodies via joints + for(var j = 0; i < this._jl; j++) { + if(!this.joints[j]) { + continue; + } + // combine + var awake1 = this.joints[j].body1.isAwake && !this.joints[j].body1.isStatic; + var awake2 = this.joints[j].body2.isAwake && !this.joints[j].body2.isStatic; + if(awake1 ^ awake2) { + if(!awake1) { + this.joints[j].body1.awake(true); + } + if(!awake2) { + this.joints[j].body2.awake(true); + } + } } - - 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); - Advanced.Manager.dump("Velocity Solvers", this.bodyArr[1]); + this.velocitySolver(velocityIterations); + Advanced.Manager.dump("Velocity Solvers", this.bodies[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); + for(var i = 0; i < this._bl; i++) { + if(this.bodies[i] && this.bodies[i].isDynamic && this.bodies[i].isAwake) { + this.bodies[i].updatePosition(this._delta); } } - Advanced.Manager.dump("Update Position", this.bodyArr[1]); + Advanced.Manager.dump("Update Position", this.bodies[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]); + for(var i = 0; i < this._jl; i++) { + if(this.joints[i] && this.joints[i].breakable && (this.joints[i].getReactionForce(this._deltaInv).lengthSq() >= this.joints[i].maxForce * this.joints[i].maxForce)) { + this.removeJoint(this.joints[i]); } } - // 8) Iterative position constraints solver - var positionSolved = this.positionSolver(pos_iteration); - Advanced.Manager.dump("Position Solver", this.bodyArr[1]); + // 8) Iterative position constraints solver (result stored in this._positionSolved) + this.positionSolver(positionIterations); + Advanced.Manager.dump("Position Solver", this.bodies[1]); // 9) Sync the Transforms - for(var i = 0; i < bl; i++) { - if(this.bodyArr[i]) { - this.bodyArr[i].syncTransform(); + for(var i = 0; i < this._bl; i++) { + if(this.bodies[i]) { + this.bodies[i].syncTransform(); } } - Advanced.Manager.dump("Sync Transform", this.bodyArr[1]); + Advanced.Manager.dump("Sync Transform", this.bodies[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); - } - // 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'); + if(this.postSolve) { + for(var i = 0; i < this._cl; i++) { + this.postSolve(this.contactSolvers[i]); } } - Advanced.Manager.dump("Cache Data", this.bodyArr[1]); + // 11) Cache Body Data + for(var i = 0; i < this._bl; i++) { + if(this.bodies[i] && this.bodies[i].isDynamic && this.bodies[i].isAwake) { + this.bodies[i].cacheData('post solve collision callback'); + } + } + Advanced.Manager.dump("Cache Data", this.bodies[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(allowSleep) { + this._minSleepTime = 999999; + for(var i = 0; i < this._bl; i++) { + if(!this.bodies[i] || this.bodies[i].isDynamic == false) { + continue; + } + if(this.bodies[i].angularVelocity * this.bodies[i].angularVelocity > this._angTolSqr || this.bodies[i].velocity.dot(this.bodies[i].velocity) > this._linTolSqr) { + this.bodies[i].sleepTime = 0; + this._minSleepTime = 0; + } else { + this.bodies[i].sleepTime += this._delta; + this._minSleepTime = Math.min(this._minSleepTime, this.bodies[i].sleepTime); + } + } + if(this._positionSolved && this._minSleepTime >= Space.TIME_TO_SLEEP) { + for(var i = 0; i < this._bl; i++) { + if(this.bodies[i]) { + this.bodies[i].awake(false); + } + } + } } - - 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; @@ -21597,6 +21569,7 @@ var Phaser; // Check not already part of this body shape.body = this; this.shapes.push(shape); + this.shapesLength = this.shapes.length; return shape; }; Body.prototype.removeShape = function (shape) { @@ -21605,6 +21578,7 @@ var Phaser; this.shapes.splice(index, 1); shape.body = undefined; } + this.shapesLength = this.shapes.length; }; Body.prototype.setMass = function (mass) { this.mass = mass; diff --git a/build/phaser.d.ts b/build/phaser.d.ts index ee5d593d..782a3b9c 100644 --- a/build/phaser.d.ts +++ b/build/phaser.d.ts @@ -9944,13 +9944,26 @@ module Phaser.Physics.Advanced { module Phaser.Physics.Advanced { class Space { constructor(); + private _delta; + private _deltaInv; + private _bl; + private _jl; + private _cl; + private _linTolSqr; + private _angTolSqr; + private _minSleepTime; + private _positionSolved; + private _shape1; + private _shape2; + private _contactsOk; + private _jointsOk; static TIME_TO_SLEEP: number; static SLEEP_LINEAR_TOLERANCE: number; static SLEEP_ANGULAR_TOLERANCE: number; - public bodyArr: Body[]; - public bodyHash; - public jointArr: IJoint[]; - public jointHash; + public bodies: Body[]; + private bodyHash; + public joints: IJoint[]; + private jointHash; public numContacts: number; public contactSolvers: ContactSolver[]; public postSolve; @@ -9969,12 +9982,12 @@ module Phaser.Physics.Advanced { public findVertexByPoint(p, minDist, refVertexId): number; public findEdgeByPoint(p, minDist, refEdgeId): number; public findJointByPoint(p, minDist, refJointId): number; - public findContactSolver(shape1, shape2): ContactSolver; - public genTemporalContactSolvers(): any[]; - public initSolver(dt, dt_inv, warmStarting): void; - public velocitySolver(iteration): void; - public positionSolver(iteration): bool; - public step(dt, vel_iteration, pos_iteration, warmStarting, allowSleep): void; + private findContactSolver(shape1, shape2); + private genTemporalContactSolvers(); + private initSolver(warmStarting); + private velocitySolver(iterations); + private positionSolver(iterations); + public step(dt: number, velocityIterations: number, positionIterations: number, warmStarting: bool, allowSleep: bool): void; } } /** @@ -10045,6 +10058,7 @@ module Phaser.Physics.Advanced { public sleepTime: number; public awaked: bool; public shapes: IShape[]; + public shapesLength: number; public joints: IJoint[]; public jointHash: {}; public bounds: Bounds; @@ -10084,7 +10098,7 @@ module Phaser.Physics.Advanced { public updateVelocity(gravity, dt, damping): void; public inContact(body2: Body): bool; public clamp(v, min, max); - public updatePosition(dt): void; + public updatePosition(dt: number): void; public resetForce(): void; public applyForce(force: Vec2, p: Vec2): void; public applyForceToCenter(force: Vec2): void; diff --git a/build/phaser.js b/build/phaser.js index ae3e1c09..96d3a9b8 100644 --- a/build/phaser.js +++ b/build/phaser.js @@ -2539,10 +2539,10 @@ var Phaser; * @return {boolean} True if frame with given name found, otherwise return false. */ function (name) { - if(this._frameNames[name]) { - return true; + if(this._frameNames[name] == null) { + return false; } - return false; + return true; }; FrameData.prototype.getFrameRange = /** * Get ranges of frames in an array. @@ -3534,6 +3534,7 @@ var Phaser; */ function () { if(this.enabled) { + this.enabled = false; this.game.input.removeGameObject(this.indexID); } }; @@ -3766,7 +3767,9 @@ var Phaser; this._pointerData[pointer.id].isDragged = true; if(this.dragFromCenter) { // Move the sprite to the middle of the pointer - this._dragPoint.setTo(-this.sprite.worldView.halfWidth, -this.sprite.worldView.halfHeight); + //this._dragPoint.setTo(-this.sprite.worldView.halfWidth, -this.sprite.worldView.halfHeight); + //this._dragPoint.setTo(this.sprite.transform.center.x, this.sprite.transform.center.y); + this._dragPoint.setTo(this.sprite.x - pointer.x, this.sprite.y - pointer.y); } else { this._dragPoint.setTo(this.sprite.x - pointer.x, this.sprite.y - pointer.y); } @@ -5516,6 +5519,7 @@ var Phaser; */ function (object, splice) { if (typeof splice === "undefined") { splice = false; } + console.log('removing from group'); this._i = this.members.indexOf(object); if(this._i < 0 || (this._i >= this.members.length)) { return null; @@ -5526,6 +5530,7 @@ var Phaser; } else { this.members[this._i] = null; } + console.log('nulled'); if(object['events']) { object['events'].onRemovedFromGroup.dispatch(object, this); } @@ -5575,7 +5580,7 @@ var Phaser; }; Group.prototype.bringToTop = function (child) { // If child not in this group, or is already at the top of the group, return false - if(child.group.ID != this.ID || child.z == this._zCounter) { + if(!child || child.group == null || child.group.ID != this.ID || child.z == this._zCounter) { return false; } this.sort(); @@ -10716,6 +10721,10 @@ var Phaser; var json = JSON.parse(data); for(var i = 0; i < json.layers.length; i++) { var layer = new Phaser.TilemapLayer(this.game, this, key, Tilemap.FORMAT_TILED_JSON, json.layers[i].name, json.tilewidth, json.tileheight); + // Check it's a data layer + if(!json.layers[i].data) { + continue; + } layer.alpha = json.layers[i].opacity; layer.visible = json.layers[i].visible; layer.tileMargin = json.tilesets[0].margin; @@ -16166,6 +16175,7 @@ var Phaser; **/ function (index) { if(this.inputObjects[index]) { + console.log('object removed from the input manager', index); this.inputObjects[index] = null; } }; @@ -19155,11 +19165,11 @@ var Phaser; this.lastTime = Date.now(); this.frameRateHz = 60; this.timeDelta = 0; - this.paused = false; + //public paused: bool = false; + //public step: bool = false; // step through the simulation (i.e. per click) + this.paused = true; 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; @@ -19175,8 +19185,8 @@ var Phaser; Manager.log = []; }; Manager.write = function write(s) { - //Manager.debug.textContent += s + "\n"; - }; + Manager.debug.textContent += s + "\n"; + }; Manager.writeAll = function writeAll() { for(var i = 0; i < Manager.log.length; i++) { //Manager.debug.textContent += Manager.log[i]; @@ -19263,12 +19273,7 @@ var Phaser; if(this.timeDelta > h) { this.timeDelta = 0; } - //if (sceneIndex < demoArr.length) - //{ - // demo = demoArr[sceneIndex]; - // demo.runFrame(); - //} - } + } //frameCount++; }; Manager.prototype.pixelsToMeters = function (value) { @@ -20803,10 +20808,10 @@ var Phaser; var Space = (function () { function Space() { this.stepCount = 0; - this.bodyArr = []; + this.bodies = []; this.bodyHash = { }; - this.jointArr = []; + this.joints = []; this.jointHash = { }; this.numContacts = 0; @@ -20814,6 +20819,8 @@ var Phaser; //this.postSolve(arb) { }; this.gravity = new Phaser.Vec2(0, 10); this.damping = 0; + this._linTolSqr = Space.SLEEP_LINEAR_TOLERANCE * Space.SLEEP_LINEAR_TOLERANCE; + this._angTolSqr = Space.SLEEP_ANGULAR_TOLERANCE * Space.SLEEP_ANGULAR_TOLERANCE; } Space.TIME_TO_SLEEP = 0.5; Space.SLEEP_LINEAR_TOLERANCE = 0.5; @@ -20822,15 +20829,15 @@ var Phaser; Advanced.Manager.shapeCounter = 0; Advanced.Manager.bodyCounter = 0; Advanced.Manager.jointCounter = 0; - for(var i = 0; i < this.bodyArr.length; i++) { - if(this.bodyArr[i]) { - this.removeBody(this.bodyArr[i]); + for(var i = 0; i < this.bodies.length; i++) { + if(this.bodies[i]) { + this.removeBody(this.bodies[i]); } } - this.bodyArr = []; + this.bodies = []; this.bodyHash = { }; - this.jointArr = []; + this.joints = []; this.jointHash = { }; this.contactSolvers = []; @@ -20840,7 +20847,7 @@ var Phaser; if(this.bodyHash[body.id] != undefined) { return; } - var index = this.bodyArr.push(body) - 1; + var index = this.bodies.push(body) - 1; this.bodyHash[body.id] = index; body.awake(true); body.space = this; @@ -20850,7 +20857,7 @@ var Phaser; if(this.bodyHash[body.id] == undefined) { return; } - // Remove linked joint + // Remove linked joints for(var i = 0; i < body.joints.length; i++) { if(body.joints[i]) { this.removeJoint(body.joints[i]); @@ -20859,7 +20866,7 @@ var Phaser; body.space = null; var index = this.bodyHash[body.id]; delete this.bodyHash[body.id]; - delete this.bodyArr[index]; + delete this.bodies[index]; }; Space.prototype.addJoint = function (joint) { if(this.jointHash[joint.id] != undefined) { @@ -20867,7 +20874,7 @@ var Phaser; } joint.body1.awake(true); joint.body2.awake(true); - var index = this.jointArr.push(joint) - 1; + var index = this.joints.push(joint) - 1; this.jointHash[joint.id] = index; var index = joint.body1.joints.push(joint) - 1; joint.body1.jointHash[joint.id] = index; @@ -20888,12 +20895,12 @@ var Phaser; delete joint.body2.joints[index]; var index = this.jointHash[joint.id]; delete this.jointHash[joint.id]; - delete this.jointArr[index]; + delete this.joints[index]; }; Space.prototype.findShapeByPoint = function (p, refShape) { var firstShape; - for(var i = 0; i < this.bodyArr.length; i++) { - var body = this.bodyArr[i]; + for(var i = 0; i < this.bodies.length; i++) { + var body = this.bodies[i]; if(!body) { continue; } @@ -20916,8 +20923,8 @@ var Phaser; }; Space.prototype.findBodyByPoint = function (p, refBody) { var firstBody; - for(var i = 0; i < this.bodyArr.length; i++) { - var body = this.bodyArr[i]; + for(var i = 0; i < this.bodies.length; i++) { + var body = this.bodies[i]; if(!body) { continue; } @@ -20939,11 +20946,10 @@ var Phaser; } return firstBody; }; - Space.prototype.shapeById = // TODO: Replace this function to shape hashing - function (id) { + Space.prototype.shapeById = function (id) { var shape; - for(var i = 0; i < this.bodyArr.length; i++) { - var body = this.bodyArr[i]; + for(var i = 0; i < this.bodies.length; i++) { + var body = this.bodies[i]; if(!body) { continue; } @@ -20958,15 +20964,15 @@ var Phaser; Space.prototype.jointById = function (id) { var index = this.jointHash[id]; if(index != undefined) { - return this.jointArr[index]; + return this.joints[index]; } return null; }; Space.prototype.findVertexByPoint = function (p, minDist, refVertexId) { var firstVertexId = -1; refVertexId = refVertexId || -1; - for(var i = 0; i < this.bodyArr.length; i++) { - var body = this.bodyArr[i]; + for(var i = 0; i < this.bodies.length; i++) { + var body = this.bodies[i]; if(!body) { continue; } @@ -20992,8 +20998,8 @@ var Phaser; Space.prototype.findEdgeByPoint = function (p, minDist, refEdgeId) { var firstEdgeId = -1; refEdgeId = refEdgeId || -1; - for(var i = 0; i < this.bodyArr.length; i++) { - var body = this.bodyArr[i]; + for(var i = 0; i < this.bodies.length; i++) { + var body = this.bodies[i]; if(!body) { continue; } @@ -21023,8 +21029,8 @@ var Phaser; var firstJointId = -1; var dsq = minDist * minDist; refJointId = refJointId || -1; - for(var i = 0; i < this.jointArr.length; i++) { - var joint = this.jointArr[i]; + for(var i = 0; i < this.joints.length; i++) { + var joint = this.joints[i]; if(!joint) { continue; } @@ -21049,8 +21055,8 @@ 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++) { + Advanced.Manager.write('findContactSolver. Length: ' + this._cl); + for(var i = 0; i < this._cl; i++) { var contactSolver = this.contactSolvers[i]; if(shape1 == contactSolver.shape1 && shape2 == contactSolver.shape2) { return contactSolver; @@ -21060,255 +21066,221 @@ var Phaser; }; Space.prototype.genTemporalContactSolvers = function () { Advanced.Manager.write('genTemporalContactSolvers'); - var newContactSolverArr = []; - var bl = this.bodyArr.length; + this._cl = 0; + this.contactSolvers.length = 0; this.numContacts = 0; - for(var body1_index = 0; body1_index < bl; body1_index++) { - var body1 = this.bodyArr[body1_index]; - if(!body1) { + for(var body1Index = 0; body1Index < this._bl; body1Index++) { + if(!this.bodies[body1Index]) { continue; } - body1.stepCount = this.stepCount; - for(var body2_index = 0; body2_index < bl; body2_index++) { - var body2 = this.bodyArr[body2_index]; - if(body1.inContact(body2) == false) { + this.bodies[body1Index].stepCount = this.stepCount; + for(var body2Index = 0; body2Index < this._bl; body2Index++) { + if(this.bodies[body1Index].inContact(this.bodies[body2Index]) == false) { continue; } 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]; - var shape2 = body2.shapes[j]; + for(var i = 0; i < this.bodies[body1Index].shapesLength; i++) { + for(var j = 0; j < this.bodies[body2Index].shapesLength; j++) { + this._shape1 = this.bodies[body1Index].shapes[i]; + this._shape2 = this.bodies[body2Index].shapes[j]; var contactArr = []; - if(!Advanced.Manager.collision.collide(shape1, shape2, contactArr)) { + if(!Advanced.Manager.collision.collide(this._shape1, this._shape2, contactArr)) { continue; } - if(shape1.type > shape2.type) { - var temp = shape1; - shape1 = shape2; - shape2 = temp; + if(this._shape1.type > this._shape2.type) { + var temp = this._shape1; + this._shape1 = this._shape2; + this._shape2 = temp; } this.numContacts += contactArr.length; - var contactSolver = this.findContactSolver(shape1, shape2); + // Result stored in this._contactSolver (see what we can do about generating some re-usable solvers) + var contactSolver = this.findContactSolver(this._shape1, this._shape2); Advanced.Manager.write('findContactSolver result: ' + contactSolver); if(contactSolver) { contactSolver.update(contactArr); - newContactSolverArr.push(contactSolver); + this.contactSolvers.push(contactSolver); } else { Advanced.Manager.write('awake both bodies'); - body1.awake(true); - body2.awake(true); - var newContactSolver = new Advanced.ContactSolver(shape1, shape2); + this.bodies[body1Index].awake(true); + this.bodies[body2Index].awake(true); + var newContactSolver = new Advanced.ContactSolver(this._shape1, this._shape2); newContactSolver.contacts = contactArr; - newContactSolver.elasticity = Math.max(shape1.elasticity, shape2.elasticity); - newContactSolver.friction = Math.sqrt(shape1.friction * shape2.friction); - newContactSolverArr.push(newContactSolver); + newContactSolver.elasticity = Math.max(this._shape1.elasticity, this._shape2.elasticity); + newContactSolver.friction = Math.sqrt(this._shape1.friction * this._shape2.friction); + this.contactSolvers.push(newContactSolver); Advanced.Manager.write('new contact solver'); - //console.log(newContactSolver); - } + } } } } } - return newContactSolverArr; + this._cl = this.contactSolvers.length; }; - Space.prototype.initSolver = function (dt, dt_inv, warmStarting) { + Space.prototype.initSolver = function (warmStarting) { Advanced.Manager.write('initSolver'); - Advanced.Manager.write('contactSolvers.length: ' + this.contactSolvers.length); - //var t0 = Date.now(); + Advanced.Manager.write('contactSolvers.length: ' + this._cl); // Initialize contact solvers - for(var i = 0; i < this.contactSolvers.length; i++) { - this.contactSolvers[i].initSolver(dt_inv); + for(var c = 0; c < this._cl; c++) { + this.contactSolvers[c].initSolver(this._deltaInv); + // Warm starting (apply cached impulse) + if(warmStarting) { + this.contactSolvers[c].warmStart(); + } } // Initialize joint solver - for(var i = 0; i < this.jointArr.length; i++) { - if(this.jointArr[i]) { - this.jointArr[i].initSolver(dt, warmStarting); + for(var j = 0; j < this.joints.length; j++) { + if(this.joints[j]) { + this.joints[j].initSolver(this._delta, warmStarting); } } // Warm starting (apply cached impulse) - if(warmStarting) { - for(var i = 0; i < this.contactSolvers.length; i++) { - this.contactSolvers[i].warmStart(); - } + /* + if (warmStarting) + { + for (var c = 0; c < this._cl; c++) + { + this.contactSolvers[c].warmStart(); } - //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++) { - if(this.jointArr[j]) { - this.jointArr[j].solveVelocityConstraints(); + Space.prototype.velocitySolver = function (iterations) { + Advanced.Manager.write('velocitySolver, iterations: ' + iterations + ' csa len: ' + this._cl); + for(var i = 0; i < iterations; i++) { + for(var j = 0; j < this._jl; j++) { + if(this.joints[j]) { + this.joints[j].solveVelocityConstraints(); } } - for(var j = 0; j < this.contactSolvers.length; j++) { - this.contactSolvers[j].solveVelocityConstraints(); + for(var c = 0; c < this._cl; c++) { + this.contactSolvers[c].solveVelocityConstraints(); } } }; - Space.prototype.positionSolver = function (iteration) { - var positionSolved = false; - for(var i = 0; i < iteration; i++) { - var contactsOk = true; - var jointsOk = true; - for(var j = 0; j < this.contactSolvers.length; j++) { - var contactOk = this.contactSolvers[j].solvePositionConstraints(); - contactsOk = contactOk && contactsOk; + Space.prototype.positionSolver = function (iterations) { + this._positionSolved = false; + for(var i = 0; i < iterations; i++) { + this._contactsOk = true; + this._jointsOk = true; + for(var c = 0; c < this._cl; c++) { + this._contactsOk = this.contactSolvers[c].solvePositionConstraints() && this._contactsOk; } - for(var j = 0; j < this.jointArr.length; j++) { - if(this.jointArr[j]) { - var jointOk = this.jointArr[j].solvePositionConstraints(); - jointsOk = jointOk && jointsOk; + for(var j = 0; j < this._jl; j++) { + if(this.joints[j]) { + this._jointsOk = this.joints[j].solvePositionConstraints() && this._jointsOk; } } - if(contactsOk && jointsOk) { + if(this._contactsOk && this._jointsOk) { // exit early if the position errors are small - positionSolved = true; + this._positionSolved = true; break; } } - return positionSolved; + return this._positionSolved; }; - Space.prototype.step = function (dt, vel_iteration, pos_iteration, warmStarting, allowSleep) { + Space.prototype.step = // Step through the physics simulation + function (dt, velocityIterations, positionIterations, 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._delta = dt; + this._deltaInv = 1 / dt; + this._bl = this.bodies.length; + this._jl = this.joints.length; this.stepCount++; - // 1) Generate Contact Solvers - this.contactSolvers = this.genTemporalContactSolvers(); - Advanced.Manager.dump("Contact Solvers", this.bodyArr[1]); + // 1) Generate Contact Solvers (into the this.contactSolvers array) + this.genTemporalContactSolvers(); + Advanced.Manager.dump("Contact Solvers", this.bodies[1]); // 2) Initialize the Contact Solvers - this.initSolver(dt, dt_inv, warmStarting); - Advanced.Manager.dump("Init Solver", this.bodyArr[1]); + this.initSolver(warmStarting); + Advanced.Manager.dump("Init Solver", this.bodies[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._bl; i++) { + if(this.bodies[i] && this.bodies[i].isDynamic && this.bodies[i].isAwake) { + this.bodies[i].updateVelocity(this.gravity, this._delta, this.damping); } } - 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; + Advanced.Manager.dump("Update Velocity", this.bodies[1]); + // 4) Awaken bodies via joints + for(var j = 0; i < this._jl; j++) { + if(!this.joints[j]) { + continue; + } + // combine + var awake1 = this.joints[j].body1.isAwake && !this.joints[j].body1.isStatic; + var awake2 = this.joints[j].body2.isAwake && !this.joints[j].body2.isStatic; + if(awake1 ^ awake2) { + if(!awake1) { + this.joints[j].body1.awake(true); + } + if(!awake2) { + this.joints[j].body2.awake(true); + } + } } - - 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); - Advanced.Manager.dump("Velocity Solvers", this.bodyArr[1]); + this.velocitySolver(velocityIterations); + Advanced.Manager.dump("Velocity Solvers", this.bodies[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); + for(var i = 0; i < this._bl; i++) { + if(this.bodies[i] && this.bodies[i].isDynamic && this.bodies[i].isAwake) { + this.bodies[i].updatePosition(this._delta); } } - Advanced.Manager.dump("Update Position", this.bodyArr[1]); + Advanced.Manager.dump("Update Position", this.bodies[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]); + for(var i = 0; i < this._jl; i++) { + if(this.joints[i] && this.joints[i].breakable && (this.joints[i].getReactionForce(this._deltaInv).lengthSq() >= this.joints[i].maxForce * this.joints[i].maxForce)) { + this.removeJoint(this.joints[i]); } } - // 8) Iterative position constraints solver - var positionSolved = this.positionSolver(pos_iteration); - Advanced.Manager.dump("Position Solver", this.bodyArr[1]); + // 8) Iterative position constraints solver (result stored in this._positionSolved) + this.positionSolver(positionIterations); + Advanced.Manager.dump("Position Solver", this.bodies[1]); // 9) Sync the Transforms - for(var i = 0; i < bl; i++) { - if(this.bodyArr[i]) { - this.bodyArr[i].syncTransform(); + for(var i = 0; i < this._bl; i++) { + if(this.bodies[i]) { + this.bodies[i].syncTransform(); } } - Advanced.Manager.dump("Sync Transform", this.bodyArr[1]); + Advanced.Manager.dump("Sync Transform", this.bodies[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); - } - // 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'); + if(this.postSolve) { + for(var i = 0; i < this._cl; i++) { + this.postSolve(this.contactSolvers[i]); } } - Advanced.Manager.dump("Cache Data", this.bodyArr[1]); + // 11) Cache Body Data + for(var i = 0; i < this._bl; i++) { + if(this.bodies[i] && this.bodies[i].isDynamic && this.bodies[i].isAwake) { + this.bodies[i].cacheData('post solve collision callback'); + } + } + Advanced.Manager.dump("Cache Data", this.bodies[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(allowSleep) { + this._minSleepTime = 999999; + for(var i = 0; i < this._bl; i++) { + if(!this.bodies[i] || this.bodies[i].isDynamic == false) { + continue; + } + if(this.bodies[i].angularVelocity * this.bodies[i].angularVelocity > this._angTolSqr || this.bodies[i].velocity.dot(this.bodies[i].velocity) > this._linTolSqr) { + this.bodies[i].sleepTime = 0; + this._minSleepTime = 0; + } else { + this.bodies[i].sleepTime += this._delta; + this._minSleepTime = Math.min(this._minSleepTime, this.bodies[i].sleepTime); + } + } + if(this._positionSolved && this._minSleepTime >= Space.TIME_TO_SLEEP) { + for(var i = 0; i < this._bl; i++) { + if(this.bodies[i]) { + this.bodies[i].awake(false); + } + } + } } - - 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; @@ -21597,6 +21569,7 @@ var Phaser; // Check not already part of this body shape.body = this; this.shapes.push(shape); + this.shapesLength = this.shapes.length; return shape; }; Body.prototype.removeShape = function (shape) { @@ -21605,6 +21578,7 @@ var Phaser; this.shapes.splice(index, 1); shape.body = undefined; } + this.shapesLength = this.shapes.length; }; Body.prototype.setMass = function (mass) { this.mass = mass; From d19ad4976d91cc19be0b53e4c71f5b0162758260 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Wed, 26 Jun 2013 05:44:56 +0100 Subject: [PATCH 2/3] Merged Advanced Physics with core. --- Phaser/Game.ts | 55 +- Phaser/Motion.ts | 21 + Phaser/Phaser.csproj | 142 +- Phaser/World.ts | 20 +- Phaser/components/TilemapLayer.ts | 4 +- Phaser/components/Transform.ts | 2 +- Phaser/gameobjects/Emitter.ts | 18 +- Phaser/gameobjects/GameObjectFactory.ts | 16 +- Phaser/gameobjects/Particle.ts | 47 +- Phaser/gameobjects/Sprite.ts | 20 +- Phaser/math/QuadTree.ts | 7 +- Phaser/physics/ArcadePhysics.ts | 1121 --- Phaser/physics/Body.ts | 798 +- Phaser/physics/{advanced => }/Bounds.ts | 28 +- Phaser/physics/{advanced => }/Collision.ts | 33 +- Phaser/physics/{advanced => }/Contact.ts | 6 +- .../physics/{advanced => }/ContactSolver.ts | 8 +- Phaser/physics/{advanced => }/Manager.ts | 52 +- Phaser/physics/PhysicsManager.ts | 1116 --- Phaser/physics/{advanced => }/Plane.ts | 6 +- Phaser/physics/{advanced => }/Space.ts | 16 +- Phaser/physics/advanced/Body.ts | 680 -- .../physics/{advanced => }/joints/IJoint.ts | 12 +- Phaser/physics/{advanced => }/joints/Joint.ts | 16 +- Phaser/physics/{advanced => }/shapes/Box.ts | 14 +- .../physics/{advanced => }/shapes/Circle.ts | 8 +- .../physics/{advanced => }/shapes/IShape.ts | 12 +- Phaser/physics/{advanced => }/shapes/Poly.ts | 16 +- .../physics/{advanced => }/shapes/Segment.ts | 10 +- Phaser/physics/{advanced => }/shapes/Shape.ts | 12 +- .../physics/{advanced => }/shapes/Triangle.ts | 6 +- Phaser/utils/ColorUtils.ts | 2 +- Phaser/utils/DebugUtils.ts | 72 +- Phaser/utils/SpriteUtils.ts | 4 +- README.md | 12 +- Tests/Tests.csproj | 18 +- Tests/cameras/world sprite.js | 5 - Tests/cameras/world sprite.ts | 6 - Tests/input/world drag.js | 1 - Tests/input/world drag.ts | 2 - Tests/phaser.js | 8360 ++++++----------- Tests/physics/body1.js | 7 - Tests/physics/body1.ts | 8 - Tests/physics/simple test 1.js | 25 + Tests/physics/simple test 1.ts | 40 + Tests/scrollzones/blasteroids.js | 4 +- Tests/scrollzones/blasteroids.ts | 2 +- Tests/sprites/create sprite 1.js | 7 +- Tests/sprites/create sprite 1.ts | 5 +- build/phaser.d.ts | 1636 ++-- build/phaser.js | 8360 ++++++----------- 51 files changed, 7930 insertions(+), 14968 deletions(-) delete mode 100644 Phaser/physics/ArcadePhysics.ts rename Phaser/physics/{advanced => }/Bounds.ts (86%) rename Phaser/physics/{advanced => }/Collision.ts (91%) rename Phaser/physics/{advanced => }/Contact.ts (91%) rename Phaser/physics/{advanced => }/ContactSolver.ts (98%) rename Phaser/physics/{advanced => }/Manager.ts (91%) delete mode 100644 Phaser/physics/PhysicsManager.ts rename Phaser/physics/{advanced => }/Plane.ts (75%) rename Phaser/physics/{advanced => }/Space.ts (98%) delete mode 100644 Phaser/physics/advanced/Body.ts rename Phaser/physics/{advanced => }/joints/IJoint.ts (71%) rename Phaser/physics/{advanced => }/joints/Joint.ts (70%) rename Phaser/physics/{advanced => }/shapes/Box.ts (63%) rename Phaser/physics/{advanced => }/shapes/Circle.ts (92%) rename Phaser/physics/{advanced => }/shapes/IShape.ts (74%) rename Phaser/physics/{advanced => }/shapes/Poly.ts (93%) rename Phaser/physics/{advanced => }/shapes/Segment.ts (94%) rename Phaser/physics/{advanced => }/shapes/Shape.ts (77%) rename Phaser/physics/{advanced => }/shapes/Triangle.ts (81%) create mode 100644 Tests/physics/simple test 1.js create mode 100644 Tests/physics/simple test 1.ts diff --git a/Phaser/Game.ts b/Phaser/Game.ts index 49e96bc9..469069f5 100644 --- a/Phaser/Game.ts +++ b/Phaser/Game.ts @@ -82,18 +82,6 @@ module Phaser { */ public _raf: RequestAnimationFrame; - /** - * Max allowable accumulation. - * @type {number} - */ - private _maxAccumulation: number = 32; - - /** - * Total number of milliseconds elapsed since last update loop. - * @type {number} - */ - private _accumulator: number = 0; - /** * Milliseconds of time per step of the game loop. * @type {number} @@ -231,6 +219,12 @@ module Phaser { */ public world: World; + /** + * Reference to the physics manager. + * @type {Physics.Manager} + */ + public physics: Physics.Manager; + /** * Instance of repeatable random data generator helper. * @type {RandomDataGenerator} @@ -293,6 +287,7 @@ module Phaser { this.tweens = new TweenManager(this); this.input = new Input(this); this.rnd = new RandomDataGenerator([(Date.now() * Math.random()).toString()]); + this.physics = new Physics.Manager(this); this.setRenderer(Phaser.Types.RENDERER_CANVAS); @@ -300,12 +295,12 @@ module Phaser { this.stage.boot(); this.input.boot(); - this.framerate = 60; this.isBooted = true; // Set-up some static helper references DebugUtils.game = this; ColorUtils.game = this; + DebugUtils.context = this.stage.context; // Display the default game screen? if (this.onInitCallback == null && this.onCreateCallback == null && this.onUpdateCallback == null && this.onRenderCallback == null && this._pendingState == null) @@ -396,20 +391,8 @@ module Phaser { this.tweens.update(); this.input.update(); this.stage.update(); - - this._accumulator += this.time.delta; - - if (this._accumulator > this._maxAccumulation) - { - this._accumulator = this._maxAccumulation; - } - - while (this._accumulator >= this._step) - { - this.time.elapsed = this.time.timeScale * (this._step / 1000); - this.world.update(); - this._accumulator = this._accumulator - this._step; - } + this.physics.update(); + this.world.update(); if (this._loadComplete && this.onUpdateCallback) { @@ -624,21 +607,6 @@ module Phaser { } - public get framerate(): number { - return 1000 / this._step; - } - - public set framerate(value: number) { - - this._step = 1000 / value; - - if (this._maxAccumulation < this._step) - { - this._maxAccumulation = this._step; - } - - } - /** * Checks for overlaps between two objects using the world QuadTree. Can be GameObject vs. GameObject, GameObject vs. Group or Group vs. Group. * Note: Does not take the objects scrollFactor into account. All overlaps are check in world space. @@ -650,7 +618,8 @@ module Phaser { * @returns {boolean} true if the objects overlap, otherwise false. */ public collide(objectOrGroup1 = null, objectOrGroup2 = null, notifyCallback = null, context? = this.callbackContext): bool { - return this.world.physics.overlap(objectOrGroup1, objectOrGroup2, notifyCallback, this.world.physics.separate, context); + //return this.world.physics.overlap(objectOrGroup1, objectOrGroup2, notifyCallback, this.world.physics.separate, context); + return false; } public get camera(): Camera { diff --git a/Phaser/Motion.ts b/Phaser/Motion.ts index 16e4a040..a469c4a7 100644 --- a/Phaser/Motion.ts +++ b/Phaser/Motion.ts @@ -52,6 +52,7 @@ module Phaser { * @param {number} maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms */ public moveTowardsObject(source: Sprite, dest: Sprite, speed: number = 60, maxTime: number = 0) { + var a: number = this.angleBetween(source, dest); if (maxTime > 0) @@ -79,6 +80,8 @@ module Phaser { * @param {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically */ public accelerateTowardsObject(source: Sprite, dest: Sprite, speed: number, xSpeedMax: number, ySpeedMax: number) { + + /* var a: number = this.angleBetween(source, dest); source.body.velocity.x = 0; @@ -89,6 +92,7 @@ module Phaser { source.body.maxVelocity.x = xSpeedMax; source.body.maxVelocity.y = ySpeedMax; + */ } @@ -103,6 +107,7 @@ module Phaser { * @param {number} maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms */ public moveTowardsMouse(source: Sprite, speed: number = 60, maxTime: number = 0) { + var a: number = this.angleBetweenMouse(source); if (maxTime > 0) @@ -129,6 +134,8 @@ module Phaser { * @param {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically */ public accelerateTowardsMouse(source: Sprite, speed: number, xSpeedMax: number, ySpeedMax: number) { + + /* var a: number = this.angleBetweenMouse(source); source.body.velocity.x = 0; @@ -139,6 +146,8 @@ module Phaser { source.body.maxVelocity.x = xSpeedMax; source.body.maxVelocity.y = ySpeedMax; + */ + } /** @@ -153,6 +162,7 @@ module Phaser { * @param {number} maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms */ public moveTowardsPoint(source: Sprite, target: Point, speed: number = 60, maxTime: number = 0) { + var a: number = this.angleBetweenPoint(source, target); if (maxTime > 0) @@ -179,6 +189,8 @@ module Phaser { * @param {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically */ public accelerateTowardsPoint(source: Sprite, target: Point, speed: number, xSpeedMax: number, ySpeedMax: number) { + + /* var a: number = this.angleBetweenPoint(source, target); source.body.velocity.x = 0; @@ -189,6 +201,8 @@ module Phaser { source.body.maxVelocity.x = xSpeedMax; source.body.maxVelocity.y = ySpeedMax; + */ + } /** @@ -240,6 +254,7 @@ module Phaser { * @return {number} The angle (in radians unless asDegrees is true) */ public angleBetweenPoint(a: Sprite, target: Point, asDegrees: bool = false): number { + var dx: number = (target.x) - (a.x + a.transform.origin.x); var dy: number = (target.y) - (a.y + a.transform.origin.y); @@ -251,6 +266,7 @@ module Phaser { { return Math.atan2(dy, dx); } + } /** @@ -287,6 +303,8 @@ module Phaser { * @return {Point} An Point where Point.x contains the velocity x value and Point.y contains the velocity y value */ public velocityFromFacing(parent: Sprite, speed: number): Point { + + /* var a: number; if (parent.body.facing == Types.LEFT) @@ -307,6 +325,9 @@ module Phaser { } return new Point(Math.cos(a) * speed, Math.sin(a) * speed); + */ + + return new Point; } diff --git a/Phaser/Phaser.csproj b/Phaser/Phaser.csproj index 0873a13b..9776fa7a 100644 --- a/Phaser/Phaser.csproj +++ b/Phaser/Phaser.csproj @@ -56,9 +56,7 @@ ../build/phaser.js true - - - + AnimationManager.ts @@ -143,7 +141,6 @@ - @@ -177,83 +174,72 @@ Motion.ts - - - - Body.ts - - - - Bounds.ts - - - - - Collision.ts - - - Contact.ts - - - - ContactSolver.ts - - - - - IJoint.ts - - - - Joint.ts - - - Manager.ts - - - - - - - Plane.ts - - - Box.ts - - - - Circle.ts - - - IShape.ts - - - - Poly.ts - - - - Segment.ts - - - Shape.ts - - - - Triangle.ts - - - - Space.ts - - - ArcadePhysics.ts - Body.ts - - PhysicsManager.ts + + + Bounds.ts + + + + Collision.ts + + + + Contact.ts + + + + ContactSolver.ts + + + + + IJoint.ts + + + + Joint.ts + + + Manager.ts + + + + Plane.ts + + + + + Box.ts + + + + Circle.ts + + + + IShape.ts + + + + Poly.ts + + + + Segment.ts + + + + Shape.ts + + + + Triangle.ts + + + Space.ts HeadlessRenderer.ts diff --git a/Phaser/World.ts b/Phaser/World.ts index cbabd992..3d04e365 100644 --- a/Phaser/World.ts +++ b/Phaser/World.ts @@ -2,7 +2,7 @@ /// /// /// -/// +/// /** * Phaser - World @@ -59,10 +59,10 @@ module Phaser { public bounds: Rectangle; /** - * Reference to the physics manager. - * @type {Physics.PhysicsManager} + * The Gravity of the World (defaults to 0,0, or no gravity at all) + * @type {Vec2} */ - public physics: Physics.PhysicsManager; + public gravity: Phaser.Vec2; /** * Object container stores every object created with `create*` methods. @@ -81,8 +81,6 @@ module Phaser { this.group = new Group(this._game, 0); - this.physics = new Physics.PhysicsManager(this._game, this.width, this.height); - } /** @@ -90,7 +88,6 @@ module Phaser { */ public update() { - //this.physics.update(); this.group.update(); this.cameras.update(); @@ -101,7 +98,6 @@ module Phaser { */ public postUpdate() { - //this.physics.postUpdate(); this.group.postUpdate(); this.cameras.postUpdate(); @@ -112,7 +108,6 @@ module Phaser { */ public destroy() { - //this.physics.destroy(); this.group.destroy(); this.cameras.destroy(); @@ -125,7 +120,7 @@ module Phaser { * @param height {number} New height of the world. * @param [updateCameraBounds] {boolean} Update camera bounds automatically or not. Default to true. */ - public setSize(width: number, height: number, updateCameraBounds: bool = true, updatePhysicsBounds: bool = true) { + public setSize(width: number, height: number, updateCameraBounds: bool = true) { this.bounds.width = width; this.bounds.height = height; @@ -135,11 +130,6 @@ module Phaser { this._game.camera.setBounds(0, 0, width, height); } - if (updatePhysicsBounds == true) - { - //this.physics.bounds.copyFrom(this.bounds); - } - // dispatch world resize event } diff --git a/Phaser/components/TilemapLayer.ts b/Phaser/components/TilemapLayer.ts index b26b26bf..21360b63 100644 --- a/Phaser/components/TilemapLayer.ts +++ b/Phaser/components/TilemapLayer.ts @@ -375,8 +375,7 @@ module Phaser { this._tempBlockResults = []; this.getTempBlock(this._tempTileX, this._tempTileY, this._tempTileW, this._tempTileH, true); - Phaser.Physics.PhysicsManager.TILE_OVERLAP = false; - + /* for (var r = 0; r < this._tempTileBlock.length; r++) { if (this._game.world.physics.separateTile(object, this._tempTileBlock[r].x * this.tileWidth, this._tempTileBlock[r].y * this.tileHeight, this.tileWidth, this.tileHeight, this._tempTileBlock[r].tile.mass, this._tempTileBlock[r].tile.collideLeft, this._tempTileBlock[r].tile.collideRight, this._tempTileBlock[r].tile.collideUp, this._tempTileBlock[r].tile.collideDown, this._tempTileBlock[r].tile.separateX, this._tempTileBlock[r].tile.separateY) == true) @@ -384,6 +383,7 @@ module Phaser { this._tempBlockResults.push({ x: this._tempTileBlock[r].x, y: this._tempTileBlock[r].y, tile: this._tempTileBlock[r].tile }); } } + */ return this._tempBlockResults; diff --git a/Phaser/components/Transform.ts b/Phaser/components/Transform.ts index 1112529a..47e51866 100644 --- a/Phaser/components/Transform.ts +++ b/Phaser/components/Transform.ts @@ -183,7 +183,7 @@ module Phaser.Components { dirty = true; } - // If it has moved, updated the edges and center + // If it has moved, update the edges and center if (dirty || this.parent.x != this._pos.x || this.parent.y != this._pos.y) { this.center.x = this.parent.x + this._distance * this._scA.y; diff --git a/Phaser/gameobjects/Emitter.ts b/Phaser/gameobjects/Emitter.ts index 661a38bd..4ed7b653 100644 --- a/Phaser/gameobjects/Emitter.ts +++ b/Phaser/gameobjects/Emitter.ts @@ -238,19 +238,19 @@ module Phaser { if (collide > 0) { - particle.body.allowCollisions = Types.ANY; + //particle.body.allowCollisions = Types.ANY; particle.body.type = Types.BODY_DYNAMIC; particle.width *= collide; particle.height *= collide; } else { - particle.body.allowCollisions = Types.NONE; + //particle.body.allowCollisions = Types.NONE; } particle.exists = false; // Center the origin for rotation assistance - particle.transform.origin.setTo(particle.body.bounds.halfWidth, particle.body.bounds.halfHeight); + //particle.transform.origin.setTo(particle.body.bounds.halfWidth, particle.body.bounds.halfHeight); this.add(particle); @@ -363,7 +363,7 @@ module Phaser { var particle: Particle = this.recycle(Particle); particle.lifespan = this.lifespan; - particle.body.bounce.setTo(this.bounce, this.bounce); + //particle.body.bounce.setTo(this.bounce, this.bounce); SpriteUtils.reset(particle, this.x - (particle.width >> 1) + this.game.math.random() * this.width, this.y - (particle.height >> 1) + this.game.math.random() * this.height); particle.visible = true; @@ -385,7 +385,7 @@ module Phaser { particle.body.velocity.y = this.minParticleSpeed.y; } - particle.body.acceleration.y = this.gravity; + //particle.body.acceleration.y = this.gravity; if (this.minRotation != this.maxRotation && this.minRotation !== 0 && this.maxRotation !== 0) { @@ -401,8 +401,8 @@ module Phaser { particle.rotation = this.game.math.random() * 360 - 180; } - particle.body.drag.x = this.particleDrag.x; - particle.body.drag.y = this.particleDrag.y; + //particle.body.drag.x = this.particleDrag.x; + //particle.body.drag.y = this.particleDrag.y; particle.onEmit(); } @@ -457,8 +457,8 @@ module Phaser { * @param Object {object} The Object that you want to sync up with. */ public at(object: Sprite) { - this.x = object.body.bounds.halfWidth - (this.width >> 1); - this.y = object.body.bounds.halfHeight - (this.height >> 1); + //this.x = object.body.bounds.halfWidth - (this.width >> 1); + //this.y = object.body.bounds.halfHeight - (this.height >> 1); } } diff --git a/Phaser/gameobjects/GameObjectFactory.ts b/Phaser/gameobjects/GameObjectFactory.ts index d74ac54c..47bc8f2b 100644 --- a/Phaser/gameobjects/GameObjectFactory.ts +++ b/Phaser/gameobjects/GameObjectFactory.ts @@ -72,10 +72,24 @@ module Phaser { * @param [bodyType] {number} The physics body type of the object (defaults to BODY_DISABLED) * @returns {Sprite} The newly created sprite object. */ - public sprite(x: number, y: number, key?: string = '', frame? = null, bodyType?: number = Phaser.Types.BODY_DYNAMIC): Sprite { + public sprite(x: number, y: number, key?: string = '', frame? = null, bodyType?: number = Phaser.Types.BODY_DISABLED): Sprite { return this._world.group.add(new Sprite(this._game, x, y, key, frame, bodyType)); } + /** + * Create a new Sprite with the physics automatically created and set to DYNAMIC. The Sprite position offset is set to its center. + * + * @param x {number} X position of the new sprite. + * @param y {number} Y position of the new sprite. + * @param [key] {string} The image key as defined in the Game.Cache to use as the texture for this sprite + * @param [frame] {string|number} If the sprite uses an image from a texture atlas or sprite sheet you can pass the frame here. Either a number for a frame ID or a string for a frame name. + * @param [shapeType] The default body shape is either 0 for a Box or 1 for a Circle. See Sprite.body.addShape for custom shapes (polygons, etc) + * @returns {Sprite} The newly created sprite object. + */ + public physicsSprite(x: number, y: number, key?: string = '', frame? = null, shapeType?:number = 0): Sprite { + return this._world.group.add(new Sprite(this._game, x, y, key, frame, Phaser.Types.BODY_DYNAMIC, shapeType)); + } + /** * Create a new DynamicTexture with specific size. * diff --git a/Phaser/gameobjects/Particle.ts b/Phaser/gameobjects/Particle.ts index ffbc074d..1bae82e5 100644 --- a/Phaser/gameobjects/Particle.ts +++ b/Phaser/gameobjects/Particle.ts @@ -22,7 +22,6 @@ module Phaser { this.body.type = Types.BODY_DYNAMIC; this.lifespan = 0; - this.friction = 500; } @@ -34,15 +33,7 @@ module Phaser { public lifespan: number; /** - * Determines how quickly the particles come to rest on the ground. - * Only used if the particle has gravity-like acceleration applied. - * @default 500 - */ - public friction: number; - - /** - * The particle's main update logic. Basically it checks to see if it should - * be dead yet, and then has some special bounce behavior if there is some gravity on it. + * The particle's main update logic. Basically it checks to see if it should be dead yet. */ public update() { @@ -59,42 +50,6 @@ module Phaser { this.kill(); } - //simpler bounce/spin behavior for now - if (this.body.touching) - { - if (this.body.angularVelocity != 0) - { - this.body.angularVelocity = -this.body.angularVelocity; - } - } - - if (this.body.acceleration.y > 0) //special behavior for particles with gravity - { - if (this.body.touching & Types.FLOOR) - { - this.body.drag.x = this.friction; - - if (!(this.body.wasTouching & Types.FLOOR)) - { - if (this.body.velocity.y < -this.body.bounce.y * 10) - { - if (this.body.angularVelocity != 0) - { - this.body.angularVelocity *= -this.body.bounce.y; - } - } - else - { - this.body.velocity.y = 0; - this.body.angularVelocity = 0; - } - } - } - else - { - this.body.drag.x = 0; - } - } } /** diff --git a/Phaser/gameobjects/Sprite.ts b/Phaser/gameobjects/Sprite.ts index 488bf62f..524c4009 100644 --- a/Phaser/gameobjects/Sprite.ts +++ b/Phaser/gameobjects/Sprite.ts @@ -23,9 +23,10 @@ module Phaser { * @param [x] {number} the initial x position of the sprite. * @param [y] {number} the initial y position of the sprite. * @param [key] {string} Key of the graphic you want to load for this sprite. - * @param [bodyType] {number} The physics body type of the object (defaults to BODY_DYNAMIC) + * @param [bodyType] {number} The physics body type of the object (defaults to BODY_DISABLED) + * @param [shapeType] {number} The physics shape the body will consist of (either Box (0) or Circle (1), for custom types see body.addShape) */ - constructor(game: Game, x?: number = 0, y?: number = 0, key?: string = null, frame? = null, bodyType?: number = Phaser.Types.BODY_DYNAMIC) { + constructor(game: Game, x?: number = 0, y?: number = 0, key?: string = null, frame? = null, bodyType?: number = Phaser.Types.BODY_DISABLED, shapeType?:number = 0) { this.game = game; this.type = Phaser.Types.SPRITE; @@ -67,7 +68,13 @@ module Phaser { } } - this.body = new Phaser.Physics.Body(this, bodyType); + if (bodyType !== Phaser.Types.BODY_DISABLED) + { + this.body = new Phaser.Physics.Body(this, bodyType, 0, 0, shapeType); + this.game.physics.addBody(this.body); + this.transform.origin.setTo(0.5, 0.5); + } + this.worldView = new Rectangle(x, y, this.width, this.height); this.cameraView = new Rectangle(x, y, this.width, this.height); @@ -118,7 +125,7 @@ module Phaser { /** * Sprite physics body. */ - public body: Phaser.Physics.Body; + public body: Phaser.Physics.Body = null; /** * The texture used to render the Sprite. @@ -268,8 +275,6 @@ module Phaser { this.worldView.x = (this.x * this.transform.scrollFactor.x) - (this.width * this.transform.origin.x); this.worldView.y = (this.y * this.transform.scrollFactor.y) - (this.height * this.transform.origin.y); - //this.worldView.x = this.x * this.transform.scrollFactor.x; - //this.worldView.y = this.y * this.transform.scrollFactor.y; this.worldView.width = this.width; this.worldView.height = this.height; @@ -281,7 +286,7 @@ module Phaser { } /** - * Override this function to update your class's position and appearance. + * Override this function to update your sprites position and appearance. */ public update() { } @@ -292,7 +297,6 @@ module Phaser { public postUpdate() { this.animations.update(); - this.body.postUpdate(); /* if (this.worldBounds != null) diff --git a/Phaser/math/QuadTree.ts b/Phaser/math/QuadTree.ts index 738ab331..03a44fc8 100644 --- a/Phaser/math/QuadTree.ts +++ b/Phaser/math/QuadTree.ts @@ -23,7 +23,7 @@ module Phaser { * @param {Number} height Desired height of this node. * @param {Number} parent The parent branch or node. Pass null to create a root. */ - constructor(manager: Phaser.Physics.PhysicsManager, x: number, y: number, width: number, height: number, parent: QuadTree = null) { + constructor(manager: Phaser.Physics.Manager, x: number, y: number, width: number, height: number, parent: QuadTree = null) { super(x, y, width, height); @@ -104,7 +104,7 @@ module Phaser { private _overlapProcessed: bool; private _checkObject; - public static physics: Phaser.Physics.PhysicsManager; + public static physics: Phaser.Physics.Manager; /** * Flag for specifying that you want to add an object to the A list. @@ -625,7 +625,7 @@ module Phaser { continue; } - //if (QuadTree._object.body.bounds.checkHullIntersection(this._checkObject.body.bounds)) + /* if (QuadTree.physics.checkHullIntersection(QuadTree._object.body, this._checkObject.body)) { //Execute callback functions if they exist @@ -646,6 +646,7 @@ module Phaser { } } } + */ QuadTree._iterator = QuadTree._iterator.next; diff --git a/Phaser/physics/ArcadePhysics.ts b/Phaser/physics/ArcadePhysics.ts deleted file mode 100644 index 00ae9b18..00000000 --- a/Phaser/physics/ArcadePhysics.ts +++ /dev/null @@ -1,1121 +0,0 @@ -/// -/// -/// -/// -/// - -/** -* Phaser - PhysicsManager -* -* Your game only has one PhysicsManager instance and it's responsible for looking after, creating and colliding -* all of the physics objects in the world. -*/ - - -module Phaser.Physics { - - export class ArcadePhysics { - - constructor(game: Game, width: number, height: number) { - - this.game = game; - - this.gravity = new Vec2; - this.drag = new Vec2; - this.bounce = new Vec2; - this.angularDrag = 0; - - this.bounds = new Rectangle(0, 0, width, height); - - this._distance = new Vec2; - this._tangent = new Vec2; - - this.members = new Group(game); - - } - - /** - * Local private reference to Game. - */ - public game: Game; - - /** - * Physics object pool - */ - public members: Group; - - // Temp calculation vars - private _drag: number; - private _delta: number; - private _velocityDelta: number; - private _length: number = 0; - private _distance: Vec2; - private _tangent: Vec2; - private _separatedX: bool; - private _separatedY: bool; - private _overlap: number; - private _maxOverlap: number; - private _obj1Velocity: number; - private _obj2Velocity: number; - private _obj1NewVelocity: number; - private _obj2NewVelocity: number; - private _average: number; - private _quadTree: QuadTree; - private _quadTreeResult: bool; - - public bounds: Rectangle; - - public gravity: Vec2; - public drag: Vec2; - public bounce: Vec2; - public angularDrag: number; - - /** - * The overlap bias is used when calculating hull overlap before separation - change it if you have especially small or large GameObjects - * @type {number} - */ - static OVERLAP_BIAS: number = 4; - - /** - * The overlap bias is used when calculating hull overlap before separation - change it if you have especially small or large GameObjects - * @type {number} - */ - static TILE_OVERLAP: bool = false; - - /** - * @type {number} - */ - public worldDivisions: number = 6; - - - /* - public update() { - - this._length = this._objects.length; - - for (var i = 0; i < this._length; i++) - { - if (this._objects[i]) - { - this._objects[i].preUpdate(); - this.updateMotion(this._objects[i]); - this.collideWorld(this._objects[i]); - - for (var x = 0; x < this._length; x++) - { - if (this._objects[x] && this._objects[x] !== this._objects[i]) - { - //this.collideShapes(this._objects[i], this._objects[x]); - var r = this.NEWseparate(this._objects[i], this._objects[x]); - //console.log('sep', r); - } - } - - } - } - - } - - public render() { - - // iterate through the objects here, updating and colliding - for (var i = 0; i < this._length; i++) - { - if (this._objects[i]) - { - this._objects[i].render(this.game.stage.context); - } - } - - } -*/ - - public updateMotion(body: Phaser.Physics.Body) { - - if (body.type == Types.BODY_DISABLED) - { - return; - } - - this._velocityDelta = (this.computeVelocity(body.angularVelocity, body.gravity.x, body.angularAcceleration, body.angularDrag, body.maxAngular) - body.angularVelocity) / 2; - body.angularVelocity += this._velocityDelta; - body.sprite.transform.rotation += body.angularVelocity * this.game.time.elapsed; - body.angularVelocity += this._velocityDelta; - - this._velocityDelta = (this.computeVelocity(body.velocity.x, body.gravity.x, body.acceleration.x, body.drag.x) - body.velocity.x) / 2; - body.velocity.x += this._velocityDelta; - this._delta = body.velocity.x * this.game.time.elapsed; - body.velocity.x += this._velocityDelta; - //body.position.x += this._delta; - body.sprite.x += this._delta; - - this._velocityDelta = (this.computeVelocity(body.velocity.y, body.gravity.y, body.acceleration.y, body.drag.y) - body.velocity.y) / 2; - body.velocity.y += this._velocityDelta; - this._delta = body.velocity.y * this.game.time.elapsed; - body.velocity.y += this._velocityDelta; - //body.position.y += this._delta; - body.sprite.y += this._delta; - - } - - /** - * A tween-like function that takes a starting velocity and some other factors and returns an altered velocity. - * - * @param {number} Velocity Any component of velocity (e.g. 20). - * @param {number} Acceleration Rate at which the velocity is changing. - * @param {number} Drag Really kind of a deceleration, this is how much the velocity changes if Acceleration is not set. - * @param {number} Max An absolute value cap for the velocity. - * - * @return {number} The altered Velocity value. - */ - public computeVelocity(velocity: number, gravity: number = 0, acceleration: number = 0, drag: number = 0, max: number = 10000): number { - - if (acceleration !== 0) - { - velocity += (acceleration + gravity) * this.game.time.elapsed; - } - else if (drag !== 0) - { - this._drag = drag * this.game.time.elapsed; - - if (velocity - this._drag > 0) - { - velocity = velocity - this._drag; - } - else if (velocity + this._drag < 0) - { - velocity += this._drag; - } - else - { - velocity = 0; - } - - velocity += gravity; - } - - if ((velocity != 0) && (max != 10000)) - { - if (velocity > max) - { - velocity = max; - } - else if (velocity < -max) - { - velocity = -max; - } - } - - return velocity; - - } - - /** - * The core Collision separation method. - * @param body1 The first Physics.Body to separate - * @param body2 The second Physics.Body to separate - * @returns {boolean} Returns true if the bodies were separated, otherwise false. - */ - public separate(body1: Body, body2: Body): bool { - - this._separatedX = this.separateBodyX(body1, body2); - this._separatedY = this.separateBodyY(body1, body2); - - return this._separatedX || this._separatedY; - - } - - public checkHullIntersection(body1: Body, body2:Body): bool { - return ((body1.hullX + body1.hullWidth > body2.hullX) && (body1.hullX < body2.hullX + body2.hullWidth) && (body1.hullY + body1.hullHeight > body2.hullY) && (body1.hullY < body2.hullY + body2.hullHeight)); - } - - /** - * Separates the two objects on their x axis - * @param object1 The first GameObject to separate - * @param object2 The second GameObject to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the X axis. - */ - public separateBodyX(body1: Body, body2: Body): bool { - - // Can't separate two disabled or static objects - if ((body1.type == Types.BODY_DISABLED || body1.type == Types.BODY_STATIC) && (body2.type == Types.BODY_DISABLED || body2.type == Types.BODY_STATIC)) - { - return false; - } - - // First, get the two object deltas - this._overlap = 0; - - if (body1.deltaX != body2.deltaX) - { - if (RectangleUtils.intersects(body1.bounds, body2.bounds)) - { - this._maxOverlap = body1.deltaXAbs + body2.deltaXAbs + PhysicsManager.OVERLAP_BIAS; - - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if (body1.deltaX > body2.deltaX) - { - this._overlap = body1.bounds.right - body2.bounds.x; - - if ((this._overlap > this._maxOverlap) || !(body1.allowCollisions & Types.RIGHT) || !(body2.allowCollisions & Types.LEFT)) - { - this._overlap = 0; - } - else - { - body1.touching |= Types.RIGHT; - body2.touching |= Types.LEFT; - } - } - else if (body1.deltaX < body2.deltaX) - { - this._overlap = body1.bounds.x - body2.bounds.width - body2.bounds.x; - - if ((-this._overlap > this._maxOverlap) || !(body1.allowCollisions & Types.LEFT) || !(body2.allowCollisions & Types.RIGHT)) - { - this._overlap = 0; - } - else - { - body1.touching |= Types.LEFT; - body2.touching |= Types.RIGHT; - } - } - } - } - - // Then adjust their positions and velocities accordingly (if there was any overlap) - if (this._overlap != 0) - { - this._obj1Velocity = body1.velocity.x; - this._obj2Velocity = body2.velocity.x; - - /** - * Dynamic = gives and receives impacts - * Static = gives but doesn't receive impacts, cannot be moved by physics - * Kinematic = gives impacts, but never receives, can be moved by physics - */ - - // 2 dynamic bodies will exchange velocities - if (body1.type == Types.BODY_DYNAMIC && body2.type == Types.BODY_DYNAMIC) - { - this._overlap *= 0.5; - body1.position.x = body1.position.x - this._overlap; - body2.position.x += this._overlap; - - this._obj1NewVelocity = Math.sqrt((this._obj2Velocity * this._obj2Velocity * body2.mass) / body1.mass) * ((this._obj2Velocity > 0) ? 1 : -1); - this._obj2NewVelocity = Math.sqrt((this._obj1Velocity * this._obj1Velocity * body1.mass) / body2.mass) * ((this._obj1Velocity > 0) ? 1 : -1); - this._average = (this._obj1NewVelocity + this._obj2NewVelocity) * 0.5; - this._obj1NewVelocity -= this._average; - this._obj2NewVelocity -= this._average; - body1.velocity.x = this._average + this._obj1NewVelocity * body1.bounce.x; - body2.velocity.x = this._average + this._obj2NewVelocity * body2.bounce.x; - } - else if (body2.type != Types.BODY_DYNAMIC) - { - // Body 2 is Static or Kinematic - this._overlap *= 2; - body1.position.x -= this._overlap; - body1.velocity.x = this._obj2Velocity - this._obj1Velocity * body1.bounce.x; - } - else if (body1.type != Types.BODY_DYNAMIC) - { - // Body 1 is Static or Kinematic - this._overlap *= 2; - body2.position.x += this._overlap; - body2.velocity.x = this._obj1Velocity - this._obj2Velocity * body2.bounce.x; - } - - return true; - } - else - { - return false; - } - - } - - /** - * Separates the two objects on their y axis - * @param object1 The first GameObject to separate - * @param object2 The second GameObject to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis. - */ - public separateBodyY(body1: Body, body2: Body): bool { - - // Can't separate two immovable objects - if ((body1.type == Types.BODY_DISABLED || body1.type == Types.BODY_STATIC) && (body2.type == Types.BODY_DISABLED || body2.type == Types.BODY_STATIC)) - { - return false; - } - - // First, get the two object deltas - this._overlap = 0; - - if (body1.deltaY != body2.deltaY) - { - if (RectangleUtils.intersects(body1.bounds, body2.bounds)) - { - // This is the only place to use the DeltaAbs values - this._maxOverlap = body1.deltaYAbs + body2.deltaYAbs + PhysicsManager.OVERLAP_BIAS; - - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if (body1.deltaY > body2.deltaY) - { - this._overlap = body1.bounds.bottom - body2.bounds.y; - - if ((this._overlap > this._maxOverlap) || !(body1.allowCollisions & Types.DOWN) || !(body2.allowCollisions & Types.UP)) - { - this._overlap = 0; - } - else - { - body1.touching |= Types.DOWN; - body2.touching |= Types.UP; - } - } - else if (body1.deltaY < body2.deltaY) - { - this._overlap = body1.bounds.y - body2.bounds.height - body2.bounds.y; - - if ((-this._overlap > this._maxOverlap) || !(body1.allowCollisions & Types.UP) || !(body2.allowCollisions & Types.DOWN)) - { - this._overlap = 0; - } - else - { - body1.touching |= Types.UP; - body2.touching |= Types.DOWN; - } - } - } - } - - // Then adjust their positions and velocities accordingly (if there was any overlap) - if (this._overlap != 0) - { - this._obj1Velocity = body1.velocity.y; - this._obj2Velocity = body2.velocity.y; - - /** - * Dynamic = gives and receives impacts - * Static = gives but doesn't receive impacts, cannot be moved by physics - * Kinematic = gives impacts, but never receives, can be moved by physics - */ - - if (body1.type == Types.BODY_DYNAMIC && body2.type == Types.BODY_DYNAMIC) - { - this._overlap *= 0.5; - body1.position.y = body1.position.y - this._overlap; - body2.position.y += this._overlap; - - this._obj1NewVelocity = Math.sqrt((this._obj2Velocity * this._obj2Velocity * body2.mass) / body1.mass) * ((this._obj2Velocity > 0) ? 1 : -1); - this._obj2NewVelocity = Math.sqrt((this._obj1Velocity * this._obj1Velocity * body1.mass) / body2.mass) * ((this._obj1Velocity > 0) ? 1 : -1); - var average: number = (this._obj1NewVelocity + this._obj2NewVelocity) * 0.5; - this._obj1NewVelocity -= average; - this._obj2NewVelocity -= average; - body1.velocity.y = average + this._obj1NewVelocity * body1.bounce.y; - body2.velocity.y = average + this._obj2NewVelocity * body2.bounce.y; - } - else if (body2.type != Types.BODY_DYNAMIC) - { - this._overlap *= 2; - body1.position.y -= this._overlap; - body1.velocity.y = this._obj2Velocity - this._obj1Velocity * body1.bounce.y; - // This is special case code that handles things like horizontal moving platforms you can ride - //if (body2.parent.active && body2.moves && (body1.deltaY > body2.deltaY)) - if (body2.sprite.active && (body1.deltaY > body2.deltaY)) - { - body1.position.x += body2.position.x - body2.oldPosition.x; - } - } - else if (body1.type != Types.BODY_DYNAMIC) - { - this._overlap *= 2; - body2.position.y += this._overlap; - body2.velocity.y = this._obj1Velocity - this._obj2Velocity * body2.bounce.y; - // This is special case code that handles things like horizontal moving platforms you can ride - //if (object1.active && body1.moves && (body1.deltaY < body2.deltaY)) - if (body1.sprite.active && (body1.deltaY < body2.deltaY)) - { - body2.position.x += body1.position.x - body1.oldPosition.x; - } - } - - return true; - } - else - { - return false; - } - } - - - - - - - - /* - private TILEseparate(shapeA: IPhysicsShape, shapeB: IPhysicsShape, distance: Vec2, tangent: Vec2) { - - if (tangent.x == 1) - { - console.log('1 The left side of ShapeA hit the right side of ShapeB', Math.floor(distance.x)); - shapeA.physics.touching |= Phaser.Types.LEFT; - shapeB.physics.touching |= Phaser.Types.RIGHT; - } - else if (tangent.x == -1) - { - console.log('2 The right side of ShapeA hit the left side of ShapeB', Math.floor(distance.x)); - shapeA.physics.touching |= Phaser.Types.RIGHT; - shapeB.physics.touching |= Phaser.Types.LEFT; - } - - if (tangent.y == 1) - { - console.log('3 The top of ShapeA hit the bottom of ShapeB', Math.floor(distance.y)); - shapeA.physics.touching |= Phaser.Types.UP; - shapeB.physics.touching |= Phaser.Types.DOWN; - } - else if (tangent.y == -1) - { - console.log('4 The bottom of ShapeA hit the top of ShapeB', Math.floor(distance.y)); - shapeA.physics.touching |= Phaser.Types.DOWN; - shapeB.physics.touching |= Phaser.Types.UP; - } - - - // only apply collision response forces if the object is travelling into, and not out of, the collision - var dot = Vec2Utils.dot(shapeA.physics.velocity, tangent); - - if (dot < 0) - { - console.log('in to', dot); - - // Apply horizontal bounce - if (shapeA.physics.bounce.x > 0) - { - shapeA.physics.velocity.x *= -(shapeA.physics.bounce.x); - } - else - { - shapeA.physics.velocity.x = 0; - } - // Apply horizontal bounce - if (shapeA.physics.bounce.y > 0) - { - shapeA.physics.velocity.y *= -(shapeA.physics.bounce.y); - } - else - { - shapeA.physics.velocity.y = 0; - } - } - else - { - console.log('out of', dot); - } - - shapeA.position.x += Math.floor(distance.x); - //shapeA.bounds.x += Math.floor(distance.x); - - shapeA.position.y += Math.floor(distance.y); - //shapeA.bounds.y += distance.y; - - console.log('------------------------------------------------'); - - } - - private collideWorld(shape:IPhysicsShape) { - - // Collide on the x-axis - this._distance.x = shape.world.bounds.x - (shape.position.x - shape.bounds.halfWidth); - - if (0 < this._distance.x) - { - // Hit Left - this._tangent.setTo(1, 0); - this.separateXWall(shape, this._distance, this._tangent); - } - else - { - this._distance.x = (shape.position.x + shape.bounds.halfWidth) - shape.world.bounds.right; - - if (0 < this._distance.x) - { - // Hit Right - this._tangent.setTo(-1, 0); - this._distance.reverse(); - this.separateXWall(shape, this._distance, this._tangent); - } - } - - // Collide on the y-axis - this._distance.y = shape.world.bounds.y - (shape.position.y - shape.bounds.halfHeight); - - if (0 < this._distance.y) - { - // Hit Top - this._tangent.setTo(0, 1); - this.separateYWall(shape, this._distance, this._tangent); - } - else - { - this._distance.y = (shape.position.y + shape.bounds.halfHeight) - shape.world.bounds.bottom; - - if (0 < this._distance.y) - { - // Hit Bottom - this._tangent.setTo(0, -1); - this._distance.reverse(); - this.separateYWall(shape, this._distance, this._tangent); - } - } - - } - - private separateX(shapeA: IPhysicsShape, shapeB: IPhysicsShape, distance: Vec2, tangent: Vec2) { - - if (tangent.x == 1) - { - console.log('The left side of ShapeA hit the right side of ShapeB', distance.x); - shapeA.physics.touching |= Phaser.Types.LEFT; - shapeB.physics.touching |= Phaser.Types.RIGHT; - } - else - { - console.log('The right side of ShapeA hit the left side of ShapeB', distance.x); - shapeA.physics.touching |= Phaser.Types.RIGHT; - shapeB.physics.touching |= Phaser.Types.LEFT; - } - - // collision edges - //shapeA.oH = tangent.x; - - // only apply collision response forces if the object is travelling into, and not out of, the collision - if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) - { - // Apply horizontal bounce - if (shapeA.physics.bounce.x > 0) - { - shapeA.physics.velocity.x *= -(shapeA.physics.bounce.x); - } - else - { - shapeA.physics.velocity.x = 0; - } - } - - shapeA.position.x += distance.x; - shapeA.bounds.x += distance.x; - - } - - private separateY(shapeA: IPhysicsShape, shapeB: IPhysicsShape, distance: Vec2, tangent: Vec2) { - - if (tangent.y == 1) - { - console.log('The top of ShapeA hit the bottom of ShapeB', distance.y); - shapeA.physics.touching |= Phaser.Types.UP; - shapeB.physics.touching |= Phaser.Types.DOWN; - } - else - { - console.log('The bottom of ShapeA hit the top of ShapeB', distance.y); - shapeA.physics.touching |= Phaser.Types.DOWN; - shapeB.physics.touching |= Phaser.Types.UP; - } - - // collision edges - //shapeA.oV = tangent.y; - - // only apply collision response forces if the object is travelling into, and not out of, the collision - if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) - { - // Apply horizontal bounce - if (shapeA.physics.bounce.y > 0) - { - shapeA.physics.velocity.y *= -(shapeA.physics.bounce.y); - } - else - { - shapeA.physics.velocity.y = 0; - } - } - - shapeA.position.y += distance.y; - shapeA.bounds.y += distance.y; - - } - - private separateXWall(shapeA: IPhysicsShape, distance: Vec2, tangent: Vec2) { - - if (tangent.x == 1) - { - console.log('The left side of ShapeA hit the right side of ShapeB', distance.x); - shapeA.physics.touching |= Phaser.Types.LEFT; - } - else - { - console.log('The right side of ShapeA hit the left side of ShapeB', distance.x); - shapeA.physics.touching |= Phaser.Types.RIGHT; - } - - // collision edges - //shapeA.oH = tangent.x; - - // only apply collision response forces if the object is travelling into, and not out of, the collision - if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) - { - // Apply horizontal bounce - if (shapeA.physics.bounce.x > 0) - { - shapeA.physics.velocity.x *= -(shapeA.physics.bounce.x); - } - else - { - shapeA.physics.velocity.x = 0; - } - } - - shapeA.position.x += distance.x; - - } - - private separateYWall(shapeA: IPhysicsShape, distance: Vec2, tangent: Vec2) { - - if (tangent.y == 1) - { - console.log('The top of ShapeA hit the bottom of ShapeB', distance.y); - shapeA.physics.touching |= Phaser.Types.UP; - } - else - { - console.log('The bottom of ShapeA hit the top of ShapeB', distance.y); - shapeA.physics.touching |= Phaser.Types.DOWN; - } - - // collision edges - //shapeA.oV = tangent.y; - - // only apply collision response forces if the object is travelling into, and not out of, the collision - if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) - { - // Apply horizontal bounce - if (shapeA.physics.bounce.y > 0) - { - shapeA.physics.velocity.y *= -(shapeA.physics.bounce.y); - } - else - { - shapeA.physics.velocity.y = 0; - } - } - - shapeA.position.y += distance.y; - - } - */ - - /** - * Checks for overlaps between two objects using the world QuadTree. Can be Sprite vs. Sprite, Sprite vs. Group or Group vs. Group. - * Note: Does not take the objects scrollFactor into account. All overlaps are check in world space. - * @param object1 The first Sprite or Group to check. If null the world.group is used. - * @param object2 The second Sprite or Group to check. - * @param notifyCallback A callback function that is called if the objects overlap. The two objects will be passed to this function in the same order in which you passed them to Collision.overlap. - * @param processCallback A callback function that lets you perform additional checks against the two objects if they overlap. If this is set then notifyCallback will only be called if processCallback returns true. - * @param context The context in which the callbacks will be called - * @returns {boolean} true if the objects overlap, otherwise false. - */ - public overlap(object1 = null, object2 = null, notifyCallback = null, processCallback = null, context = null): bool { - - /* - if (object1 == null) - { - object1 = this.game.world.group; - } - - if (object2 == object1) - { - object2 = null; - } - - QuadTree.divisions = this.worldDivisions; - - this._quadTree = new Phaser.QuadTree(this, this.bounds.x, this.bounds.y, this.bounds.width, this.bounds.height); - - this._quadTree.load(object1, object2, notifyCallback, processCallback, context); - - this._quadTreeResult = this._quadTree.execute(); - - console.log('over', this._quadTreeResult); - - this._quadTree.destroy(); - - this._quadTree = null; - - return this._quadTreeResult; - */ - - return false; - - } - - - - - - - /** - * Collision resolution specifically for GameObjects vs. Tiles. - * @param object The GameObject to separate - * @param tile The Tile to separate - * @returns {boolean} Whether the objects in fact touched and were separated - */ - public separateTile(object:Sprite, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool, collideUp: bool, collideDown: bool, separateX: bool, separateY: bool): bool { - - //var separatedX: bool = this.separateTileX(object, x, y, width, height, mass, collideLeft, collideRight, separateX); - //var separatedY: bool = this.separateTileY(object, x, y, width, height, mass, collideUp, collideDown, separateY); - - //return separatedX || separatedY; - - return false; - - } - - /** - * Separates the two objects on their x axis - * @param object The GameObject to separate - * @param tile The Tile to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the X axis. - */ - /* - public separateTileX(object:Sprite, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool, separate: bool): bool { - - // Can't separate two immovable objects (tiles are always immovable) - if (object.immovable) - { - return false; - } - - // First, get the object delta - var overlap: number = 0; - var objDelta: number = object.x - object.last.x; - //var objDelta: number = object.collisionMask.deltaX; - - if (objDelta != 0) - { - // Check if the X hulls actually overlap - var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; - //var objDeltaAbs: number = object.collisionMask.deltaXAbs; - var objBounds: Rectangle = new Rectangle(object.x - ((objDelta > 0) ? objDelta : 0), object.last.y, object.width + ((objDelta > 0) ? objDelta : -objDelta), object.height); - - if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) - { - var maxOverlap: number = objDeltaAbs + Collision.OVERLAP_BIAS; - - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if (objDelta > 0) - { - overlap = object.x + object.width - x; - - if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.RIGHT) || collideLeft == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.RIGHT; - } - } - else if (objDelta < 0) - { - overlap = object.x - width - x; - - if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.LEFT) || collideRight == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.LEFT; - } - - } - - } - } - - // Then adjust their positions and velocities accordingly (if there was any overlap) - if (overlap != 0) - { - if (separate == true) - { - //console.log(' - object.x = object.x - overlap; - object.velocity.x = -(object.velocity.x * object.elasticity); - } - - Collision.TILE_OVERLAP = true; - return true; - } - else - { - return false; - } - - } - */ - - /** - * Separates the two objects on their y axis - * @param object The first GameObject to separate - * @param tile The second GameObject to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis. - */ - /* - public separateTileY(object: Sprite, x: number, y: number, width: number, height: number, mass: number, collideUp: bool, collideDown: bool, separate: bool): bool { - - // Can't separate two immovable objects (tiles are always immovable) - if (object.immovable) - { - return false; - } - - // First, get the two object deltas - var overlap: number = 0; - var objDelta: number = object.y - object.last.y; - - if (objDelta != 0) - { - // Check if the Y hulls actually overlap - var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; - var objBounds: Rectangle = new Rectangle(object.x, object.y - ((objDelta > 0) ? objDelta : 0), object.width, object.height + objDeltaAbs); - - if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) - { - var maxOverlap: number = objDeltaAbs + Collision.OVERLAP_BIAS; - - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if (objDelta > 0) - { - overlap = object.y + object.height - y; - - if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.DOWN) || collideUp == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.DOWN; - } - } - else if (objDelta < 0) - { - overlap = object.y - height - y; - - if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.UP) || collideDown == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.UP; - } - } - } - } - - // TODO - with super low velocities you get lots of stuttering, set some kind of base minimum here - - // Then adjust their positions and velocities accordingly (if there was any overlap) - if (overlap != 0) - { - if (separate == true) - { - object.y = object.y - overlap; - object.velocity.y = -(object.velocity.y * object.elasticity); - } - - Collision.TILE_OVERLAP = true; - return true; - } - else - { - return false; - } - } - */ - - - /** - * Separates the two objects on their x axis - * @param object The GameObject to separate - * @param tile The Tile to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the X axis. - */ - /* - public static NEWseparateTileX(object:Sprite, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool, separate: bool): bool { - - // Can't separate two immovable objects (tiles are always immovable) - if (object.immovable) - { - return false; - } - - // First, get the object delta - var overlap: number = 0; - - if (object.collisionMask.deltaX != 0) - { - // Check if the X hulls actually overlap - //var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; - //var objBounds: Rectangle = new Rectangle(object.x - ((objDelta > 0) ? objDelta : 0), object.last.y, object.width + ((objDelta > 0) ? objDelta : -objDelta), object.height); - - //if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) - if (object.collisionMask.intersectsRaw(x, x + width, y, y + height)) - { - var maxOverlap: number = object.collisionMask.deltaXAbs + Collision.OVERLAP_BIAS; - - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if (object.collisionMask.deltaX > 0) - { - //overlap = object.x + object.width - x; - overlap = object.collisionMask.right - x; - - if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.RIGHT) || collideLeft == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.RIGHT; - } - } - else if (object.collisionMask.deltaX < 0) - { - //overlap = object.x - width - x; - overlap = object.collisionMask.x - width - x; - - if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.LEFT) || collideRight == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.LEFT; - } - - } - - } - } - - // Then adjust their positions and velocities accordingly (if there was any overlap) - if (overlap != 0) - { - if (separate == true) - { - object.x = object.x - overlap; - object.velocity.x = -(object.velocity.x * object.elasticity); - } - - Collision.TILE_OVERLAP = true; - return true; - } - else - { - return false; - } - - } - */ - - /** - * Separates the two objects on their y axis - * @param object The first GameObject to separate - * @param tile The second GameObject to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis. - */ - /* - public NEWseparateTileY(object: Sprite, x: number, y: number, width: number, height: number, mass: number, collideUp: bool, collideDown: bool, separate: bool): bool { - - // Can't separate two immovable objects (tiles are always immovable) - if (object.immovable) - { - return false; - } - - // First, get the two object deltas - var overlap: number = 0; - //var objDelta: number = object.y - object.last.y; - - if (object.collisionMask.deltaY != 0) - { - // Check if the Y hulls actually overlap - //var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; - //var objBounds: Rectangle = new Rectangle(object.x, object.y - ((objDelta > 0) ? objDelta : 0), object.width, object.height + objDeltaAbs); - - //if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) - if (object.collisionMask.intersectsRaw(x, x + width, y, y + height)) - { - //var maxOverlap: number = objDeltaAbs + Collision.OVERLAP_BIAS; - var maxOverlap: number = object.collisionMask.deltaYAbs + Collision.OVERLAP_BIAS; - - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if (object.collisionMask.deltaY > 0) - { - //overlap = object.y + object.height - y; - overlap = object.collisionMask.bottom - y; - - if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.DOWN) || collideUp == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.DOWN; - } - } - else if (object.collisionMask.deltaY < 0) - { - //overlap = object.y - height - y; - overlap = object.collisionMask.y - height - y; - - if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.UP) || collideDown == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.UP; - } - } - } - } - - // TODO - with super low velocities you get lots of stuttering, set some kind of base minimum here - - // Then adjust their positions and velocities accordingly (if there was any overlap) - if (overlap != 0) - { - if (separate == true) - { - object.y = object.y - overlap; - object.velocity.y = -(object.velocity.y * object.elasticity); - } - - Collision.TILE_OVERLAP = true; - return true; - } - else - { - return false; - } - } - */ - - } - -} \ No newline at end of file diff --git a/Phaser/physics/Body.ts b/Phaser/physics/Body.ts index a4b7a9f8..aa9c82d1 100644 --- a/Phaser/physics/Body.ts +++ b/Phaser/physics/Body.ts @@ -1,52 +1,93 @@ /// /// /// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// /** -* Phaser - Physics - Body +* Phaser - Advanced Physics - Body +* +* Based on the work Ju Hyung Lee started in JS PhyRus. */ module Phaser.Physics { export class Body { - constructor(sprite: Phaser.Sprite, type: number) { + constructor(sprite: Phaser.Sprite, type: number, x?: number = 0, y?: number = 0, shapeType?: number = 0) { - this.sprite = sprite; - this.game = sprite.game; + this.id = Phaser.Physics.Manager.bodyCounter++; + this.name = 'body' + this.id; this.type = type; - // Fixture properties - // Will extend into its own class at a later date - can move the fixture defs there and add shape support, but this will do for 1.0 release - this.bounds = new Rectangle; - - this._width = sprite.width; - this._height = sprite.height; - - - // Body properties - this.gravity = Vec2Utils.clone(this.game.world.physics.gravity); - this.bounce = Vec2Utils.clone(this.game.world.physics.bounce); - - this.velocity = new Vec2; - this.acceleration = new Vec2; - this.drag = Vec2Utils.clone(this.game.world.physics.drag); - this.maxVelocity = new Vec2(10000, 10000); + if (sprite) + { + this.sprite = sprite; + this.game = sprite.game; + this.position = new Phaser.Vec2(Phaser.Physics.Manager.pixelsToMeters(sprite.x), Phaser.Physics.Manager.pixelsToMeters(sprite.y)); + this.angle = sprite.rotation; + } + else + { + this.position = new Phaser.Vec2(Phaser.Physics.Manager.pixelsToMeters(x), Phaser.Physics.Manager.pixelsToMeters(y)); + this.angle = 0; + } + this.transform = new Phaser.Transform(this.position, this.angle); + this.centroid = new Phaser.Vec2; + this.velocity = new Phaser.Vec2; + this.force = new Phaser.Vec2; this.angularVelocity = 0; - this.angularAcceleration = 0; - this.angularDrag = 0; + this.torque = 0; + this.linearDamping = 0; + this.angularDamping = 0; + this.sleepTime = 0; + this.awaked = false; - this.touching = Types.NONE; - this.wasTouching = Types.NONE; - this.allowCollisions = Types.ANY; + this.shapes = []; + this.joints = []; + this.jointHash = {}; - this.position = new Vec2(sprite.x + this.bounds.halfWidth, sprite.y + this.bounds.halfHeight); - this.oldPosition = new Vec2(sprite.x + this.bounds.halfWidth, sprite.y + this.bounds.halfHeight); - this.offset = new Vec2; + this.bounds = new Bounds; + + this.allowCollisions = Phaser.Types.ANY; + this.fixedRotation = false; + + this.categoryBits = 0x0001; + this.maskBits = 0xFFFF; + + this.stepCount = 0; + + if (sprite) + { + if (shapeType == 0) + { + this.addBox(0, 0, this.sprite.width, this.sprite.height, 1, 1, 1); + } + else + { + this.addCircle(Math.max(this.sprite.width, this.sprite.height) / 2, 0, 0, 1, 1, 1); + } + } } + public toString(): string { + return "[{Body (name=" + this.name + " velocity=" + this.velocity.toString() + " angularVelocity: " + this.angularVelocity + ")}]"; + } + + private _tempVec2: Phaser.Vec2 = new Phaser.Vec2; + /** * Reference to Phaser.Game */ @@ -57,6 +98,16 @@ module Phaser.Physics { */ public sprite: Phaser.Sprite; + /** + * The Body ID + */ + public id: number; + + /** + * The Body name + */ + public name: string; + /** * The type of Body (disabled, dynamic, static or kinematic) * Disabled = skips all physics operations / tests (default) @@ -67,243 +118,586 @@ module Phaser.Physics { */ public type: number; - public gravity: Vec2; - public bounce: Vec2; + public angle: number; - public velocity: Vec2; - public acceleration: Vec2; - public drag: Vec2; - public maxVelocity: Vec2; + // Local to world transform + public transform: Phaser.Transform; - public angularVelocity: number = 0; - public angularAcceleration: number = 0; - public angularDrag: number = 0; - public maxAngular: number = 10000; + // Local center of mass + public centroid: Phaser.Vec2; - /** - * Orientation of the object. - * @type {number} - */ - public facing: number; + // World position of centroid + public position: Phaser.Vec2; - public touching: number; + // Velocity + public velocity: Phaser.Vec2; + + // Force + public force: Phaser.Vec2; + + // Angular velocity + public angularVelocity: number; + + // Torque + public torque: number; + + // Linear damping + public linearDamping: number; + + // Angular damping + public angularDamping: number; + + // Sleep time + public sleepTime: number; + + // Awaked + public awaked: bool; + + // Allow Collisions public allowCollisions: number; - public wasTouching: number; - public mass: number = 1; - public position: Vec2; - public oldPosition: Vec2; - public offset: Vec2; - public bounds: Rectangle; + // Shapes + public shapes: IShape[] = []; + // Length of the shapes array + public shapesLength: number; + // Joints + public joints: IJoint[] = []; + public jointHash = {}; - private _width: number = 0; - private _height: number = 0; + // Bounds of all shapes + public bounds: Bounds; - public get x(): number { - return this.sprite.x + this.offset.x; - } + public mass: number; + public massInverted: number; + public inertia: number; + public inertiaInverted: number; - public get y(): number { - return this.sprite.y + this.offset.y; - } + public fixedRotation = false; + public categoryBits = 0x0001; + public maskBits = 0xFFFF; + public stepCount = 0; + public space: Space; - public set width(value: number) { - this._width = value; - } + public duplicate() { - public set height(value: number) { - this._height = value; - } + console.log('body duplicate called'); - public get width(): number { - return this._width * this.sprite.transform.scale.x; - } + //var body = new Body(this.type, this.transform.t, this.angle); + + //for (var i = 0; i < this.shapes.length; i++) + //{ + // body.addShape(this.shapes[i].duplicate()); + //} - public get height(): number { - return this._height * this.sprite.transform.scale.y; - } + //body.resetMassData(); - public preUpdate() { + //return body; - this.oldPosition.copyFrom(this.position); + } - this.bounds.x = this.x; - this.bounds.y = this.y; - this.bounds.width = this.width; - this.bounds.height = this.height; + public get isDisabled(): bool { + return this.type == Phaser.Types.BODY_DISABLED ? true : false; + } - } + public get isStatic(): bool { + return this.type == Phaser.Types.BODY_STATIC ? true : false; + } - // Shall we do this? Or just update the values directly in the separate functions? But then the bounds will be out of sync - as long as - // the bounds are updated and used in calculations then we can do one final sprite movement here I guess? - public postUpdate() { + public get isKinetic(): bool { + return this.type == Phaser.Types.BODY_KINETIC ? true : false; + } - // if this is all it does maybe move elsewhere? Sprite postUpdate? - if (this.type !== Phaser.Types.BODY_DISABLED) + public get isDynamic(): bool { + return this.type == Phaser.Types.BODY_DYNAMIC ? true : false; + } + + public setType(type: number) { + + if (type == this.type) + { + return; + } + + this.force.setTo(0, 0); + this.velocity.setTo(0, 0); + this.torque = 0; + this.angularVelocity = 0; + this.type = type; + + this.awake(true); + + } + + public addPoly(verts, elasticity?: number = 1, friction?: number = 1, density?: number = 1): Phaser.Physics.Shapes.Poly { + + var poly: Phaser.Physics.Shapes.Poly = new Phaser.Physics.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.Shapes.Triangle { + + var tri: Phaser.Physics.Shapes.Triangle = new Phaser.Physics.Shapes.Triangle(x1, y1, x2, y2, x3, y3); + tri.elasticity = elasticity; + tri.friction = friction; + tri.density = density; + + this.addShape(tri); + this.resetMassData(); + + return tri; + + } + + public addBox(x: number, y: number, width: number, height: number, elasticity?: number = 1, friction?: number = 1, density?: number = 1): Phaser.Physics.Shapes.Box { + + var box: Phaser.Physics.Shapes.Box = new Phaser.Physics.Shapes.Box(x, y, width, height); + box.elasticity = elasticity; + box.friction = friction; + box.density = density; + + this.addShape(box); + this.resetMassData(); + + return box; + + } + + public addCircle(radius: number, x?: number = 0, y?: number = 0, elasticity?: number = 1, friction?: number = 1, density?: number = 1): Phaser.Physics.Shapes.Circle { + + var circle: Phaser.Physics.Shapes.Circle = new Phaser.Physics.Shapes.Circle(radius, x, y); + circle.elasticity = elasticity; + circle.friction = friction; + circle.density = density; + + this.addShape(circle); + this.resetMassData(); + + return circle; + + } + + public addShape(shape) { + + // Check not already part of this body + shape.body = this; + + this.shapes.push(shape); + + this.shapesLength = this.shapes.length; + + return shape; + + } + + public removeShape(shape) { + + var index = this.shapes.indexOf(shape); + + if (index != -1) + { + this.shapes.splice(index, 1); + shape.body = undefined; + } + + this.shapesLength = this.shapes.length; + + } + + private setMass(mass) { + + this.mass = mass; + this.massInverted = mass > 0 ? 1 / mass : 0; + + } + + private setInertia(inertia) { + + this.inertia = inertia; + this.inertiaInverted = inertia > 0 ? 1 / inertia : 0; + + } + + public setTransform(pos, angle) { + + // inject the transform into this.position + this.transform.setTo(pos, angle); + Manager.write('setTransform: ' + this.position.toString()); + Manager.write('centroid: ' + this.centroid.toString()); + Phaser.TransformUtils.transform(this.transform, this.centroid, this.position); + Manager.write('post setTransform: ' + this.position.toString()); + //this.position.copyFrom(this.transform.transform(this.centroid)); + this.angle = angle; + + } + + 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); + // 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('--------------------'); + + } + + public getWorldPoint(p:Phaser.Vec2) { + // OPTIMISE: Creating new vector + return Phaser.TransformUtils.transform(this.transform, p); + } + + public getWorldVector(v:Phaser.Vec2) { + // OPTIMISE: Creating new vector + return Phaser.TransformUtils.rotate(this.transform, v); + } + + public getLocalPoint(p:Phaser.Vec2) { + // OPTIMISE: Creating new vector + return Phaser.TransformUtils.untransform(this.transform, p); + } + + public getLocalVector(v:Phaser.Vec2) { + // OPTIMISE: Creating new vector + return Phaser.TransformUtils.unrotate(this.transform, v); + } + + public setFixedRotation(flag) { + this.fixedRotation = flag; + this.resetMassData(); + } + + public resetMassData() { + + this.centroid.setTo(0, 0); + this.mass = 0; + this.massInverted = 0; + this.inertia = 0; + this.inertiaInverted = 0; + + if (this.isDynamic == false) + { + Phaser.TransformUtils.transform(this.transform, this.centroid, this.position); + //this.position.copyFrom(this.transform.transform(this.centroid)); + return; + } + + var totalMassCentroid = new Phaser.Vec2(0, 0); + var totalMass = 0; + var totalInertia = 0; + + for (var i = 0; i < this.shapes.length; i++) + { + var shape = this.shapes[i]; + var centroid = shape.centroid(); + var mass = shape.area() * shape.density; + var inertia = shape.inertia(mass); + + //console.log('rmd', centroid, shape); + + totalMassCentroid.multiplyAddByScalar(centroid, mass); + totalMass += mass; + totalInertia += inertia; + } + + //this.centroid.copy(vec2.scale(totalMassCentroid, 1 / totalMass)); + Phaser.Vec2Utils.scale(totalMassCentroid, 1 / totalMass, this.centroid); + + this.setMass(totalMass); + + if (!this.fixedRotation) + { + this.setInertia(totalInertia - totalMass * Phaser.Vec2Utils.dot(this.centroid, this.centroid)); + } + + // Move center of mass + var oldPosition: Phaser.Vec2 = Phaser.Vec2Utils.clone(this.position); + Phaser.TransformUtils.transform(this.transform, this.centroid, this.position); + + // Update center of mass velocity + oldPosition.subtract(this.position); + this.velocity.multiplyAddByScalar(Phaser.Vec2Utils.perp(oldPosition, oldPosition), this.angularVelocity); + + } + + public resetJointAnchors() { + + for (var i = 0; i < this.joints.length; i++) + { + var joint = this.joints[i]; + + if (!joint) + { + continue; + } + + var anchor1 = joint.getWorldAnchor1(); + var anchor2 = joint.getWorldAnchor2(); + + joint.setWorldAnchor1(anchor1); + joint.setWorldAnchor2(anchor2); + } + } + + public cacheData(source:string = '') { + + 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: 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) { + + Phaser.Vec2Utils.multiplyAdd(gravity, this.force, this.massInverted, this._tempVec2); + Phaser.Vec2Utils.multiplyAdd(this.velocity, this._tempVec2, dt, this.velocity); + + this.angularVelocity = this.angularVelocity + this.torque * this.inertiaInverted * dt; + + // Apply damping. + // ODE: dv/dt + c * v = 0 + // Solution: v(t) = v0 * exp(-c * t) + // Time step: v(t + dt) = v0 * exp(-c * (t + dt)) = v0 * exp(-c * t) * exp(-c * dt) = v * exp(-c * dt) + // v2 = exp(-c * dt) * v1 + // Taylor expansion: + // v2 = (1.0f - c * dt) * v1 + this.velocity.scale(this.clamp(1 - dt * (damping + this.linearDamping), 0, 1)); + this.angularVelocity *= this.clamp(1 - dt * (damping + this.angularDamping), 0, 1); + + this.force.setTo(0, 0); + this.torque = 0; + + } + + 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)) { - this.game.world.physics.updateMotion(this); - - this.wasTouching = this.touching; - this.touching = Phaser.Types.NONE; - + return false; } - this.position.setTo(this.x, this.y); + return true; + } + + public clamp(v, min, max) { + return v < min ? min : (v > max ? max : v); } - public get hullWidth(): number { + public updatePosition(dt:number) { - if (this.deltaX > 0) - { - return this.bounds.width + this.deltaX; - } - else - { - return this.bounds.width - this.deltaX; - } + this.position.add(Phaser.Vec2Utils.scale(this.velocity, dt, this._tempVec2)); - } + this.angle += this.angularVelocity * dt; - public get hullHeight(): number { + if (this.sprite) + { + this.sprite.x = this.position.x * 50; + this.sprite.y = this.position.y * 50; + // Obey fixed rotation? + this.sprite.rotation = this.game.math.radiansToDegrees(this.angle); + } - if (this.deltaY > 0) - { - return this.bounds.height + this.deltaY; - } - else - { - return this.bounds.height - this.deltaY; - } + } - } + public resetForce() { + this.force.setTo(0, 0); + this.torque = 0; + } - public get hullX(): number { + public applyForce(force:Phaser.Vec2, p:Phaser.Vec2) { - if (this.position.x < this.oldPosition.x) - { - return this.position.x; - } - else - { - return this.oldPosition.x; - } + if (this.isDynamic == false) + { + return; + } - } + if (this.isAwake == false) + { + this.awake(true); + } - public get hullY(): number { + this.force.add(force); - if (this.position.y < this.oldPosition.y) - { - return this.position.y; - } - else - { - return this.oldPosition.y; - } + Phaser.Vec2Utils.subtract(p, this.position, this._tempVec2); - } + this.torque += Phaser.Vec2Utils.cross(this._tempVec2, force); - public get deltaXAbs(): number { - return (this.deltaX > 0 ? this.deltaX : -this.deltaX); - } + } - public get deltaYAbs(): number { - return (this.deltaY > 0 ? this.deltaY : -this.deltaY); - } + public applyForceToCenter(force:Phaser.Vec2) { - public get deltaX(): number { - return this.position.x - this.oldPosition.x; - } + if (this.isDynamic == false) + { + return; + } - public get deltaY(): number { - return this.position.y - this.oldPosition.y; - } + if (this.isAwake == false) + { + this.awake(true); + } + this.force.add(force); + } + public applyTorque(torque:number) { + if (this.isDynamic == false) + { + return; + } + if (this.isAwake == false) + { + this.awake(true); + } + this.torque += torque; + } + public applyLinearImpulse(impulse:Phaser.Vec2, p:Phaser.Vec2) { + if (this.isDynamic == false) + { + return; + } - // MOVE THESE TO A UTIL + if (this.isAwake == false) + { + this.awake(true); + } - public render(context:CanvasRenderingContext2D) { + this.velocity.multiplyAddByScalar(impulse, this.massInverted); - context.beginPath(); - context.strokeStyle = 'rgb(0,255,0)'; - context.strokeRect(this.position.x - this.bounds.halfWidth, this.position.y - this.bounds.halfHeight, this.bounds.width, this.bounds.height); - context.stroke(); - context.closePath(); + Phaser.Vec2Utils.subtract(p, this.position, this._tempVec2); - // center point - context.fillStyle = 'rgb(0,255,0)'; - context.fillRect(this.position.x, this.position.y, 2, 2); + this.angularVelocity += Phaser.Vec2Utils.cross(this._tempVec2, impulse) * this.inertiaInverted; - if (this.touching & Phaser.Types.LEFT) - { - context.beginPath(); - context.strokeStyle = 'rgb(255,0,0)'; - context.moveTo(this.position.x - this.bounds.halfWidth, this.position.y - this.bounds.halfHeight); - context.lineTo(this.position.x - this.bounds.halfWidth, this.position.y + this.bounds.halfHeight); - context.stroke(); - context.closePath(); - } - if (this.touching & Phaser.Types.RIGHT) - { - context.beginPath(); - context.strokeStyle = 'rgb(255,0,0)'; - context.moveTo(this.position.x + this.bounds.halfWidth, this.position.y - this.bounds.halfHeight); - context.lineTo(this.position.x + this.bounds.halfWidth, this.position.y + this.bounds.halfHeight); - context.stroke(); - context.closePath(); - } + } - if (this.touching & Phaser.Types.UP) - { - context.beginPath(); - context.strokeStyle = 'rgb(255,0,0)'; - context.moveTo(this.position.x - this.bounds.halfWidth, this.position.y - this.bounds.halfHeight); - context.lineTo(this.position.x + this.bounds.halfWidth, this.position.y - this.bounds.halfHeight); - context.stroke(); - context.closePath(); - } - if (this.touching & Phaser.Types.DOWN) - { - context.beginPath(); - context.strokeStyle = 'rgb(255,0,0)'; - context.moveTo(this.position.x - this.bounds.halfWidth, this.position.y + this.bounds.halfHeight); - context.lineTo(this.position.x + this.bounds.halfWidth, this.position.y + this.bounds.halfHeight); - context.stroke(); - context.closePath(); - } + public applyAngularImpulse(impulse: number) { - } + if (this.isDynamic == false) + { + return; + } + if (this.isAwake == false) + { + this.awake(true); + } - /** - * Render debug infos. (including name, bounds info, position and some other properties) - * @param x {number} X position of the debug info to be rendered. - * @param y {number} Y position of the debug info to be rendered. - * @param [color] {number} color of the debug info to be rendered. (format is css color string) - */ - public renderDebugInfo(x: number, y: number, color?: string = 'rgb(255,255,255)') { + this.angularVelocity += impulse * this.inertiaInverted; - this.sprite.texture.context.fillStyle = color; - this.sprite.texture.context.fillText('Sprite: (' + this.sprite.width + ' x ' + this.sprite.height + ')', x, y); - //this.sprite.texture.context.fillText('x: ' + this._sprite.frameBounds.x.toFixed(1) + ' y: ' + this._sprite.frameBounds.y.toFixed(1) + ' rotation: ' + this._sprite.rotation.toFixed(1), x, y + 14); - this.sprite.texture.context.fillText('x: ' + this.bounds.x.toFixed(1) + ' y: ' + this.bounds.y.toFixed(1) + ' rotation: ' + this.sprite.transform.rotation.toFixed(0), x, y + 14); - this.sprite.texture.context.fillText('vx: ' + this.velocity.x.toFixed(1) + ' vy: ' + this.velocity.y.toFixed(1), x, y + 28); - this.sprite.texture.context.fillText('acx: ' + this.acceleration.x.toFixed(1) + ' acy: ' + this.acceleration.y.toFixed(1), x, y + 42); - this.sprite.texture.context.fillText('angVx: ' + this.angularVelocity.toFixed(1) + ' angAc: ' + this.angularAcceleration.toFixed(1), x, y + 56); + } - } + public kineticEnergy() { + var vsq = this.velocity.dot(this.velocity); + var wsq = this.angularVelocity * this.angularVelocity; + + return 0.5 * (this.mass * vsq + this.inertia * wsq); + + } + + public get isAwake(): bool { + return this.awaked; + } + + public awake(flag) { + + this.awaked = flag; + + if (flag) + { + this.sleepTime = 0; + } + else + { + this.velocity.setTo(0, 0); + this.angularVelocity = 0; + this.force.setTo(0, 0); + this.torque = 0; + } + + } + + public isCollidable(other:Body) { + + if (this == other) + { + return false; + } + + if (this.isDynamic == false && other.isDynamic == false) + { + return false; + } + + if (!(this.maskBits & other.categoryBits) || !(other.maskBits & this.categoryBits)) + { + return false; + } + + for (var i = 0; i < this.joints.length; i++) + { + var joint = this.joints[i]; + + if (!this.joints[i] || (!this.joints[i].collideConnected && other.jointHash[this.joints[i].id] != undefined)) + { + return false; + } + } + + return true; + + } } diff --git a/Phaser/physics/advanced/Bounds.ts b/Phaser/physics/Bounds.ts similarity index 86% rename from Phaser/physics/advanced/Bounds.ts rename to Phaser/physics/Bounds.ts index b5eb34f8..7e054a07 100644 --- a/Phaser/physics/advanced/Bounds.ts +++ b/Phaser/physics/Bounds.ts @@ -1,6 +1,6 @@ -/// -/// -/// +/// +/// +/// /** * Phaser - 2D AABB @@ -8,7 +8,7 @@ * A 2D AABB object */ -module Phaser.Physics.Advanced { +module Phaser.Physics { export class Bounds { @@ -72,19 +72,27 @@ module Phaser.Physics.Advanced { } public get x(): number { - return Phaser.Physics.Advanced.Manager.metersToPixels(this.mins.x); + return Phaser.Physics.Manager.metersToPixels(this.mins.x); } public get y(): number { - return Phaser.Physics.Advanced.Manager.metersToPixels(this.mins.y); + return Phaser.Physics.Manager.metersToPixels(this.mins.y); } public get width(): number { - return Phaser.Physics.Advanced.Manager.metersToPixels(this.maxs.x - this.mins.x); + return Phaser.Physics.Manager.metersToPixels(this.maxs.x - this.mins.x); } public get height(): number { - return Phaser.Physics.Advanced.Manager.metersToPixels(this.maxs.y - this.mins.y); + return Phaser.Physics.Manager.metersToPixels(this.maxs.y - this.mins.y); + } + + public get right(): number { + return this.x + this.width; + } + + public get bottom(): number { + return this.y + this.height; } public isEmpty(): bool { @@ -125,11 +133,13 @@ module Phaser.Physics.Advanced { return this; } - public addBounds2(mins, maxs) { + public addBounds2(mins, maxs): Bounds { + if (this.mins.x > mins.x) this.mins.x = mins.x; if (this.maxs.x < maxs.x) this.maxs.x = maxs.x; if (this.mins.y > mins.y) this.mins.y = mins.y; if (this.maxs.y < maxs.y) this.maxs.y = maxs.y; + return this; } diff --git a/Phaser/physics/advanced/Collision.ts b/Phaser/physics/Collision.ts similarity index 91% rename from Phaser/physics/advanced/Collision.ts rename to Phaser/physics/Collision.ts index 465a1658..8d749a06 100644 --- a/Phaser/physics/advanced/Collision.ts +++ b/Phaser/physics/Collision.ts @@ -1,6 +1,6 @@ -/// -/// -/// +/// +/// +/// /// /// /// @@ -15,13 +15,10 @@ * Based on the work Ju Hyung Lee started in JS PhyRus. */ -module Phaser.Physics.Advanced { +module Phaser.Physics { export class Collision { - constructor() { - } - public collide(a, b, contacts: Contact[]) { // Circle (a is the circle) @@ -114,11 +111,11 @@ module Phaser.Physics.Advanced { } - public circle2Circle(circ1: Phaser.Physics.Advanced.Shapes.Circle, circ2: Phaser.Physics.Advanced.Shapes.Circle, contactArr: Contact[]) { + public circle2Circle(circ1: Phaser.Physics.Shapes.Circle, circ2: Phaser.Physics.Shapes.Circle, contactArr: Contact[]) { return this._circle2Circle(circ1.tc, circ1.radius, circ2.tc, circ2.radius, contactArr); } - public circle2Segment(circ: Phaser.Physics.Advanced.Shapes.Circle, seg: Phaser.Physics.Advanced.Shapes.Segment, contactArr: Contact[]) { + public circle2Segment(circ: Phaser.Physics.Shapes.Circle, seg: Phaser.Physics.Shapes.Segment, contactArr: Contact[]) { var rsum = circ.radius + seg.radius; @@ -179,7 +176,7 @@ module Phaser.Physics.Advanced { } - public circle2Poly(circ: Phaser.Physics.Advanced.Shapes.Circle, poly: Phaser.Physics.Advanced.Shapes.Poly, contactArr: Contact[]) { + public circle2Poly(circ: Phaser.Physics.Shapes.Circle, poly: Phaser.Physics.Shapes.Poly, contactArr: Contact[]) { var minDist = -999999; var minIdx = -1; @@ -230,7 +227,7 @@ module Phaser.Physics.Advanced { } - public segmentPointDistanceSq(seg: Phaser.Physics.Advanced.Shapes.Segment, p) { + public segmentPointDistanceSq(seg: Phaser.Physics.Shapes.Segment, p) { var w: Phaser.Vec2 = new Phaser.Vec2; var d: Phaser.Vec2 = new Phaser.Vec2; @@ -259,7 +256,7 @@ module Phaser.Physics.Advanced { } // FIXME and optimise me lots!!! - public segment2Segment(seg1: Phaser.Physics.Advanced.Shapes.Segment, seg2: Phaser.Physics.Advanced.Shapes.Segment, contactArr: Contact[]) { + public segment2Segment(seg1: Phaser.Physics.Shapes.Segment, seg2: Phaser.Physics.Shapes.Segment, contactArr: Contact[]) { var d = []; d[0] = this.segmentPointDistanceSq(seg1, seg2.ta); @@ -307,7 +304,7 @@ module Phaser.Physics.Advanced { } // Identify vertexes that have penetrated the segment. - public findPointsBehindSeg(contactArr: Contact[], seg: Phaser.Physics.Advanced.Shapes.Segment, poly: Phaser.Physics.Advanced.Shapes.Poly, dist: number, coef: number) { + public findPointsBehindSeg(contactArr: Contact[], seg: Phaser.Physics.Shapes.Segment, poly: Phaser.Physics.Shapes.Poly, dist: number, coef: number) { var dta = Phaser.Vec2Utils.cross(seg.tn, seg.ta); var dtb = Phaser.Vec2Utils.cross(seg.tn, seg.tb); @@ -332,7 +329,7 @@ module Phaser.Physics.Advanced { } } - public segment2Poly(seg: Phaser.Physics.Advanced.Shapes.Segment, poly: Phaser.Physics.Advanced.Shapes.Poly, contactArr: Contact[]) { + public segment2Poly(seg: Phaser.Physics.Shapes.Segment, poly: Phaser.Physics.Shapes.Poly, contactArr: Contact[]) { var seg_td = Phaser.Vec2Utils.dot(seg.tn, seg.ta); var seg_d1 = poly.distanceOnPlane(seg.tn, seg_td) - seg.radius; @@ -442,7 +439,7 @@ 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: Phaser.Physics.Advanced.Plane[], num: number) { + public findMSA(poly: Phaser.Physics.Shapes.Poly, planes: Phaser.Physics.Plane[], num: number) { var min_dist: number = -999999; var min_index: number = -1; @@ -468,7 +465,7 @@ module Phaser.Physics.Advanced { } - public findVertsFallback(contactArr: Contact[], poly1: Phaser.Physics.Advanced.Shapes.Poly, poly2: Phaser.Physics.Advanced.Shapes.Poly, n, dist: number) { + public findVertsFallback(contactArr: Contact[], poly1: Phaser.Physics.Shapes.Poly, poly2: Phaser.Physics.Shapes.Poly, n, dist: number) { var num = 0; @@ -499,7 +496,7 @@ module Phaser.Physics.Advanced { } // Find the overlapped vertices. - public findVerts(contactArr: Contact[], poly1: Phaser.Physics.Advanced.Shapes.Poly, poly2: Phaser.Physics.Advanced.Shapes.Poly, n, dist: number) { + public findVerts(contactArr: Contact[], poly1: Phaser.Physics.Shapes.Poly, poly2: Phaser.Physics.Shapes.Poly, n, dist: number) { var num = 0; @@ -529,7 +526,7 @@ module Phaser.Physics.Advanced { } - public poly2Poly(poly1: Phaser.Physics.Advanced.Shapes.Poly, poly2: Phaser.Physics.Advanced.Shapes.Poly, contactArr: Contact[]) { + public poly2Poly(poly1: Phaser.Physics.Shapes.Poly, poly2: Phaser.Physics.Shapes.Poly, contactArr: Contact[]) { var msa1 = this.findMSA(poly2, poly1.tplanes, poly1.verts.length); diff --git a/Phaser/physics/advanced/Contact.ts b/Phaser/physics/Contact.ts similarity index 91% rename from Phaser/physics/advanced/Contact.ts rename to Phaser/physics/Contact.ts index d927764b..1ae8f776 100644 --- a/Phaser/physics/advanced/Contact.ts +++ b/Phaser/physics/Contact.ts @@ -1,5 +1,5 @@ -/// -/// +/// +/// /// /// /// @@ -10,7 +10,7 @@ * Based on the work Ju Hyung Lee started in JS PhyRus. */ -module Phaser.Physics.Advanced { +module Phaser.Physics { export class Contact { diff --git a/Phaser/physics/advanced/ContactSolver.ts b/Phaser/physics/ContactSolver.ts similarity index 98% rename from Phaser/physics/advanced/ContactSolver.ts rename to Phaser/physics/ContactSolver.ts index 3e5244c9..f43db61f 100644 --- a/Phaser/physics/advanced/ContactSolver.ts +++ b/Phaser/physics/ContactSolver.ts @@ -1,6 +1,6 @@ -/// -/// -/// +/// +/// +/// /// /// /// @@ -32,7 +32,7 @@ // NOTE: lambda is an impulse in constraint space. //------------------------------------------------------------------------------------------------- -module Phaser.Physics.Advanced { +module Phaser.Physics { export class ContactSolver { diff --git a/Phaser/physics/advanced/Manager.ts b/Phaser/physics/Manager.ts similarity index 91% rename from Phaser/physics/advanced/Manager.ts rename to Phaser/physics/Manager.ts index 7fa322d8..9b672efd 100644 --- a/Phaser/physics/advanced/Manager.ts +++ b/Phaser/physics/Manager.ts @@ -1,15 +1,15 @@ -/// +/// /// /// /** -* Phaser - Advanced Physics Manager +* Phaser - Physics Manager * -* Your game only has one PhysicsManager instance and it's responsible for looking after, creating and colliding -* all of the physics objects in the world. +* The Physics Manager is responsible for looking after, creating and colliding +* all of the physics bodies and joints in the world. */ -module Phaser.Physics.Advanced { +module Phaser.Physics { export class Manager { @@ -17,7 +17,9 @@ module Phaser.Physics.Advanced { this.game = game; - this.space = new Space(); + this.gravity = new Phaser.Vec2; + + this.space = new Space(this); Manager.collision = new Collision(); @@ -31,12 +33,12 @@ module Phaser.Physics.Advanced { public static debug: HTMLTextAreaElement; public static clear() { - Manager.debug.textContent = ""; + //Manager.debug.textContent = ""; Manager.log = []; } public static write(s: string) { - Manager.debug.textContent += s + "\n"; + //Manager.debug.textContent += s + "\n"; } public static writeAll() { @@ -52,6 +54,7 @@ module Phaser.Physics.Advanced { 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"; @@ -78,6 +81,7 @@ module Phaser.Physics.Advanced { s += "TPlane 3: " + body.shapes[0].tplanes[3].normal.toString() + "\n"; Manager.log.push(s); + */ } @@ -98,9 +102,9 @@ module Phaser.Physics.Advanced { public static JOINT_TYPE_MOUSE: number = 7; public static JOINT_LINEAR_SLOP: number = 0.0008; - public static JOINT_ANGULAR_SLOP: number = 2 * Phaser.GameMath.DEG_TO_RAD; + public static JOINT_ANGULAR_SLOP: number = 2 * 0.017453292519943294444444444444444; public static JOINT_MAX_LINEAR_CORRECTION: number = 0.5; - public static JOINT_MAX_ANGULAR_CORRECTION: number = 8 * Phaser.GameMath.DEG_TO_RAD; + public static JOINT_MAX_ANGULAR_CORRECTION: number = 8 * 0.017453292519943294444444444444444; public static JOINT_LIMIT_STATE_INACTIVE: number = 0; public static JOINT_LIMIT_STATE_AT_LOWER: number = 1; @@ -119,19 +123,21 @@ module Phaser.Physics.Advanced { public lastTime: number = Date.now(); public frameRateHz: number = 60; public timeDelta: number = 0; - //public paused: bool = false; - //public step: bool = false; // step through the simulation (i.e. per click) - public paused: bool = true; + 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; + public gravity: Phaser.Vec2; + + public update() { + // Get these from Phaser.Time instead var time = Date.now(); var frameTime = (time - this.lastTime) / 1000; this.lastTime = time; @@ -176,6 +182,22 @@ module Phaser.Physics.Advanced { } + public addBody(body: Body) { + this.space.addBody(body); + } + + public removeBody(body: Body) { + this.space.removeBody(body); + } + + public addJoint(joint: IJoint) { + this.space.addJoint(joint); + } + + public removeJoint(joint: IJoint) { + this.space.removeJoint(joint); + } + public pixelsToMeters(value: number): number { return value * 0.02; } diff --git a/Phaser/physics/PhysicsManager.ts b/Phaser/physics/PhysicsManager.ts deleted file mode 100644 index ab24ed07..00000000 --- a/Phaser/physics/PhysicsManager.ts +++ /dev/null @@ -1,1116 +0,0 @@ -/// -/// -/// -/// -/// - -/** -* Phaser - PhysicsManager -* -* Your game only has one PhysicsManager instance and it's responsible for looking after, creating and colliding -* all of the physics objects in the world. -*/ - -module Phaser.Physics { - - export class PhysicsManager { - - constructor(game: Game, width: number, height: number) { - - this.game = game; - - this.gravity = new Vec2; - this.drag = new Vec2; - this.bounce = new Vec2; - this.angularDrag = 0; - - this.bounds = new Rectangle(0, 0, width, height); - - this._distance = new Vec2; - this._tangent = new Vec2; - - this.members = new Group(game); - - } - - /** - * Local private reference to Game. - */ - public game: Game; - - /** - * Physics object pool - */ - public members: Group; - - // Temp calculation vars - private _drag: number; - private _delta: number; - private _velocityDelta: number; - private _length: number = 0; - private _distance: Vec2; - private _tangent: Vec2; - private _separatedX: bool; - private _separatedY: bool; - private _overlap: number; - private _maxOverlap: number; - private _obj1Velocity: number; - private _obj2Velocity: number; - private _obj1NewVelocity: number; - private _obj2NewVelocity: number; - private _average: number; - private _quadTree: QuadTree; - private _quadTreeResult: bool; - - public bounds: Rectangle; - - public gravity: Vec2; - public drag: Vec2; - public bounce: Vec2; - public angularDrag: number; - - /** - * The overlap bias is used when calculating hull overlap before separation - change it if you have especially small or large GameObjects - * @type {number} - */ - static OVERLAP_BIAS: number = 4; - - /** - * The overlap bias is used when calculating hull overlap before separation - change it if you have especially small or large GameObjects - * @type {number} - */ - static TILE_OVERLAP: bool = false; - - /** - * @type {number} - */ - public worldDivisions: number = 6; - - - /* - public update() { - - this._length = this._objects.length; - - for (var i = 0; i < this._length; i++) - { - if (this._objects[i]) - { - this._objects[i].preUpdate(); - this.updateMotion(this._objects[i]); - this.collideWorld(this._objects[i]); - - for (var x = 0; x < this._length; x++) - { - if (this._objects[x] && this._objects[x] !== this._objects[i]) - { - //this.collideShapes(this._objects[i], this._objects[x]); - var r = this.NEWseparate(this._objects[i], this._objects[x]); - //console.log('sep', r); - } - } - - } - } - - } - - public render() { - - // iterate through the objects here, updating and colliding - for (var i = 0; i < this._length; i++) - { - if (this._objects[i]) - { - this._objects[i].render(this.game.stage.context); - } - } - - } -*/ - - public updateMotion(body: Phaser.Physics.Body) { - - if (body.type == Types.BODY_DISABLED) - { - return; - } - - this._velocityDelta = (this.computeVelocity(body.angularVelocity, body.gravity.x, body.angularAcceleration, body.angularDrag, body.maxAngular) - body.angularVelocity) / 2; - body.angularVelocity += this._velocityDelta; - body.sprite.transform.rotation += body.angularVelocity * this.game.time.elapsed; - body.angularVelocity += this._velocityDelta; - - this._velocityDelta = (this.computeVelocity(body.velocity.x, body.gravity.x, body.acceleration.x, body.drag.x) - body.velocity.x) / 2; - body.velocity.x += this._velocityDelta; - this._delta = body.velocity.x * this.game.time.elapsed; - body.velocity.x += this._velocityDelta; - //body.position.x += this._delta; - body.sprite.x += this._delta; - - this._velocityDelta = (this.computeVelocity(body.velocity.y, body.gravity.y, body.acceleration.y, body.drag.y) - body.velocity.y) / 2; - body.velocity.y += this._velocityDelta; - this._delta = body.velocity.y * this.game.time.elapsed; - body.velocity.y += this._velocityDelta; - //body.position.y += this._delta; - body.sprite.y += this._delta; - - } - - /** - * A tween-like function that takes a starting velocity and some other factors and returns an altered velocity. - * - * @param {number} Velocity Any component of velocity (e.g. 20). - * @param {number} Acceleration Rate at which the velocity is changing. - * @param {number} Drag Really kind of a deceleration, this is how much the velocity changes if Acceleration is not set. - * @param {number} Max An absolute value cap for the velocity. - * - * @return {number} The altered Velocity value. - */ - public computeVelocity(velocity: number, gravity: number = 0, acceleration: number = 0, drag: number = 0, max: number = 10000): number { - - if (acceleration !== 0) - { - velocity += (acceleration + gravity) * this.game.time.elapsed; - } - else if (drag !== 0) - { - this._drag = drag * this.game.time.elapsed; - - if (velocity - this._drag > 0) - { - velocity = velocity - this._drag; - } - else if (velocity + this._drag < 0) - { - velocity += this._drag; - } - else - { - velocity = 0; - } - - velocity += gravity; - } - - if ((velocity != 0) && (max != 10000)) - { - if (velocity > max) - { - velocity = max; - } - else if (velocity < -max) - { - velocity = -max; - } - } - - return velocity; - - } - - /** - * The core Collision separation method. - * @param body1 The first Physics.Body to separate - * @param body2 The second Physics.Body to separate - * @returns {boolean} Returns true if the bodies were separated, otherwise false. - */ - public separate(body1: Body, body2: Body): bool { - - this._separatedX = this.separateBodyX(body1, body2); - this._separatedY = this.separateBodyY(body1, body2); - - return this._separatedX || this._separatedY; - - } - - public checkHullIntersection(body1: Body, body2:Body): bool { - return ((body1.hullX + body1.hullWidth > body2.hullX) && (body1.hullX < body2.hullX + body2.hullWidth) && (body1.hullY + body1.hullHeight > body2.hullY) && (body1.hullY < body2.hullY + body2.hullHeight)); - } - - /** - * Separates the two objects on their x axis - * @param object1 The first GameObject to separate - * @param object2 The second GameObject to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the X axis. - */ - public separateBodyX(body1: Body, body2: Body): bool { - - // Can't separate two disabled or static objects - if ((body1.type == Types.BODY_DISABLED || body1.type == Types.BODY_STATIC) && (body2.type == Types.BODY_DISABLED || body2.type == Types.BODY_STATIC)) - { - return false; - } - - // First, get the two object deltas - this._overlap = 0; - - if (body1.deltaX != body2.deltaX) - { - if (RectangleUtils.intersects(body1.bounds, body2.bounds)) - { - this._maxOverlap = body1.deltaXAbs + body2.deltaXAbs + PhysicsManager.OVERLAP_BIAS; - - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if (body1.deltaX > body2.deltaX) - { - this._overlap = body1.bounds.right - body2.bounds.x; - - if ((this._overlap > this._maxOverlap) || !(body1.allowCollisions & Types.RIGHT) || !(body2.allowCollisions & Types.LEFT)) - { - this._overlap = 0; - } - else - { - body1.touching |= Types.RIGHT; - body2.touching |= Types.LEFT; - } - } - else if (body1.deltaX < body2.deltaX) - { - this._overlap = body1.bounds.x - body2.bounds.width - body2.bounds.x; - - if ((-this._overlap > this._maxOverlap) || !(body1.allowCollisions & Types.LEFT) || !(body2.allowCollisions & Types.RIGHT)) - { - this._overlap = 0; - } - else - { - body1.touching |= Types.LEFT; - body2.touching |= Types.RIGHT; - } - } - } - } - - // Then adjust their positions and velocities accordingly (if there was any overlap) - if (this._overlap != 0) - { - this._obj1Velocity = body1.velocity.x; - this._obj2Velocity = body2.velocity.x; - - /** - * Dynamic = gives and receives impacts - * Static = gives but doesn't receive impacts, cannot be moved by physics - * Kinematic = gives impacts, but never receives, can be moved by physics - */ - - // 2 dynamic bodies will exchange velocities - if (body1.type == Types.BODY_DYNAMIC && body2.type == Types.BODY_DYNAMIC) - { - this._overlap *= 0.5; - body1.position.x = body1.position.x - this._overlap; - body2.position.x += this._overlap; - - this._obj1NewVelocity = Math.sqrt((this._obj2Velocity * this._obj2Velocity * body2.mass) / body1.mass) * ((this._obj2Velocity > 0) ? 1 : -1); - this._obj2NewVelocity = Math.sqrt((this._obj1Velocity * this._obj1Velocity * body1.mass) / body2.mass) * ((this._obj1Velocity > 0) ? 1 : -1); - this._average = (this._obj1NewVelocity + this._obj2NewVelocity) * 0.5; - this._obj1NewVelocity -= this._average; - this._obj2NewVelocity -= this._average; - body1.velocity.x = this._average + this._obj1NewVelocity * body1.bounce.x; - body2.velocity.x = this._average + this._obj2NewVelocity * body2.bounce.x; - } - else if (body2.type != Types.BODY_DYNAMIC) - { - // Body 2 is Static or Kinematic - this._overlap *= 2; - body1.position.x -= this._overlap; - body1.velocity.x = this._obj2Velocity - this._obj1Velocity * body1.bounce.x; - } - else if (body1.type != Types.BODY_DYNAMIC) - { - // Body 1 is Static or Kinematic - this._overlap *= 2; - body2.position.x += this._overlap; - body2.velocity.x = this._obj1Velocity - this._obj2Velocity * body2.bounce.x; - } - - return true; - } - else - { - return false; - } - - } - - /** - * Separates the two objects on their y axis - * @param object1 The first GameObject to separate - * @param object2 The second GameObject to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis. - */ - public separateBodyY(body1: Body, body2: Body): bool { - - // Can't separate two immovable objects - if ((body1.type == Types.BODY_DISABLED || body1.type == Types.BODY_STATIC) && (body2.type == Types.BODY_DISABLED || body2.type == Types.BODY_STATIC)) - { - return false; - } - - // First, get the two object deltas - this._overlap = 0; - - if (body1.deltaY != body2.deltaY) - { - if (RectangleUtils.intersects(body1.bounds, body2.bounds)) - { - // This is the only place to use the DeltaAbs values - this._maxOverlap = body1.deltaYAbs + body2.deltaYAbs + PhysicsManager.OVERLAP_BIAS; - - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if (body1.deltaY > body2.deltaY) - { - this._overlap = body1.bounds.bottom - body2.bounds.y; - - if ((this._overlap > this._maxOverlap) || !(body1.allowCollisions & Types.DOWN) || !(body2.allowCollisions & Types.UP)) - { - this._overlap = 0; - } - else - { - body1.touching |= Types.DOWN; - body2.touching |= Types.UP; - } - } - else if (body1.deltaY < body2.deltaY) - { - this._overlap = body1.bounds.y - body2.bounds.height - body2.bounds.y; - - if ((-this._overlap > this._maxOverlap) || !(body1.allowCollisions & Types.UP) || !(body2.allowCollisions & Types.DOWN)) - { - this._overlap = 0; - } - else - { - body1.touching |= Types.UP; - body2.touching |= Types.DOWN; - } - } - } - } - - // Then adjust their positions and velocities accordingly (if there was any overlap) - if (this._overlap != 0) - { - this._obj1Velocity = body1.velocity.y; - this._obj2Velocity = body2.velocity.y; - - /** - * Dynamic = gives and receives impacts - * Static = gives but doesn't receive impacts, cannot be moved by physics - * Kinematic = gives impacts, but never receives, can be moved by physics - */ - - if (body1.type == Types.BODY_DYNAMIC && body2.type == Types.BODY_DYNAMIC) - { - this._overlap *= 0.5; - body1.position.y = body1.position.y - this._overlap; - body2.position.y += this._overlap; - - this._obj1NewVelocity = Math.sqrt((this._obj2Velocity * this._obj2Velocity * body2.mass) / body1.mass) * ((this._obj2Velocity > 0) ? 1 : -1); - this._obj2NewVelocity = Math.sqrt((this._obj1Velocity * this._obj1Velocity * body1.mass) / body2.mass) * ((this._obj1Velocity > 0) ? 1 : -1); - var average: number = (this._obj1NewVelocity + this._obj2NewVelocity) * 0.5; - this._obj1NewVelocity -= average; - this._obj2NewVelocity -= average; - body1.velocity.y = average + this._obj1NewVelocity * body1.bounce.y; - body2.velocity.y = average + this._obj2NewVelocity * body2.bounce.y; - } - else if (body2.type != Types.BODY_DYNAMIC) - { - this._overlap *= 2; - body1.position.y -= this._overlap; - body1.velocity.y = this._obj2Velocity - this._obj1Velocity * body1.bounce.y; - // This is special case code that handles things like horizontal moving platforms you can ride - //if (body2.parent.active && body2.moves && (body1.deltaY > body2.deltaY)) - if (body2.sprite.active && (body1.deltaY > body2.deltaY)) - { - body1.position.x += body2.position.x - body2.oldPosition.x; - } - } - else if (body1.type != Types.BODY_DYNAMIC) - { - this._overlap *= 2; - body2.position.y += this._overlap; - body2.velocity.y = this._obj1Velocity - this._obj2Velocity * body2.bounce.y; - // This is special case code that handles things like horizontal moving platforms you can ride - //if (object1.active && body1.moves && (body1.deltaY < body2.deltaY)) - if (body1.sprite.active && (body1.deltaY < body2.deltaY)) - { - body2.position.x += body1.position.x - body1.oldPosition.x; - } - } - - return true; - } - else - { - return false; - } - } - - - - - - - - /* - private TILEseparate(shapeA: IPhysicsShape, shapeB: IPhysicsShape, distance: Vec2, tangent: Vec2) { - - if (tangent.x == 1) - { - console.log('1 The left side of ShapeA hit the right side of ShapeB', Math.floor(distance.x)); - shapeA.physics.touching |= Phaser.Types.LEFT; - shapeB.physics.touching |= Phaser.Types.RIGHT; - } - else if (tangent.x == -1) - { - console.log('2 The right side of ShapeA hit the left side of ShapeB', Math.floor(distance.x)); - shapeA.physics.touching |= Phaser.Types.RIGHT; - shapeB.physics.touching |= Phaser.Types.LEFT; - } - - if (tangent.y == 1) - { - console.log('3 The top of ShapeA hit the bottom of ShapeB', Math.floor(distance.y)); - shapeA.physics.touching |= Phaser.Types.UP; - shapeB.physics.touching |= Phaser.Types.DOWN; - } - else if (tangent.y == -1) - { - console.log('4 The bottom of ShapeA hit the top of ShapeB', Math.floor(distance.y)); - shapeA.physics.touching |= Phaser.Types.DOWN; - shapeB.physics.touching |= Phaser.Types.UP; - } - - - // only apply collision response forces if the object is travelling into, and not out of, the collision - var dot = Vec2Utils.dot(shapeA.physics.velocity, tangent); - - if (dot < 0) - { - console.log('in to', dot); - - // Apply horizontal bounce - if (shapeA.physics.bounce.x > 0) - { - shapeA.physics.velocity.x *= -(shapeA.physics.bounce.x); - } - else - { - shapeA.physics.velocity.x = 0; - } - // Apply horizontal bounce - if (shapeA.physics.bounce.y > 0) - { - shapeA.physics.velocity.y *= -(shapeA.physics.bounce.y); - } - else - { - shapeA.physics.velocity.y = 0; - } - } - else - { - console.log('out of', dot); - } - - shapeA.position.x += Math.floor(distance.x); - //shapeA.bounds.x += Math.floor(distance.x); - - shapeA.position.y += Math.floor(distance.y); - //shapeA.bounds.y += distance.y; - - console.log('------------------------------------------------'); - - } - - private collideWorld(shape:IPhysicsShape) { - - // Collide on the x-axis - this._distance.x = shape.world.bounds.x - (shape.position.x - shape.bounds.halfWidth); - - if (0 < this._distance.x) - { - // Hit Left - this._tangent.setTo(1, 0); - this.separateXWall(shape, this._distance, this._tangent); - } - else - { - this._distance.x = (shape.position.x + shape.bounds.halfWidth) - shape.world.bounds.right; - - if (0 < this._distance.x) - { - // Hit Right - this._tangent.setTo(-1, 0); - this._distance.reverse(); - this.separateXWall(shape, this._distance, this._tangent); - } - } - - // Collide on the y-axis - this._distance.y = shape.world.bounds.y - (shape.position.y - shape.bounds.halfHeight); - - if (0 < this._distance.y) - { - // Hit Top - this._tangent.setTo(0, 1); - this.separateYWall(shape, this._distance, this._tangent); - } - else - { - this._distance.y = (shape.position.y + shape.bounds.halfHeight) - shape.world.bounds.bottom; - - if (0 < this._distance.y) - { - // Hit Bottom - this._tangent.setTo(0, -1); - this._distance.reverse(); - this.separateYWall(shape, this._distance, this._tangent); - } - } - - } - - private separateX(shapeA: IPhysicsShape, shapeB: IPhysicsShape, distance: Vec2, tangent: Vec2) { - - if (tangent.x == 1) - { - console.log('The left side of ShapeA hit the right side of ShapeB', distance.x); - shapeA.physics.touching |= Phaser.Types.LEFT; - shapeB.physics.touching |= Phaser.Types.RIGHT; - } - else - { - console.log('The right side of ShapeA hit the left side of ShapeB', distance.x); - shapeA.physics.touching |= Phaser.Types.RIGHT; - shapeB.physics.touching |= Phaser.Types.LEFT; - } - - // collision edges - //shapeA.oH = tangent.x; - - // only apply collision response forces if the object is travelling into, and not out of, the collision - if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) - { - // Apply horizontal bounce - if (shapeA.physics.bounce.x > 0) - { - shapeA.physics.velocity.x *= -(shapeA.physics.bounce.x); - } - else - { - shapeA.physics.velocity.x = 0; - } - } - - shapeA.position.x += distance.x; - shapeA.bounds.x += distance.x; - - } - - private separateY(shapeA: IPhysicsShape, shapeB: IPhysicsShape, distance: Vec2, tangent: Vec2) { - - if (tangent.y == 1) - { - console.log('The top of ShapeA hit the bottom of ShapeB', distance.y); - shapeA.physics.touching |= Phaser.Types.UP; - shapeB.physics.touching |= Phaser.Types.DOWN; - } - else - { - console.log('The bottom of ShapeA hit the top of ShapeB', distance.y); - shapeA.physics.touching |= Phaser.Types.DOWN; - shapeB.physics.touching |= Phaser.Types.UP; - } - - // collision edges - //shapeA.oV = tangent.y; - - // only apply collision response forces if the object is travelling into, and not out of, the collision - if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) - { - // Apply horizontal bounce - if (shapeA.physics.bounce.y > 0) - { - shapeA.physics.velocity.y *= -(shapeA.physics.bounce.y); - } - else - { - shapeA.physics.velocity.y = 0; - } - } - - shapeA.position.y += distance.y; - shapeA.bounds.y += distance.y; - - } - - private separateXWall(shapeA: IPhysicsShape, distance: Vec2, tangent: Vec2) { - - if (tangent.x == 1) - { - console.log('The left side of ShapeA hit the right side of ShapeB', distance.x); - shapeA.physics.touching |= Phaser.Types.LEFT; - } - else - { - console.log('The right side of ShapeA hit the left side of ShapeB', distance.x); - shapeA.physics.touching |= Phaser.Types.RIGHT; - } - - // collision edges - //shapeA.oH = tangent.x; - - // only apply collision response forces if the object is travelling into, and not out of, the collision - if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) - { - // Apply horizontal bounce - if (shapeA.physics.bounce.x > 0) - { - shapeA.physics.velocity.x *= -(shapeA.physics.bounce.x); - } - else - { - shapeA.physics.velocity.x = 0; - } - } - - shapeA.position.x += distance.x; - - } - - private separateYWall(shapeA: IPhysicsShape, distance: Vec2, tangent: Vec2) { - - if (tangent.y == 1) - { - console.log('The top of ShapeA hit the bottom of ShapeB', distance.y); - shapeA.physics.touching |= Phaser.Types.UP; - } - else - { - console.log('The bottom of ShapeA hit the top of ShapeB', distance.y); - shapeA.physics.touching |= Phaser.Types.DOWN; - } - - // collision edges - //shapeA.oV = tangent.y; - - // only apply collision response forces if the object is travelling into, and not out of, the collision - if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) - { - // Apply horizontal bounce - if (shapeA.physics.bounce.y > 0) - { - shapeA.physics.velocity.y *= -(shapeA.physics.bounce.y); - } - else - { - shapeA.physics.velocity.y = 0; - } - } - - shapeA.position.y += distance.y; - - } - */ - - /** - * Checks for overlaps between two objects using the world QuadTree. Can be Sprite vs. Sprite, Sprite vs. Group or Group vs. Group. - * Note: Does not take the objects scrollFactor into account. All overlaps are check in world space. - * @param object1 The first Sprite or Group to check. If null the world.group is used. - * @param object2 The second Sprite or Group to check. - * @param notifyCallback A callback function that is called if the objects overlap. The two objects will be passed to this function in the same order in which you passed them to Collision.overlap. - * @param processCallback A callback function that lets you perform additional checks against the two objects if they overlap. If this is set then notifyCallback will only be called if processCallback returns true. - * @param context The context in which the callbacks will be called - * @returns {boolean} true if the objects overlap, otherwise false. - */ - public overlap(object1 = null, object2 = null, notifyCallback = null, processCallback = null, context = null): bool { - - if (object1 == null) - { - object1 = this.game.world.group; - } - - if (object2 == object1) - { - object2 = null; - } - - QuadTree.divisions = this.worldDivisions; - - this._quadTree = new QuadTree(this, this.bounds.x, this.bounds.y, this.bounds.width, this.bounds.height); - - this._quadTree.load(object1, object2, notifyCallback, processCallback, context); - - this._quadTreeResult = this._quadTree.execute(); - - console.log('over', this._quadTreeResult); - - this._quadTree.destroy(); - - this._quadTree = null; - - return this._quadTreeResult; - - } - - - - - - - /** - * Collision resolution specifically for GameObjects vs. Tiles. - * @param object The GameObject to separate - * @param tile The Tile to separate - * @returns {boolean} Whether the objects in fact touched and were separated - */ - public separateTile(object:Sprite, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool, collideUp: bool, collideDown: bool, separateX: bool, separateY: bool): bool { - - //var separatedX: bool = this.separateTileX(object, x, y, width, height, mass, collideLeft, collideRight, separateX); - //var separatedY: bool = this.separateTileY(object, x, y, width, height, mass, collideUp, collideDown, separateY); - - //return separatedX || separatedY; - - return false; - - } - - /** - * Separates the two objects on their x axis - * @param object The GameObject to separate - * @param tile The Tile to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the X axis. - */ - /* - public separateTileX(object:Sprite, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool, separate: bool): bool { - - // Can't separate two immovable objects (tiles are always immovable) - if (object.immovable) - { - return false; - } - - // First, get the object delta - var overlap: number = 0; - var objDelta: number = object.x - object.last.x; - //var objDelta: number = object.collisionMask.deltaX; - - if (objDelta != 0) - { - // Check if the X hulls actually overlap - var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; - //var objDeltaAbs: number = object.collisionMask.deltaXAbs; - var objBounds: Rectangle = new Rectangle(object.x - ((objDelta > 0) ? objDelta : 0), object.last.y, object.width + ((objDelta > 0) ? objDelta : -objDelta), object.height); - - if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) - { - var maxOverlap: number = objDeltaAbs + Collision.OVERLAP_BIAS; - - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if (objDelta > 0) - { - overlap = object.x + object.width - x; - - if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.RIGHT) || collideLeft == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.RIGHT; - } - } - else if (objDelta < 0) - { - overlap = object.x - width - x; - - if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.LEFT) || collideRight == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.LEFT; - } - - } - - } - } - - // Then adjust their positions and velocities accordingly (if there was any overlap) - if (overlap != 0) - { - if (separate == true) - { - //console.log(' - object.x = object.x - overlap; - object.velocity.x = -(object.velocity.x * object.elasticity); - } - - Collision.TILE_OVERLAP = true; - return true; - } - else - { - return false; - } - - } - */ - - /** - * Separates the two objects on their y axis - * @param object The first GameObject to separate - * @param tile The second GameObject to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis. - */ - /* - public separateTileY(object: Sprite, x: number, y: number, width: number, height: number, mass: number, collideUp: bool, collideDown: bool, separate: bool): bool { - - // Can't separate two immovable objects (tiles are always immovable) - if (object.immovable) - { - return false; - } - - // First, get the two object deltas - var overlap: number = 0; - var objDelta: number = object.y - object.last.y; - - if (objDelta != 0) - { - // Check if the Y hulls actually overlap - var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; - var objBounds: Rectangle = new Rectangle(object.x, object.y - ((objDelta > 0) ? objDelta : 0), object.width, object.height + objDeltaAbs); - - if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) - { - var maxOverlap: number = objDeltaAbs + Collision.OVERLAP_BIAS; - - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if (objDelta > 0) - { - overlap = object.y + object.height - y; - - if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.DOWN) || collideUp == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.DOWN; - } - } - else if (objDelta < 0) - { - overlap = object.y - height - y; - - if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.UP) || collideDown == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.UP; - } - } - } - } - - // TODO - with super low velocities you get lots of stuttering, set some kind of base minimum here - - // Then adjust their positions and velocities accordingly (if there was any overlap) - if (overlap != 0) - { - if (separate == true) - { - object.y = object.y - overlap; - object.velocity.y = -(object.velocity.y * object.elasticity); - } - - Collision.TILE_OVERLAP = true; - return true; - } - else - { - return false; - } - } - */ - - - /** - * Separates the two objects on their x axis - * @param object The GameObject to separate - * @param tile The Tile to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the X axis. - */ - /* - public static NEWseparateTileX(object:Sprite, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool, separate: bool): bool { - - // Can't separate two immovable objects (tiles are always immovable) - if (object.immovable) - { - return false; - } - - // First, get the object delta - var overlap: number = 0; - - if (object.collisionMask.deltaX != 0) - { - // Check if the X hulls actually overlap - //var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; - //var objBounds: Rectangle = new Rectangle(object.x - ((objDelta > 0) ? objDelta : 0), object.last.y, object.width + ((objDelta > 0) ? objDelta : -objDelta), object.height); - - //if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) - if (object.collisionMask.intersectsRaw(x, x + width, y, y + height)) - { - var maxOverlap: number = object.collisionMask.deltaXAbs + Collision.OVERLAP_BIAS; - - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if (object.collisionMask.deltaX > 0) - { - //overlap = object.x + object.width - x; - overlap = object.collisionMask.right - x; - - if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.RIGHT) || collideLeft == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.RIGHT; - } - } - else if (object.collisionMask.deltaX < 0) - { - //overlap = object.x - width - x; - overlap = object.collisionMask.x - width - x; - - if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.LEFT) || collideRight == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.LEFT; - } - - } - - } - } - - // Then adjust their positions and velocities accordingly (if there was any overlap) - if (overlap != 0) - { - if (separate == true) - { - object.x = object.x - overlap; - object.velocity.x = -(object.velocity.x * object.elasticity); - } - - Collision.TILE_OVERLAP = true; - return true; - } - else - { - return false; - } - - } - */ - - /** - * Separates the two objects on their y axis - * @param object The first GameObject to separate - * @param tile The second GameObject to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis. - */ - /* - public NEWseparateTileY(object: Sprite, x: number, y: number, width: number, height: number, mass: number, collideUp: bool, collideDown: bool, separate: bool): bool { - - // Can't separate two immovable objects (tiles are always immovable) - if (object.immovable) - { - return false; - } - - // First, get the two object deltas - var overlap: number = 0; - //var objDelta: number = object.y - object.last.y; - - if (object.collisionMask.deltaY != 0) - { - // Check if the Y hulls actually overlap - //var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; - //var objBounds: Rectangle = new Rectangle(object.x, object.y - ((objDelta > 0) ? objDelta : 0), object.width, object.height + objDeltaAbs); - - //if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) - if (object.collisionMask.intersectsRaw(x, x + width, y, y + height)) - { - //var maxOverlap: number = objDeltaAbs + Collision.OVERLAP_BIAS; - var maxOverlap: number = object.collisionMask.deltaYAbs + Collision.OVERLAP_BIAS; - - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if (object.collisionMask.deltaY > 0) - { - //overlap = object.y + object.height - y; - overlap = object.collisionMask.bottom - y; - - if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.DOWN) || collideUp == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.DOWN; - } - } - else if (object.collisionMask.deltaY < 0) - { - //overlap = object.y - height - y; - overlap = object.collisionMask.y - height - y; - - if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.UP) || collideDown == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.UP; - } - } - } - } - - // TODO - with super low velocities you get lots of stuttering, set some kind of base minimum here - - // Then adjust their positions and velocities accordingly (if there was any overlap) - if (overlap != 0) - { - if (separate == true) - { - object.y = object.y - overlap; - object.velocity.y = -(object.velocity.y * object.elasticity); - } - - Collision.TILE_OVERLAP = true; - return true; - } - else - { - return false; - } - } - */ - - } - -} \ No newline at end of file diff --git a/Phaser/physics/advanced/Plane.ts b/Phaser/physics/Plane.ts similarity index 75% rename from Phaser/physics/advanced/Plane.ts rename to Phaser/physics/Plane.ts index 965c5600..3d15be03 100644 --- a/Phaser/physics/advanced/Plane.ts +++ b/Phaser/physics/Plane.ts @@ -1,5 +1,5 @@ -/// -/// +/// +/// /// /// @@ -9,7 +9,7 @@ * Based on the work Ju Hyung Lee started in JS PhyRus. */ -module Phaser.Physics.Advanced { +module Phaser.Physics { export class Plane { diff --git a/Phaser/physics/advanced/Space.ts b/Phaser/physics/Space.ts similarity index 98% rename from Phaser/physics/advanced/Space.ts rename to Phaser/physics/Space.ts index 4eecf70e..f8e8d9bb 100644 --- a/Phaser/physics/advanced/Space.ts +++ b/Phaser/physics/Space.ts @@ -1,5 +1,5 @@ -/// -/// +/// +/// /// /// /// @@ -14,11 +14,13 @@ * Based on the work Ju Hyung Lee started in JS PhyRus. */ -module Phaser.Physics.Advanced { +module Phaser.Physics { export class Space { - constructor() { + constructor(manager: Phaser.Physics.Manager) { + + this._manager = manager; this.bodies = []; this.bodyHash = {}; @@ -29,7 +31,7 @@ module Phaser.Physics.Advanced { this.numContacts = 0; this.contactSolvers = []; - this.gravity = new Phaser.Vec2(0, 10); + this.gravity = this._manager.gravity; this.damping = 0; this._linTolSqr = Space.SLEEP_LINEAR_TOLERANCE * Space.SLEEP_LINEAR_TOLERANCE; @@ -37,6 +39,8 @@ module Phaser.Physics.Advanced { } + private _manager: Phaser.Physics.Manager; + // Delta Timer private _delta: number; private _deltaInv: number; @@ -68,7 +72,7 @@ module Phaser.Physics.Advanced { public static TIME_TO_SLEEP = 0.5; public static SLEEP_LINEAR_TOLERANCE = 0.5; - public static SLEEP_ANGULAR_TOLERANCE = 2 * Phaser.GameMath.DEG_TO_RAD; + public static SLEEP_ANGULAR_TOLERANCE = 2 * 0.017453292519943294444444444444444; public bodies: Body[]; public joints: IJoint[]; diff --git a/Phaser/physics/advanced/Body.ts b/Phaser/physics/advanced/Body.ts deleted file mode 100644 index 41bd828a..00000000 --- a/Phaser/physics/advanced/Body.ts +++ /dev/null @@ -1,680 +0,0 @@ -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// - -/** -* Phaser - Advanced Physics - Body -* -* Based on the work Ju Hyung Lee started in JS PhyRus. -*/ - -module Phaser.Physics.Advanced { - - export class Body { - - constructor(sprite: Phaser.Sprite, type: number, x?: number = 0, y?: number = 0) { - - this.id = Phaser.Physics.Advanced.Manager.bodyCounter++; - this.name = 'body' + this.id; - this.type = type; - - if (sprite) - { - this.sprite = sprite; - this.game = sprite.game; - this.position = new Phaser.Vec2(Phaser.Physics.Advanced.Manager.pixelsToMeters(sprite.x), Phaser.Physics.Advanced.Manager.pixelsToMeters(sprite.y)); - this.angle = sprite.rotation; - } - else - { - 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); - this.centroid = new Phaser.Vec2; - this.velocity = new Phaser.Vec2; - this.force = new Phaser.Vec2; - this.angularVelocity = 0; - this.torque = 0; - this.linearDamping = 0; - this.angularDamping = 0; - this.sleepTime = 0; - this.awaked = false; - - this.shapes = []; - this.joints = []; - this.jointHash = {}; - - this.bounds = new Bounds; - - this.fixedRotation = false; - - this.categoryBits = 0x0001; - this.maskBits = 0xFFFF; - - this.stepCount = 0; - - } - - public toString(): string { - return "[{Body (name=" + this.name + " velocity=" + this.velocity.toString() + " angularVelocity: " + this.angularVelocity + ")}]"; - } - - private _tempVec2: Phaser.Vec2 = new Phaser.Vec2; - - /** - * Reference to Phaser.Game - */ - public game: Game; - - /** - * Reference to the parent Sprite - */ - public sprite: Phaser.Sprite; - - /** - * The Body ID - */ - public id: number; - - /** - * The Body name - */ - public name: string; - - /** - * The type of Body (disabled, dynamic, static or kinematic) - * Disabled = skips all physics operations / tests (default) - * Dynamic = gives and receives impacts - * Static = gives but doesn't receive impacts, cannot be moved by physics - * Kinematic = gives impacts, but never receives, can be moved by physics - * @type {number} - */ - public type: number; - - public angle: number; - - // Local to world transform - public transform: Phaser.Transform; - - // Local center of mass - public centroid: Phaser.Vec2; - - // World position of centroid - public position: Phaser.Vec2; - - // Velocity - public velocity: Phaser.Vec2; - - // Force - public force: Phaser.Vec2; - - // Angular velocity - public angularVelocity: number; - - // Torque - public torque: number; - - // Linear damping - public linearDamping: number; - - // Angular damping - public angularDamping: number; - - // Sleep time - public sleepTime: number; - - // Awaked - public awaked: bool; - - // Shapes - public shapes: IShape[] = []; - - // Length of the shapes array - public shapesLength: number; - - // Joints - public joints: IJoint[] = []; - public jointHash = {}; - - // 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; - public stepCount = 0; - public space: Space; - - public duplicate() { - - console.log('body duplicate called'); - - //var body = new Body(this.type, this.transform.t, this.angle); - - //for (var i = 0; i < this.shapes.length; i++) - //{ - // body.addShape(this.shapes[i].duplicate()); - //} - - //body.resetMassData(); - - //return body; - - } - - public get isDisabled(): bool { - return this.type == Phaser.Types.BODY_DISABLED ? true : false; - } - - public get isStatic(): bool { - return this.type == Phaser.Types.BODY_STATIC ? true : false; - } - - public get isKinetic(): bool { - return this.type == Phaser.Types.BODY_KINETIC ? true : false; - } - - public get isDynamic(): bool { - return this.type == Phaser.Types.BODY_DYNAMIC ? true : false; - } - - public setType(type: number) { - - if (type == this.type) - { - return; - } - - this.force.setTo(0, 0); - this.velocity.setTo(0, 0); - this.torque = 0; - this.angularVelocity = 0; - this.type = type; - - this.awake(true); - - } - - public 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 - shape.body = this; - - this.shapes.push(shape); - - this.shapesLength = this.shapes.length; - - return shape; - - } - - public removeShape(shape) { - - var index = this.shapes.indexOf(shape); - - if (index != -1) - { - this.shapes.splice(index, 1); - shape.body = undefined; - } - - this.shapesLength = this.shapes.length; - - } - - private setMass(mass) { - - this.mass = mass; - this.massInverted = mass > 0 ? 1 / mass : 0; - - } - - private setInertia(inertia) { - - this.inertia = inertia; - this.inertiaInverted = inertia > 0 ? 1 / inertia : 0; - - } - - public setTransform(pos, angle) { - - // inject the transform into this.position - this.transform.setTo(pos, angle); - Manager.write('setTransform: ' + this.position.toString()); - Manager.write('centroid: ' + this.centroid.toString()); - Phaser.TransformUtils.transform(this.transform, this.centroid, this.position); - Manager.write('post setTransform: ' + this.position.toString()); - //this.position.copyFrom(this.transform.transform(this.centroid)); - this.angle = angle; - - } - - 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); - // 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('--------------------'); - - } - - public getWorldPoint(p:Phaser.Vec2) { - // OPTIMISE: Creating new vector - return Phaser.TransformUtils.transform(this.transform, p); - } - - public getWorldVector(v:Phaser.Vec2) { - // OPTIMISE: Creating new vector - return Phaser.TransformUtils.rotate(this.transform, v); - } - - public getLocalPoint(p:Phaser.Vec2) { - // OPTIMISE: Creating new vector - return Phaser.TransformUtils.untransform(this.transform, p); - } - - public getLocalVector(v:Phaser.Vec2) { - // OPTIMISE: Creating new vector - return Phaser.TransformUtils.unrotate(this.transform, v); - } - - public setFixedRotation(flag) { - this.fixedRotation = flag; - this.resetMassData(); - } - - public resetMassData() { - - this.centroid.setTo(0, 0); - this.mass = 0; - this.massInverted = 0; - this.inertia = 0; - this.inertiaInverted = 0; - - if (this.isDynamic == false) - { - Phaser.TransformUtils.transform(this.transform, this.centroid, this.position); - //this.position.copyFrom(this.transform.transform(this.centroid)); - return; - } - - var totalMassCentroid = new Phaser.Vec2(0, 0); - var totalMass = 0; - var totalInertia = 0; - - for (var i = 0; i < this.shapes.length; i++) - { - var shape = this.shapes[i]; - var centroid = shape.centroid(); - var mass = shape.area() * shape.density; - var inertia = shape.inertia(mass); - - //console.log('rmd', centroid, shape); - - totalMassCentroid.multiplyAddByScalar(centroid, mass); - totalMass += mass; - totalInertia += inertia; - } - - //this.centroid.copy(vec2.scale(totalMassCentroid, 1 / totalMass)); - Phaser.Vec2Utils.scale(totalMassCentroid, 1 / totalMass, this.centroid); - - this.setMass(totalMass); - - if (!this.fixedRotation) - { - this.setInertia(totalInertia - totalMass * Phaser.Vec2Utils.dot(this.centroid, this.centroid)); - } - - // Move center of mass - var oldPosition: Phaser.Vec2 = Phaser.Vec2Utils.clone(this.position); - Phaser.TransformUtils.transform(this.transform, this.centroid, this.position); - - // Update center of mass velocity - oldPosition.subtract(this.position); - this.velocity.multiplyAddByScalar(Phaser.Vec2Utils.perp(oldPosition, oldPosition), this.angularVelocity); - - } - - public resetJointAnchors() { - - for (var i = 0; i < this.joints.length; i++) - { - var joint = this.joints[i]; - - if (!joint) - { - continue; - } - - var anchor1 = joint.getWorldAnchor1(); - var anchor2 = joint.getWorldAnchor2(); - - joint.setWorldAnchor1(anchor1); - joint.setWorldAnchor2(anchor2); - } - } - - public cacheData(source:string = '') { - - 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: 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) { - - Phaser.Vec2Utils.multiplyAdd(gravity, this.force, this.massInverted, this._tempVec2); - Phaser.Vec2Utils.multiplyAdd(this.velocity, this._tempVec2, dt, this.velocity); - - this.angularVelocity = this.angularVelocity + this.torque * this.inertiaInverted * dt; - - // Apply damping. - // ODE: dv/dt + c * v = 0 - // Solution: v(t) = v0 * exp(-c * t) - // Time step: v(t + dt) = v0 * exp(-c * (t + dt)) = v0 * exp(-c * t) * exp(-c * dt) = v * exp(-c * dt) - // v2 = exp(-c * dt) * v1 - // Taylor expansion: - // v2 = (1.0f - c * dt) * v1 - this.velocity.scale(this.clamp(1 - dt * (damping + this.linearDamping), 0, 1)); - this.angularVelocity *= this.clamp(1 - dt * (damping + this.angularDamping), 0, 1); - - this.force.setTo(0, 0); - this.torque = 0; - - } - - 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:number) { - - this.position.add(Phaser.Vec2Utils.scale(this.velocity, dt, this._tempVec2)); - - this.angle += this.angularVelocity * dt; - - } - - public resetForce() { - this.force.setTo(0, 0); - this.torque = 0; - } - - public applyForce(force:Phaser.Vec2, p:Phaser.Vec2) { - - if (this.isDynamic == false) - { - return; - } - - if (this.isAwake == false) - { - this.awake(true); - } - - this.force.add(force); - - Phaser.Vec2Utils.subtract(p, this.position, this._tempVec2); - - this.torque += Phaser.Vec2Utils.cross(this._tempVec2, force); - - } - - public applyForceToCenter(force:Phaser.Vec2) { - - if (this.isDynamic == false) - { - return; - } - - if (this.isAwake == false) - { - this.awake(true); - } - - this.force.add(force); - - } - - public applyTorque(torque:number) { - - if (this.isDynamic == false) - { - return; - } - - if (this.isAwake == false) - { - this.awake(true); - } - - this.torque += torque; - - } - - public applyLinearImpulse(impulse:Phaser.Vec2, p:Phaser.Vec2) { - - if (this.isDynamic == false) - { - return; - } - - if (this.isAwake == false) - { - this.awake(true); - } - - this.velocity.multiplyAddByScalar(impulse, this.massInverted); - - Phaser.Vec2Utils.subtract(p, this.position, this._tempVec2); - - this.angularVelocity += Phaser.Vec2Utils.cross(this._tempVec2, impulse) * this.inertiaInverted; - - } - - public applyAngularImpulse(impulse: number) { - - if (this.isDynamic == false) - { - return; - } - - if (this.isAwake == false) - { - this.awake(true); - } - - this.angularVelocity += impulse * this.inertiaInverted; - - } - - public kineticEnergy() { - - var vsq = this.velocity.dot(this.velocity); - var wsq = this.angularVelocity * this.angularVelocity; - - return 0.5 * (this.mass * vsq + this.inertia * wsq); - - } - - public get isAwake(): bool { - return this.awaked; - } - - public awake(flag) { - - this.awaked = flag; - - if (flag) - { - this.sleepTime = 0; - } - else - { - this.velocity.setTo(0, 0); - this.angularVelocity = 0; - this.force.setTo(0, 0); - this.torque = 0; - } - - } - - public isCollidable(other:Body) { - - if (this == other) - { - return false; - } - - if (this.isDynamic == false && other.isDynamic == false) - { - return false; - } - - if (!(this.maskBits & other.categoryBits) || !(other.maskBits & this.categoryBits)) - { - return false; - } - - for (var i = 0; i < this.joints.length; i++) - { - var joint = this.joints[i]; - - if (!this.joints[i] || (!this.joints[i].collideConnected && other.jointHash[this.joints[i].id] != undefined)) - { - return false; - } - } - - return true; - - } - - } - -} \ No newline at end of file diff --git a/Phaser/physics/advanced/joints/IJoint.ts b/Phaser/physics/joints/IJoint.ts similarity index 71% rename from Phaser/physics/advanced/joints/IJoint.ts rename to Phaser/physics/joints/IJoint.ts index 1f0f1fb9..fdeb393a 100644 --- a/Phaser/physics/advanced/joints/IJoint.ts +++ b/Phaser/physics/joints/IJoint.ts @@ -1,6 +1,6 @@ -/// -/// -/// +/// +/// +/// /// /// @@ -10,15 +10,15 @@ * Based on the work Ju Hyung Lee started in JS PhyRus. */ -module Phaser.Physics.Advanced { +module Phaser.Physics { export interface IJoint { id: number; type: number; - body1: Phaser.Physics.Advanced.Body; - body2: Phaser.Physics.Advanced.Body; + body1: Phaser.Physics.Body; + body2: Phaser.Physics.Body; collideConnected; // bool? maxForce: number; diff --git a/Phaser/physics/advanced/joints/Joint.ts b/Phaser/physics/joints/Joint.ts similarity index 70% rename from Phaser/physics/advanced/joints/Joint.ts rename to Phaser/physics/joints/Joint.ts index 6a64ae79..3f850959 100644 --- a/Phaser/physics/advanced/joints/Joint.ts +++ b/Phaser/physics/joints/Joint.ts @@ -1,6 +1,6 @@ -/// -/// -/// +/// +/// +/// /// /// @@ -10,13 +10,13 @@ * Based on the work Ju Hyung Lee started in JS PhyRus. */ -module Phaser.Physics.Advanced { +module Phaser.Physics { export class Joint { - constructor(type: number, body1:Phaser.Physics.Advanced.Body, body2:Phaser.Physics.Advanced.Body, collideConnected) { + constructor(type: number, body1:Phaser.Physics.Body, body2:Phaser.Physics.Body, collideConnected) { - this.id = Phaser.Physics.Advanced.Manager.jointCounter++; + this.id = Phaser.Physics.Manager.jointCounter++; this.type = type; this.body1 = body1; @@ -32,8 +32,8 @@ module Phaser.Physics.Advanced { public id: number; public type: number; - public body1: Phaser.Physics.Advanced.Body; - public body2: Phaser.Physics.Advanced.Body; + public body1: Phaser.Physics.Body; + public body2: Phaser.Physics.Body; public collideConnected; // bool? public maxForce: number; diff --git a/Phaser/physics/advanced/shapes/Box.ts b/Phaser/physics/shapes/Box.ts similarity index 63% rename from Phaser/physics/advanced/shapes/Box.ts rename to Phaser/physics/shapes/Box.ts index c252a504..461faf86 100644 --- a/Phaser/physics/advanced/shapes/Box.ts +++ b/Phaser/physics/shapes/Box.ts @@ -1,4 +1,4 @@ -/// +/// /// /// /// @@ -10,17 +10,17 @@ * Based on the work Ju Hyung Lee started in JS PhyRus. */ -module Phaser.Physics.Advanced.Shapes { +module Phaser.Physics.Shapes { - export class Box extends Phaser.Physics.Advanced.Shapes.Poly { + export class Box extends Phaser.Physics.Shapes.Poly { // Give in pixels constructor(x, y, width, height) { - //x = Manager.pixelsToMeters(x); - //y = Manager.pixelsToMeters(y); - //width = Manager.pixelsToMeters(width); - //height = Manager.pixelsToMeters(height); + 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/Circle.ts b/Phaser/physics/shapes/Circle.ts similarity index 92% rename from Phaser/physics/advanced/shapes/Circle.ts rename to Phaser/physics/shapes/Circle.ts index 0f12673b..23997aa5 100644 --- a/Phaser/physics/advanced/shapes/Circle.ts +++ b/Phaser/physics/shapes/Circle.ts @@ -1,5 +1,5 @@ -/// -/// +/// +/// /// /// /// @@ -10,9 +10,9 @@ * Based on the work Ju Hyung Lee started in JS PhyRus. */ -module Phaser.Physics.Advanced.Shapes { +module Phaser.Physics.Shapes { - export class Circle extends Phaser.Physics.Advanced.Shape implements IShape { + export class Circle extends Phaser.Physics.Shape implements IShape { constructor(radius: number, x?: number = 0, y?: number = 0) { diff --git a/Phaser/physics/advanced/shapes/IShape.ts b/Phaser/physics/shapes/IShape.ts similarity index 74% rename from Phaser/physics/advanced/shapes/IShape.ts rename to Phaser/physics/shapes/IShape.ts index 8ef1dbb5..1e49f5a9 100644 --- a/Phaser/physics/advanced/shapes/IShape.ts +++ b/Phaser/physics/shapes/IShape.ts @@ -1,6 +1,6 @@ -/// -/// -/// +/// +/// +/// /// /// /// @@ -11,7 +11,7 @@ * Based on the work Ju Hyung Lee started in JS PhyRus. */ -module Phaser.Physics.Advanced { +module Phaser.Physics { export interface IShape { @@ -34,9 +34,9 @@ module Phaser.Physics.Advanced { findVertexByPoint(p: Phaser.Vec2, minDist: number): number; verts: Phaser.Vec2[]; - planes: Phaser.Physics.Advanced.Plane[]; + planes: Phaser.Physics.Plane[]; tverts: Phaser.Vec2[]; - tplanes: Phaser.Physics.Advanced.Plane[]; + tplanes: Phaser.Physics.Plane[]; convexity: bool; } diff --git a/Phaser/physics/advanced/shapes/Poly.ts b/Phaser/physics/shapes/Poly.ts similarity index 93% rename from Phaser/physics/advanced/shapes/Poly.ts rename to Phaser/physics/shapes/Poly.ts index 0a8e3f77..a11cdc6f 100644 --- a/Phaser/physics/advanced/shapes/Poly.ts +++ b/Phaser/physics/shapes/Poly.ts @@ -1,5 +1,5 @@ -/// -/// +/// +/// /// /// /// @@ -11,9 +11,9 @@ * Based on the work Ju Hyung Lee started in JS PhyRus. */ -module Phaser.Physics.Advanced.Shapes { +module Phaser.Physics.Shapes { - export class Poly extends Phaser.Physics.Advanced.Shape implements IShape { + export class Poly extends Phaser.Physics.Shape implements IShape { // 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 @@ -33,7 +33,7 @@ module Phaser.Physics.Advanced.Shapes { this.verts[i] = new Phaser.Vec2(verts[i].x, verts[i].y); this.tverts[i] = this.verts[i]; //this.tverts[i] = new Phaser.Vec2(verts[i].x, verts[i].y); - this.tplanes[i] = new Phaser.Physics.Advanced.Plane(new Phaser.Vec2, 0); + this.tplanes[i] = new Phaser.Physics.Plane(new Phaser.Vec2, 0); } } @@ -62,12 +62,12 @@ 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] = new Phaser.Physics.Advanced.Plane(n, Phaser.Vec2Utils.dot(n, a)); + this.planes[i] = new Phaser.Physics.Plane(n, Phaser.Vec2Utils.dot(n, a)); this.tverts[i] = Phaser.Vec2Utils.clone(this.verts[i]); // reference??? //this.tverts[i] = this.verts[i]; // reference??? - this.tplanes[i] = new Phaser.Physics.Advanced.Plane(new Phaser.Vec2, 0); + this.tplanes[i] = new Phaser.Physics.Plane(new Phaser.Vec2, 0); } for (var i = 0; i < this.verts.length; i++) @@ -85,7 +85,7 @@ module Phaser.Physics.Advanced.Shapes { } public duplicate() { - return new Phaser.Physics.Advanced.Shapes.Poly(this.verts); + return new Phaser.Physics.Shapes.Poly(this.verts); } public recenter(c) { diff --git a/Phaser/physics/advanced/shapes/Segment.ts b/Phaser/physics/shapes/Segment.ts similarity index 94% rename from Phaser/physics/advanced/shapes/Segment.ts rename to Phaser/physics/shapes/Segment.ts index 51ebc470..b949206e 100644 --- a/Phaser/physics/advanced/shapes/Segment.ts +++ b/Phaser/physics/shapes/Segment.ts @@ -1,5 +1,5 @@ -/// -/// +/// +/// /// /// /// @@ -10,9 +10,9 @@ * Based on the work Ju Hyung Lee started in JS PhyRus. */ -module Phaser.Physics.Advanced.Shapes { +module Phaser.Physics.Shapes { - export class Segment extends Phaser.Physics.Advanced.Shape implements IShape { + export class Segment extends Phaser.Physics.Shape implements IShape { constructor(a, b, radius: number) { @@ -52,7 +52,7 @@ module Phaser.Physics.Advanced.Shapes { } public duplicate() { - return new Phaser.Physics.Advanced.Shapes.Segment(this.a, this.b, this.radius); + return new Phaser.Physics.Shapes.Segment(this.a, this.b, this.radius); } public recenter(c) { diff --git a/Phaser/physics/advanced/shapes/Shape.ts b/Phaser/physics/shapes/Shape.ts similarity index 77% rename from Phaser/physics/advanced/shapes/Shape.ts rename to Phaser/physics/shapes/Shape.ts index c1d81c2c..ed206c8e 100644 --- a/Phaser/physics/advanced/shapes/Shape.ts +++ b/Phaser/physics/shapes/Shape.ts @@ -1,5 +1,5 @@ -/// -/// +/// +/// /// /// /// @@ -11,13 +11,13 @@ * Based on the work Ju Hyung Lee started in JS PhyRus. */ -module Phaser.Physics.Advanced { +module Phaser.Physics { export class Shape { constructor(type: number) { - this.id = Phaser.Physics.Advanced.Manager.shapeCounter++; + this.id = Phaser.Physics.Manager.shapeCounter++; this.type = type; this.elasticity = 0.0; @@ -33,10 +33,10 @@ module Phaser.Physics.Advanced { public body: Body; public verts: Phaser.Vec2[]; - public planes: Phaser.Physics.Advanced.Plane[]; + public planes: Phaser.Physics.Plane[]; public tverts: Phaser.Vec2[]; - public tplanes: Phaser.Physics.Advanced.Plane[]; + public tplanes: Phaser.Physics.Plane[]; public convexity: bool; diff --git a/Phaser/physics/advanced/shapes/Triangle.ts b/Phaser/physics/shapes/Triangle.ts similarity index 81% rename from Phaser/physics/advanced/shapes/Triangle.ts rename to Phaser/physics/shapes/Triangle.ts index 7b88e013..8d78647d 100644 --- a/Phaser/physics/advanced/shapes/Triangle.ts +++ b/Phaser/physics/shapes/Triangle.ts @@ -1,4 +1,4 @@ -/// +/// /// /// /// @@ -10,9 +10,9 @@ * Based on the work Ju Hyung Lee started in JS PhyRus. */ -module Phaser.Physics.Advanced.Shapes { +module Phaser.Physics.Shapes { - export class Triangle extends Phaser.Physics.Advanced.Shapes.Poly { + export class Triangle extends Phaser.Physics.Shapes.Poly { constructor(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number) { diff --git a/Phaser/utils/ColorUtils.ts b/Phaser/utils/ColorUtils.ts index 9f26ca8e..9ca2aa8c 100644 --- a/Phaser/utils/ColorUtils.ts +++ b/Phaser/utils/ColorUtils.ts @@ -124,7 +124,7 @@ module Phaser { if (threshold >= 359 || threshold <= 0) { - throw Error("FlxColor Warning: Invalid threshold given to getSplitComplementHarmony()"); + throw Error("ColorUtils Warning: Invalid threshold given to getSplitComplementHarmony()"); } var opposite: number = ColorUtils.game.math.wrapValue(hsv.hue, 180, 359); diff --git a/Phaser/utils/DebugUtils.ts b/Phaser/utils/DebugUtils.ts index ec2220b7..c593f7ed 100644 --- a/Phaser/utils/DebugUtils.ts +++ b/Phaser/utils/DebugUtils.ts @@ -17,6 +17,12 @@ module Phaser { static game: Game; + /** + * Render context of stage's canvas. + * @type {CanvasRenderingContext2D} + */ + static context: CanvasRenderingContext2D; + /** * Render debug infos. (including name, bounds info, position and some other properties) * @param x {number} X position of the debug info to be rendered. @@ -25,14 +31,14 @@ module Phaser { */ static renderSpriteInfo(sprite: Sprite, x: number, y: number, color?: string = 'rgb(255,255,255)') { - DebugUtils.game.stage.context.fillStyle = color; - DebugUtils.game.stage.context.fillText('Sprite: ' + ' (' + sprite.width + ' x ' + sprite.height + ') origin: ' + sprite.transform.origin.x + ' x ' + sprite.transform.origin.y, x, y); - DebugUtils.game.stage.context.fillText('x: ' + sprite.x.toFixed(1) + ' y: ' + sprite.y.toFixed(1) + ' rotation: ' + sprite.rotation.toFixed(1), x, y + 14); - DebugUtils.game.stage.context.fillText('wx: ' + sprite.worldView.x + ' wy: ' + sprite.worldView.y + ' ww: ' + sprite.worldView.width.toFixed(1) + ' wh: ' + sprite.worldView.height.toFixed(1) + ' wb: ' + sprite.worldView.bottom + ' wr: ' + sprite.worldView.right, x, y + 28); - DebugUtils.game.stage.context.fillText('sx: ' + sprite.transform.scale.x.toFixed(1) + ' sy: ' + sprite.transform.scale.y.toFixed(1), x, y + 42); - DebugUtils.game.stage.context.fillText('tx: ' + sprite.texture.width.toFixed(1) + ' ty: ' + sprite.texture.height.toFixed(1), x, y + 56); - DebugUtils.game.stage.context.fillText('cx: ' + sprite.cameraView.x + ' cy: ' + sprite.cameraView.y + ' cw: ' + sprite.cameraView.width + ' ch: ' + sprite.cameraView.height + ' cb: ' + sprite.cameraView.bottom + ' cr: ' + sprite.cameraView.right, x, y + 70); - DebugUtils.game.stage.context.fillText('inCamera: ' + DebugUtils.game.renderer.inCamera(DebugUtils.game.camera, sprite), x, y + 84); + DebugUtils.context.fillStyle = color; + DebugUtils.context.fillText('Sprite: ' + ' (' + sprite.width + ' x ' + sprite.height + ') origin: ' + sprite.transform.origin.x + ' x ' + sprite.transform.origin.y, x, y); + DebugUtils.context.fillText('x: ' + sprite.x.toFixed(1) + ' y: ' + sprite.y.toFixed(1) + ' rotation: ' + sprite.rotation.toFixed(1), x, y + 14); + DebugUtils.context.fillText('wx: ' + sprite.worldView.x + ' wy: ' + sprite.worldView.y + ' ww: ' + sprite.worldView.width.toFixed(1) + ' wh: ' + sprite.worldView.height.toFixed(1) + ' wb: ' + sprite.worldView.bottom + ' wr: ' + sprite.worldView.right, x, y + 28); + DebugUtils.context.fillText('sx: ' + sprite.transform.scale.x.toFixed(1) + ' sy: ' + sprite.transform.scale.y.toFixed(1), x, y + 42); + DebugUtils.context.fillText('tx: ' + sprite.texture.width.toFixed(1) + ' ty: ' + sprite.texture.height.toFixed(1), x, y + 56); + DebugUtils.context.fillText('cx: ' + sprite.cameraView.x + ' cy: ' + sprite.cameraView.y + ' cw: ' + sprite.cameraView.width + ' ch: ' + sprite.cameraView.height + ' cb: ' + sprite.cameraView.bottom + ' cr: ' + sprite.cameraView.right, x, y + 70); + DebugUtils.context.fillText('inCamera: ' + DebugUtils.game.renderer.inCamera(DebugUtils.game.camera, sprite), x, y + 84); } @@ -43,29 +49,53 @@ module Phaser { camera = DebugUtils.game.camera; } - //var dx = (camera.screenView.x * sprite.transform.scrollFactor.x) + sprite.x - (camera.worldView.x * sprite.transform.scrollFactor.x); - //var dy = (camera.screenView.y * sprite.transform.scrollFactor.y) + sprite.y - (camera.worldView.y * sprite.transform.scrollFactor.y); var dx = sprite.worldView.x; var dy = sprite.worldView.y; - DebugUtils.game.stage.context.fillStyle = color; - DebugUtils.game.stage.context.fillRect(dx, dy, sprite.width, sprite.height); + DebugUtils.context.fillStyle = color; + DebugUtils.context.fillRect(dx, dy, sprite.width, sprite.height); } - static renderSpritePhysicsBody(sprite: Sprite, camera?: Camera = null, color?: string = 'rgba(255,0,0,0.2)') { + static renderPhysicsBody(body: Phaser.Physics.Body, lineWidth: number = 1, fillStyle: string = 'rgba(0,255,0,0.2)', sleepStyle: string = 'rgba(100,100,100,0.2)') { - if (camera == null) + for (var s = 0; s < body.shapes.length; s++) { - camera = DebugUtils.game.camera; + DebugUtils.context.beginPath(); + + if (body.shapes[s].type == Phaser.Physics.Manager.SHAPE_TYPE_POLY) + { + var verts = body.shapes[s].tverts; + + DebugUtils.context.moveTo((body.position.x + verts[0].x) * 50, (body.position.y + verts[0].y) * 50); + + for (var i = 0; i < verts.length; i++) { + DebugUtils.context.lineTo((body.position.x + verts[i].x) * 50, (body.position.y + verts[i].y) * 50); + } + + DebugUtils.context.lineTo((body.position.x + verts[verts.length - 1].x) * 50, (body.position.y + verts[verts.length - 1].y) * 50); + } + else if (body.shapes[s].type == Phaser.Physics.Manager.SHAPE_TYPE_CIRCLE) + { + var circle = body.shapes[s]; + DebugUtils.context.arc(circle.tc.x * 50, circle.tc.y * 50, circle.radius * 50, 0, Math.PI * 2, false); + } + + DebugUtils.context.closePath(); + + if (body.isAwake) + { + DebugUtils.context.fillStyle = fillStyle; + } + else + { + DebugUtils.context.fillStyle = sleepStyle; + } + + DebugUtils.context.fill(); + } - var dx = (camera.screenView.x * sprite.transform.scrollFactor.x) + sprite.body.x - (camera.worldView.x * sprite.transform.scrollFactor.x); - var dy = (camera.screenView.y * sprite.transform.scrollFactor.y) + sprite.body.y - (camera.worldView.y * sprite.transform.scrollFactor.y); - - DebugUtils.game.stage.context.fillStyle = color; - DebugUtils.game.stage.context.fillRect(dx, dy, sprite.body.width, sprite.body.height); - } } diff --git a/Phaser/utils/SpriteUtils.ts b/Phaser/utils/SpriteUtils.ts index 28b597d1..be61a296 100644 --- a/Phaser/utils/SpriteUtils.ts +++ b/Phaser/utils/SpriteUtils.ts @@ -272,8 +272,8 @@ module Phaser { static reset(sprite: Sprite, x: number, y: number) { sprite.revive(); - sprite.body.touching = Types.NONE; - sprite.body.wasTouching = Types.NONE; + //sprite.body.touching = Types.NONE; + //sprite.body.wasTouching = Types.NONE; sprite.x = x; sprite.y = y; sprite.body.velocity.x = 0; diff --git a/README.md b/README.md index bd59ca53..d92e7722 100644 --- a/README.md +++ b/README.md @@ -44,15 +44,17 @@ TODO: * Drag Sprite with "snap to center" uses local coords not world, so fails on scrolling world (no center lock works fine) * Need to be able to set the current tilemap layer, then the getTileXY default layer uses that one if no other given * Pointer worldX/Y don't appear to be correct for some reason - - +* Create a Pixel game object type (useful for particles / fx) * Sprite collision events * See which functions in the input component can move elsewhere (utils) * Move all of the renderDebugInfo methods to the DebugUtils class * Check bounds/edge points when sprite is only 1x1 sized :) - * See what I can move out of Body and into a BodyUtils class. * See about optimising Advanced Physics a lot more, so it doesn't create lots of Vec2s everywhere. +* QuadTree.physics.checkHullIntersection +* Fix the Motion methods for the new physics system +* Moved findShapeByPoint etc from Space to Manager (or at least add a proxy to them) + V1.0.0 @@ -71,7 +73,7 @@ V1.0.0 * Added Tween.loop property so they can now re-run themselves indefinitely. * Added Tween.yoyo property so they can reverse themselves after completing. * Added Gravity to the Physics component. -* Removed Sprite.rotation - use Sprite.angle instead +* Removed Sprite.angle - use Sprite.rotation instead * Optimised separateX/Y and overlap so they don't use any temporary vars any more. * Added the new Physics.Body object to all Sprites. Used for all physics calculations in-game. Will be extended for Fixtures/Joints in future. * Added SpriteUtils.setOriginToCenter to quickly set the origin of a sprite based on either frameBounds or body.bounds @@ -83,7 +85,7 @@ V1.0.0 * Added Group.addNewSprite(x,y,key) for quick addition of new Sprites to a Group * Fixed Group.sort so the sortHandler is called correctly * Added Group.swap(a,b) to swap the z-index of 2 objects with optional rendering update boolean -* Sprites dispatch killed/revived and added to and removed from Group events. +* Sprites dispatch new events for: killed, revived, added to Group and removed from Group. * Added Input drag, bounds, sprite bounds and snapping support. * Added the new ColorUtils class full of lots of handy color manipulation functions. * Fixed issue in Camera.inCamera check where it wouldn't take into consideration the Sprites scrollFactor. diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 27a5bcf9..3af754cb 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -65,7 +65,6 @@ scrollfactor 2.ts - @@ -174,25 +173,14 @@ when particles collide.ts - - aabb 1.ts - - - - aabb vs aabb 1.ts - - - - - body1.ts - - - obb vs obb.ts + + + simple test 1.ts ballscroller.ts diff --git a/Tests/cameras/world sprite.js b/Tests/cameras/world sprite.js index 588a638a..93ac9c22 100644 --- a/Tests/cameras/world sprite.js +++ b/Tests/cameras/world sprite.js @@ -12,9 +12,6 @@ function create() { game.add.sprite(0, 0, 'backdrop'); ball = game.add.sprite(200, 200, 'ball'); - ball.body.offset.setTo(-16, -16); - ball.body.width = 100; - ball.body.height = 100; ball.body.velocity.x = 50; ball.transform.scale.setTo(2, 2); } @@ -56,7 +53,5 @@ function render() { game.camera.renderDebugInfo(32, 32); Phaser.DebugUtils.renderSpriteInfo(ball, 32, 200); - //Phaser.DebugUtils.renderSpriteBounds(ball); - Phaser.DebugUtils.renderSpritePhysicsBody(ball); } })(); diff --git a/Tests/cameras/world sprite.ts b/Tests/cameras/world sprite.ts index 597b4c67..62d4ecd6 100644 --- a/Tests/cameras/world sprite.ts +++ b/Tests/cameras/world sprite.ts @@ -24,10 +24,6 @@ ball = game.add.sprite(200, 200, 'ball'); - ball.body.offset.setTo(-16, -16); - ball.body.width = 100; - ball.body.height = 100; - ball.body.velocity.x = 50; ball.transform.scale.setTo(2, 2); @@ -83,8 +79,6 @@ game.camera.renderDebugInfo(32, 32); Phaser.DebugUtils.renderSpriteInfo(ball, 32, 200); - //Phaser.DebugUtils.renderSpriteBounds(ball); - Phaser.DebugUtils.renderSpritePhysicsBody(ball); } diff --git a/Tests/input/world drag.js b/Tests/input/world drag.js index f6a3d3ab..e75a9887 100644 --- a/Tests/input/world drag.js +++ b/Tests/input/world drag.js @@ -33,7 +33,6 @@ } function render() { game.camera.renderDebugInfo(32, 32); - test.body.renderDebugInfo(300, 32); Phaser.DebugUtils.renderSpriteInfo(test, 32, 200); game.input.renderDebugInfo(300, 200); } diff --git a/Tests/input/world drag.ts b/Tests/input/world drag.ts index afbb9f87..d2572724 100644 --- a/Tests/input/world drag.ts +++ b/Tests/input/world drag.ts @@ -62,8 +62,6 @@ game.camera.renderDebugInfo(32, 32); - test.body.renderDebugInfo(300, 32); - Phaser.DebugUtils.renderSpriteInfo(test, 32, 200); game.input.renderDebugInfo(300, 200); diff --git a/Tests/phaser.js b/Tests/phaser.js index 96d3a9b8..661e4d30 100644 --- a/Tests/phaser.js +++ b/Tests/phaser.js @@ -708,20 +708,28 @@ var Phaser; QuadTree._iterator = QuadTree._iterator.next; continue; } - //if (QuadTree._object.body.bounds.checkHullIntersection(this._checkObject.body.bounds)) - if(QuadTree.physics.checkHullIntersection(QuadTree._object.body, this._checkObject.body)) { - //Execute callback functions if they exist - if((QuadTree._processingCallback == null) || QuadTree._processingCallback(QuadTree._object, this._checkObject)) { - this._overlapProcessed = true; - } - if(this._overlapProcessed && (QuadTree._notifyCallback != null)) { - if(QuadTree._callbackContext !== null) { - QuadTree._notifyCallback.call(QuadTree._callbackContext, QuadTree._object, this._checkObject); - } else { - QuadTree._notifyCallback(QuadTree._object, this._checkObject); - } - } + /* + if (QuadTree.physics.checkHullIntersection(QuadTree._object.body, this._checkObject.body)) + { + //Execute callback functions if they exist + if ((QuadTree._processingCallback == null) || QuadTree._processingCallback(QuadTree._object, this._checkObject)) + { + this._overlapProcessed = true; } + + if (this._overlapProcessed && (QuadTree._notifyCallback != null)) + { + if (QuadTree._callbackContext !== null) + { + QuadTree._notifyCallback.call(QuadTree._callbackContext, QuadTree._object, this._checkObject); + } + else + { + QuadTree._notifyCallback(QuadTree._object, this._checkObject); + } + } + } + */ QuadTree._iterator = QuadTree._iterator.next; } return this._overlapProcessed; @@ -1587,7 +1595,7 @@ var Phaser; if (typeof threshold === "undefined") { threshold = 30; } var hsv = ColorUtils.RGBtoHSV(color); if(threshold >= 359 || threshold <= 0) { - throw Error("FlxColor Warning: Invalid threshold given to getSplitComplementHarmony()"); + throw Error("ColorUtils Warning: Invalid threshold given to getSplitComplementHarmony()"); } var opposite = ColorUtils.game.math.wrapValue(hsv.hue, 180, 359); var warmer = ColorUtils.game.math.wrapValue(hsv.hue, opposite - threshold, 359); @@ -3195,7 +3203,7 @@ var Phaser; this._prevRotation = this.rotation; dirty = true; } - // If it has moved, updated the edges and center + // If it has moved, update the edges and center if(dirty || this.parent.x != this._pos.x || this.parent.y != this._pos.y) { this.center.x = this.parent.x + this._distance * this._scA.y; this.center.y = this.parent.y + this._distance * this._scA.x; @@ -4260,231 +4268,2817 @@ var Phaser; } */ })(Phaser || (Phaser = {})); +/// +/// +/** +* Phaser - 2D Transform +* +* A 2D Transform +*/ +var Phaser; +(function (Phaser) { + var Transform = (function () { + /** + * Creates a new 2D Transform object. + * @class Transform + * @constructor + * @return {Transform} This object + **/ + function Transform(pos, angle) { + this.t = Phaser.Vec2Utils.clone(pos); + this.c = Math.cos(angle); + this.s = Math.sin(angle); + this.angle = angle; + } + Transform.prototype.toString = function () { + return 't=' + this.t.toString() + ' c=' + this.c + ' s=' + this.s + ' a=' + this.angle; + }; + Transform.prototype.setTo = function (pos, angle) { + this.t.copyFrom(pos); + this.c = Math.cos(angle); + this.s = Math.sin(angle); + return this; + }; + Transform.prototype.setRotation = function (angle) { + if(angle !== this.angle) { + this.c = Math.cos(angle); + this.s = Math.sin(angle); + this.angle = angle; + } + return this; + }; + Transform.prototype.setPosition = function (p) { + this.t.copyFrom(p); + return this; + }; + Transform.prototype.identity = function () { + this.t.setTo(0, 0); + this.c = 1; + this.s = 0; + return this; + }; + return Transform; + })(); + Phaser.Transform = Transform; +})(Phaser || (Phaser = {})); +/// +/// +/// +/** +* Phaser - TransformUtils +* +* A collection of methods useful for manipulating and performing operations on 2D Transforms. +* +*/ +var Phaser; +(function (Phaser) { + var TransformUtils = (function () { + function TransformUtils() { } + TransformUtils.rotate = function rotate(t, v, out) { + if (typeof out === "undefined") { out = new Phaser.Vec2(); } + //return new vec2(v.x * this.c - v.y * this.s, v.x * this.s + v.y * this.c); + return out.setTo(v.x * t.c - v.y * t.s, v.x * t.s + v.y * t.c); + }; + TransformUtils.unrotate = function unrotate(t, v, out) { + if (typeof out === "undefined") { out = new Phaser.Vec2(); } + //return new vec2(v.x * this.c + v.y * this.s, -v.x * this.s + v.y * this.c); + return out.setTo(v.x * t.c + v.y * t.s, -v.x * t.s + v.y * t.c); + }; + TransformUtils.transform = function transform(t, v, out) { + if (typeof out === "undefined") { out = new Phaser.Vec2(); } + //return new vec2(v.x * this.c - v.y * this.s + this.t.x, v.x * this.s + v.y * this.c + this.t.y); + return out.setTo(v.x * t.c - v.y * t.s + t.t.x, v.x * t.s + v.y * t.c + t.t.y); + }; + TransformUtils.untransform = function untransform(t, v, out) { + if (typeof out === "undefined") { out = new Phaser.Vec2(); } + var px = v.x - t.t.x; + var py = v.y - t.t.y; + //return new vec2(px * this.c + py * this.s, -px * this.s + py * this.c); + return out.setTo(px * t.c + py * t.s, -px * t.s + py * t.c); + }; + return TransformUtils; + })(); + Phaser.TransformUtils = TransformUtils; +})(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + /// + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Joint + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + (function (Physics) { + var Joint = (function () { + function Joint(type, body1, body2, collideConnected) { + this.id = Phaser.Physics.Manager.jointCounter++; + this.type = type; + this.body1 = body1; + this.body2 = body2; + this.collideConnected = collideConnected; + this.maxForce = 9999999999; + this.breakable = false; + } + Joint.prototype.getWorldAnchor1 = function () { + return this.body1.getWorldPoint(this.anchor1); + }; + Joint.prototype.getWorldAnchor2 = function () { + return this.body2.getWorldPoint(this.anchor2); + }; + Joint.prototype.setWorldAnchor1 = function (anchor1) { + this.anchor1 = this.body1.getLocalPoint(anchor1); + }; + Joint.prototype.setWorldAnchor2 = function (anchor2) { + this.anchor2 = this.body2.getLocalPoint(anchor2); + }; + return Joint; + })(); + Physics.Joint = Joint; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + /// + /// + /// + /** + * Phaser - Physics Manager + * + * The Physics Manager is responsible for looking after, creating and colliding + * all of the physics bodies and joints in the world. + */ + (function (Physics) { + var Manager = (function () { + function Manager(game) { + this.lastTime = Date.now(); + this.frameRateHz = 60; + this.timeDelta = 0; + this.paused = false; + this.step = false; + // step through the simulation (i.e. per click) + //public paused: bool = true; + //public step: bool = false; // step through the simulation (i.e. per click) + this.velocityIterations = 8; + this.positionIterations = 4; + this.allowSleep = true; + this.warmStarting = true; + this.game = game; + this.gravity = new Phaser.Vec2(); + this.space = new Physics.Space(this); + Manager.collision = new Physics.Collision(); + } + Manager.clear = function clear() { + //Manager.debug.textContent = ""; + Manager.log = []; + }; + Manager.write = function write(s) { + //Manager.debug.textContent += s + "\n"; + }; + Manager.writeAll = function writeAll() { + for(var i = 0; i < Manager.log.length; i++) { + //Manager.debug.textContent += Manager.log[i]; + } + }; + Manager.log = []; + Manager.dump = function dump(phase, body) { + /* + var s = "\n\nPhase: " + phase + "\n"; + s += "Position: " + body.position.toString() + "\n"; + s += "Velocity: " + body.velocity.toString() + "\n"; + s += "Angle: " + body.angle + "\n"; + s += "Force: " + body.force.toString() + "\n"; + s += "Torque: " + body.torque + "\n"; + s += "Bounds: " + body.bounds.toString() + "\n"; + s += "Shape ***\n"; + s += "Vert 0: " + body.shapes[0].verts[0].toString() + "\n"; + s += "Vert 1: " + body.shapes[0].verts[1].toString() + "\n"; + s += "Vert 2: " + body.shapes[0].verts[2].toString() + "\n"; + s += "Vert 3: " + body.shapes[0].verts[3].toString() + "\n"; + s += "TVert 0: " + body.shapes[0].tverts[0].toString() + "\n"; + s += "TVert 1: " + body.shapes[0].tverts[1].toString() + "\n"; + s += "TVert 2: " + body.shapes[0].tverts[2].toString() + "\n"; + s += "TVert 3: " + body.shapes[0].tverts[3].toString() + "\n"; + s += "Plane 0: " + body.shapes[0].planes[0].normal.toString() + "\n"; + s += "Plane 1: " + body.shapes[0].planes[1].normal.toString() + "\n"; + s += "Plane 2: " + body.shapes[0].planes[2].normal.toString() + "\n"; + s += "Plane 3: " + body.shapes[0].planes[3].normal.toString() + "\n"; + s += "TPlane 0: " + body.shapes[0].tplanes[0].normal.toString() + "\n"; + s += "TPlane 1: " + body.shapes[0].tplanes[1].normal.toString() + "\n"; + s += "TPlane 2: " + body.shapes[0].tplanes[2].normal.toString() + "\n"; + s += "TPlane 3: " + body.shapes[0].tplanes[3].normal.toString() + "\n"; + + Manager.log.push(s); + */ + }; + Manager.SHAPE_TYPE_CIRCLE = 0; + Manager.SHAPE_TYPE_SEGMENT = 1; + Manager.SHAPE_TYPE_POLY = 2; + Manager.SHAPE_NUM_TYPES = 3; + Manager.JOINT_TYPE_ANGLE = 0; + Manager.JOINT_TYPE_REVOLUTE = 1; + Manager.JOINT_TYPE_WELD = 2; + Manager.JOINT_TYPE_WHEEL = 3; + Manager.JOINT_TYPE_PRISMATIC = 4; + Manager.JOINT_TYPE_DISTANCE = 5; + Manager.JOINT_TYPE_ROPE = 6; + Manager.JOINT_TYPE_MOUSE = 7; + Manager.JOINT_LINEAR_SLOP = 0.0008; + Manager.JOINT_ANGULAR_SLOP = 2 * 0.017453292519943294444444444444444; + Manager.JOINT_MAX_LINEAR_CORRECTION = 0.5; + Manager.JOINT_MAX_ANGULAR_CORRECTION = 8 * 0.017453292519943294444444444444444; + Manager.JOINT_LIMIT_STATE_INACTIVE = 0; + Manager.JOINT_LIMIT_STATE_AT_LOWER = 1; + Manager.JOINT_LIMIT_STATE_AT_UPPER = 2; + Manager.JOINT_LIMIT_STATE_EQUAL_LIMITS = 3; + Manager.CONTACT_SOLVER_COLLISION_SLOP = 0.0008; + Manager.CONTACT_SOLVER_BAUMGARTE = 0.28; + Manager.CONTACT_SOLVER_MAX_LINEAR_CORRECTION = 1; + Manager.bodyCounter = 0; + Manager.jointCounter = 0; + Manager.shapeCounter = 0; + Manager.prototype.update = function () { + // Get these from Phaser.Time instead + var time = Date.now(); + var frameTime = (time - this.lastTime) / 1000; + this.lastTime = time; + // if rAf - why? + frameTime = Math.floor(frameTime * 60 + 0.5) / 60; + //if (!mouseDown) + //{ + // var p = canvasToWorld(mousePosition); + // var body = space.findBodyByPoint(p); + // //domCanvas.style.cursor = body ? "pointer" : "default"; + //} + if(!this.paused || this.step) { + Manager.clear(); + var h = 1 / this.frameRateHz; + this.timeDelta += frameTime; + if(this.step) { + this.step = false; + this.timeDelta = h; + } + for(var maxSteps = 4; maxSteps > 0 && this.timeDelta >= h; maxSteps--) { + this.space.step(h, this.velocityIterations, this.positionIterations, this.warmStarting, this.allowSleep); + this.timeDelta -= h; + } + if(this.timeDelta > h) { + this.timeDelta = 0; + } + } + //frameCount++; + }; + Manager.prototype.addBody = function (body) { + this.space.addBody(body); + }; + Manager.prototype.removeBody = function (body) { + this.space.removeBody(body); + }; + Manager.prototype.addJoint = function (joint) { + this.space.addJoint(joint); + }; + Manager.prototype.removeJoint = function (joint) { + this.space.removeJoint(joint); + }; + Manager.prototype.pixelsToMeters = function (value) { + return value * 0.02; + }; + Manager.prototype.metersToPixels = function (value) { + return value * 50; + }; + Manager.pixelsToMeters = function pixelsToMeters(value) { + return value * 0.02; + }; + Manager.metersToPixels = function metersToPixels(value) { + return value * 50; + }; + Manager.p2m = function p2m(value) { + return value * 0.02; + }; + Manager.m2p = function m2p(value) { + return value * 50; + }; + Manager.areaForCircle = function areaForCircle(radius_outer, radius_inner) { + return Math.PI * (radius_outer * radius_outer - radius_inner * radius_inner); + }; + Manager.inertiaForCircle = function inertiaForCircle(mass, center, radius_outer, radius_inner) { + return mass * ((radius_outer * radius_outer + radius_inner * radius_inner) * 0.5 + center.lengthSq()); + }; + Manager.areaForSegment = function areaForSegment(a, b, radius) { + return radius * (Math.PI * radius + 2 * Phaser.Vec2Utils.distance(a, b)); + }; + Manager.centroidForSegment = function centroidForSegment(a, b) { + return Phaser.Vec2Utils.scale(Phaser.Vec2Utils.add(a, b), 0.5); + }; + Manager.inertiaForSegment = function inertiaForSegment(mass, a, b) { + var distsq = Phaser.Vec2Utils.distanceSq(b, a); + var offset = Phaser.Vec2Utils.scale(Phaser.Vec2Utils.add(a, b), 0.5); + return mass * (distsq / 12 + offset.lengthSq()); + }; + Manager.areaForPoly = function areaForPoly(verts) { + var area = 0; + for(var i = 0; i < verts.length; i++) { + area += Phaser.Vec2Utils.cross(verts[i], verts[(i + 1) % verts.length]); + } + return area / 2; + }; + Manager.centroidForPoly = function centroidForPoly(verts) { + var area = 0; + var vsum = new Phaser.Vec2(); + for(var i = 0; i < verts.length; i++) { + var v1 = verts[i]; + var v2 = verts[(i + 1) % verts.length]; + var cross = Phaser.Vec2Utils.cross(v1, v2); + area += cross; + // SO many vecs created here - unroll these bad boys + vsum.add(Phaser.Vec2Utils.scale(Phaser.Vec2Utils.add(v1, v2), cross)); + } + return Phaser.Vec2Utils.scale(vsum, 1 / (3 * area)); + }; + Manager.inertiaForPoly = function inertiaForPoly(mass, verts, offset) { + var sum1 = 0; + var sum2 = 0; + for(var i = 0; i < verts.length; i++) { + var v1 = Phaser.Vec2Utils.add(verts[i], offset); + var v2 = Phaser.Vec2Utils.add(verts[(i + 1) % verts.length], offset); + var a = Phaser.Vec2Utils.cross(v2, v1); + var b = Phaser.Vec2Utils.dot(v1, v1) + Phaser.Vec2Utils.dot(v1, v2) + Phaser.Vec2Utils.dot(v2, v2); + sum1 += a * b; + sum2 += a; + } + return (mass * sum1) / (6 * sum2); + }; + Manager.inertiaForBox = function inertiaForBox(mass, w, h) { + return mass * (w * w + h * h) / 12; + }; + Manager.createConvexHull = // Create the convex hull using the Gift wrapping algorithm (http://en.wikipedia.org/wiki/Gift_wrapping_algorithm) + function createConvexHull(points) { + // Find the right most point on the hull + var i0 = 0; + var x0 = points[0].x; + for(var i = 1; i < points.length; i++) { + var x = points[i].x; + if(x > x0 || (x == x0 && points[i].y < points[i0].y)) { + i0 = i; + x0 = x; + } + } + var n = points.length; + var hull = []; + var m = 0; + var ih = i0; + while(1) { + hull[m] = ih; + var ie = 0; + for(var j = 1; j < n; j++) { + if(ie == ih) { + ie = j; + continue; + } + var r = Phaser.Vec2Utils.subtract(points[ie], points[hull[m]]); + var v = Phaser.Vec2Utils.subtract(points[j], points[hull[m]]); + var c = Phaser.Vec2Utils.cross(r, v); + if(c < 0) { + ie = j; + } + // Collinearity check + if(c == 0 && v.lengthSq() > r.lengthSq()) { + ie = j; + } + } + m++; + ih = ie; + if(ie == i0) { + break; + } + } + // Copy vertices + var newPoints = []; + for(var i = 0; i < m; ++i) { + newPoints.push(points[hull[i]]); + } + return newPoints; + }; + return Manager; + })(); + Physics.Manager = Manager; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + /// + /// + /// + /** + * Phaser - 2D AABB + * + * A 2D AABB object + */ + (function (Physics) { + var Bounds = (function () { + /** + * Creates a new 2D AABB object. + * @class Bounds + * @constructor + * @return {Bounds} This object + **/ + function Bounds(mins, maxs) { + if (typeof mins === "undefined") { mins = null; } + if (typeof maxs === "undefined") { maxs = null; } + if(mins) { + this.mins = Phaser.Vec2Utils.clone(mins); + } else { + this.mins = new Phaser.Vec2(999999, 999999); + } + if(maxs) { + this.maxs = Phaser.Vec2Utils.clone(maxs); + } else { + this.maxs = new Phaser.Vec2(999999, 999999); + } + } + Bounds.prototype.toString = function () { + return [ + "mins:", + this.mins.toString(), + "maxs:", + this.maxs.toString() + ].join(" "); + }; + Bounds.prototype.setTo = function (mins, maxs) { + this.mins.setTo(mins.x, mins.y); + this.maxs.setTo(maxs.x, maxs.y); + }; + Bounds.prototype.copy = function (b) { + this.mins.copyFrom(b.mins); + this.maxs.copyFrom(b.maxs); + return this; + }; + Bounds.prototype.clear = function () { + this.mins.setTo(999999, 999999); + this.maxs.setTo(-999999, -999999); + return this; + }; + Object.defineProperty(Bounds.prototype, "x", { + get: function () { + return Phaser.Physics.Manager.metersToPixels(this.mins.x); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Bounds.prototype, "y", { + get: function () { + return Phaser.Physics.Manager.metersToPixels(this.mins.y); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Bounds.prototype, "width", { + get: function () { + return Phaser.Physics.Manager.metersToPixels(this.maxs.x - this.mins.x); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Bounds.prototype, "height", { + get: function () { + return Phaser.Physics.Manager.metersToPixels(this.maxs.y - this.mins.y); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Bounds.prototype, "right", { + get: function () { + return this.x + this.width; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Bounds.prototype, "bottom", { + get: function () { + return this.y + this.height; + }, + enumerable: true, + configurable: true + }); + Bounds.prototype.isEmpty = function () { + return (this.mins.x > this.maxs.x || this.mins.y > this.maxs.y); + }; + Bounds.prototype.getPerimeter = /* + public getCenter() { + return vec2.scale(vec2.add(this.mins, this.maxs), 0.5); + } + + public getExtent() { + return vec2.scale(vec2.sub(this.maxs, this.mins), 0.5); + } + */ + function () { + return (this.maxs.x - this.mins.x + this.maxs.y - this.mins.y) * 2; + }; + Bounds.prototype.addPoint = function (p) { + if(this.mins.x > p.x) { + this.mins.x = p.x; + } + if(this.maxs.x < p.x) { + this.maxs.x = p.x; + } + if(this.mins.y > p.y) { + this.mins.y = p.y; + } + if(this.maxs.y < p.y) { + this.maxs.y = p.y; + } + return this; + }; + Bounds.prototype.addBounds = function (b) { + if(this.mins.x > b.mins.x) { + this.mins.x = b.mins.x; + } + if(this.maxs.x < b.maxs.x) { + this.maxs.x = b.maxs.x; + } + if(this.mins.y > b.mins.y) { + this.mins.y = b.mins.y; + } + if(this.maxs.y < b.maxs.y) { + this.maxs.y = b.maxs.y; + } + return this; + }; + Bounds.prototype.addBounds2 = function (mins, maxs) { + if(this.mins.x > mins.x) { + this.mins.x = mins.x; + } + if(this.maxs.x < maxs.x) { + this.maxs.x = maxs.x; + } + if(this.mins.y > mins.y) { + this.mins.y = mins.y; + } + if(this.maxs.y < maxs.y) { + this.maxs.y = maxs.y; + } + return this; + }; + Bounds.prototype.addExtents = function (center, extent_x, extent_y) { + if(this.mins.x > center.x - extent_x) { + this.mins.x = center.x - extent_x; + } + if(this.maxs.x < center.x + extent_x) { + this.maxs.x = center.x + extent_x; + } + if(this.mins.y > center.y - extent_y) { + this.mins.y = center.y - extent_y; + } + if(this.maxs.y < center.y + extent_y) { + this.maxs.y = center.y + extent_y; + } + return this; + }; + Bounds.prototype.expand = function (ax, ay) { + this.mins.x -= ax; + this.mins.y -= ay; + this.maxs.x += ax; + this.maxs.y += ay; + return this; + }; + Bounds.prototype.containPoint = function (p) { + if(p.x < this.mins.x || p.x > this.maxs.x || p.y < this.mins.y || p.y > this.maxs.y) { + return false; + } + return true; + }; + Bounds.prototype.intersectsBounds = function (b) { + if(this.mins.x > b.maxs.x || this.maxs.x < b.mins.x || this.mins.y > b.maxs.y || this.maxs.y < b.mins.y) { + return false; + } + return true; + }; + Bounds.expand = function expand(b, ax, ay) { + var b = new Bounds(b.mins, b.maxs); + b.expand(ax, ay); + return b; + }; + return Bounds; + })(); + Physics.Bounds = Bounds; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + })(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + /// + /// + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Shape + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + (function (Physics) { + var Shape = (function () { + function Shape(type) { + this.id = Phaser.Physics.Manager.shapeCounter++; + this.type = type; + this.elasticity = 0.0; + this.friction = 1.0; + this.density = 1; + this.bounds = new Physics.Bounds(); + } + Shape.prototype.findEdgeByPoint = // Over-ridden by ShapePoly + function (p, minDist) { + return -1; + }; + return Shape; + })(); + Physics.Shape = Shape; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + /// + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Contact + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + (function (Physics) { + var Contact = (function () { + function Contact(p, n, d, hash) { + this.hash = hash; + this.point = p; + this.normal = n; + this.depth = d; + this.lambdaNormal = 0; + this.lambdaTangential = 0; + this.r1 = new Phaser.Vec2(); + this.r2 = new Phaser.Vec2(); + this.r1_local = new Phaser.Vec2(); + this.r2_local = new Phaser.Vec2(); + } + return Contact; + })(); + Physics.Contact = Contact; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); var Phaser; (function (Phaser) { /// /// /// + /// + /// + /// + /// /** - * Phaser - Physics - Body + * Phaser - Advanced Physics - ContactSolver + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + //------------------------------------------------------------------------------------------------- + // Contact Constraint + // + // Non-penetration constraint: + // C = dot(p2 - p1, n) + // Cdot = dot(v2 - v1, n) + // J = [ -n, -cross(r1, n), n, cross(r2, n) ] + // + // impulse = JT * lambda = [ -n * lambda, -cross(r1, n) * lambda, n * lambda, cross(r1, n) * lambda ] + // + // Friction constraint: + // C = dot(p2 - p1, t) + // Cdot = dot(v2 - v1, t) + // J = [ -t, -cross(r1, t), t, cross(r2, t) ] + // + // impulse = JT * lambda = [ -t * lambda, -cross(r1, t) * lambda, t * lambda, cross(r1, t) * lambda ] + // + // NOTE: lambda is an impulse in constraint space. + //------------------------------------------------------------------------------------------------- + (function (Physics) { + var ContactSolver = (function () { + function ContactSolver(shape1, shape2) { + this.shape1 = shape1; + this.shape2 = shape2; + this.contacts = []; + this.elasticity = 1; + this.friction = 1; + } + ContactSolver.prototype.update = function (newContactArr) { + for(var i = 0; i < newContactArr.length; i++) { + var newContact = newContactArr[i]; + var k = -1; + for(var j = 0; j < this.contacts.length; j++) { + if(newContact.hash == this.contacts[j].hash) { + k = j; + break; + } + } + if(k > -1) { + newContact.lambdaNormal = this.contacts[k].lambdaNormal; + newContact.lambdaTangential = this.contacts[k].lambdaTangential; + } + } + this.contacts = newContactArr; + }; + ContactSolver.prototype.initSolver = function (dt_inv) { + var body1 = this.shape1.body; + var body2 = this.shape2.body; + var sum_m_inv = body1.massInverted + body2.massInverted; + for(var i = 0; i < this.contacts.length; i++) { + var con = this.contacts[i]; + //console.log('initSolver con'); + //console.log(con); + // Transformed r1, r2 + Phaser.Vec2Utils.subtract(con.point, body1.position, con.r1); + Phaser.Vec2Utils.subtract(con.point, body2.position, con.r2); + //con.r1 = vec2.sub(con.point, body1.p); + //con.r2 = vec2.sub(con.point, body2.p); + // Local r1, r2 + Phaser.TransformUtils.unrotate(body1.transform, con.r1, con.r1_local); + Phaser.TransformUtils.unrotate(body2.transform, con.r2, con.r2_local); + //con.r1_local = body1.transform.unrotate(con.r1); + //con.r2_local = body2.transform.unrotate(con.r2); + var n = con.normal; + var t = Phaser.Vec2Utils.perp(con.normal); + // invEMn = J * invM * JT + // J = [ -n, -cross(r1, n), n, cross(r2, n) ] + var sn1 = Phaser.Vec2Utils.cross(con.r1, n); + var sn2 = Phaser.Vec2Utils.cross(con.r2, n); + var emn_inv = sum_m_inv + body1.inertiaInverted * sn1 * sn1 + body2.inertiaInverted * sn2 * sn2; + con.emn = emn_inv == 0 ? 0 : 1 / emn_inv; + // invEMt = J * invM * JT + // J = [ -t, -cross(r1, t), t, cross(r2, t) ] + var st1 = Phaser.Vec2Utils.cross(con.r1, t); + var st2 = Phaser.Vec2Utils.cross(con.r2, t); + var emt_inv = sum_m_inv + body1.inertiaInverted * st1 * st1 + body2.inertiaInverted * st2 * st2; + con.emt = emt_inv == 0 ? 0 : 1 / emt_inv; + // Linear velocities at contact point + // in 2D: cross(w, r) = perp(r) * w + var v1 = new Phaser.Vec2(); + var v2 = new Phaser.Vec2(); + Phaser.Vec2Utils.multiplyAdd(body1.velocity, Phaser.Vec2Utils.perp(con.r1), body1.angularVelocity, v1); + Phaser.Vec2Utils.multiplyAdd(body2.velocity, Phaser.Vec2Utils.perp(con.r2), body2.angularVelocity, v2); + //var v1 = vec2.mad(body1.v, vec2.perp(con.r1), body1.w); + //var v2 = vec2.mad(body2.v, vec2.perp(con.r2), body2.w); + // relative velocity at contact point + var rv = new Phaser.Vec2(); + Phaser.Vec2Utils.subtract(v2, v1, rv); + //var rv = vec2.sub(v2, v1); + // bounce velocity dot n + con.bounce = Phaser.Vec2Utils.dot(rv, con.normal) * this.elasticity; + } + }; + ContactSolver.prototype.warmStart = function () { + var body1 = this.shape1.body; + var body2 = this.shape2.body; + for(var i = 0; i < this.contacts.length; i++) { + var con = this.contacts[i]; + var n = con.normal; + var lambda_n = con.lambdaNormal; + var lambda_t = con.lambdaTangential; + // Apply accumulated impulses + //var impulse = vec2.rotate_vec(new vec2(lambda_n, lambda_t), n); + //var impulse = new vec2(lambda_n * n.x - lambda_t * n.y, lambda_t * n.x + lambda_n * n.y); + var impulse = new Phaser.Vec2(lambda_n * n.x - lambda_t * n.y, lambda_t * n.x + lambda_n * n.y); + //console.log('phaser warmStart impulse ' + i + ' = ' + impulse.toString()); + body1.velocity.multiplyAddByScalar(impulse, -body1.massInverted); + //body1.v.mad(impulse, -body1.m_inv); + body1.angularVelocity -= Phaser.Vec2Utils.cross(con.r1, impulse) * body1.inertiaInverted; + //body1.w -= vec2.cross(con.r1, impulse) * body1.i_inv; + body2.velocity.multiplyAddByScalar(impulse, body2.massInverted); + //body2.v.mad(impulse, body2.m_inv); + body2.angularVelocity += Phaser.Vec2Utils.cross(con.r2, impulse) * body2.inertiaInverted; + //body2.w += vec2.cross(con.r2, impulse) * body2.i_inv; + } + }; + ContactSolver.prototype.solveVelocityConstraints = function () { + var body1 = this.shape1.body; + var body2 = this.shape2.body; + Physics.Manager.write('solveVelocityConstraints. Body1: ' + body1.name + ' Body2: ' + body2.name); + Physics.Manager.write('Shape 1: ' + this.shape1.type + ' Shape 2: ' + this.shape2.type); + var m1_inv = body1.massInverted; + var i1_inv = body1.inertiaInverted; + var m2_inv = body2.massInverted; + var i2_inv = body2.inertiaInverted; + Physics.Manager.write('m1_inv: ' + m1_inv); + Physics.Manager.write('i1_inv: ' + i1_inv); + Physics.Manager.write('m2_inv: ' + m2_inv); + Physics.Manager.write('i2_inv: ' + i2_inv); + for(var i = 0; i < this.contacts.length; i++) { + Physics.Manager.write('------------ solve con ' + i); + var con = this.contacts[i]; + var n = con.normal; + var t = Phaser.Vec2Utils.perp(n); + var r1 = con.r1; + var r2 = con.r2; + // Linear velocities at contact point + // in 2D: cross(w, r) = perp(r) * w + var v1 = new Phaser.Vec2(); + var v2 = new Phaser.Vec2(); + Phaser.Vec2Utils.multiplyAdd(body1.velocity, Phaser.Vec2Utils.perp(r1), body1.angularVelocity, v1); + //var v1 = vec2.mad(body1.v, vec2.perp(r1), body1.w); + Physics.Manager.write('v1 ' + v1.toString()); + Phaser.Vec2Utils.multiplyAdd(body2.velocity, Phaser.Vec2Utils.perp(r2), body2.angularVelocity, v2); + //var v2 = vec2.mad(body2.v, vec2.perp(r2), body2.w); + Physics.Manager.write('v2 ' + v2.toString()); + // Relative velocity at contact point + var rv = new Phaser.Vec2(); + Phaser.Vec2Utils.subtract(v2, v1, rv); + //var rv = vec2.sub(v2, v1); + Physics.Manager.write('rv ' + rv.toString()); + // Compute normal constraint impulse + adding bounce as a velocity bias + // lambda_n = -EMn * J * V + var lambda_n = -con.emn * (Phaser.Vec2Utils.dot(n, rv) + con.bounce); + Physics.Manager.write('lambda_n: ' + lambda_n); + // Accumulate and clamp + var lambda_n_old = con.lambdaNormal; + con.lambdaNormal = Math.max(lambda_n_old + lambda_n, 0); + //con.lambdaNormal = this.clamp(lambda_n_old + lambda_n, 0); + lambda_n = con.lambdaNormal - lambda_n_old; + Physics.Manager.write('lambda_n clamped: ' + lambda_n); + // Compute frictional constraint impulse + // lambda_t = -EMt * J * V + var lambda_t = -con.emt * Phaser.Vec2Utils.dot(t, rv); + // Max friction constraint impulse (Coulomb's Law) + var lambda_t_max = con.lambdaNormal * this.friction; + // Accumulate and clamp + var lambda_t_old = con.lambdaTangential; + con.lambdaTangential = this.clamp(lambda_t_old + lambda_t, -lambda_t_max, lambda_t_max); + lambda_t = con.lambdaTangential - lambda_t_old; + // Apply the final impulses + //var impulse = vec2.rotate_vec(new vec2(lambda_n, lambda_t), n); + var impulse = new Phaser.Vec2(lambda_n * n.x - lambda_t * n.y, lambda_t * n.x + lambda_n * n.y); + Physics.Manager.write('impulse: ' + impulse.toString()); + body1.velocity.multiplyAddByScalar(impulse, -m1_inv); + //body1.v.mad(impulse, -m1_inv); + body1.angularVelocity -= Phaser.Vec2Utils.cross(r1, impulse) * i1_inv; + //body1.w -= vec2.cross(r1, impulse) * i1_inv; + body2.velocity.multiplyAddByScalar(impulse, m2_inv); + //body2.v.mad(impulse, m2_inv); + body2.angularVelocity += Phaser.Vec2Utils.cross(r2, impulse) * i2_inv; + //body2.w += vec2.cross(r2, impulse) * i2_inv; + Physics.Manager.write('body1: ' + body1.toString()); + Physics.Manager.write('body2: ' + body2.toString()); + } + }; + ContactSolver.prototype.solvePositionConstraints = function () { + var body1 = this.shape1.body; + var body2 = this.shape2.body; + Physics.Manager.write('solvePositionConstraints'); + var m1_inv = body1.massInverted; + var i1_inv = body1.inertiaInverted; + var m2_inv = body2.massInverted; + var i2_inv = body2.inertiaInverted; + var sum_m_inv = m1_inv + m2_inv; + var max_penetration = 0; + for(var i = 0; i < this.contacts.length; i++) { + Physics.Manager.write('------------- solvePositionConstraints ' + i); + var con = this.contacts[i]; + var n = con.normal; + var r1 = new Phaser.Vec2(); + var r2 = new Phaser.Vec2(); + // Transformed r1, r2 + Phaser.Vec2Utils.rotate(con.r1_local, body1.angle, r1); + //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); + Physics.Manager.write('r1_local.x = ' + con.r1_local.x + ' r1_local.y = ' + con.r1_local.y + ' angle: ' + body1.angle); + Physics.Manager.write('r1 rotated: r1.x = ' + r1.x + ' r1.y = ' + r1.y); + Physics.Manager.write('r2_local.x = ' + con.r2_local.x + ' r2_local.y = ' + con.r2_local.y + ' angle: ' + body2.angle); + Physics.Manager.write('r2 rotated: r2.x = ' + r2.x + ' r2.y = ' + r2.y); + // Contact points (corrected) + var p1 = new Phaser.Vec2(); + var p2 = new Phaser.Vec2(); + Phaser.Vec2Utils.add(body1.position, r1, p1); + //var p1 = vec2.add(body1.p, r1); + Phaser.Vec2Utils.add(body2.position, r2, p2); + //var p2 = vec2.add(body2.p, r2); + Physics.Manager.write('body1.pos.x=' + body1.position.x + ' y=' + body1.position.y); + Physics.Manager.write('body2.pos.x=' + body2.position.x + ' y=' + body2.position.y); + // Corrected delta vector + var dp = new Phaser.Vec2(); + Phaser.Vec2Utils.subtract(p2, p1, dp); + //var dp = vec2.sub(p2, p1); + // Position constraint + var c = Phaser.Vec2Utils.dot(dp, n) + con.depth; + var correction = this.clamp(Physics.Manager.CONTACT_SOLVER_BAUMGARTE * (c + Physics.Manager.CONTACT_SOLVER_COLLISION_SLOP), -Physics.Manager.CONTACT_SOLVER_MAX_LINEAR_CORRECTION, 0); + if(correction == 0) { + continue; + } + // We don't need max_penetration less than or equal slop + max_penetration = Math.max(max_penetration, -c); + // Compute lambda for position constraint + // Solve (J * invM * JT) * lambda = -C / dt + var sn1 = Phaser.Vec2Utils.cross(r1, n); + var sn2 = Phaser.Vec2Utils.cross(r2, n); + var em_inv = sum_m_inv + body1.inertiaInverted * sn1 * sn1 + body2.inertiaInverted * sn2 * sn2; + var lambda_dt = em_inv == 0 ? 0 : -correction / em_inv; + // Apply correction impulses + var impulse_dt = new Phaser.Vec2(); + Phaser.Vec2Utils.scale(n, lambda_dt, impulse_dt); + //var impulse_dt = vec2.scale(n, lambda_dt); + body1.position.multiplyAddByScalar(impulse_dt, -m1_inv); + //body1.p.mad(impulse_dt, -m1_inv); + body1.angle -= sn1 * lambda_dt * i1_inv; + body2.position.multiplyAddByScalar(impulse_dt, m2_inv); + //body2.p.mad(impulse_dt, m2_inv); + body2.angle += sn2 * lambda_dt * i2_inv; + Physics.Manager.write('body1.pos.x=' + body1.position.x + ' y=' + body1.position.y); + Physics.Manager.write('body2.pos.x=' + body2.position.x + ' y=' + body2.position.y); + } + Physics.Manager.write('max_penetration: ' + max_penetration); + return max_penetration <= Physics.Manager.CONTACT_SOLVER_COLLISION_SLOP * 3; + }; + ContactSolver.prototype.clamp = function (v, min, max) { + return v < min ? min : (v > max ? max : v); + }; + return ContactSolver; + })(); + Physics.ContactSolver = ContactSolver; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + (function (Physics) { + /// + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Shape - Circle + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + (function (Shapes) { + var Circle = (function (_super) { + __extends(Circle, _super); + function Circle(radius, x, y) { + if (typeof x === "undefined") { x = 0; } + if (typeof y === "undefined") { y = 0; } + _super.call(this, Physics.Manager.SHAPE_TYPE_CIRCLE); + x = Physics.Manager.pixelsToMeters(x); + y = Physics.Manager.pixelsToMeters(y); + radius = Physics.Manager.pixelsToMeters(radius); + this.center = new Phaser.Vec2(x, y); + this.radius = radius; + this.tc = new Phaser.Vec2(); + this.finishVerts(); + } + Circle.prototype.finishVerts = function () { + this.radius = Math.abs(this.radius); + }; + Circle.prototype.duplicate = function () { + return new Circle(this.center.x, this.center.y, this.radius); + }; + Circle.prototype.recenter = function (c) { + this.center.subtract(c); + }; + Circle.prototype.transform = function (xf) { + Phaser.TransformUtils.transform(xf, this.center, this.center); + //this.center = xf.transform(this.center); + }; + Circle.prototype.untransform = function (xf) { + Phaser.TransformUtils.untransform(xf, this.center, this.center); + //this.center = xf.untransform(this.center); + }; + Circle.prototype.area = function () { + return Physics.Manager.areaForCircle(this.radius, 0); + }; + Circle.prototype.centroid = function () { + return Phaser.Vec2Utils.clone(this.center); + }; + Circle.prototype.inertia = function (mass) { + return Physics.Manager.inertiaForCircle(mass, this.center, this.radius, 0); + }; + Circle.prototype.cacheData = function (xf) { + Phaser.TransformUtils.transform(xf, this.center, this.tc); + //this.tc = xf.transform(this.center); + this.bounds.mins.setTo(this.tc.x - this.radius, this.tc.y - this.radius); + this.bounds.maxs.setTo(this.tc.x + this.radius, this.tc.y + this.radius); + }; + Circle.prototype.pointQuery = function (p) { + //return vec2.distsq(this.tc, p) < (this.r * this.r); + return Phaser.Vec2Utils.distanceSq(this.tc, p) < (this.radius * this.radius); + }; + Circle.prototype.findVertexByPoint = function (p, minDist) { + var dsq = minDist * minDist; + if(Phaser.Vec2Utils.distanceSq(this.tc, p) < dsq) { + return 0; + } + return -1; + }; + Circle.prototype.distanceOnPlane = function (n, d) { + Phaser.Vec2Utils.dot(n, this.tc) - this.radius - d; + }; + return Circle; + })(Phaser.Physics.Shape); + Shapes.Circle = Circle; + })(Physics.Shapes || (Physics.Shapes = {})); + var Shapes = Physics.Shapes; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Plane + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + (function (Physics) { + var Plane = (function () { + function Plane(normal, d) { + this.normal = normal; + this.d = d; + } + return Plane; + })(); + Physics.Plane = Plane; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + (function (Physics) { + /// + /// + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Shapes - Convex Polygon + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + (function (Shapes) { + var Poly = (function (_super) { + __extends(Poly, _super); + // Verts is an optional array of objects, the objects must have public x and y properties which will be used + // to seed this polygon (i.e. Vec2 objects, or just straight JS objects) and must wind COUNTER clockwise + function Poly(verts) { + _super.call(this, Physics.Manager.SHAPE_TYPE_POLY); + this.verts = []; + this.planes = []; + this.tverts = []; + this.tplanes = []; + if(verts) { + for(var i = 0; i < verts.length; i++) { + this.verts[i] = new Phaser.Vec2(verts[i].x, verts[i].y); + this.tverts[i] = this.verts[i]; + //this.tverts[i] = new Phaser.Vec2(verts[i].x, verts[i].y); + this.tplanes[i] = new Phaser.Physics.Plane(new Phaser.Vec2(), 0); + } + } + this.finishVerts(); + } + Poly.prototype.finishVerts = function () { + if(this.verts.length < 2) { + this.convexity = false; + this.planes = []; + return; + } + this.convexity = true; + this.tverts = []; + this.tplanes = []; + // Must be counter-clockwise verts + for(var i = 0; i < this.verts.length; i++) { + var a = this.verts[i]; + var b = this.verts[(i + 1) % this.verts.length]; + var n = Phaser.Vec2Utils.normalize(Phaser.Vec2Utils.perp(Phaser.Vec2Utils.subtract(a, b))); + this.planes[i] = new Phaser.Physics.Plane(n, Phaser.Vec2Utils.dot(n, a)); + this.tverts[i] = Phaser.Vec2Utils.clone(this.verts[i])// reference??? + ; + //this.tverts[i] = this.verts[i]; // reference??? + this.tplanes[i] = new Phaser.Physics.Plane(new Phaser.Vec2(), 0); + } + for(var i = 0; i < this.verts.length; i++) { + //var b = this.verts[(i + 2) % this.verts.length]; + //var n = this.planes[i].normal; + //var d = this.planes[i].d; + if(Phaser.Vec2Utils.dot(this.planes[i].normal, this.verts[(i + 2) % this.verts.length]) - this.planes[i].d > 0) { + this.convexity = false; + } + } + }; + Poly.prototype.duplicate = function () { + return new Phaser.Physics.Shapes.Poly(this.verts); + }; + Poly.prototype.recenter = function (c) { + for(var i = 0; i < this.verts.length; i++) { + this.verts[i].subtract(c); + } + }; + Poly.prototype.transform = function (xf) { + for(var i = 0; i < this.verts.length; i++) { + this.verts[i] = Phaser.TransformUtils.transform(xf, this.verts[i]); + //this.verts[i] = xf.transform(this.verts[i]); + } + }; + Poly.prototype.untransform = function (xf) { + for(var i = 0; i < this.verts.length; i++) { + this.verts[i] = Phaser.TransformUtils.untransform(xf, this.verts[i]); + //this.verts[i] = xf.untransform(this.verts[i]); + } + }; + Poly.prototype.area = function () { + return Physics.Manager.areaForPoly(this.verts); + }; + Poly.prototype.centroid = function () { + return Physics.Manager.centroidForPoly(this.verts); + }; + Poly.prototype.inertia = function (mass) { + return Physics.Manager.inertiaForPoly(mass, this.verts, new Phaser.Vec2()); + }; + Poly.prototype.cacheData = function (xf) { + this.bounds.clear(); + var numVerts = this.verts.length; + Physics.Manager.write('----------- Poly cacheData = ' + numVerts); + if(numVerts == 0) { + return; + } + for(var i = 0; i < numVerts; i++) { + this.tverts[i] = Phaser.TransformUtils.transform(xf, this.verts[i]); + //this.tverts[i] = xf.transform(this.verts[i]); + Physics.Manager.write('tvert' + i + ' = ' + this.tverts[i].toString()); + } + if(numVerts < 2) { + this.bounds.addPoint(this.tverts[0]); + return; + } + for(var i = 0; i < numVerts; i++) { + var a = this.tverts[i]; + var b = this.tverts[(i + 1) % numVerts]; + var n = Phaser.Vec2Utils.normalize(Phaser.Vec2Utils.perp(Phaser.Vec2Utils.subtract(a, b))); + Physics.Manager.write('a = ' + a.toString()); + Physics.Manager.write('b = ' + b.toString()); + Physics.Manager.write('n = ' + n.toString()); + this.tplanes[i].normal = n; + this.tplanes[i].d = Phaser.Vec2Utils.dot(n, a); + Physics.Manager.write('tplanes' + i + ' n = ' + this.tplanes[i].normal.toString()); + Physics.Manager.write('tplanes' + i + ' d = ' + this.tplanes[i].d.toString()); + this.bounds.addPoint(a); + } + }; + Poly.prototype.pointQuery = function (p) { + if(!this.bounds.containPoint(p)) { + return false; + } + return this.containPoint(p); + }; + Poly.prototype.findVertexByPoint = function (p, minDist) { + var dsq = minDist * minDist; + for(var i = 0; i < this.tverts.length; i++) { + if(Phaser.Vec2Utils.distanceSq(this.tverts[i], p) < dsq) { + return i; + } + } + return -1; + }; + Poly.prototype.findEdgeByPoint = function (p, minDist) { + var dsq = minDist * minDist; + var numVerts = this.tverts.length; + for(var i = 0; i < this.tverts.length; i++) { + var v1 = this.tverts[i]; + var v2 = this.tverts[(i + 1) % numVerts]; + var n = this.tplanes[i].normal; + var dtv1 = Phaser.Vec2Utils.cross(v1, n); + var dtv2 = Phaser.Vec2Utils.cross(v2, n); + var dt = Phaser.Vec2Utils.cross(p, n); + if(dt > dtv1) { + if(Phaser.Vec2Utils.distanceSq(v1, p) < dsq) { + return i; + } + } else if(dt < dtv2) { + if(Phaser.Vec2Utils.distanceSq(v2, p) < dsq) { + return i; + } + } else { + var dist = Phaser.Vec2Utils.dot(n, p) - Phaser.Vec2Utils.dot(n, v1); + if(dist * dist < dsq) { + return i; + } + } + } + return -1; + }; + Poly.prototype.distanceOnPlane = function (n, d) { + var min = 999999; + for(var i = 0; i < this.verts.length; i++) { + min = Math.min(min, Phaser.Vec2Utils.dot(n, this.tverts[i])); + } + return min - d; + }; + Poly.prototype.containPoint = function (p) { + for(var i = 0; i < this.verts.length; i++) { + var plane = this.tplanes[i]; + if(Phaser.Vec2Utils.dot(plane.normal, p) - plane.d > 0) { + return false; + } + } + return true; + }; + Poly.prototype.containPointPartial = function (p, n) { + for(var i = 0; i < this.verts.length; i++) { + var plane = this.tplanes[i]; + if(Phaser.Vec2Utils.dot(plane.normal, n) < 0.0001) { + continue; + } + if(Phaser.Vec2Utils.dot(plane.normal, p) - plane.d > 0) { + return false; + } + } + return true; + }; + return Poly; + })(Phaser.Physics.Shape); + Shapes.Poly = Poly; + })(Physics.Shapes || (Physics.Shapes = {})); + var Shapes = Physics.Shapes; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + (function (Physics) { + /// + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Shapes - Segment + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + (function (Shapes) { + var Segment = (function (_super) { + __extends(Segment, _super); + function Segment(a, b, radius) { + _super.call(this, Physics.Manager.SHAPE_TYPE_SEGMENT); + this.a = a.duplicate(); + this.b = b.duplicate(); + this.radius = radius; + this.normal = Phaser.Vec2Utils.perp(Phaser.Vec2Utils.subtract(b, a)); + this.normal.normalize(); + this.ta = new Phaser.Vec2(); + this.tb = new Phaser.Vec2(); + this.tn = new Phaser.Vec2(); + this.finishVerts(); + } + Segment.prototype.finishVerts = function () { + this.normal = Phaser.Vec2Utils.perp(Phaser.Vec2Utils.subtract(this.b, this.a)); + this.normal.normalize(); + this.radius = Math.abs(this.radius); + }; + Segment.prototype.duplicate = function () { + return new Phaser.Physics.Shapes.Segment(this.a, this.b, this.radius); + }; + Segment.prototype.recenter = function (c) { + this.a.subtract(c); + this.b.subtract(c); + }; + Segment.prototype.transform = function (xf) { + Phaser.TransformUtils.transform(xf, this.a, this.a); + Phaser.TransformUtils.transform(xf, this.b, this.b); + //this.a = xf.transform(this.a); + //this.b = xf.transform(this.b); + }; + Segment.prototype.untransform = function (xf) { + Phaser.TransformUtils.untransform(xf, this.a, this.a); + Phaser.TransformUtils.untransform(xf, this.b, this.b); + //this.a = xf.untransform(this.a); + //this.b = xf.untransform(this.b); + }; + Segment.prototype.area = function () { + return Physics.Manager.areaForSegment(this.a, this.b, this.radius); + }; + Segment.prototype.centroid = function () { + return Physics.Manager.centroidForSegment(this.a, this.b); + }; + Segment.prototype.inertia = function (mass) { + return Physics.Manager.inertiaForSegment(mass, this.a, this.b); + }; + Segment.prototype.cacheData = function (xf) { + Phaser.TransformUtils.transform(xf, this.a, this.ta); + Phaser.TransformUtils.transform(xf, this.b, this.tb); + //this.ta = xf.transform(this.a); + //this.tb = xf.transform(this.b); + this.tn = Phaser.Vec2Utils.perp(Phaser.Vec2Utils.subtract(this.tb, this.ta)).normalize(); + var l; + var r; + var t; + var b; + if(this.ta.x < this.tb.x) { + l = this.ta.x; + r = this.tb.x; + } else { + l = this.tb.x; + r = this.ta.x; + } + if(this.ta.y < this.tb.y) { + b = this.ta.y; + t = this.tb.y; + } else { + b = this.tb.y; + t = this.ta.y; + } + this.bounds.mins.setTo(l - this.radius, b - this.radius); + this.bounds.maxs.setTo(r + this.radius, t + this.radius); + }; + Segment.prototype.pointQuery = function (p) { + if(!this.bounds.containPoint(p)) { + return false; + } + var dn = Phaser.Vec2Utils.dot(this.tn, p) - Phaser.Vec2Utils.dot(this.ta, this.tn); + var dist = Math.abs(dn); + if(dist > this.radius) { + return false; + } + var dt = Phaser.Vec2Utils.cross(p, this.tn); + var dta = Phaser.Vec2Utils.cross(this.ta, this.tn); + var dtb = Phaser.Vec2Utils.cross(this.tb, this.tn); + if(dt <= dta) { + if(dt < dta - this.radius) { + return false; + } + return Phaser.Vec2Utils.distanceSq(this.ta, p) < (this.radius * this.radius); + } else if(dt > dtb) { + if(dt > dtb + this.radius) { + return false; + } + return Phaser.Vec2Utils.distanceSq(this.tb, p) < (this.radius * this.radius); + } + return true; + }; + Segment.prototype.findVertexByPoint = function (p, minDist) { + var dsq = minDist * minDist; + if(Phaser.Vec2Utils.distanceSq(this.ta, p) < dsq) { + return 0; + } + if(Phaser.Vec2Utils.distanceSq(this.tb, p) < dsq) { + return 1; + } + return -1; + }; + Segment.prototype.distanceOnPlane = function (n, d) { + var a = Phaser.Vec2Utils.dot(n, this.ta) - this.radius; + var b = Phaser.Vec2Utils.dot(n, this.tb) - this.radius; + return Math.min(a, b) - d; + }; + return Segment; + })(Phaser.Physics.Shape); + Shapes.Segment = Segment; + })(Physics.Shapes || (Physics.Shapes = {})); + var Shapes = Physics.Shapes; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Collision Handlers + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + (function (Physics) { + var Collision = (function () { + function Collision() { } + Collision.prototype.collide = function (a, b, contacts) { + // Circle (a is the circle) + if(a.type == Physics.Manager.SHAPE_TYPE_CIRCLE) { + if(b.type == Physics.Manager.SHAPE_TYPE_CIRCLE) { + return this.circle2Circle(a, b, contacts); + } else if(b.type == Physics.Manager.SHAPE_TYPE_SEGMENT) { + return this.circle2Segment(a, b, contacts); + } else if(b.type == Physics.Manager.SHAPE_TYPE_POLY) { + return this.circle2Poly(a, b, contacts); + } + } + // Segment (a is the segment) + if(a.type == Physics.Manager.SHAPE_TYPE_SEGMENT) { + if(b.type == Physics.Manager.SHAPE_TYPE_CIRCLE) { + return this.circle2Segment(b, a, contacts); + } else if(b.type == Physics.Manager.SHAPE_TYPE_SEGMENT) { + return this.segment2Segment(a, b, contacts); + } else if(b.type == Physics.Manager.SHAPE_TYPE_POLY) { + return this.segment2Poly(a, b, contacts); + } + } + // Poly (a is the poly) + if(a.type == Physics.Manager.SHAPE_TYPE_POLY) { + if(b.type == Physics.Manager.SHAPE_TYPE_CIRCLE) { + return this.circle2Poly(b, a, contacts); + } else if(b.type == Physics.Manager.SHAPE_TYPE_SEGMENT) { + return this.segment2Poly(b, a, contacts); + } else if(b.type == Physics.Manager.SHAPE_TYPE_POLY) { + return this.poly2Poly(a, b, contacts); + } + } + }; + Collision.prototype._circle2Circle = function (c1, r1, c2, r2, contactArr) { + var rmax = r1 + r2; + var t = new Phaser.Vec2(); + //var t = vec2.sub(c2, c1); + Phaser.Vec2Utils.subtract(c2, c1, t); + var distsq = t.lengthSq(); + if(distsq > rmax * rmax) { + return 0; + } + var dist = Math.sqrt(distsq); + var p = new Phaser.Vec2(); + Phaser.Vec2Utils.multiplyAdd(c1, t, 0.5 + (r1 - r2) * 0.5 / dist, p); + //var p = vec2.mad(c1, t, 0.5 + (r1 - r2) * 0.5 / dist); + var n = new Phaser.Vec2(); + //var n = (dist != 0) ? vec2.scale(t, 1 / dist) : vec2.zero; + if(dist != 0) { + Phaser.Vec2Utils.scale(t, 1 / dist, n); + } + var d = dist - rmax; + contactArr.push(new Physics.Contact(p, n, d, 0)); + return 1; + }; + Collision.prototype.circle2Circle = function (circ1, circ2, contactArr) { + return this._circle2Circle(circ1.tc, circ1.radius, circ2.tc, circ2.radius, contactArr); + }; + Collision.prototype.circle2Segment = function (circ, seg, contactArr) { + var rsum = circ.radius + seg.radius; + // Normal distance from segment + var dn = Phaser.Vec2Utils.dot(circ.tc, seg.tn) - Phaser.Vec2Utils.dot(seg.ta, seg.tn); + var dist = (dn < 0 ? dn * -1 : dn) - rsum; + if(dist > 0) { + return 0; + } + // Tangential distance along segment + var dt = Phaser.Vec2Utils.cross(circ.tc, seg.tn); + var dtMin = Phaser.Vec2Utils.cross(seg.ta, seg.tn); + var dtMax = Phaser.Vec2Utils.cross(seg.tb, seg.tn); + if(dt < dtMin) { + if(dt < dtMin - rsum) { + return 0; + } + return this._circle2Circle(circ.tc, circ.radius, seg.ta, seg.radius, contactArr); + } else if(dt > dtMax) { + if(dt > dtMax + rsum) { + return 0; + } + return this._circle2Circle(circ.tc, circ.radius, seg.tb, seg.radius, contactArr); + } + var n = new Phaser.Vec2(); + if(dn > 0) { + n.copyFrom(seg.tn); + } else { + Phaser.Vec2Utils.negative(seg.tn, n); + } + //var n = (dn > 0) ? seg.tn : vec2.neg(seg.tn); + var c1 = new Phaser.Vec2(); + Phaser.Vec2Utils.multiplyAdd(circ.tc, n, -(circ.radius + dist * 0.5), c1); + var c2 = new Phaser.Vec2(); + Phaser.Vec2Utils.negative(n, c2); + contactArr.push(new Physics.Contact(c1, c2, dist, 0)); + //contactArr.push(new Contact(vec2.mad(circ.tc, n, -(circ.r + dist * 0.5)), vec2.neg(n), dist, 0)); + return 1; + }; + Collision.prototype.circle2Poly = function (circ, poly, contactArr) { + var minDist = -999999; + var minIdx = -1; + for(var i = 0; i < poly.verts.length; i++) { + var plane = poly.tplanes[i]; + var dist = Phaser.Vec2Utils.dot(circ.tc, plane.normal) - plane.d - circ.radius; + if(dist > 0) { + return 0; + } else if(dist > minDist) { + minDist = dist; + minIdx = i; + } + } + var n = poly.tplanes[minIdx].normal; + var a = poly.tverts[minIdx]; + var b = poly.tverts[(minIdx + 1) % poly.verts.length]; + var dta = Phaser.Vec2Utils.cross(a, n); + var dtb = Phaser.Vec2Utils.cross(b, n); + var dt = Phaser.Vec2Utils.cross(circ.tc, n); + if(dt > dta) { + return this._circle2Circle(circ.tc, circ.radius, a, 0, contactArr); + } else if(dt < dtb) { + return this._circle2Circle(circ.tc, circ.radius, b, 0, contactArr); + } + var c1 = new Phaser.Vec2(); + Phaser.Vec2Utils.multiplyAdd(circ.tc, n, -(circ.radius + minDist * 0.5), c1); + var c2 = new Phaser.Vec2(); + Phaser.Vec2Utils.negative(n, c2); + contactArr.push(new Physics.Contact(c1, c2, minDist, 0)); + //contactArr.push(new Contact(vec2.mad(circ.tc, n, -(circ.r + minDist * 0.5)), vec2.neg(n), minDist, 0)); + return 1; + }; + Collision.prototype.segmentPointDistanceSq = function (seg, p) { + var w = new Phaser.Vec2(); + var d = new Phaser.Vec2(); + Phaser.Vec2Utils.subtract(p, seg.ta, w); + Phaser.Vec2Utils.subtract(seg.tb, seg.ta, d); + //var w = vec2.sub(p, seg.ta); + //var d = vec2.sub(seg.tb, seg.ta); + var proj = w.dot(d); + if(proj <= 0) { + return w.dot(w); + } + var vsq = d.dot(d); + if(proj >= vsq) { + return w.dot(w) - 2 * proj + vsq; + } + return w.dot(w) - proj * proj / vsq; + }; + Collision.prototype.segment2Segment = // FIXME and optimise me lots!!! + function (seg1, seg2, contactArr) { + var d = []; + d[0] = this.segmentPointDistanceSq(seg1, seg2.ta); + d[1] = this.segmentPointDistanceSq(seg1, seg2.tb); + d[2] = this.segmentPointDistanceSq(seg2, seg1.ta); + d[3] = this.segmentPointDistanceSq(seg2, seg1.tb); + var idx1 = d[0] < d[1] ? 0 : 1; + var idx2 = d[2] < d[3] ? 2 : 3; + var idxm = d[idx1] < d[idx2] ? idx1 : idx2; + var s, t; + var u = Phaser.Vec2Utils.subtract(seg1.tb, seg1.ta); + var v = Phaser.Vec2Utils.subtract(seg2.tb, seg2.ta); + switch(idxm) { + case 0: + s = Phaser.Vec2Utils.dot(Phaser.Vec2Utils.subtract(seg2.ta, seg1.ta), u) / Phaser.Vec2Utils.dot(u, u); + s = s < 0 ? 0 : (s > 1 ? 1 : s); + t = 0; + break; + case 1: + s = Phaser.Vec2Utils.dot(Phaser.Vec2Utils.subtract(seg2.tb, seg1.ta), u) / Phaser.Vec2Utils.dot(u, u); + s = s < 0 ? 0 : (s > 1 ? 1 : s); + t = 1; + break; + case 2: + s = 0; + t = Phaser.Vec2Utils.dot(Phaser.Vec2Utils.subtract(seg1.ta, seg2.ta), v) / Phaser.Vec2Utils.dot(v, v); + t = t < 0 ? 0 : (t > 1 ? 1 : t); + break; + case 3: + s = 1; + t = Phaser.Vec2Utils.dot(Phaser.Vec2Utils.subtract(seg1.tb, seg2.ta), v) / Phaser.Vec2Utils.dot(v, v); + t = t < 0 ? 0 : (t > 1 ? 1 : t); + break; + } + var minp1 = Phaser.Vec2Utils.multiplyAdd(seg1.ta, u, s); + var minp2 = Phaser.Vec2Utils.multiplyAdd(seg2.ta, v, t); + return this._circle2Circle(minp1, seg1.radius, minp2, seg2.radius, contactArr); + }; + Collision.prototype.findPointsBehindSeg = // Identify vertexes that have penetrated the segment. + function (contactArr, seg, poly, dist, coef) { + var dta = Phaser.Vec2Utils.cross(seg.tn, seg.ta); + var dtb = Phaser.Vec2Utils.cross(seg.tn, seg.tb); + var n = new Phaser.Vec2(); + Phaser.Vec2Utils.scale(seg.tn, coef, n); + //var n = vec2.scale(seg.tn, coef); + for(var i = 0; i < poly.verts.length; i++) { + var v = poly.tverts[i]; + if(Phaser.Vec2Utils.dot(v, n) < Phaser.Vec2Utils.dot(seg.tn, seg.ta) * coef + seg.radius) { + var dt = Phaser.Vec2Utils.cross(seg.tn, v); + if(dta >= dt && dt >= dtb) { + contactArr.push(new Physics.Contact(v, n, dist, (poly.id << 16) | i)); + } + } + } + }; + Collision.prototype.segment2Poly = function (seg, poly, contactArr) { + var seg_td = Phaser.Vec2Utils.dot(seg.tn, seg.ta); + var seg_d1 = poly.distanceOnPlane(seg.tn, seg_td) - seg.radius; + if(seg_d1 > 0) { + return 0; + } + var n = new Phaser.Vec2(); + Phaser.Vec2Utils.negative(seg.tn, n); + var seg_d2 = poly.distanceOnPlane(n, -seg_td) - seg.radius; + //var seg_d2 = poly.distanceOnPlane(vec2.neg(seg.tn), -seg_td) - seg.r; + if(seg_d2 > 0) { + return 0; + } + var poly_d = -999999; + var poly_i = -1; + for(var i = 0; i < poly.verts.length; i++) { + var plane = poly.tplanes[i]; + var dist = seg.distanceOnPlane(plane.normal, plane.d); + if(dist > 0) { + return 0; + } + if(dist > poly_d) { + poly_d = dist; + poly_i = i; + } + } + var poly_n = new Phaser.Vec2(); + Phaser.Vec2Utils.negative(poly.tplanes[poly_i].normal, poly_n); + //var poly_n = vec2.neg(poly.tplanes[poly_i].n); + var va = new Phaser.Vec2(); + Phaser.Vec2Utils.multiplyAdd(seg.ta, poly_n, seg.radius, va); + //var va = vec2.mad(seg.ta, poly_n, seg.r); + var vb = new Phaser.Vec2(); + Phaser.Vec2Utils.multiplyAdd(seg.tb, poly_n, seg.radius, vb); + //var vb = vec2.mad(seg.tb, poly_n, seg.r); + if(poly.containPoint(va)) { + contactArr.push(new Physics.Contact(va, poly_n, poly_d, (seg.id << 16) | 0)); + } + if(poly.containPoint(vb)) { + contactArr.push(new Physics.Contact(vb, poly_n, poly_d, (seg.id << 16) | 1)); + } + // Floating point precision problems here. + // This will have to do for now. + poly_d -= 0.1; + if(seg_d1 >= poly_d || seg_d2 >= poly_d) { + if(seg_d1 > seg_d2) { + this.findPointsBehindSeg(contactArr, seg, poly, seg_d1, 1); + } else { + this.findPointsBehindSeg(contactArr, seg, poly, seg_d2, -1); + } + } + // If no other collision points are found, try colliding endpoints. + if(contactArr.length == 0) { + var poly_a = poly.tverts[poly_i]; + var poly_b = poly.tverts[(poly_i + 1) % poly.verts.length]; + if(this._circle2Circle(seg.ta, seg.radius, poly_a, 0, contactArr)) { + return 1; + } + if(this._circle2Circle(seg.tb, seg.radius, poly_a, 0, contactArr)) { + return 1; + } + if(this._circle2Circle(seg.ta, seg.radius, poly_b, 0, contactArr)) { + return 1; + } + if(this._circle2Circle(seg.tb, seg.radius, poly_b, 0, contactArr)) { + return 1; + } + } + return contactArr.length; + }; + Collision.prototype.findMSA = // Find the minimum separating axis for the given poly and plane list. + function (poly, planes, num) { + var min_dist = -999999; + var min_index = -1; + for(var i = 0; i < num; i++) { + var dist = poly.distanceOnPlane(planes[i].normal, planes[i].d); + if(dist > 0) { + // no collision + return { + dist: 0, + index: -1 + }; + } else if(dist > min_dist) { + min_dist = dist; + min_index = i; + } + } + // new object - see what we can do here + return { + dist: min_dist, + index: min_index + }; + }; + Collision.prototype.findVertsFallback = function (contactArr, poly1, poly2, n, dist) { + var num = 0; + for(var i = 0; i < poly1.verts.length; i++) { + var v = poly1.tverts[i]; + if(poly2.containPointPartial(v, n)) { + contactArr.push(new Physics.Contact(v, n, dist, (poly1.id << 16) | i)); + num++; + } + } + for(var i = 0; i < poly2.verts.length; i++) { + var v = poly2.tverts[i]; + if(poly1.containPointPartial(v, n)) { + contactArr.push(new Physics.Contact(v, n, dist, (poly2.id << 16) | i)); + num++; + } + } + return num; + }; + Collision.prototype.findVerts = // Find the overlapped vertices. + function (contactArr, poly1, poly2, n, dist) { + var num = 0; + for(var i = 0; i < poly1.verts.length; i++) { + var v = poly1.tverts[i]; + if(poly2.containPoint(v)) { + contactArr.push(new Physics.Contact(v, n, dist, (poly1.id << 16) | i)); + num++; + } + } + for(var i = 0; i < poly2.verts.length; i++) { + var v = poly2.tverts[i]; + if(poly1.containPoint(v)) { + contactArr.push(new Physics.Contact(v, n, dist, (poly2.id << 16) | i)); + num++; + } + } + return num > 0 ? num : this.findVertsFallback(contactArr, poly1, poly2, n, dist); + }; + Collision.prototype.poly2Poly = function (poly1, poly2, contactArr) { + var msa1 = this.findMSA(poly2, poly1.tplanes, poly1.verts.length); + if(msa1.index == -1) { + console.log('poly2poly 0', msa1); + return 0; + } + var msa2 = this.findMSA(poly1, poly2.tplanes, poly2.verts.length); + if(msa2.index == -1) { + console.log('poly2poly 1', msa2); + return 0; + } + // Penetration normal direction should be from poly1 to poly2 + if(msa1.dist > msa2.dist) { + return this.findVerts(contactArr, poly1, poly2, poly1.tplanes[msa1.index].normal, msa1.dist); + } + return this.findVerts(contactArr, poly1, poly2, Phaser.Vec2Utils.negative(poly2.tplanes[msa2.index].normal), msa2.dist); + }; + return Collision; + })(); + Physics.Collision = Collision; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + })(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + /// + /// + /// + /// + /// + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Space + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + (function (Physics) { + var Space = (function () { + function Space(manager) { + this.postSolve = null; + this.stepCount = 0; + this._manager = manager; + this.bodies = []; + this.bodyHash = { + }; + this.joints = []; + this.jointHash = { + }; + this.numContacts = 0; + this.contactSolvers = []; + this.gravity = this._manager.gravity; + this.damping = 0; + this._linTolSqr = Space.SLEEP_LINEAR_TOLERANCE * Space.SLEEP_LINEAR_TOLERANCE; + this._angTolSqr = Space.SLEEP_ANGULAR_TOLERANCE * Space.SLEEP_ANGULAR_TOLERANCE; + } + Space.TIME_TO_SLEEP = 0.5; + Space.SLEEP_LINEAR_TOLERANCE = 0.5; + Space.SLEEP_ANGULAR_TOLERANCE = 2 * 0.017453292519943294444444444444444; + Space.prototype.clear = function () { + Physics.Manager.shapeCounter = 0; + Physics.Manager.bodyCounter = 0; + Physics.Manager.jointCounter = 0; + for(var i = 0; i < this.bodies.length; i++) { + if(this.bodies[i]) { + this.removeBody(this.bodies[i]); + } + } + this.bodies = []; + this.bodyHash = { + }; + this.joints = []; + this.jointHash = { + }; + this.contactSolvers = []; + this.stepCount = 0; + }; + Space.prototype.addBody = function (body) { + if(this.bodyHash[body.id] != undefined) { + return; + } + var index = this.bodies.push(body) - 1; + this.bodyHash[body.id] = index; + body.awake(true); + body.space = this; + body.cacheData('addBody'); + }; + Space.prototype.removeBody = function (body) { + if(this.bodyHash[body.id] == undefined) { + return; + } + // Remove linked joints + for(var i = 0; i < body.joints.length; i++) { + if(body.joints[i]) { + this.removeJoint(body.joints[i]); + } + } + body.space = null; + var index = this.bodyHash[body.id]; + delete this.bodyHash[body.id]; + delete this.bodies[index]; + }; + Space.prototype.addJoint = function (joint) { + if(this.jointHash[joint.id] != undefined) { + return; + } + joint.body1.awake(true); + joint.body2.awake(true); + var index = this.joints.push(joint) - 1; + this.jointHash[joint.id] = index; + var index = joint.body1.joints.push(joint) - 1; + joint.body1.jointHash[joint.id] = index; + var index = joint.body2.joints.push(joint) - 1; + joint.body2.jointHash[joint.id] = index; + }; + Space.prototype.removeJoint = function (joint) { + if(this.jointHash[joint.id] == undefined) { + return; + } + joint.body1.awake(true); + joint.body2.awake(true); + var index = joint.body1.jointHash[joint.id]; + delete joint.body1.jointHash[joint.id]; + delete joint.body1.joints[index]; + var index = joint.body2.jointHash[joint.id]; + delete joint.body2.jointHash[joint.id]; + delete joint.body2.joints[index]; + var index = this.jointHash[joint.id]; + delete this.jointHash[joint.id]; + delete this.joints[index]; + }; + Space.prototype.findShapeByPoint = function (p, refShape) { + var firstShape; + for(var i = 0; i < this.bodies.length; i++) { + var body = this.bodies[i]; + if(!body) { + continue; + } + for(var j = 0; j < body.shapes.length; j++) { + var shape = body.shapes[j]; + if(shape.pointQuery(p)) { + if(!refShape) { + return shape; + } + if(!firstShape) { + firstShape = shape; + } + if(shape == refShape) { + refShape = null; + } + } + } + } + return firstShape; + }; + Space.prototype.findBodyByPoint = function (p, refBody) { + var firstBody; + for(var i = 0; i < this.bodies.length; i++) { + var body = this.bodies[i]; + if(!body) { + continue; + } + for(var j = 0; j < body.shapes.length; j++) { + var shape = body.shapes[j]; + if(shape.pointQuery(p)) { + if(!refBody) { + return shape.body; + } + if(!firstBody) { + firstBody = shape.body; + } + if(shape.body == refBody) { + refBody = null; + } + break; + } + } + } + return firstBody; + }; + Space.prototype.shapeById = function (id) { + var shape; + for(var i = 0; i < this.bodies.length; i++) { + var body = this.bodies[i]; + if(!body) { + continue; + } + for(var j = 0; j < body.shapes.length; j++) { + if(body.shapes[j].id == id) { + return body.shapes[j]; + } + } + } + return null; + }; + Space.prototype.jointById = function (id) { + var index = this.jointHash[id]; + if(index != undefined) { + return this.joints[index]; + } + return null; + }; + Space.prototype.findVertexByPoint = function (p, minDist, refVertexId) { + var firstVertexId = -1; + refVertexId = refVertexId || -1; + for(var i = 0; i < this.bodies.length; i++) { + var body = this.bodies[i]; + if(!body) { + continue; + } + for(var j = 0; j < body.shapes.length; j++) { + var shape = body.shapes[j]; + var index = shape.findVertexByPoint(p, minDist); + if(index != -1) { + var vertex = (shape.id << 16) | index; + if(refVertexId == -1) { + return vertex; + } + if(firstVertexId == -1) { + firstVertexId = vertex; + } + if(vertex == refVertexId) { + refVertexId = -1; + } + } + } + } + return firstVertexId; + }; + Space.prototype.findEdgeByPoint = function (p, minDist, refEdgeId) { + var firstEdgeId = -1; + refEdgeId = refEdgeId || -1; + for(var i = 0; i < this.bodies.length; i++) { + var body = this.bodies[i]; + if(!body) { + continue; + } + for(var j = 0; j < body.shapes.length; j++) { + var shape = body.shapes[j]; + if(shape.type != Physics.Manager.SHAPE_TYPE_POLY) { + continue; + } + var index = shape.findEdgeByPoint(p, minDist); + if(index != -1) { + var edge = (shape.id << 16) | index; + if(refEdgeId == -1) { + return edge; + } + if(firstEdgeId == -1) { + firstEdgeId = edge; + } + if(edge == refEdgeId) { + refEdgeId = -1; + } + } + } + } + return firstEdgeId; + }; + Space.prototype.findJointByPoint = function (p, minDist, refJointId) { + var firstJointId = -1; + var dsq = minDist * minDist; + refJointId = refJointId || -1; + for(var i = 0; i < this.joints.length; i++) { + var joint = this.joints[i]; + if(!joint) { + continue; + } + var jointId = -1; + if(Phaser.Vec2Utils.distanceSq(p, joint.getWorldAnchor1()) < dsq) { + jointId = (joint.id << 16 | 0); + } else if(Phaser.Vec2Utils.distanceSq(p, joint.getWorldAnchor2()) < dsq) { + jointId = (joint.id << 16 | 1); + } + if(jointId != -1) { + if(refJointId == -1) { + return jointId; + } + if(firstJointId == -1) { + firstJointId = jointId; + } + if(jointId == refJointId) { + refJointId = -1; + } + } + } + return firstJointId; + }; + Space.prototype.findContactSolver = function (shape1, shape2) { + Physics.Manager.write('findContactSolver. Length: ' + this._cl); + for(var i = 0; i < this._cl; i++) { + var contactSolver = this.contactSolvers[i]; + if(shape1 == contactSolver.shape1 && shape2 == contactSolver.shape2) { + return contactSolver; + } + } + return null; + }; + Space.prototype.genTemporalContactSolvers = function () { + Physics.Manager.write('genTemporalContactSolvers'); + this._cl = 0; + this.contactSolvers.length = 0; + this.numContacts = 0; + for(var body1Index = 0; body1Index < this._bl; body1Index++) { + if(!this.bodies[body1Index]) { + continue; + } + this.bodies[body1Index].stepCount = this.stepCount; + for(var body2Index = 0; body2Index < this._bl; body2Index++) { + if(this.bodies[body1Index].inContact(this.bodies[body2Index]) == false) { + continue; + } + Physics.Manager.write('body1 and body2 intersect'); + for(var i = 0; i < this.bodies[body1Index].shapesLength; i++) { + for(var j = 0; j < this.bodies[body2Index].shapesLength; j++) { + this._shape1 = this.bodies[body1Index].shapes[i]; + this._shape2 = this.bodies[body2Index].shapes[j]; + var contactArr = []; + if(!Physics.Manager.collision.collide(this._shape1, this._shape2, contactArr)) { + continue; + } + if(this._shape1.type > this._shape2.type) { + var temp = this._shape1; + this._shape1 = this._shape2; + this._shape2 = temp; + } + this.numContacts += contactArr.length; + // Result stored in this._contactSolver (see what we can do about generating some re-usable solvers) + var contactSolver = this.findContactSolver(this._shape1, this._shape2); + Physics.Manager.write('findContactSolver result: ' + contactSolver); + if(contactSolver) { + contactSolver.update(contactArr); + this.contactSolvers.push(contactSolver); + } else { + Physics.Manager.write('awake both bodies'); + this.bodies[body1Index].awake(true); + this.bodies[body2Index].awake(true); + var newContactSolver = new Physics.ContactSolver(this._shape1, this._shape2); + newContactSolver.contacts = contactArr; + newContactSolver.elasticity = Math.max(this._shape1.elasticity, this._shape2.elasticity); + newContactSolver.friction = Math.sqrt(this._shape1.friction * this._shape2.friction); + this.contactSolvers.push(newContactSolver); + Physics.Manager.write('new contact solver'); + } + } + } + } + } + this._cl = this.contactSolvers.length; + }; + Space.prototype.initSolver = function (warmStarting) { + Physics.Manager.write('initSolver'); + Physics.Manager.write('contactSolvers.length: ' + this._cl); + // Initialize contact solvers + for(var c = 0; c < this._cl; c++) { + this.contactSolvers[c].initSolver(this._deltaInv); + // Warm starting (apply cached impulse) + if(warmStarting) { + this.contactSolvers[c].warmStart(); + } + } + // Initialize joint solver + for(var j = 0; j < this.joints.length; j++) { + if(this.joints[j]) { + this.joints[j].initSolver(this._delta, warmStarting); + } + } + // Warm starting (apply cached impulse) + /* + if (warmStarting) + { + for (var c = 0; c < this._cl; c++) + { + this.contactSolvers[c].warmStart(); + } + } + */ + }; + Space.prototype.velocitySolver = function (iterations) { + Physics.Manager.write('velocitySolver, iterations: ' + iterations + ' csa len: ' + this._cl); + for(var i = 0; i < iterations; i++) { + for(var j = 0; j < this._jl; j++) { + if(this.joints[j]) { + this.joints[j].solveVelocityConstraints(); + } + } + for(var c = 0; c < this._cl; c++) { + this.contactSolvers[c].solveVelocityConstraints(); + } + } + }; + Space.prototype.positionSolver = function (iterations) { + this._positionSolved = false; + for(var i = 0; i < iterations; i++) { + this._contactsOk = true; + this._jointsOk = true; + for(var c = 0; c < this._cl; c++) { + this._contactsOk = this.contactSolvers[c].solvePositionConstraints() && this._contactsOk; + } + for(var j = 0; j < this._jl; j++) { + if(this.joints[j]) { + this._jointsOk = this.joints[j].solvePositionConstraints() && this._jointsOk; + } + } + if(this._contactsOk && this._jointsOk) { + // exit early if the position errors are small + this._positionSolved = true; + break; + } + } + return this._positionSolved; + }; + Space.prototype.step = // Step through the physics simulation + function (dt, velocityIterations, positionIterations, warmStarting, allowSleep) { + Physics.Manager.clear(); + Physics.Manager.write('Space step ' + this.stepCount); + this._delta = dt; + this._deltaInv = 1 / dt; + this._bl = this.bodies.length; + this._jl = this.joints.length; + this.stepCount++; + // 1) Generate Contact Solvers (into the this.contactSolvers array) + this.genTemporalContactSolvers(); + Physics.Manager.dump("Contact Solvers", this.bodies[1]); + // 2) Initialize the Contact Solvers + this.initSolver(warmStarting); + Physics.Manager.dump("Init Solver", this.bodies[1]); + // 3) Intergrate velocity + for(var i = 0; i < this._bl; i++) { + if(this.bodies[i] && this.bodies[i].isDynamic && this.bodies[i].isAwake) { + this.bodies[i].updateVelocity(this.gravity, this._delta, this.damping); + } + } + Physics.Manager.dump("Update Velocity", this.bodies[1]); + // 4) Awaken bodies via joints + for(var j = 0; i < this._jl; j++) { + if(!this.joints[j]) { + continue; + } + // combine + var awake1 = this.joints[j].body1.isAwake && !this.joints[j].body1.isStatic; + var awake2 = this.joints[j].body2.isAwake && !this.joints[j].body2.isStatic; + if(awake1 ^ awake2) { + if(!awake1) { + this.joints[j].body1.awake(true); + } + if(!awake2) { + this.joints[j].body2.awake(true); + } + } + } + // 5) Iterative velocity constraints solver + this.velocitySolver(velocityIterations); + Physics.Manager.dump("Velocity Solvers", this.bodies[1]); + // 6) Intergrate position + for(var i = 0; i < this._bl; i++) { + if(this.bodies[i] && this.bodies[i].isDynamic && this.bodies[i].isAwake) { + this.bodies[i].updatePosition(this._delta); + } + } + Physics.Manager.dump("Update Position", this.bodies[1]); + // 7) Process breakable joint + for(var i = 0; i < this._jl; i++) { + if(this.joints[i] && this.joints[i].breakable && (this.joints[i].getReactionForce(this._deltaInv).lengthSq() >= this.joints[i].maxForce * this.joints[i].maxForce)) { + this.removeJoint(this.joints[i]); + } + } + // 8) Iterative position constraints solver (result stored in this._positionSolved) + this.positionSolver(positionIterations); + Physics.Manager.dump("Position Solver", this.bodies[1]); + // 9) Sync the Transforms + for(var i = 0; i < this._bl; i++) { + if(this.bodies[i]) { + this.bodies[i].syncTransform(); + } + } + Physics.Manager.dump("Sync Transform", this.bodies[1]); + // 10) Post solve collision callback + if(this.postSolve) { + for(var i = 0; i < this._cl; i++) { + this.postSolve(this.contactSolvers[i]); + } + } + // 11) Cache Body Data + for(var i = 0; i < this._bl; i++) { + if(this.bodies[i] && this.bodies[i].isDynamic && this.bodies[i].isAwake) { + this.bodies[i].cacheData('post solve collision callback'); + } + } + Physics.Manager.dump("Cache Data", this.bodies[1]); + Physics.Manager.writeAll(); + // 12) Process sleeping + if(allowSleep) { + this._minSleepTime = 999999; + for(var i = 0; i < this._bl; i++) { + if(!this.bodies[i] || this.bodies[i].isDynamic == false) { + continue; + } + if(this.bodies[i].angularVelocity * this.bodies[i].angularVelocity > this._angTolSqr || this.bodies[i].velocity.dot(this.bodies[i].velocity) > this._linTolSqr) { + this.bodies[i].sleepTime = 0; + this._minSleepTime = 0; + } else { + this.bodies[i].sleepTime += this._delta; + this._minSleepTime = Math.min(this._minSleepTime, this.bodies[i].sleepTime); + } + } + if(this._positionSolved && this._minSleepTime >= Space.TIME_TO_SLEEP) { + for(var i = 0; i < this._bl; i++) { + if(this.bodies[i]) { + this.bodies[i].awake(false); + } + } + } + } + }; + return Space; + })(); + Physics.Space = Space; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + (function (Physics) { + /// + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Shapes - Triangle + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + (function (Shapes) { + var Triangle = (function (_super) { + __extends(Triangle, _super); + function Triangle(x1, y1, x2, y2, x3, y3) { + x1 = Physics.Manager.pixelsToMeters(x1); + y1 = Physics.Manager.pixelsToMeters(y1); + x2 = Physics.Manager.pixelsToMeters(x2); + y2 = Physics.Manager.pixelsToMeters(y2); + x3 = Physics.Manager.pixelsToMeters(x3); + y3 = Physics.Manager.pixelsToMeters(y3); + _super.call(this, [ + { + x: x1, + y: y1 + }, + { + x: x2, + y: y2 + }, + { + x: x3, + y: y3 + } + ]); + } + return Triangle; + })(Phaser.Physics.Shapes.Poly); + Shapes.Triangle = Triangle; + })(Physics.Shapes || (Physics.Shapes = {})); + var Shapes = Physics.Shapes; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + (function (Physics) { + /// + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Shapes - Box + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + (function (Shapes) { + var Box = (function (_super) { + __extends(Box, _super); + // Give in pixels + function Box(x, y, width, height) { + x = Physics.Manager.pixelsToMeters(x); + y = Physics.Manager.pixelsToMeters(y); + width = Physics.Manager.pixelsToMeters(width); + height = Physics.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.Shapes.Poly); + Shapes.Box = Box; + })(Physics.Shapes || (Physics.Shapes = {})); + var Shapes = Physics.Shapes; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Body + * + * Based on the work Ju Hyung Lee started in JS PhyRus. */ (function (Physics) { var Body = (function () { - function Body(sprite, type) { - this.angularVelocity = 0; - this.angularAcceleration = 0; - this.angularDrag = 0; - this.maxAngular = 10000; - this.mass = 1; - this._width = 0; - this._height = 0; - this.sprite = sprite; - this.game = sprite.game; + function Body(sprite, type, x, y, shapeType) { + if (typeof x === "undefined") { x = 0; } + if (typeof y === "undefined") { y = 0; } + if (typeof shapeType === "undefined") { shapeType = 0; } + this._tempVec2 = new Phaser.Vec2(); + // Shapes + this.shapes = []; + // Joints + this.joints = []; + this.jointHash = { + }; + this.fixedRotation = false; + this.categoryBits = 0x0001; + this.maskBits = 0xFFFF; + this.stepCount = 0; + this.id = Phaser.Physics.Manager.bodyCounter++; + this.name = 'body' + this.id; this.type = type; - // Fixture properties - // Will extend into its own class at a later date - can move the fixture defs there and add shape support, but this will do for 1.0 release - this.bounds = new Phaser.Rectangle(); - this._width = sprite.width; - this._height = sprite.height; - // Body properties - this.gravity = Phaser.Vec2Utils.clone(this.game.world.physics.gravity); - this.bounce = Phaser.Vec2Utils.clone(this.game.world.physics.bounce); + if(sprite) { + this.sprite = sprite; + this.game = sprite.game; + this.position = new Phaser.Vec2(Phaser.Physics.Manager.pixelsToMeters(sprite.x), Phaser.Physics.Manager.pixelsToMeters(sprite.y)); + this.angle = sprite.rotation; + } else { + this.position = new Phaser.Vec2(Phaser.Physics.Manager.pixelsToMeters(x), Phaser.Physics.Manager.pixelsToMeters(y)); + this.angle = 0; + } + this.transform = new Phaser.Transform(this.position, this.angle); + this.centroid = new Phaser.Vec2(); this.velocity = new Phaser.Vec2(); - this.acceleration = new Phaser.Vec2(); - this.drag = Phaser.Vec2Utils.clone(this.game.world.physics.drag); - this.maxVelocity = new Phaser.Vec2(10000, 10000); + this.force = new Phaser.Vec2(); this.angularVelocity = 0; - this.angularAcceleration = 0; - this.angularDrag = 0; - this.touching = Phaser.Types.NONE; - this.wasTouching = Phaser.Types.NONE; + this.torque = 0; + this.linearDamping = 0; + this.angularDamping = 0; + this.sleepTime = 0; + this.awaked = false; + this.shapes = []; + this.joints = []; + this.jointHash = { + }; + this.bounds = new Physics.Bounds(); this.allowCollisions = Phaser.Types.ANY; - this.position = new Phaser.Vec2(sprite.x + this.bounds.halfWidth, sprite.y + this.bounds.halfHeight); - this.oldPosition = new Phaser.Vec2(sprite.x + this.bounds.halfWidth, sprite.y + this.bounds.halfHeight); - this.offset = new Phaser.Vec2(); + this.fixedRotation = false; + this.categoryBits = 0x0001; + this.maskBits = 0xFFFF; + this.stepCount = 0; + if(sprite) { + if(shapeType == 0) { + this.addBox(0, 0, this.sprite.width, this.sprite.height, 1, 1, 1); + } else { + this.addCircle(Math.max(this.sprite.width, this.sprite.height) / 2, 0, 0, 1, 1, 1); + } + } } - Object.defineProperty(Body.prototype, "x", { - get: function () { - return this.sprite.x + this.offset.x; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Body.prototype, "y", { - get: function () { - return this.sprite.y + this.offset.y; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Body.prototype, "width", { - get: function () { - return this._width * this.sprite.transform.scale.x; - }, - set: function (value) { - this._width = value; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Body.prototype, "height", { - get: function () { - return this._height * this.sprite.transform.scale.y; - }, - set: function (value) { - this._height = value; - }, - enumerable: true, - configurable: true - }); - Body.prototype.preUpdate = function () { - this.oldPosition.copyFrom(this.position); - this.bounds.x = this.x; - this.bounds.y = this.y; - this.bounds.width = this.width; - this.bounds.height = this.height; + Body.prototype.toString = function () { + return "[{Body (name=" + this.name + " velocity=" + this.velocity.toString() + " angularVelocity: " + this.angularVelocity + ")}]"; }; - Body.prototype.postUpdate = // Shall we do this? Or just update the values directly in the separate functions? But then the bounds will be out of sync - as long as - // the bounds are updated and used in calculations then we can do one final sprite movement here I guess? - function () { - // if this is all it does maybe move elsewhere? Sprite postUpdate? - if(this.type !== Phaser.Types.BODY_DISABLED) { - this.game.world.physics.updateMotion(this); - this.wasTouching = this.touching; - this.touching = Phaser.Types.NONE; + Body.prototype.duplicate = function () { + console.log('body duplicate called'); + //var body = new Body(this.type, this.transform.t, this.angle); + //for (var i = 0; i < this.shapes.length; i++) + //{ + // body.addShape(this.shapes[i].duplicate()); + //} + //body.resetMassData(); + //return body; + }; + Object.defineProperty(Body.prototype, "isDisabled", { + get: function () { + return this.type == Phaser.Types.BODY_DISABLED ? true : false; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Body.prototype, "isStatic", { + get: function () { + return this.type == Phaser.Types.BODY_STATIC ? true : false; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Body.prototype, "isKinetic", { + get: function () { + return this.type == Phaser.Types.BODY_KINETIC ? true : false; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Body.prototype, "isDynamic", { + get: function () { + return this.type == Phaser.Types.BODY_DYNAMIC ? true : false; + }, + enumerable: true, + configurable: true + }); + Body.prototype.setType = function (type) { + if(type == this.type) { + return; } - this.position.setTo(this.x, this.y); + this.force.setTo(0, 0); + this.velocity.setTo(0, 0); + this.torque = 0; + this.angularVelocity = 0; + this.type = type; + this.awake(true); }; - Object.defineProperty(Body.prototype, "hullWidth", { - get: function () { - if(this.deltaX > 0) { - return this.bounds.width + this.deltaX; - } else { - return this.bounds.width - this.deltaX; - } - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Body.prototype, "hullHeight", { - get: function () { - if(this.deltaY > 0) { - return this.bounds.height + this.deltaY; - } else { - return this.bounds.height - this.deltaY; - } - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Body.prototype, "hullX", { - get: function () { - if(this.position.x < this.oldPosition.x) { - return this.position.x; - } else { - return this.oldPosition.x; - } - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Body.prototype, "hullY", { - get: function () { - if(this.position.y < this.oldPosition.y) { - return this.position.y; - } else { - return this.oldPosition.y; - } - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Body.prototype, "deltaXAbs", { - get: function () { - return (this.deltaX > 0 ? this.deltaX : -this.deltaX); - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Body.prototype, "deltaYAbs", { - get: function () { - return (this.deltaY > 0 ? this.deltaY : -this.deltaY); - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Body.prototype, "deltaX", { - get: function () { - return this.position.x - this.oldPosition.x; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Body.prototype, "deltaY", { - get: function () { - return this.position.y - this.oldPosition.y; - }, - enumerable: true, - configurable: true - }); - Body.prototype.render = // MOVE THESE TO A UTIL - function (context) { - context.beginPath(); - context.strokeStyle = 'rgb(0,255,0)'; - context.strokeRect(this.position.x - this.bounds.halfWidth, this.position.y - this.bounds.halfHeight, this.bounds.width, this.bounds.height); - context.stroke(); - context.closePath(); - // center point - context.fillStyle = 'rgb(0,255,0)'; - context.fillRect(this.position.x, this.position.y, 2, 2); - if(this.touching & Phaser.Types.LEFT) { - context.beginPath(); - context.strokeStyle = 'rgb(255,0,0)'; - context.moveTo(this.position.x - this.bounds.halfWidth, this.position.y - this.bounds.halfHeight); - context.lineTo(this.position.x - this.bounds.halfWidth, this.position.y + this.bounds.halfHeight); - context.stroke(); - context.closePath(); + Body.prototype.addPoly = function (verts, elasticity, friction, density) { + if (typeof elasticity === "undefined") { elasticity = 1; } + if (typeof friction === "undefined") { friction = 1; } + if (typeof density === "undefined") { density = 1; } + var poly = new Phaser.Physics.Shapes.Poly(verts); + poly.elasticity = elasticity; + poly.friction = friction; + poly.density = density; + this.addShape(poly); + this.resetMassData(); + return poly; + }; + Body.prototype.addTriangle = function (x1, y1, x2, y2, x3, y3, elasticity, friction, density) { + if (typeof elasticity === "undefined") { elasticity = 1; } + if (typeof friction === "undefined") { friction = 1; } + if (typeof density === "undefined") { density = 1; } + var tri = new Phaser.Physics.Shapes.Triangle(x1, y1, x2, y2, x3, y3); + tri.elasticity = elasticity; + tri.friction = friction; + tri.density = density; + this.addShape(tri); + this.resetMassData(); + return tri; + }; + Body.prototype.addBox = function (x, y, width, height, elasticity, friction, density) { + if (typeof elasticity === "undefined") { elasticity = 1; } + if (typeof friction === "undefined") { friction = 1; } + if (typeof density === "undefined") { density = 1; } + var box = new Phaser.Physics.Shapes.Box(x, y, width, height); + box.elasticity = elasticity; + box.friction = friction; + box.density = density; + this.addShape(box); + this.resetMassData(); + return box; + }; + Body.prototype.addCircle = function (radius, x, y, elasticity, friction, density) { + if (typeof x === "undefined") { x = 0; } + if (typeof y === "undefined") { y = 0; } + if (typeof elasticity === "undefined") { elasticity = 1; } + if (typeof friction === "undefined") { friction = 1; } + if (typeof density === "undefined") { density = 1; } + var circle = new Phaser.Physics.Shapes.Circle(radius, x, y); + circle.elasticity = elasticity; + circle.friction = friction; + circle.density = density; + this.addShape(circle); + this.resetMassData(); + return circle; + }; + Body.prototype.addShape = function (shape) { + // Check not already part of this body + shape.body = this; + this.shapes.push(shape); + this.shapesLength = this.shapes.length; + return shape; + }; + Body.prototype.removeShape = function (shape) { + var index = this.shapes.indexOf(shape); + if(index != -1) { + this.shapes.splice(index, 1); + shape.body = undefined; } - if(this.touching & Phaser.Types.RIGHT) { - context.beginPath(); - context.strokeStyle = 'rgb(255,0,0)'; - context.moveTo(this.position.x + this.bounds.halfWidth, this.position.y - this.bounds.halfHeight); - context.lineTo(this.position.x + this.bounds.halfWidth, this.position.y + this.bounds.halfHeight); - context.stroke(); - context.closePath(); + this.shapesLength = this.shapes.length; + }; + Body.prototype.setMass = function (mass) { + this.mass = mass; + this.massInverted = mass > 0 ? 1 / mass : 0; + }; + Body.prototype.setInertia = function (inertia) { + this.inertia = inertia; + this.inertiaInverted = inertia > 0 ? 1 / inertia : 0; + }; + Body.prototype.setTransform = function (pos, angle) { + // inject the transform into this.position + this.transform.setTo(pos, angle); + Physics.Manager.write('setTransform: ' + this.position.toString()); + Physics.Manager.write('centroid: ' + this.centroid.toString()); + Phaser.TransformUtils.transform(this.transform, this.centroid, this.position); + Physics.Manager.write('post setTransform: ' + this.position.toString()); + //this.position.copyFrom(this.transform.transform(this.centroid)); + this.angle = angle; + }; + Body.prototype.syncTransform = function () { + Physics.Manager.write('syncTransform:'); + Physics.Manager.write('p: ' + this.position.toString()); + Physics.Manager.write('centroid: ' + this.centroid.toString()); + Physics.Manager.write('xf: ' + this.transform.toString()); + Physics.Manager.write('a: ' + this.angle); + this.transform.setRotation(this.angle); + // OPTIMISE: Creating new vector + Phaser.Vec2Utils.subtract(this.position, Phaser.TransformUtils.rotate(this.transform, this.centroid), this.transform.t); + Physics.Manager.write('--------------------'); + Physics.Manager.write('xf: ' + this.transform.toString()); + Physics.Manager.write('--------------------'); + }; + Body.prototype.getWorldPoint = function (p) { + // OPTIMISE: Creating new vector + return Phaser.TransformUtils.transform(this.transform, p); + }; + Body.prototype.getWorldVector = function (v) { + // OPTIMISE: Creating new vector + return Phaser.TransformUtils.rotate(this.transform, v); + }; + Body.prototype.getLocalPoint = function (p) { + // OPTIMISE: Creating new vector + return Phaser.TransformUtils.untransform(this.transform, p); + }; + Body.prototype.getLocalVector = function (v) { + // OPTIMISE: Creating new vector + return Phaser.TransformUtils.unrotate(this.transform, v); + }; + Body.prototype.setFixedRotation = function (flag) { + this.fixedRotation = flag; + this.resetMassData(); + }; + Body.prototype.resetMassData = function () { + this.centroid.setTo(0, 0); + this.mass = 0; + this.massInverted = 0; + this.inertia = 0; + this.inertiaInverted = 0; + if(this.isDynamic == false) { + Phaser.TransformUtils.transform(this.transform, this.centroid, this.position); + //this.position.copyFrom(this.transform.transform(this.centroid)); + return; } - if(this.touching & Phaser.Types.UP) { - context.beginPath(); - context.strokeStyle = 'rgb(255,0,0)'; - context.moveTo(this.position.x - this.bounds.halfWidth, this.position.y - this.bounds.halfHeight); - context.lineTo(this.position.x + this.bounds.halfWidth, this.position.y - this.bounds.halfHeight); - context.stroke(); - context.closePath(); + var totalMassCentroid = new Phaser.Vec2(0, 0); + var totalMass = 0; + var totalInertia = 0; + for(var i = 0; i < this.shapes.length; i++) { + var shape = this.shapes[i]; + var centroid = shape.centroid(); + var mass = shape.area() * shape.density; + var inertia = shape.inertia(mass); + //console.log('rmd', centroid, shape); + totalMassCentroid.multiplyAddByScalar(centroid, mass); + totalMass += mass; + totalInertia += inertia; } - if(this.touching & Phaser.Types.DOWN) { - context.beginPath(); - context.strokeStyle = 'rgb(255,0,0)'; - context.moveTo(this.position.x - this.bounds.halfWidth, this.position.y + this.bounds.halfHeight); - context.lineTo(this.position.x + this.bounds.halfWidth, this.position.y + this.bounds.halfHeight); - context.stroke(); - context.closePath(); + //this.centroid.copy(vec2.scale(totalMassCentroid, 1 / totalMass)); + Phaser.Vec2Utils.scale(totalMassCentroid, 1 / totalMass, this.centroid); + this.setMass(totalMass); + if(!this.fixedRotation) { + this.setInertia(totalInertia - totalMass * Phaser.Vec2Utils.dot(this.centroid, this.centroid)); + } + // Move center of mass + var oldPosition = Phaser.Vec2Utils.clone(this.position); + Phaser.TransformUtils.transform(this.transform, this.centroid, this.position); + // Update center of mass velocity + oldPosition.subtract(this.position); + this.velocity.multiplyAddByScalar(Phaser.Vec2Utils.perp(oldPosition, oldPosition), this.angularVelocity); + }; + Body.prototype.resetJointAnchors = function () { + for(var i = 0; i < this.joints.length; i++) { + var joint = this.joints[i]; + if(!joint) { + continue; + } + var anchor1 = joint.getWorldAnchor1(); + var anchor2 = joint.getWorldAnchor2(); + joint.setWorldAnchor1(anchor1); + joint.setWorldAnchor2(anchor2); } }; - Body.prototype.renderDebugInfo = /** - * Render debug infos. (including name, bounds info, position and some other properties) - * @param x {number} X position of the debug info to be rendered. - * @param y {number} Y position of the debug info to be rendered. - * @param [color] {number} color of the debug info to be rendered. (format is css color string) - */ - function (x, y, color) { - if (typeof color === "undefined") { color = 'rgb(255,255,255)'; } - this.sprite.texture.context.fillStyle = color; - this.sprite.texture.context.fillText('Sprite: (' + this.sprite.width + ' x ' + this.sprite.height + ')', x, y); - //this.sprite.texture.context.fillText('x: ' + this._sprite.frameBounds.x.toFixed(1) + ' y: ' + this._sprite.frameBounds.y.toFixed(1) + ' rotation: ' + this._sprite.rotation.toFixed(1), x, y + 14); - this.sprite.texture.context.fillText('x: ' + this.bounds.x.toFixed(1) + ' y: ' + this.bounds.y.toFixed(1) + ' rotation: ' + this.sprite.transform.rotation.toFixed(0), x, y + 14); - this.sprite.texture.context.fillText('vx: ' + this.velocity.x.toFixed(1) + ' vy: ' + this.velocity.y.toFixed(1), x, y + 28); - this.sprite.texture.context.fillText('acx: ' + this.acceleration.x.toFixed(1) + ' acy: ' + this.acceleration.y.toFixed(1), x, y + 42); - this.sprite.texture.context.fillText('angVx: ' + this.angularVelocity.toFixed(1) + ' angAc: ' + this.angularAcceleration.toFixed(1), x, y + 56); + Body.prototype.cacheData = function (source) { + if (typeof source === "undefined") { source = ''; } + Physics.Manager.write('cacheData -- start'); + Physics.Manager.write('p: ' + this.position.toString()); + Physics.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); + } + Physics.Manager.write('bounds: ' + this.bounds.toString()); + Physics.Manager.write('p: ' + this.position.toString()); + Physics.Manager.write('xf: ' + this.transform.toString()); + Physics.Manager.write('cacheData -- stop'); + }; + Body.prototype.updateVelocity = function (gravity, dt, damping) { + Phaser.Vec2Utils.multiplyAdd(gravity, this.force, this.massInverted, this._tempVec2); + Phaser.Vec2Utils.multiplyAdd(this.velocity, this._tempVec2, dt, this.velocity); + this.angularVelocity = this.angularVelocity + this.torque * this.inertiaInverted * dt; + // Apply damping. + // ODE: dv/dt + c * v = 0 + // Solution: v(t) = v0 * exp(-c * t) + // Time step: v(t + dt) = v0 * exp(-c * (t + dt)) = v0 * exp(-c * t) * exp(-c * dt) = v * exp(-c * dt) + // v2 = exp(-c * dt) * v1 + // Taylor expansion: + // v2 = (1.0f - c * dt) * v1 + this.velocity.scale(this.clamp(1 - dt * (damping + this.linearDamping), 0, 1)); + this.angularVelocity *= this.clamp(1 - dt * (damping + this.angularDamping), 0, 1); + this.force.setTo(0, 0); + this.torque = 0; + }; + Body.prototype.inContact = function (body2) { + if(!body2 || this.stepCount == body2.stepCount) { + return false; + } + if(!(this.isAwake && this.isStatic == false) && !(body2.isAwake && body2.isStatic == false)) { + return false; + } + if(this.isCollidable(body2) == false) { + return false; + } + if(!this.bounds.intersectsBounds(body2.bounds)) { + return false; + } + return true; + }; + Body.prototype.clamp = function (v, min, max) { + return v < min ? min : (v > max ? max : v); + }; + Body.prototype.updatePosition = function (dt) { + this.position.add(Phaser.Vec2Utils.scale(this.velocity, dt, this._tempVec2)); + this.angle += this.angularVelocity * dt; + if(this.sprite) { + this.sprite.x = this.position.x * 50; + this.sprite.y = this.position.y * 50; + // Obey fixed rotation? + this.sprite.rotation = this.game.math.radiansToDegrees(this.angle); + } + }; + Body.prototype.resetForce = function () { + this.force.setTo(0, 0); + this.torque = 0; + }; + Body.prototype.applyForce = function (force, p) { + if(this.isDynamic == false) { + return; + } + if(this.isAwake == false) { + this.awake(true); + } + this.force.add(force); + Phaser.Vec2Utils.subtract(p, this.position, this._tempVec2); + this.torque += Phaser.Vec2Utils.cross(this._tempVec2, force); + }; + Body.prototype.applyForceToCenter = function (force) { + if(this.isDynamic == false) { + return; + } + if(this.isAwake == false) { + this.awake(true); + } + this.force.add(force); + }; + Body.prototype.applyTorque = function (torque) { + if(this.isDynamic == false) { + return; + } + if(this.isAwake == false) { + this.awake(true); + } + this.torque += torque; + }; + Body.prototype.applyLinearImpulse = function (impulse, p) { + if(this.isDynamic == false) { + return; + } + if(this.isAwake == false) { + this.awake(true); + } + this.velocity.multiplyAddByScalar(impulse, this.massInverted); + Phaser.Vec2Utils.subtract(p, this.position, this._tempVec2); + this.angularVelocity += Phaser.Vec2Utils.cross(this._tempVec2, impulse) * this.inertiaInverted; + }; + Body.prototype.applyAngularImpulse = function (impulse) { + if(this.isDynamic == false) { + return; + } + if(this.isAwake == false) { + this.awake(true); + } + this.angularVelocity += impulse * this.inertiaInverted; + }; + Body.prototype.kineticEnergy = function () { + var vsq = this.velocity.dot(this.velocity); + var wsq = this.angularVelocity * this.angularVelocity; + return 0.5 * (this.mass * vsq + this.inertia * wsq); + }; + Object.defineProperty(Body.prototype, "isAwake", { + get: function () { + return this.awaked; + }, + enumerable: true, + configurable: true + }); + Body.prototype.awake = function (flag) { + this.awaked = flag; + if(flag) { + this.sleepTime = 0; + } else { + this.velocity.setTo(0, 0); + this.angularVelocity = 0; + this.force.setTo(0, 0); + this.torque = 0; + } + }; + Body.prototype.isCollidable = function (other) { + if(this == other) { + return false; + } + if(this.isDynamic == false && other.isDynamic == false) { + return false; + } + if(!(this.maskBits & other.categoryBits) || !(other.maskBits & this.categoryBits)) { + return false; + } + for(var i = 0; i < this.joints.length; i++) { + var joint = this.joints[i]; + if(!this.joints[i] || (!this.joints[i].collideConnected && other.jointHash[this.joints[i].id] != undefined)) { + return false; + } + } + return true; }; return Body; })(); @@ -4514,14 +7108,20 @@ var Phaser; * @param [x] {number} the initial x position of the sprite. * @param [y] {number} the initial y position of the sprite. * @param [key] {string} Key of the graphic you want to load for this sprite. - * @param [bodyType] {number} The physics body type of the object (defaults to BODY_DYNAMIC) + * @param [bodyType] {number} The physics body type of the object (defaults to BODY_DISABLED) + * @param [shapeType] {number} The physics shape the body will consist of (either Box (0) or Circle (1), for custom types see body.addShape) */ - function Sprite(game, x, y, key, frame, bodyType) { + function Sprite(game, x, y, key, frame, bodyType, shapeType) { if (typeof x === "undefined") { x = 0; } if (typeof y === "undefined") { y = 0; } if (typeof key === "undefined") { key = null; } if (typeof frame === "undefined") { frame = null; } - if (typeof bodyType === "undefined") { bodyType = Phaser.Types.BODY_DYNAMIC; } + if (typeof bodyType === "undefined") { bodyType = Phaser.Types.BODY_DISABLED; } + if (typeof shapeType === "undefined") { shapeType = 0; } + /** + * Sprite physics body. + */ + this.body = null; /** * A boolean representing if the Sprite has been modified in any way via a scale, rotate, flip or skew. */ @@ -4569,7 +7169,11 @@ var Phaser; this.frame = frame; } } - this.body = new Phaser.Physics.Body(this, bodyType); + if(bodyType !== Phaser.Types.BODY_DISABLED) { + this.body = new Phaser.Physics.Body(this, bodyType, 0, 0, shapeType); + this.game.physics.addBody(this.body); + this.transform.origin.setTo(0.5, 0.5); + } this.worldView = new Phaser.Rectangle(x, y, this.width, this.height); this.cameraView = new Phaser.Rectangle(x, y, this.width, this.height); this.transform.setCache(); @@ -4654,8 +7258,6 @@ var Phaser; this.transform.update(); this.worldView.x = (this.x * this.transform.scrollFactor.x) - (this.width * this.transform.origin.x); this.worldView.y = (this.y * this.transform.scrollFactor.y) - (this.height * this.transform.origin.y); - //this.worldView.x = this.x * this.transform.scrollFactor.x; - //this.worldView.y = this.y * this.transform.scrollFactor.y; this.worldView.width = this.width; this.worldView.height = this.height; if(this.modified == false && (!this.transform.scale.equals(1) || !this.transform.skew.equals(0) || this.transform.rotation != 0 || this.transform.rotationOffset != 0 || this.texture.flippedX || this.texture.flippedY)) { @@ -4663,7 +7265,7 @@ var Phaser; } }; Sprite.prototype.update = /** - * Override this function to update your class's position and appearance. + * Override this function to update your sprites position and appearance. */ function () { }; @@ -4672,7 +7274,6 @@ var Phaser; */ function () { this.animations.update(); - this.body.postUpdate(); /* if (this.worldBounds != null) { @@ -4960,8 +7561,8 @@ var Phaser; */ function reset(sprite, x, y) { sprite.revive(); - sprite.body.touching = Phaser.Types.NONE; - sprite.body.wasTouching = Phaser.Types.NONE; + //sprite.body.touching = Types.NONE; + //sprite.body.wasTouching = Types.NONE; sprite.x = x; sprite.y = y; sprite.body.velocity.x = 0; @@ -9436,11 +12037,9 @@ var Phaser; _super.call(this, game); this.body.type = Phaser.Types.BODY_DYNAMIC; this.lifespan = 0; - this.friction = 500; } Particle.prototype.update = /** - * The particle's main update logic. Basically it checks to see if it should - * be dead yet, and then has some special bounce behavior if there is some gravity on it. + * The particle's main update logic. Basically it checks to see if it should be dead yet. */ function () { // Lifespan behavior @@ -9451,30 +12050,6 @@ var Phaser; if(this.lifespan <= 0) { this.kill(); } - //simpler bounce/spin behavior for now - if(this.body.touching) { - if(this.body.angularVelocity != 0) { - this.body.angularVelocity = -this.body.angularVelocity; - } - } - if(this.body.acceleration.y > 0)//special behavior for particles with gravity - { - if(this.body.touching & Phaser.Types.FLOOR) { - this.body.drag.x = this.friction; - if(!(this.body.wasTouching & Phaser.Types.FLOOR)) { - if(this.body.velocity.y < -this.body.bounce.y * 10) { - if(this.body.angularVelocity != 0) { - this.body.angularVelocity *= -this.body.bounce.y; - } - } else { - this.body.velocity.y = 0; - this.body.angularVelocity = 0; - } - } - } else { - this.body.drag.x = 0; - } - } }; Particle.prototype.onEmit = /** * Triggered whenever this object is launched by a Emitter. @@ -9591,16 +12166,16 @@ var Phaser; } } if(collide > 0) { - particle.body.allowCollisions = Phaser.Types.ANY; + //particle.body.allowCollisions = Types.ANY; particle.body.type = Phaser.Types.BODY_DYNAMIC; particle.width *= collide; particle.height *= collide; } else { - particle.body.allowCollisions = Phaser.Types.NONE; - } + //particle.body.allowCollisions = Types.NONE; + } particle.exists = false; // Center the origin for rotation assistance - particle.transform.origin.setTo(particle.body.bounds.halfWidth, particle.body.bounds.halfHeight); + //particle.transform.origin.setTo(particle.body.bounds.halfWidth, particle.body.bounds.halfHeight); this.add(particle); i++; } @@ -9686,7 +12261,7 @@ var Phaser; function () { var particle = this.recycle(Phaser.Particle); particle.lifespan = this.lifespan; - particle.body.bounce.setTo(this.bounce, this.bounce); + //particle.body.bounce.setTo(this.bounce, this.bounce); Phaser.SpriteUtils.reset(particle, this.x - (particle.width >> 1) + this.game.math.random() * this.width, this.y - (particle.height >> 1) + this.game.math.random() * this.height); particle.visible = true; if(this.minParticleSpeed.x != this.maxParticleSpeed.x) { @@ -9699,7 +12274,7 @@ var Phaser; } else { particle.body.velocity.y = this.minParticleSpeed.y; } - particle.body.acceleration.y = this.gravity; + //particle.body.acceleration.y = this.gravity; if(this.minRotation != this.maxRotation && this.minRotation !== 0 && this.maxRotation !== 0) { particle.body.angularVelocity = this.minRotation + this.game.math.random() * (this.maxRotation - this.minRotation); } else { @@ -9708,8 +12283,8 @@ var Phaser; if(particle.body.angularVelocity != 0) { particle.rotation = this.game.math.random() * 360 - 180; } - particle.body.drag.x = this.particleDrag.x; - particle.body.drag.y = this.particleDrag.y; + //particle.body.drag.x = this.particleDrag.x; + //particle.body.drag.y = this.particleDrag.y; particle.onEmit(); }; Emitter.prototype.setSize = /** @@ -9764,9 +12339,9 @@ var Phaser; * @param Object {object} The Object that you want to sync up with. */ function (object) { - this.x = object.body.bounds.halfWidth - (this.width >> 1); - this.y = object.body.bounds.halfHeight - (this.height >> 1); - }; + //this.x = object.body.bounds.halfWidth - (this.width >> 1); + //this.y = object.body.bounds.halfHeight - (this.height >> 1); + }; return Emitter; })(Phaser.Group); Phaser.Emitter = Emitter; @@ -10275,16 +12850,15 @@ var Phaser; // Loop through the tiles we've got and check overlaps accordingly (the results are stored in this._tempTileBlock) this._tempBlockResults = []; this.getTempBlock(this._tempTileX, this._tempTileY, this._tempTileW, this._tempTileH, true); - Phaser.Physics.PhysicsManager.TILE_OVERLAP = false; - for(var r = 0; r < this._tempTileBlock.length; r++) { - if(this._game.world.physics.separateTile(object, this._tempTileBlock[r].x * this.tileWidth, this._tempTileBlock[r].y * this.tileHeight, this.tileWidth, this.tileHeight, this._tempTileBlock[r].tile.mass, this._tempTileBlock[r].tile.collideLeft, this._tempTileBlock[r].tile.collideRight, this._tempTileBlock[r].tile.collideUp, this._tempTileBlock[r].tile.collideDown, this._tempTileBlock[r].tile.separateX, this._tempTileBlock[r].tile.separateY) == true) { - this._tempBlockResults.push({ - x: this._tempTileBlock[r].x, - y: this._tempTileBlock[r].y, - tile: this._tempTileBlock[r].tile - }); - } + /* + for (var r = 0; r < this._tempTileBlock.length; r++) + { + if (this._game.world.physics.separateTile(object, this._tempTileBlock[r].x * this.tileWidth, this._tempTileBlock[r].y * this.tileHeight, this.tileWidth, this.tileHeight, this._tempTileBlock[r].tile.mass, this._tempTileBlock[r].tile.collideLeft, this._tempTileBlock[r].tile.collideRight, this._tempTileBlock[r].tile.collideUp, this._tempTileBlock[r].tile.collideDown, this._tempTileBlock[r].tile.separateX, this._tempTileBlock[r].tile.separateY) == true) + { + this._tempBlockResults.push({ x: this._tempTileBlock[r].x, y: this._tempTileBlock[r].y, tile: this._tempTileBlock[r].tile }); } + } + */ return this._tempBlockResults; }; TilemapLayer.prototype.getTempBlock = /** @@ -10989,9 +13563,25 @@ var Phaser; function (x, y, key, frame, bodyType) { if (typeof key === "undefined") { key = ''; } if (typeof frame === "undefined") { frame = null; } - if (typeof bodyType === "undefined") { bodyType = Phaser.Types.BODY_DYNAMIC; } + if (typeof bodyType === "undefined") { bodyType = Phaser.Types.BODY_DISABLED; } return this._world.group.add(new Phaser.Sprite(this._game, x, y, key, frame, bodyType)); }; + GameObjectFactory.prototype.physicsSprite = /** + * Create a new Sprite with the physics automatically created and set to DYNAMIC. The Sprite position offset is set to its center. + * + * @param x {number} X position of the new sprite. + * @param y {number} Y position of the new sprite. + * @param [key] {string} The image key as defined in the Game.Cache to use as the texture for this sprite + * @param [frame] {string|number} If the sprite uses an image from a texture atlas or sprite sheet you can pass the frame here. Either a number for a frame ID or a string for a frame name. + * @param [shapeType] The default body shape is either 0 for a Box or 1 for a Circle. See Sprite.body.addShape for custom shapes (polygons, etc) + * @returns {Sprite} The newly created sprite object. + */ + function (x, y, key, frame, shapeType) { + if (typeof key === "undefined") { key = ''; } + if (typeof frame === "undefined") { frame = null; } + if (typeof shapeType === "undefined") { shapeType = 0; } + return this._world.group.add(new Phaser.Sprite(this._game, x, y, key, frame, Phaser.Types.BODY_DYNAMIC, shapeType)); + }; GameObjectFactory.prototype.dynamicTexture = /** * Create a new DynamicTexture with specific size. * @@ -12476,1111 +15066,11 @@ var Phaser; })(); Phaser.TweenManager = TweenManager; })(Phaser || (Phaser = {})); -/// -/// -/// -/// -/** -* Phaser - CircleUtils -* -* A collection of methods useful for manipulating and comparing Circle objects. -* -* TODO: -*/ -var Phaser; -(function (Phaser) { - var CircleUtils = (function () { - function CircleUtils() { } - CircleUtils.clone = /** - * Returns a new Circle object with the same values for the x, y, width, and height properties as the original Circle object. - * @method clone - * @param {Circle} a - The Circle object. - * @param {Circle} [optional] out Optional Circle object. If given the values will be set into the object, otherwise a brand new Circle object will be created and returned. - * @return {Phaser.Circle} - **/ - function clone(a, out) { - if (typeof out === "undefined") { out = new Phaser.Circle(); } - return out.setTo(a.x, a.y, a.diameter); - }; - CircleUtils.contains = /** - * Return true if the given x/y coordinates are within the Circle object. - * If you need details about the intersection then use Phaser.Intersect.circleContainsPoint instead. - * @method contains - * @param {Circle} a - The Circle object. - * @param {Number} The X value of the coordinate to test. - * @param {Number} The Y value of the coordinate to test. - * @return {Boolean} True if the coordinates are within this circle, otherwise false. - **/ - function contains(a, x, y) { - //return (a.radius * a.radius >= Collision.distanceSquared(a.x, a.y, x, y)); - return true; - }; - CircleUtils.containsPoint = /** - * Return true if the coordinates of the given Point object are within this Circle object. - * If you need details about the intersection then use Phaser.Intersect.circleContainsPoint instead. - * @method containsPoint - * @param {Circle} a - The Circle object. - * @param {Point} The Point object to test. - * @return {Boolean} True if the coordinates are within this circle, otherwise false. - **/ - function containsPoint(a, point) { - return CircleUtils.contains(a, point.x, point.y); - }; - CircleUtils.containsCircle = /** - * Return true if the given Circle is contained entirely within this Circle object. - * If you need details about the intersection then use Phaser.Intersect.circleToCircle instead. - * @method containsCircle - * @param {Circle} The Circle object to test. - * @return {Boolean} True if the coordinates are within this circle, otherwise false. - **/ - function containsCircle(a, b) { - //return ((a.radius + b.radius) * (a.radius + b.radius)) >= Collision.distanceSquared(a.x, a.y, b.x, b.y); - return true; - }; - CircleUtils.distanceBetween = /** - * Returns the distance from the center of the Circle object to the given object (can be Circle, Point or anything with x/y properties) - * @method distanceBetween - * @param {Circle} a - The Circle object. - * @param {Circle} b - The target object. Must have visible x and y properties that represent the center of the object. - * @param {Boolean} [optional] round - Round the distance to the nearest integer (default false) - * @return {Number} The distance between this Point object and the destination Point object. - **/ - function distanceBetween(a, target, round) { - if (typeof round === "undefined") { round = false; } - var dx = a.x - target.x; - var dy = a.y - target.y; - if(round === true) { - return Math.round(Math.sqrt(dx * dx + dy * dy)); - } else { - return Math.sqrt(dx * dx + dy * dy); - } - }; - CircleUtils.equals = /** - * Determines whether the two Circle objects match. This method compares the x, y and diameter properties. - * @method equals - * @param {Circle} a - The first Circle object. - * @param {Circle} b - The second Circle object. - * @return {Boolean} A value of true if the object has exactly the same values for the x, y and diameter properties as this Circle object; otherwise false. - **/ - function equals(a, b) { - return (a.x == b.x && a.y == b.y && a.diameter == b.diameter); - }; - CircleUtils.intersects = /** - * Determines whether the two Circle objects intersect. - * This method checks the radius distances between the two Circle objects to see if they intersect. - * @method intersects - * @param {Circle} a - The first Circle object. - * @param {Circle} b - The second Circle object. - * @return {Boolean} A value of true if the specified object intersects with this Circle object; otherwise false. - **/ - function intersects(a, b) { - return (CircleUtils.distanceBetween(a, b) <= (a.radius + b.radius)); - }; - CircleUtils.circumferencePoint = /** - * Returns a Point object containing the coordinates of a point on the circumference of the Circle based on the given angle. - * @method circumferencePoint - * @param {Circle} a - The first Circle object. - * @param {Number} angle The angle in radians (unless asDegrees is true) to return the point from. - * @param {Boolean} asDegrees Is the given angle in radians (false) or degrees (true)? - * @param {Phaser.Point} [optional] output An optional Point object to put the result in to. If none specified a new Point object will be created. - * @return {Phaser.Point} The Point object holding the result. - **/ - function circumferencePoint(a, angle, asDegrees, out) { - if (typeof asDegrees === "undefined") { asDegrees = false; } - if (typeof out === "undefined") { out = new Phaser.Point(); } - if(asDegrees === true) { - angle = angle * Phaser.GameMath.DEG_TO_RAD; - } - return out.setTo(a.x + a.radius * Math.cos(angle), a.y + a.radius * Math.sin(angle)); - }; - CircleUtils.intersectsRectangle = /* - public static boolean intersect(Rectangle r, Circle c) - { - float cx = Math.abs(c.x - r.x - r.halfWidth); - float xDist = r.halfWidth + c.radius; - if (cx > xDist) - return false; - float cy = Math.abs(c.y - r.y - r.halfHeight); - float yDist = r.halfHeight + c.radius; - if (cy > yDist) - return false; - if (cx <= r.halfWidth || cy <= r.halfHeight) - return true; - float xCornerDist = cx - r.halfWidth; - float yCornerDist = cy - r.halfHeight; - float xCornerDistSq = xCornerDist * xCornerDist; - float yCornerDistSq = yCornerDist * yCornerDist; - float maxCornerDistSq = c.radius * c.radius; - return xCornerDistSq + yCornerDistSq <= maxCornerDistSq; - } - */ - function intersectsRectangle(c, r) { - var cx = Math.abs(c.x - r.x - r.halfWidth); - var xDist = r.halfWidth + c.radius; - if(cx > xDist) { - return false; - } - var cy = Math.abs(c.y - r.y - r.halfHeight); - var yDist = r.halfHeight + c.radius; - if(cy > yDist) { - return false; - } - if(cx <= r.halfWidth || cy <= r.halfHeight) { - return true; - } - var xCornerDist = cx - r.halfWidth; - var yCornerDist = cy - r.halfHeight; - var xCornerDistSq = xCornerDist * xCornerDist; - var yCornerDistSq = yCornerDist * yCornerDist; - var maxCornerDistSq = c.radius * c.radius; - return xCornerDistSq + yCornerDistSq <= maxCornerDistSq; - }; - return CircleUtils; - })(); - Phaser.CircleUtils = CircleUtils; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - /// - /// - /// - /// - /// - /** - * Phaser - PhysicsManager - * - * Your game only has one PhysicsManager instance and it's responsible for looking after, creating and colliding - * all of the physics objects in the world. - */ - (function (Physics) { - var PhysicsManager = (function () { - function PhysicsManager(game, width, height) { - this._length = 0; - /** - * @type {number} - */ - this.worldDivisions = 6; - this.game = game; - this.gravity = new Phaser.Vec2(); - this.drag = new Phaser.Vec2(); - this.bounce = new Phaser.Vec2(); - this.angularDrag = 0; - this.bounds = new Phaser.Rectangle(0, 0, width, height); - this._distance = new Phaser.Vec2(); - this._tangent = new Phaser.Vec2(); - this.members = new Phaser.Group(game); - } - PhysicsManager.OVERLAP_BIAS = 4; - PhysicsManager.TILE_OVERLAP = false; - PhysicsManager.prototype.updateMotion = /* - public update() { - - this._length = this._objects.length; - - for (var i = 0; i < this._length; i++) - { - if (this._objects[i]) - { - this._objects[i].preUpdate(); - this.updateMotion(this._objects[i]); - this.collideWorld(this._objects[i]); - - for (var x = 0; x < this._length; x++) - { - if (this._objects[x] && this._objects[x] !== this._objects[i]) - { - //this.collideShapes(this._objects[i], this._objects[x]); - var r = this.NEWseparate(this._objects[i], this._objects[x]); - //console.log('sep', r); - } - } - - } - } - - } - - public render() { - - // iterate through the objects here, updating and colliding - for (var i = 0; i < this._length; i++) - { - if (this._objects[i]) - { - this._objects[i].render(this.game.stage.context); - } - } - - } - */ - function (body) { - if(body.type == Phaser.Types.BODY_DISABLED) { - return; - } - this._velocityDelta = (this.computeVelocity(body.angularVelocity, body.gravity.x, body.angularAcceleration, body.angularDrag, body.maxAngular) - body.angularVelocity) / 2; - body.angularVelocity += this._velocityDelta; - body.sprite.transform.rotation += body.angularVelocity * this.game.time.elapsed; - body.angularVelocity += this._velocityDelta; - this._velocityDelta = (this.computeVelocity(body.velocity.x, body.gravity.x, body.acceleration.x, body.drag.x) - body.velocity.x) / 2; - body.velocity.x += this._velocityDelta; - this._delta = body.velocity.x * this.game.time.elapsed; - body.velocity.x += this._velocityDelta; - //body.position.x += this._delta; - body.sprite.x += this._delta; - this._velocityDelta = (this.computeVelocity(body.velocity.y, body.gravity.y, body.acceleration.y, body.drag.y) - body.velocity.y) / 2; - body.velocity.y += this._velocityDelta; - this._delta = body.velocity.y * this.game.time.elapsed; - body.velocity.y += this._velocityDelta; - //body.position.y += this._delta; - body.sprite.y += this._delta; - }; - PhysicsManager.prototype.computeVelocity = /** - * A tween-like function that takes a starting velocity and some other factors and returns an altered velocity. - * - * @param {number} Velocity Any component of velocity (e.g. 20). - * @param {number} Acceleration Rate at which the velocity is changing. - * @param {number} Drag Really kind of a deceleration, this is how much the velocity changes if Acceleration is not set. - * @param {number} Max An absolute value cap for the velocity. - * - * @return {number} The altered Velocity value. - */ - function (velocity, gravity, acceleration, drag, max) { - if (typeof gravity === "undefined") { gravity = 0; } - if (typeof acceleration === "undefined") { acceleration = 0; } - if (typeof drag === "undefined") { drag = 0; } - if (typeof max === "undefined") { max = 10000; } - if(acceleration !== 0) { - velocity += (acceleration + gravity) * this.game.time.elapsed; - } else if(drag !== 0) { - this._drag = drag * this.game.time.elapsed; - if(velocity - this._drag > 0) { - velocity = velocity - this._drag; - } else if(velocity + this._drag < 0) { - velocity += this._drag; - } else { - velocity = 0; - } - velocity += gravity; - } - if((velocity != 0) && (max != 10000)) { - if(velocity > max) { - velocity = max; - } else if(velocity < -max) { - velocity = -max; - } - } - return velocity; - }; - PhysicsManager.prototype.separate = /** - * The core Collision separation method. - * @param body1 The first Physics.Body to separate - * @param body2 The second Physics.Body to separate - * @returns {boolean} Returns true if the bodies were separated, otherwise false. - */ - function (body1, body2) { - this._separatedX = this.separateBodyX(body1, body2); - this._separatedY = this.separateBodyY(body1, body2); - return this._separatedX || this._separatedY; - }; - PhysicsManager.prototype.checkHullIntersection = function (body1, body2) { - return ((body1.hullX + body1.hullWidth > body2.hullX) && (body1.hullX < body2.hullX + body2.hullWidth) && (body1.hullY + body1.hullHeight > body2.hullY) && (body1.hullY < body2.hullY + body2.hullHeight)); - }; - PhysicsManager.prototype.separateBodyX = /** - * Separates the two objects on their x axis - * @param object1 The first GameObject to separate - * @param object2 The second GameObject to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the X axis. - */ - function (body1, body2) { - // Can't separate two disabled or static objects - if((body1.type == Phaser.Types.BODY_DISABLED || body1.type == Phaser.Types.BODY_STATIC) && (body2.type == Phaser.Types.BODY_DISABLED || body2.type == Phaser.Types.BODY_STATIC)) { - return false; - } - // First, get the two object deltas - this._overlap = 0; - if(body1.deltaX != body2.deltaX) { - if(Phaser.RectangleUtils.intersects(body1.bounds, body2.bounds)) { - this._maxOverlap = body1.deltaXAbs + body2.deltaXAbs + PhysicsManager.OVERLAP_BIAS; - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if(body1.deltaX > body2.deltaX) { - this._overlap = body1.bounds.right - body2.bounds.x; - if((this._overlap > this._maxOverlap) || !(body1.allowCollisions & Phaser.Types.RIGHT) || !(body2.allowCollisions & Phaser.Types.LEFT)) { - this._overlap = 0; - } else { - body1.touching |= Phaser.Types.RIGHT; - body2.touching |= Phaser.Types.LEFT; - } - } else if(body1.deltaX < body2.deltaX) { - this._overlap = body1.bounds.x - body2.bounds.width - body2.bounds.x; - if((-this._overlap > this._maxOverlap) || !(body1.allowCollisions & Phaser.Types.LEFT) || !(body2.allowCollisions & Phaser.Types.RIGHT)) { - this._overlap = 0; - } else { - body1.touching |= Phaser.Types.LEFT; - body2.touching |= Phaser.Types.RIGHT; - } - } - } - } - // Then adjust their positions and velocities accordingly (if there was any overlap) - if(this._overlap != 0) { - this._obj1Velocity = body1.velocity.x; - this._obj2Velocity = body2.velocity.x; - /** - * Dynamic = gives and receives impacts - * Static = gives but doesn't receive impacts, cannot be moved by physics - * Kinematic = gives impacts, but never receives, can be moved by physics - */ - // 2 dynamic bodies will exchange velocities - if(body1.type == Phaser.Types.BODY_DYNAMIC && body2.type == Phaser.Types.BODY_DYNAMIC) { - this._overlap *= 0.5; - body1.position.x = body1.position.x - this._overlap; - body2.position.x += this._overlap; - this._obj1NewVelocity = Math.sqrt((this._obj2Velocity * this._obj2Velocity * body2.mass) / body1.mass) * ((this._obj2Velocity > 0) ? 1 : -1); - this._obj2NewVelocity = Math.sqrt((this._obj1Velocity * this._obj1Velocity * body1.mass) / body2.mass) * ((this._obj1Velocity > 0) ? 1 : -1); - this._average = (this._obj1NewVelocity + this._obj2NewVelocity) * 0.5; - this._obj1NewVelocity -= this._average; - this._obj2NewVelocity -= this._average; - body1.velocity.x = this._average + this._obj1NewVelocity * body1.bounce.x; - body2.velocity.x = this._average + this._obj2NewVelocity * body2.bounce.x; - } else if(body2.type != Phaser.Types.BODY_DYNAMIC) { - // Body 2 is Static or Kinematic - this._overlap *= 2; - body1.position.x -= this._overlap; - body1.velocity.x = this._obj2Velocity - this._obj1Velocity * body1.bounce.x; - } else if(body1.type != Phaser.Types.BODY_DYNAMIC) { - // Body 1 is Static or Kinematic - this._overlap *= 2; - body2.position.x += this._overlap; - body2.velocity.x = this._obj1Velocity - this._obj2Velocity * body2.bounce.x; - } - return true; - } else { - return false; - } - }; - PhysicsManager.prototype.separateBodyY = /** - * Separates the two objects on their y axis - * @param object1 The first GameObject to separate - * @param object2 The second GameObject to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis. - */ - function (body1, body2) { - // Can't separate two immovable objects - if((body1.type == Phaser.Types.BODY_DISABLED || body1.type == Phaser.Types.BODY_STATIC) && (body2.type == Phaser.Types.BODY_DISABLED || body2.type == Phaser.Types.BODY_STATIC)) { - return false; - } - // First, get the two object deltas - this._overlap = 0; - if(body1.deltaY != body2.deltaY) { - if(Phaser.RectangleUtils.intersects(body1.bounds, body2.bounds)) { - // This is the only place to use the DeltaAbs values - this._maxOverlap = body1.deltaYAbs + body2.deltaYAbs + PhysicsManager.OVERLAP_BIAS; - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if(body1.deltaY > body2.deltaY) { - this._overlap = body1.bounds.bottom - body2.bounds.y; - if((this._overlap > this._maxOverlap) || !(body1.allowCollisions & Phaser.Types.DOWN) || !(body2.allowCollisions & Phaser.Types.UP)) { - this._overlap = 0; - } else { - body1.touching |= Phaser.Types.DOWN; - body2.touching |= Phaser.Types.UP; - } - } else if(body1.deltaY < body2.deltaY) { - this._overlap = body1.bounds.y - body2.bounds.height - body2.bounds.y; - if((-this._overlap > this._maxOverlap) || !(body1.allowCollisions & Phaser.Types.UP) || !(body2.allowCollisions & Phaser.Types.DOWN)) { - this._overlap = 0; - } else { - body1.touching |= Phaser.Types.UP; - body2.touching |= Phaser.Types.DOWN; - } - } - } - } - // Then adjust their positions and velocities accordingly (if there was any overlap) - if(this._overlap != 0) { - this._obj1Velocity = body1.velocity.y; - this._obj2Velocity = body2.velocity.y; - /** - * Dynamic = gives and receives impacts - * Static = gives but doesn't receive impacts, cannot be moved by physics - * Kinematic = gives impacts, but never receives, can be moved by physics - */ - if(body1.type == Phaser.Types.BODY_DYNAMIC && body2.type == Phaser.Types.BODY_DYNAMIC) { - this._overlap *= 0.5; - body1.position.y = body1.position.y - this._overlap; - body2.position.y += this._overlap; - this._obj1NewVelocity = Math.sqrt((this._obj2Velocity * this._obj2Velocity * body2.mass) / body1.mass) * ((this._obj2Velocity > 0) ? 1 : -1); - this._obj2NewVelocity = Math.sqrt((this._obj1Velocity * this._obj1Velocity * body1.mass) / body2.mass) * ((this._obj1Velocity > 0) ? 1 : -1); - var average = (this._obj1NewVelocity + this._obj2NewVelocity) * 0.5; - this._obj1NewVelocity -= average; - this._obj2NewVelocity -= average; - body1.velocity.y = average + this._obj1NewVelocity * body1.bounce.y; - body2.velocity.y = average + this._obj2NewVelocity * body2.bounce.y; - } else if(body2.type != Phaser.Types.BODY_DYNAMIC) { - this._overlap *= 2; - body1.position.y -= this._overlap; - body1.velocity.y = this._obj2Velocity - this._obj1Velocity * body1.bounce.y; - // This is special case code that handles things like horizontal moving platforms you can ride - //if (body2.parent.active && body2.moves && (body1.deltaY > body2.deltaY)) - if(body2.sprite.active && (body1.deltaY > body2.deltaY)) { - body1.position.x += body2.position.x - body2.oldPosition.x; - } - } else if(body1.type != Phaser.Types.BODY_DYNAMIC) { - this._overlap *= 2; - body2.position.y += this._overlap; - body2.velocity.y = this._obj1Velocity - this._obj2Velocity * body2.bounce.y; - // This is special case code that handles things like horizontal moving platforms you can ride - //if (object1.active && body1.moves && (body1.deltaY < body2.deltaY)) - if(body1.sprite.active && (body1.deltaY < body2.deltaY)) { - body2.position.x += body1.position.x - body1.oldPosition.x; - } - } - return true; - } else { - return false; - } - }; - PhysicsManager.prototype.overlap = /* - private TILEseparate(shapeA: IPhysicsShape, shapeB: IPhysicsShape, distance: Vec2, tangent: Vec2) { - - if (tangent.x == 1) - { - console.log('1 The left side of ShapeA hit the right side of ShapeB', Math.floor(distance.x)); - shapeA.physics.touching |= Phaser.Types.LEFT; - shapeB.physics.touching |= Phaser.Types.RIGHT; - } - else if (tangent.x == -1) - { - console.log('2 The right side of ShapeA hit the left side of ShapeB', Math.floor(distance.x)); - shapeA.physics.touching |= Phaser.Types.RIGHT; - shapeB.physics.touching |= Phaser.Types.LEFT; - } - - if (tangent.y == 1) - { - console.log('3 The top of ShapeA hit the bottom of ShapeB', Math.floor(distance.y)); - shapeA.physics.touching |= Phaser.Types.UP; - shapeB.physics.touching |= Phaser.Types.DOWN; - } - else if (tangent.y == -1) - { - console.log('4 The bottom of ShapeA hit the top of ShapeB', Math.floor(distance.y)); - shapeA.physics.touching |= Phaser.Types.DOWN; - shapeB.physics.touching |= Phaser.Types.UP; - } - - - // only apply collision response forces if the object is travelling into, and not out of, the collision - var dot = Vec2Utils.dot(shapeA.physics.velocity, tangent); - - if (dot < 0) - { - console.log('in to', dot); - - // Apply horizontal bounce - if (shapeA.physics.bounce.x > 0) - { - shapeA.physics.velocity.x *= -(shapeA.physics.bounce.x); - } - else - { - shapeA.physics.velocity.x = 0; - } - // Apply horizontal bounce - if (shapeA.physics.bounce.y > 0) - { - shapeA.physics.velocity.y *= -(shapeA.physics.bounce.y); - } - else - { - shapeA.physics.velocity.y = 0; - } - } - else - { - console.log('out of', dot); - } - - shapeA.position.x += Math.floor(distance.x); - //shapeA.bounds.x += Math.floor(distance.x); - - shapeA.position.y += Math.floor(distance.y); - //shapeA.bounds.y += distance.y; - - console.log('------------------------------------------------'); - - } - - private collideWorld(shape:IPhysicsShape) { - - // Collide on the x-axis - this._distance.x = shape.world.bounds.x - (shape.position.x - shape.bounds.halfWidth); - - if (0 < this._distance.x) - { - // Hit Left - this._tangent.setTo(1, 0); - this.separateXWall(shape, this._distance, this._tangent); - } - else - { - this._distance.x = (shape.position.x + shape.bounds.halfWidth) - shape.world.bounds.right; - - if (0 < this._distance.x) - { - // Hit Right - this._tangent.setTo(-1, 0); - this._distance.reverse(); - this.separateXWall(shape, this._distance, this._tangent); - } - } - - // Collide on the y-axis - this._distance.y = shape.world.bounds.y - (shape.position.y - shape.bounds.halfHeight); - - if (0 < this._distance.y) - { - // Hit Top - this._tangent.setTo(0, 1); - this.separateYWall(shape, this._distance, this._tangent); - } - else - { - this._distance.y = (shape.position.y + shape.bounds.halfHeight) - shape.world.bounds.bottom; - - if (0 < this._distance.y) - { - // Hit Bottom - this._tangent.setTo(0, -1); - this._distance.reverse(); - this.separateYWall(shape, this._distance, this._tangent); - } - } - - } - - private separateX(shapeA: IPhysicsShape, shapeB: IPhysicsShape, distance: Vec2, tangent: Vec2) { - - if (tangent.x == 1) - { - console.log('The left side of ShapeA hit the right side of ShapeB', distance.x); - shapeA.physics.touching |= Phaser.Types.LEFT; - shapeB.physics.touching |= Phaser.Types.RIGHT; - } - else - { - console.log('The right side of ShapeA hit the left side of ShapeB', distance.x); - shapeA.physics.touching |= Phaser.Types.RIGHT; - shapeB.physics.touching |= Phaser.Types.LEFT; - } - - // collision edges - //shapeA.oH = tangent.x; - - // only apply collision response forces if the object is travelling into, and not out of, the collision - if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) - { - // Apply horizontal bounce - if (shapeA.physics.bounce.x > 0) - { - shapeA.physics.velocity.x *= -(shapeA.physics.bounce.x); - } - else - { - shapeA.physics.velocity.x = 0; - } - } - - shapeA.position.x += distance.x; - shapeA.bounds.x += distance.x; - - } - - private separateY(shapeA: IPhysicsShape, shapeB: IPhysicsShape, distance: Vec2, tangent: Vec2) { - - if (tangent.y == 1) - { - console.log('The top of ShapeA hit the bottom of ShapeB', distance.y); - shapeA.physics.touching |= Phaser.Types.UP; - shapeB.physics.touching |= Phaser.Types.DOWN; - } - else - { - console.log('The bottom of ShapeA hit the top of ShapeB', distance.y); - shapeA.physics.touching |= Phaser.Types.DOWN; - shapeB.physics.touching |= Phaser.Types.UP; - } - - // collision edges - //shapeA.oV = tangent.y; - - // only apply collision response forces if the object is travelling into, and not out of, the collision - if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) - { - // Apply horizontal bounce - if (shapeA.physics.bounce.y > 0) - { - shapeA.physics.velocity.y *= -(shapeA.physics.bounce.y); - } - else - { - shapeA.physics.velocity.y = 0; - } - } - - shapeA.position.y += distance.y; - shapeA.bounds.y += distance.y; - - } - - private separateXWall(shapeA: IPhysicsShape, distance: Vec2, tangent: Vec2) { - - if (tangent.x == 1) - { - console.log('The left side of ShapeA hit the right side of ShapeB', distance.x); - shapeA.physics.touching |= Phaser.Types.LEFT; - } - else - { - console.log('The right side of ShapeA hit the left side of ShapeB', distance.x); - shapeA.physics.touching |= Phaser.Types.RIGHT; - } - - // collision edges - //shapeA.oH = tangent.x; - - // only apply collision response forces if the object is travelling into, and not out of, the collision - if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) - { - // Apply horizontal bounce - if (shapeA.physics.bounce.x > 0) - { - shapeA.physics.velocity.x *= -(shapeA.physics.bounce.x); - } - else - { - shapeA.physics.velocity.x = 0; - } - } - - shapeA.position.x += distance.x; - - } - - private separateYWall(shapeA: IPhysicsShape, distance: Vec2, tangent: Vec2) { - - if (tangent.y == 1) - { - console.log('The top of ShapeA hit the bottom of ShapeB', distance.y); - shapeA.physics.touching |= Phaser.Types.UP; - } - else - { - console.log('The bottom of ShapeA hit the top of ShapeB', distance.y); - shapeA.physics.touching |= Phaser.Types.DOWN; - } - - // collision edges - //shapeA.oV = tangent.y; - - // only apply collision response forces if the object is travelling into, and not out of, the collision - if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) - { - // Apply horizontal bounce - if (shapeA.physics.bounce.y > 0) - { - shapeA.physics.velocity.y *= -(shapeA.physics.bounce.y); - } - else - { - shapeA.physics.velocity.y = 0; - } - } - - shapeA.position.y += distance.y; - - } - */ - /** - * Checks for overlaps between two objects using the world QuadTree. Can be Sprite vs. Sprite, Sprite vs. Group or Group vs. Group. - * Note: Does not take the objects scrollFactor into account. All overlaps are check in world space. - * @param object1 The first Sprite or Group to check. If null the world.group is used. - * @param object2 The second Sprite or Group to check. - * @param notifyCallback A callback function that is called if the objects overlap. The two objects will be passed to this function in the same order in which you passed them to Collision.overlap. - * @param processCallback A callback function that lets you perform additional checks against the two objects if they overlap. If this is set then notifyCallback will only be called if processCallback returns true. - * @param context The context in which the callbacks will be called - * @returns {boolean} true if the objects overlap, otherwise false. - */ - function (object1, object2, notifyCallback, processCallback, context) { - if (typeof object1 === "undefined") { object1 = null; } - if (typeof object2 === "undefined") { object2 = null; } - if (typeof notifyCallback === "undefined") { notifyCallback = null; } - if (typeof processCallback === "undefined") { processCallback = null; } - if (typeof context === "undefined") { context = null; } - if(object1 == null) { - object1 = this.game.world.group; - } - if(object2 == object1) { - object2 = null; - } - Phaser.QuadTree.divisions = this.worldDivisions; - this._quadTree = new Phaser.QuadTree(this, this.bounds.x, this.bounds.y, this.bounds.width, this.bounds.height); - this._quadTree.load(object1, object2, notifyCallback, processCallback, context); - this._quadTreeResult = this._quadTree.execute(); - console.log('over', this._quadTreeResult); - this._quadTree.destroy(); - this._quadTree = null; - return this._quadTreeResult; - }; - PhysicsManager.prototype.separateTile = /** - * Collision resolution specifically for GameObjects vs. Tiles. - * @param object The GameObject to separate - * @param tile The Tile to separate - * @returns {boolean} Whether the objects in fact touched and were separated - */ - function (object, x, y, width, height, mass, collideLeft, collideRight, collideUp, collideDown, separateX, separateY) { - //var separatedX: bool = this.separateTileX(object, x, y, width, height, mass, collideLeft, collideRight, separateX); - //var separatedY: bool = this.separateTileY(object, x, y, width, height, mass, collideUp, collideDown, separateY); - //return separatedX || separatedY; - return false; - }; - return PhysicsManager; - })(); - Physics.PhysicsManager = PhysicsManager; - /** - * Separates the two objects on their x axis - * @param object The GameObject to separate - * @param tile The Tile to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the X axis. - */ - /* - public separateTileX(object:Sprite, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool, separate: bool): bool { - - // Can't separate two immovable objects (tiles are always immovable) - if (object.immovable) - { - return false; - } - - // First, get the object delta - var overlap: number = 0; - var objDelta: number = object.x - object.last.x; - //var objDelta: number = object.collisionMask.deltaX; - - if (objDelta != 0) - { - // Check if the X hulls actually overlap - var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; - //var objDeltaAbs: number = object.collisionMask.deltaXAbs; - var objBounds: Rectangle = new Rectangle(object.x - ((objDelta > 0) ? objDelta : 0), object.last.y, object.width + ((objDelta > 0) ? objDelta : -objDelta), object.height); - - if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) - { - var maxOverlap: number = objDeltaAbs + Collision.OVERLAP_BIAS; - - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if (objDelta > 0) - { - overlap = object.x + object.width - x; - - if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.RIGHT) || collideLeft == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.RIGHT; - } - } - else if (objDelta < 0) - { - overlap = object.x - width - x; - - if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.LEFT) || collideRight == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.LEFT; - } - - } - - } - } - - // Then adjust their positions and velocities accordingly (if there was any overlap) - if (overlap != 0) - { - if (separate == true) - { - //console.log(' - object.x = object.x - overlap; - object.velocity.x = -(object.velocity.x * object.elasticity); - } - - Collision.TILE_OVERLAP = true; - return true; - } - else - { - return false; - } - - } - */ - /** - * Separates the two objects on their y axis - * @param object The first GameObject to separate - * @param tile The second GameObject to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis. - */ - /* - public separateTileY(object: Sprite, x: number, y: number, width: number, height: number, mass: number, collideUp: bool, collideDown: bool, separate: bool): bool { - - // Can't separate two immovable objects (tiles are always immovable) - if (object.immovable) - { - return false; - } - - // First, get the two object deltas - var overlap: number = 0; - var objDelta: number = object.y - object.last.y; - - if (objDelta != 0) - { - // Check if the Y hulls actually overlap - var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; - var objBounds: Rectangle = new Rectangle(object.x, object.y - ((objDelta > 0) ? objDelta : 0), object.width, object.height + objDeltaAbs); - - if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) - { - var maxOverlap: number = objDeltaAbs + Collision.OVERLAP_BIAS; - - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if (objDelta > 0) - { - overlap = object.y + object.height - y; - - if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.DOWN) || collideUp == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.DOWN; - } - } - else if (objDelta < 0) - { - overlap = object.y - height - y; - - if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.UP) || collideDown == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.UP; - } - } - } - } - - // TODO - with super low velocities you get lots of stuttering, set some kind of base minimum here - - // Then adjust their positions and velocities accordingly (if there was any overlap) - if (overlap != 0) - { - if (separate == true) - { - object.y = object.y - overlap; - object.velocity.y = -(object.velocity.y * object.elasticity); - } - - Collision.TILE_OVERLAP = true; - return true; - } - else - { - return false; - } - } - */ - /** - * Separates the two objects on their x axis - * @param object The GameObject to separate - * @param tile The Tile to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the X axis. - */ - /* - public static NEWseparateTileX(object:Sprite, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool, separate: bool): bool { - - // Can't separate two immovable objects (tiles are always immovable) - if (object.immovable) - { - return false; - } - - // First, get the object delta - var overlap: number = 0; - - if (object.collisionMask.deltaX != 0) - { - // Check if the X hulls actually overlap - //var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; - //var objBounds: Rectangle = new Rectangle(object.x - ((objDelta > 0) ? objDelta : 0), object.last.y, object.width + ((objDelta > 0) ? objDelta : -objDelta), object.height); - - //if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) - if (object.collisionMask.intersectsRaw(x, x + width, y, y + height)) - { - var maxOverlap: number = object.collisionMask.deltaXAbs + Collision.OVERLAP_BIAS; - - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if (object.collisionMask.deltaX > 0) - { - //overlap = object.x + object.width - x; - overlap = object.collisionMask.right - x; - - if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.RIGHT) || collideLeft == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.RIGHT; - } - } - else if (object.collisionMask.deltaX < 0) - { - //overlap = object.x - width - x; - overlap = object.collisionMask.x - width - x; - - if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.LEFT) || collideRight == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.LEFT; - } - - } - - } - } - - // Then adjust their positions and velocities accordingly (if there was any overlap) - if (overlap != 0) - { - if (separate == true) - { - object.x = object.x - overlap; - object.velocity.x = -(object.velocity.x * object.elasticity); - } - - Collision.TILE_OVERLAP = true; - return true; - } - else - { - return false; - } - - } - */ - /** - * Separates the two objects on their y axis - * @param object The first GameObject to separate - * @param tile The second GameObject to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis. - */ - /* - public NEWseparateTileY(object: Sprite, x: number, y: number, width: number, height: number, mass: number, collideUp: bool, collideDown: bool, separate: bool): bool { - - // Can't separate two immovable objects (tiles are always immovable) - if (object.immovable) - { - return false; - } - - // First, get the two object deltas - var overlap: number = 0; - //var objDelta: number = object.y - object.last.y; - - if (object.collisionMask.deltaY != 0) - { - // Check if the Y hulls actually overlap - //var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; - //var objBounds: Rectangle = new Rectangle(object.x, object.y - ((objDelta > 0) ? objDelta : 0), object.width, object.height + objDeltaAbs); - - //if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) - if (object.collisionMask.intersectsRaw(x, x + width, y, y + height)) - { - //var maxOverlap: number = objDeltaAbs + Collision.OVERLAP_BIAS; - var maxOverlap: number = object.collisionMask.deltaYAbs + Collision.OVERLAP_BIAS; - - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if (object.collisionMask.deltaY > 0) - { - //overlap = object.y + object.height - y; - overlap = object.collisionMask.bottom - y; - - if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.DOWN) || collideUp == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.DOWN; - } - } - else if (object.collisionMask.deltaY < 0) - { - //overlap = object.y - height - y; - overlap = object.collisionMask.y - height - y; - - if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.UP) || collideDown == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.UP; - } - } - } - } - - // TODO - with super low velocities you get lots of stuttering, set some kind of base minimum here - - // Then adjust their positions and velocities accordingly (if there was any overlap) - if (overlap != 0) - { - if (separate == true) - { - object.y = object.y - overlap; - object.velocity.y = -(object.velocity.y * object.elasticity); - } - - Collision.TILE_OVERLAP = true; - return true; - } - else - { - return false; - } - } - */ - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); /// /// /// /// -/// +/// /** * Phaser - World * @@ -13618,13 +15108,11 @@ var Phaser; */ function () { this.group = new Phaser.Group(this._game, 0); - this.physics = new Phaser.Physics.PhysicsManager(this._game, this.width, this.height); }; World.prototype.update = /** * This is called automatically every frame, and is where main logic happens. */ function () { - //this.physics.update(); this.group.update(); this.cameras.update(); }; @@ -13632,7 +15120,6 @@ var Phaser; * This is called automatically every frame, and is where main logic happens. */ function () { - //this.physics.postUpdate(); this.group.postUpdate(); this.cameras.postUpdate(); }; @@ -13640,7 +15127,6 @@ var Phaser; * Clean up memory. */ function () { - //this.physics.destroy(); this.group.destroy(); this.cameras.destroy(); }; @@ -13651,17 +15137,13 @@ var Phaser; * @param height {number} New height of the world. * @param [updateCameraBounds] {boolean} Update camera bounds automatically or not. Default to true. */ - function (width, height, updateCameraBounds, updatePhysicsBounds) { + function (width, height, updateCameraBounds) { if (typeof updateCameraBounds === "undefined") { updateCameraBounds = true; } - if (typeof updatePhysicsBounds === "undefined") { updatePhysicsBounds = true; } this.bounds.width = width; this.bounds.height = height; if(updateCameraBounds == true) { this._game.camera.setBounds(0, 0, width, height); } - if(updatePhysicsBounds == true) { - //this.physics.bounds.copyFrom(this.bounds); - } // dispatch world resize event }; Object.defineProperty(World.prototype, "width", { @@ -13789,14 +15271,19 @@ var Phaser; * @param {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically */ function (source, dest, speed, xSpeedMax, ySpeedMax) { - var a = this.angleBetween(source, dest); + /* + var a: number = this.angleBetween(source, dest); + source.body.velocity.x = 0; source.body.velocity.y = 0; + source.body.acceleration.x = Math.cos(a) * speed; source.body.acceleration.y = Math.sin(a) * speed; + source.body.maxVelocity.x = xSpeedMax; source.body.maxVelocity.y = ySpeedMax; - }; + */ + }; Motion.prototype.moveTowardsMouse = /** * Move the given Sprite towards the mouse pointer coordinates at a steady velocity * If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds.
@@ -13830,14 +15317,19 @@ var Phaser; * @param {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically */ function (source, speed, xSpeedMax, ySpeedMax) { - var a = this.angleBetweenMouse(source); + /* + var a: number = this.angleBetweenMouse(source); + source.body.velocity.x = 0; source.body.velocity.y = 0; + source.body.acceleration.x = Math.cos(a) * speed; source.body.acceleration.y = Math.sin(a) * speed; + source.body.maxVelocity.x = xSpeedMax; source.body.maxVelocity.y = ySpeedMax; - }; + */ + }; Motion.prototype.moveTowardsPoint = /** * Sets the x/y velocity on the source Sprite so it will move towards the target coordinates at the speed given (in pixels per second)
* If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds.
@@ -13873,14 +15365,19 @@ var Phaser; * @param {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically */ function (source, target, speed, xSpeedMax, ySpeedMax) { - var a = this.angleBetweenPoint(source, target); + /* + var a: number = this.angleBetweenPoint(source, target); + source.body.velocity.x = 0; source.body.velocity.y = 0; + source.body.acceleration.x = Math.cos(a) * speed; source.body.acceleration.y = Math.sin(a) * speed; + source.body.maxVelocity.x = xSpeedMax; source.body.maxVelocity.y = ySpeedMax; - }; + */ + }; Motion.prototype.distanceBetween = /** * Find the distance between two Sprites, taking their origin into account * @@ -13963,17 +15460,29 @@ var Phaser; * @return {Point} An Point where Point.x contains the velocity x value and Point.y contains the velocity y value */ function (parent, speed) { - var a; - if(parent.body.facing == Phaser.Types.LEFT) { - a = this.game.math.degreesToRadians(180); - } else if(parent.body.facing == Phaser.Types.RIGHT) { - a = this.game.math.degreesToRadians(0); - } else if(parent.body.facing == Phaser.Types.UP) { - a = this.game.math.degreesToRadians(-90); - } else if(parent.body.facing == Phaser.Types.DOWN) { - a = this.game.math.degreesToRadians(90); + /* + var a: number; + + if (parent.body.facing == Types.LEFT) + { + a = this.game.math.degreesToRadians(180); } - return new Phaser.Point(Math.cos(a) * speed, Math.sin(a) * speed); + else if (parent.body.facing == Types.RIGHT) + { + a = this.game.math.degreesToRadians(0); + } + else if (parent.body.facing == Types.UP) + { + a = this.game.math.degreesToRadians(-90); + } + else if (parent.body.facing == Types.DOWN) + { + a = this.game.math.degreesToRadians(90); + } + + return new Point(Math.cos(a) * speed, Math.sin(a) * speed); + */ + return new Phaser.Point(); }; Motion.prototype.angleBetweenMouse = /** * Find the angle (in radians) between an Sprite and the mouse, taking their x/y and origin into account. @@ -17064,14 +18573,14 @@ var Phaser; */ function renderSpriteInfo(sprite, x, y, color) { if (typeof color === "undefined") { color = 'rgb(255,255,255)'; } - DebugUtils.game.stage.context.fillStyle = color; - DebugUtils.game.stage.context.fillText('Sprite: ' + ' (' + sprite.width + ' x ' + sprite.height + ') origin: ' + sprite.transform.origin.x + ' x ' + sprite.transform.origin.y, x, y); - DebugUtils.game.stage.context.fillText('x: ' + sprite.x.toFixed(1) + ' y: ' + sprite.y.toFixed(1) + ' rotation: ' + sprite.rotation.toFixed(1), x, y + 14); - DebugUtils.game.stage.context.fillText('wx: ' + sprite.worldView.x + ' wy: ' + sprite.worldView.y + ' ww: ' + sprite.worldView.width.toFixed(1) + ' wh: ' + sprite.worldView.height.toFixed(1) + ' wb: ' + sprite.worldView.bottom + ' wr: ' + sprite.worldView.right, x, y + 28); - DebugUtils.game.stage.context.fillText('sx: ' + sprite.transform.scale.x.toFixed(1) + ' sy: ' + sprite.transform.scale.y.toFixed(1), x, y + 42); - DebugUtils.game.stage.context.fillText('tx: ' + sprite.texture.width.toFixed(1) + ' ty: ' + sprite.texture.height.toFixed(1), x, y + 56); - DebugUtils.game.stage.context.fillText('cx: ' + sprite.cameraView.x + ' cy: ' + sprite.cameraView.y + ' cw: ' + sprite.cameraView.width + ' ch: ' + sprite.cameraView.height + ' cb: ' + sprite.cameraView.bottom + ' cr: ' + sprite.cameraView.right, x, y + 70); - DebugUtils.game.stage.context.fillText('inCamera: ' + DebugUtils.game.renderer.inCamera(DebugUtils.game.camera, sprite), x, y + 84); + DebugUtils.context.fillStyle = color; + DebugUtils.context.fillText('Sprite: ' + ' (' + sprite.width + ' x ' + sprite.height + ') origin: ' + sprite.transform.origin.x + ' x ' + sprite.transform.origin.y, x, y); + DebugUtils.context.fillText('x: ' + sprite.x.toFixed(1) + ' y: ' + sprite.y.toFixed(1) + ' rotation: ' + sprite.rotation.toFixed(1), x, y + 14); + DebugUtils.context.fillText('wx: ' + sprite.worldView.x + ' wy: ' + sprite.worldView.y + ' ww: ' + sprite.worldView.width.toFixed(1) + ' wh: ' + sprite.worldView.height.toFixed(1) + ' wb: ' + sprite.worldView.bottom + ' wr: ' + sprite.worldView.right, x, y + 28); + DebugUtils.context.fillText('sx: ' + sprite.transform.scale.x.toFixed(1) + ' sy: ' + sprite.transform.scale.y.toFixed(1), x, y + 42); + DebugUtils.context.fillText('tx: ' + sprite.texture.width.toFixed(1) + ' ty: ' + sprite.texture.height.toFixed(1), x, y + 56); + DebugUtils.context.fillText('cx: ' + sprite.cameraView.x + ' cy: ' + sprite.cameraView.y + ' cw: ' + sprite.cameraView.width + ' ch: ' + sprite.cameraView.height + ' cb: ' + sprite.cameraView.bottom + ' cr: ' + sprite.cameraView.right, x, y + 70); + DebugUtils.context.fillText('inCamera: ' + DebugUtils.game.renderer.inCamera(DebugUtils.game.camera, sprite), x, y + 84); }; DebugUtils.renderSpriteBounds = function renderSpriteBounds(sprite, camera, color) { if (typeof camera === "undefined") { camera = null; } @@ -17079,23 +18588,36 @@ var Phaser; if(camera == null) { camera = DebugUtils.game.camera; } - //var dx = (camera.screenView.x * sprite.transform.scrollFactor.x) + sprite.x - (camera.worldView.x * sprite.transform.scrollFactor.x); - //var dy = (camera.screenView.y * sprite.transform.scrollFactor.y) + sprite.y - (camera.worldView.y * sprite.transform.scrollFactor.y); var dx = sprite.worldView.x; var dy = sprite.worldView.y; - DebugUtils.game.stage.context.fillStyle = color; - DebugUtils.game.stage.context.fillRect(dx, dy, sprite.width, sprite.height); + DebugUtils.context.fillStyle = color; + DebugUtils.context.fillRect(dx, dy, sprite.width, sprite.height); }; - DebugUtils.renderSpritePhysicsBody = function renderSpritePhysicsBody(sprite, camera, color) { - if (typeof camera === "undefined") { camera = null; } - if (typeof color === "undefined") { color = 'rgba(255,0,0,0.2)'; } - if(camera == null) { - camera = DebugUtils.game.camera; + DebugUtils.renderPhysicsBody = function renderPhysicsBody(body, lineWidth, fillStyle, sleepStyle) { + if (typeof lineWidth === "undefined") { lineWidth = 1; } + if (typeof fillStyle === "undefined") { fillStyle = 'rgba(0,255,0,0.2)'; } + if (typeof sleepStyle === "undefined") { sleepStyle = 'rgba(100,100,100,0.2)'; } + for(var s = 0; s < body.shapes.length; s++) { + DebugUtils.context.beginPath(); + if(body.shapes[s].type == Phaser.Physics.Manager.SHAPE_TYPE_POLY) { + var verts = body.shapes[s].tverts; + DebugUtils.context.moveTo((body.position.x + verts[0].x) * 50, (body.position.y + verts[0].y) * 50); + for(var i = 0; i < verts.length; i++) { + DebugUtils.context.lineTo((body.position.x + verts[i].x) * 50, (body.position.y + verts[i].y) * 50); + } + DebugUtils.context.lineTo((body.position.x + verts[verts.length - 1].x) * 50, (body.position.y + verts[verts.length - 1].y) * 50); + } else if(body.shapes[s].type == Phaser.Physics.Manager.SHAPE_TYPE_CIRCLE) { + var circle = body.shapes[s]; + DebugUtils.context.arc(circle.tc.x * 50, circle.tc.y * 50, circle.radius * 50, 0, Math.PI * 2, false); + } + DebugUtils.context.closePath(); + if(body.isAwake) { + DebugUtils.context.fillStyle = fillStyle; + } else { + DebugUtils.context.fillStyle = sleepStyle; + } + DebugUtils.context.fill(); } - var dx = (camera.screenView.x * sprite.transform.scrollFactor.x) + sprite.body.x - (camera.worldView.x * sprite.transform.scrollFactor.x); - var dy = (camera.screenView.y * sprite.transform.scrollFactor.y) + sprite.body.y - (camera.worldView.y * sprite.transform.scrollFactor.y); - DebugUtils.game.stage.context.fillStyle = color; - DebugUtils.game.stage.context.fillRect(dx, dy, sprite.body.width, sprite.body.height); }; return DebugUtils; })(); @@ -17167,16 +18689,6 @@ var Phaser; if (typeof destroyCallback === "undefined") { destroyCallback = null; } var _this = this; /** - * Max allowable accumulation. - * @type {number} - */ - this._maxAccumulation = 32; - /** - * Total number of milliseconds elapsed since last update loop. - * @type {number} - */ - this._accumulator = 0; - /** * Milliseconds of time per step of the game loop. * @type {number} */ @@ -17291,15 +18803,16 @@ var Phaser; this.rnd = new Phaser.RandomDataGenerator([ (Date.now() * Math.random()).toString() ]); + this.physics = new Phaser.Physics.Manager(this); this.setRenderer(Phaser.Types.RENDERER_CANVAS); this.world.boot(); this.stage.boot(); this.input.boot(); - this.framerate = 60; this.isBooted = true; // Set-up some static helper references Phaser.DebugUtils.game = this; Phaser.ColorUtils.game = this; + Phaser.DebugUtils.context = this.stage.context; // Display the default game screen? if(this.onInitCallback == null && this.onCreateCallback == null && this.onUpdateCallback == null && this.onRenderCallback == null && this._pendingState == null) { this._raf = new Phaser.RequestAnimationFrame(this, this.bootLoop); @@ -17359,15 +18872,8 @@ var Phaser; this.tweens.update(); this.input.update(); this.stage.update(); - this._accumulator += this.time.delta; - if(this._accumulator > this._maxAccumulation) { - this._accumulator = this._maxAccumulation; - } - while(this._accumulator >= this._step) { - this.time.elapsed = this.time.timeScale * (this._step / 1000); - this.world.update(); - this._accumulator = this._accumulator - this._step; - } + this.physics.update(); + this.world.update(); if(this._loadComplete && this.onUpdateCallback) { this.onUpdateCallback.call(this.callbackContext); } @@ -17523,19 +19029,6 @@ var Phaser; enumerable: true, configurable: true }); - Object.defineProperty(Game.prototype, "framerate", { - get: function () { - return 1000 / this._step; - }, - set: function (value) { - this._step = 1000 / value; - if(this._maxAccumulation < this._step) { - this._maxAccumulation = this._step; - } - }, - enumerable: true, - configurable: true - }); Game.prototype.collide = /** * Checks for overlaps between two objects using the world QuadTree. Can be GameObject vs. GameObject, GameObject vs. Group or Group vs. Group. * Note: Does not take the objects scrollFactor into account. All overlaps are check in world space. @@ -17551,7 +19044,8 @@ var Phaser; if (typeof objectOrGroup2 === "undefined") { objectOrGroup2 = null; } if (typeof notifyCallback === "undefined") { notifyCallback = null; } if (typeof context === "undefined") { context = this.callbackContext; } - return this.world.physics.overlap(objectOrGroup1, objectOrGroup2, notifyCallback, this.world.physics.separate, context); + //return this.world.physics.overlap(objectOrGroup1, objectOrGroup2, notifyCallback, this.world.physics.separate, context); + return false; }; Object.defineProperty(Game.prototype, "camera", { get: function () { @@ -17906,6 +19400,169 @@ var Phaser; Phaser.Line = Line; })(Phaser || (Phaser = {})); /// +/// +/// +/// +/** +* Phaser - CircleUtils +* +* A collection of methods useful for manipulating and comparing Circle objects. +* +* TODO: +*/ +var Phaser; +(function (Phaser) { + var CircleUtils = (function () { + function CircleUtils() { } + CircleUtils.clone = /** + * Returns a new Circle object with the same values for the x, y, width, and height properties as the original Circle object. + * @method clone + * @param {Circle} a - The Circle object. + * @param {Circle} [optional] out Optional Circle object. If given the values will be set into the object, otherwise a brand new Circle object will be created and returned. + * @return {Phaser.Circle} + **/ + function clone(a, out) { + if (typeof out === "undefined") { out = new Phaser.Circle(); } + return out.setTo(a.x, a.y, a.diameter); + }; + CircleUtils.contains = /** + * Return true if the given x/y coordinates are within the Circle object. + * If you need details about the intersection then use Phaser.Intersect.circleContainsPoint instead. + * @method contains + * @param {Circle} a - The Circle object. + * @param {Number} The X value of the coordinate to test. + * @param {Number} The Y value of the coordinate to test. + * @return {Boolean} True if the coordinates are within this circle, otherwise false. + **/ + function contains(a, x, y) { + //return (a.radius * a.radius >= Collision.distanceSquared(a.x, a.y, x, y)); + return true; + }; + CircleUtils.containsPoint = /** + * Return true if the coordinates of the given Point object are within this Circle object. + * If you need details about the intersection then use Phaser.Intersect.circleContainsPoint instead. + * @method containsPoint + * @param {Circle} a - The Circle object. + * @param {Point} The Point object to test. + * @return {Boolean} True if the coordinates are within this circle, otherwise false. + **/ + function containsPoint(a, point) { + return CircleUtils.contains(a, point.x, point.y); + }; + CircleUtils.containsCircle = /** + * Return true if the given Circle is contained entirely within this Circle object. + * If you need details about the intersection then use Phaser.Intersect.circleToCircle instead. + * @method containsCircle + * @param {Circle} The Circle object to test. + * @return {Boolean} True if the coordinates are within this circle, otherwise false. + **/ + function containsCircle(a, b) { + //return ((a.radius + b.radius) * (a.radius + b.radius)) >= Collision.distanceSquared(a.x, a.y, b.x, b.y); + return true; + }; + CircleUtils.distanceBetween = /** + * Returns the distance from the center of the Circle object to the given object (can be Circle, Point or anything with x/y properties) + * @method distanceBetween + * @param {Circle} a - The Circle object. + * @param {Circle} b - The target object. Must have visible x and y properties that represent the center of the object. + * @param {Boolean} [optional] round - Round the distance to the nearest integer (default false) + * @return {Number} The distance between this Point object and the destination Point object. + **/ + function distanceBetween(a, target, round) { + if (typeof round === "undefined") { round = false; } + var dx = a.x - target.x; + var dy = a.y - target.y; + if(round === true) { + return Math.round(Math.sqrt(dx * dx + dy * dy)); + } else { + return Math.sqrt(dx * dx + dy * dy); + } + }; + CircleUtils.equals = /** + * Determines whether the two Circle objects match. This method compares the x, y and diameter properties. + * @method equals + * @param {Circle} a - The first Circle object. + * @param {Circle} b - The second Circle object. + * @return {Boolean} A value of true if the object has exactly the same values for the x, y and diameter properties as this Circle object; otherwise false. + **/ + function equals(a, b) { + return (a.x == b.x && a.y == b.y && a.diameter == b.diameter); + }; + CircleUtils.intersects = /** + * Determines whether the two Circle objects intersect. + * This method checks the radius distances between the two Circle objects to see if they intersect. + * @method intersects + * @param {Circle} a - The first Circle object. + * @param {Circle} b - The second Circle object. + * @return {Boolean} A value of true if the specified object intersects with this Circle object; otherwise false. + **/ + function intersects(a, b) { + return (CircleUtils.distanceBetween(a, b) <= (a.radius + b.radius)); + }; + CircleUtils.circumferencePoint = /** + * Returns a Point object containing the coordinates of a point on the circumference of the Circle based on the given angle. + * @method circumferencePoint + * @param {Circle} a - The first Circle object. + * @param {Number} angle The angle in radians (unless asDegrees is true) to return the point from. + * @param {Boolean} asDegrees Is the given angle in radians (false) or degrees (true)? + * @param {Phaser.Point} [optional] output An optional Point object to put the result in to. If none specified a new Point object will be created. + * @return {Phaser.Point} The Point object holding the result. + **/ + function circumferencePoint(a, angle, asDegrees, out) { + if (typeof asDegrees === "undefined") { asDegrees = false; } + if (typeof out === "undefined") { out = new Phaser.Point(); } + if(asDegrees === true) { + angle = angle * Phaser.GameMath.DEG_TO_RAD; + } + return out.setTo(a.x + a.radius * Math.cos(angle), a.y + a.radius * Math.sin(angle)); + }; + CircleUtils.intersectsRectangle = /* + public static boolean intersect(Rectangle r, Circle c) + { + float cx = Math.abs(c.x - r.x - r.halfWidth); + float xDist = r.halfWidth + c.radius; + if (cx > xDist) + return false; + float cy = Math.abs(c.y - r.y - r.halfHeight); + float yDist = r.halfHeight + c.radius; + if (cy > yDist) + return false; + if (cx <= r.halfWidth || cy <= r.halfHeight) + return true; + float xCornerDist = cx - r.halfWidth; + float yCornerDist = cy - r.halfHeight; + float xCornerDistSq = xCornerDist * xCornerDist; + float yCornerDistSq = yCornerDist * yCornerDist; + float maxCornerDistSq = c.radius * c.radius; + return xCornerDistSq + yCornerDistSq <= maxCornerDistSq; + } + */ + function intersectsRectangle(c, r) { + var cx = Math.abs(c.x - r.x - r.halfWidth); + var xDist = r.halfWidth + c.radius; + if(cx > xDist) { + return false; + } + var cy = Math.abs(c.y - r.y - r.halfHeight); + var yDist = r.halfHeight + c.radius; + if(cy > yDist) { + return false; + } + if(cx <= r.halfWidth || cy <= r.halfHeight) { + return true; + } + var xCornerDist = cx - r.halfWidth; + var yCornerDist = cy - r.halfHeight; + var xCornerDistSq = xCornerDist * xCornerDist; + var yCornerDistSq = yCornerDist * yCornerDist; + var maxCornerDistSq = c.radius * c.radius; + return xCornerDistSq + yCornerDistSq <= maxCornerDistSq; + }; + return CircleUtils; + })(); + Phaser.CircleUtils = CircleUtils; +})(Phaser || (Phaser = {})); +/// /// /// /** @@ -18061,3795 +19718,6 @@ var Phaser; Phaser.Mat3Utils = Mat3Utils; })(Phaser || (Phaser = {})); /// -/// -/** -* Phaser - 2D Transform -* -* A 2D Transform -*/ -var Phaser; -(function (Phaser) { - var Transform = (function () { - /** - * Creates a new 2D Transform object. - * @class Transform - * @constructor - * @return {Transform} This object - **/ - function Transform(pos, angle) { - this.t = Phaser.Vec2Utils.clone(pos); - this.c = Math.cos(angle); - this.s = Math.sin(angle); - this.angle = angle; - } - Transform.prototype.toString = function () { - return 't=' + this.t.toString() + ' c=' + this.c + ' s=' + this.s + ' a=' + this.angle; - }; - Transform.prototype.setTo = function (pos, angle) { - this.t.copyFrom(pos); - this.c = Math.cos(angle); - this.s = Math.sin(angle); - return this; - }; - Transform.prototype.setRotation = function (angle) { - if(angle !== this.angle) { - this.c = Math.cos(angle); - this.s = Math.sin(angle); - this.angle = angle; - } - return this; - }; - Transform.prototype.setPosition = function (p) { - this.t.copyFrom(p); - return this; - }; - Transform.prototype.identity = function () { - this.t.setTo(0, 0); - this.c = 1; - this.s = 0; - return this; - }; - return Transform; - })(); - Phaser.Transform = Transform; -})(Phaser || (Phaser = {})); -/// -/// -/// -/** -* Phaser - TransformUtils -* -* A collection of methods useful for manipulating and performing operations on 2D Transforms. -* -*/ -var Phaser; -(function (Phaser) { - var TransformUtils = (function () { - function TransformUtils() { } - TransformUtils.rotate = function rotate(t, v, out) { - if (typeof out === "undefined") { out = new Phaser.Vec2(); } - //return new vec2(v.x * this.c - v.y * this.s, v.x * this.s + v.y * this.c); - return out.setTo(v.x * t.c - v.y * t.s, v.x * t.s + v.y * t.c); - }; - TransformUtils.unrotate = function unrotate(t, v, out) { - if (typeof out === "undefined") { out = new Phaser.Vec2(); } - //return new vec2(v.x * this.c + v.y * this.s, -v.x * this.s + v.y * this.c); - return out.setTo(v.x * t.c + v.y * t.s, -v.x * t.s + v.y * t.c); - }; - TransformUtils.transform = function transform(t, v, out) { - if (typeof out === "undefined") { out = new Phaser.Vec2(); } - //return new vec2(v.x * this.c - v.y * this.s + this.t.x, v.x * this.s + v.y * this.c + this.t.y); - return out.setTo(v.x * t.c - v.y * t.s + t.t.x, v.x * t.s + v.y * t.c + t.t.y); - }; - TransformUtils.untransform = function untransform(t, v, out) { - if (typeof out === "undefined") { out = new Phaser.Vec2(); } - var px = v.x - t.t.x; - var py = v.y - t.t.y; - //return new vec2(px * this.c + py * this.s, -px * this.s + py * this.c); - return out.setTo(px * t.c + py * t.s, -px * t.s + py * t.c); - }; - return TransformUtils; - })(); - Phaser.TransformUtils = TransformUtils; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - /// - /// - /// - /// - /// - /** - * Phaser - PhysicsManager - * - * Your game only has one PhysicsManager instance and it's responsible for looking after, creating and colliding - * all of the physics objects in the world. - */ - (function (Physics) { - var ArcadePhysics = (function () { - function ArcadePhysics(game, width, height) { - this._length = 0; - /** - * @type {number} - */ - this.worldDivisions = 6; - this.game = game; - this.gravity = new Phaser.Vec2(); - this.drag = new Phaser.Vec2(); - this.bounce = new Phaser.Vec2(); - this.angularDrag = 0; - this.bounds = new Phaser.Rectangle(0, 0, width, height); - this._distance = new Phaser.Vec2(); - this._tangent = new Phaser.Vec2(); - this.members = new Phaser.Group(game); - } - ArcadePhysics.OVERLAP_BIAS = 4; - ArcadePhysics.TILE_OVERLAP = false; - ArcadePhysics.prototype.updateMotion = /* - public update() { - - this._length = this._objects.length; - - for (var i = 0; i < this._length; i++) - { - if (this._objects[i]) - { - this._objects[i].preUpdate(); - this.updateMotion(this._objects[i]); - this.collideWorld(this._objects[i]); - - for (var x = 0; x < this._length; x++) - { - if (this._objects[x] && this._objects[x] !== this._objects[i]) - { - //this.collideShapes(this._objects[i], this._objects[x]); - var r = this.NEWseparate(this._objects[i], this._objects[x]); - //console.log('sep', r); - } - } - - } - } - - } - - public render() { - - // iterate through the objects here, updating and colliding - for (var i = 0; i < this._length; i++) - { - if (this._objects[i]) - { - this._objects[i].render(this.game.stage.context); - } - } - - } - */ - function (body) { - if(body.type == Phaser.Types.BODY_DISABLED) { - return; - } - this._velocityDelta = (this.computeVelocity(body.angularVelocity, body.gravity.x, body.angularAcceleration, body.angularDrag, body.maxAngular) - body.angularVelocity) / 2; - body.angularVelocity += this._velocityDelta; - body.sprite.transform.rotation += body.angularVelocity * this.game.time.elapsed; - body.angularVelocity += this._velocityDelta; - this._velocityDelta = (this.computeVelocity(body.velocity.x, body.gravity.x, body.acceleration.x, body.drag.x) - body.velocity.x) / 2; - body.velocity.x += this._velocityDelta; - this._delta = body.velocity.x * this.game.time.elapsed; - body.velocity.x += this._velocityDelta; - //body.position.x += this._delta; - body.sprite.x += this._delta; - this._velocityDelta = (this.computeVelocity(body.velocity.y, body.gravity.y, body.acceleration.y, body.drag.y) - body.velocity.y) / 2; - body.velocity.y += this._velocityDelta; - this._delta = body.velocity.y * this.game.time.elapsed; - body.velocity.y += this._velocityDelta; - //body.position.y += this._delta; - body.sprite.y += this._delta; - }; - ArcadePhysics.prototype.computeVelocity = /** - * A tween-like function that takes a starting velocity and some other factors and returns an altered velocity. - * - * @param {number} Velocity Any component of velocity (e.g. 20). - * @param {number} Acceleration Rate at which the velocity is changing. - * @param {number} Drag Really kind of a deceleration, this is how much the velocity changes if Acceleration is not set. - * @param {number} Max An absolute value cap for the velocity. - * - * @return {number} The altered Velocity value. - */ - function (velocity, gravity, acceleration, drag, max) { - if (typeof gravity === "undefined") { gravity = 0; } - if (typeof acceleration === "undefined") { acceleration = 0; } - if (typeof drag === "undefined") { drag = 0; } - if (typeof max === "undefined") { max = 10000; } - if(acceleration !== 0) { - velocity += (acceleration + gravity) * this.game.time.elapsed; - } else if(drag !== 0) { - this._drag = drag * this.game.time.elapsed; - if(velocity - this._drag > 0) { - velocity = velocity - this._drag; - } else if(velocity + this._drag < 0) { - velocity += this._drag; - } else { - velocity = 0; - } - velocity += gravity; - } - if((velocity != 0) && (max != 10000)) { - if(velocity > max) { - velocity = max; - } else if(velocity < -max) { - velocity = -max; - } - } - return velocity; - }; - ArcadePhysics.prototype.separate = /** - * The core Collision separation method. - * @param body1 The first Physics.Body to separate - * @param body2 The second Physics.Body to separate - * @returns {boolean} Returns true if the bodies were separated, otherwise false. - */ - function (body1, body2) { - this._separatedX = this.separateBodyX(body1, body2); - this._separatedY = this.separateBodyY(body1, body2); - return this._separatedX || this._separatedY; - }; - ArcadePhysics.prototype.checkHullIntersection = function (body1, body2) { - return ((body1.hullX + body1.hullWidth > body2.hullX) && (body1.hullX < body2.hullX + body2.hullWidth) && (body1.hullY + body1.hullHeight > body2.hullY) && (body1.hullY < body2.hullY + body2.hullHeight)); - }; - ArcadePhysics.prototype.separateBodyX = /** - * Separates the two objects on their x axis - * @param object1 The first GameObject to separate - * @param object2 The second GameObject to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the X axis. - */ - function (body1, body2) { - // Can't separate two disabled or static objects - if((body1.type == Phaser.Types.BODY_DISABLED || body1.type == Phaser.Types.BODY_STATIC) && (body2.type == Phaser.Types.BODY_DISABLED || body2.type == Phaser.Types.BODY_STATIC)) { - return false; - } - // First, get the two object deltas - this._overlap = 0; - if(body1.deltaX != body2.deltaX) { - if(Phaser.RectangleUtils.intersects(body1.bounds, body2.bounds)) { - this._maxOverlap = body1.deltaXAbs + body2.deltaXAbs + Physics.PhysicsManager.OVERLAP_BIAS; - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if(body1.deltaX > body2.deltaX) { - this._overlap = body1.bounds.right - body2.bounds.x; - if((this._overlap > this._maxOverlap) || !(body1.allowCollisions & Phaser.Types.RIGHT) || !(body2.allowCollisions & Phaser.Types.LEFT)) { - this._overlap = 0; - } else { - body1.touching |= Phaser.Types.RIGHT; - body2.touching |= Phaser.Types.LEFT; - } - } else if(body1.deltaX < body2.deltaX) { - this._overlap = body1.bounds.x - body2.bounds.width - body2.bounds.x; - if((-this._overlap > this._maxOverlap) || !(body1.allowCollisions & Phaser.Types.LEFT) || !(body2.allowCollisions & Phaser.Types.RIGHT)) { - this._overlap = 0; - } else { - body1.touching |= Phaser.Types.LEFT; - body2.touching |= Phaser.Types.RIGHT; - } - } - } - } - // Then adjust their positions and velocities accordingly (if there was any overlap) - if(this._overlap != 0) { - this._obj1Velocity = body1.velocity.x; - this._obj2Velocity = body2.velocity.x; - /** - * Dynamic = gives and receives impacts - * Static = gives but doesn't receive impacts, cannot be moved by physics - * Kinematic = gives impacts, but never receives, can be moved by physics - */ - // 2 dynamic bodies will exchange velocities - if(body1.type == Phaser.Types.BODY_DYNAMIC && body2.type == Phaser.Types.BODY_DYNAMIC) { - this._overlap *= 0.5; - body1.position.x = body1.position.x - this._overlap; - body2.position.x += this._overlap; - this._obj1NewVelocity = Math.sqrt((this._obj2Velocity * this._obj2Velocity * body2.mass) / body1.mass) * ((this._obj2Velocity > 0) ? 1 : -1); - this._obj2NewVelocity = Math.sqrt((this._obj1Velocity * this._obj1Velocity * body1.mass) / body2.mass) * ((this._obj1Velocity > 0) ? 1 : -1); - this._average = (this._obj1NewVelocity + this._obj2NewVelocity) * 0.5; - this._obj1NewVelocity -= this._average; - this._obj2NewVelocity -= this._average; - body1.velocity.x = this._average + this._obj1NewVelocity * body1.bounce.x; - body2.velocity.x = this._average + this._obj2NewVelocity * body2.bounce.x; - } else if(body2.type != Phaser.Types.BODY_DYNAMIC) { - // Body 2 is Static or Kinematic - this._overlap *= 2; - body1.position.x -= this._overlap; - body1.velocity.x = this._obj2Velocity - this._obj1Velocity * body1.bounce.x; - } else if(body1.type != Phaser.Types.BODY_DYNAMIC) { - // Body 1 is Static or Kinematic - this._overlap *= 2; - body2.position.x += this._overlap; - body2.velocity.x = this._obj1Velocity - this._obj2Velocity * body2.bounce.x; - } - return true; - } else { - return false; - } - }; - ArcadePhysics.prototype.separateBodyY = /** - * Separates the two objects on their y axis - * @param object1 The first GameObject to separate - * @param object2 The second GameObject to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis. - */ - function (body1, body2) { - // Can't separate two immovable objects - if((body1.type == Phaser.Types.BODY_DISABLED || body1.type == Phaser.Types.BODY_STATIC) && (body2.type == Phaser.Types.BODY_DISABLED || body2.type == Phaser.Types.BODY_STATIC)) { - return false; - } - // First, get the two object deltas - this._overlap = 0; - if(body1.deltaY != body2.deltaY) { - if(Phaser.RectangleUtils.intersects(body1.bounds, body2.bounds)) { - // This is the only place to use the DeltaAbs values - this._maxOverlap = body1.deltaYAbs + body2.deltaYAbs + Physics.PhysicsManager.OVERLAP_BIAS; - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if(body1.deltaY > body2.deltaY) { - this._overlap = body1.bounds.bottom - body2.bounds.y; - if((this._overlap > this._maxOverlap) || !(body1.allowCollisions & Phaser.Types.DOWN) || !(body2.allowCollisions & Phaser.Types.UP)) { - this._overlap = 0; - } else { - body1.touching |= Phaser.Types.DOWN; - body2.touching |= Phaser.Types.UP; - } - } else if(body1.deltaY < body2.deltaY) { - this._overlap = body1.bounds.y - body2.bounds.height - body2.bounds.y; - if((-this._overlap > this._maxOverlap) || !(body1.allowCollisions & Phaser.Types.UP) || !(body2.allowCollisions & Phaser.Types.DOWN)) { - this._overlap = 0; - } else { - body1.touching |= Phaser.Types.UP; - body2.touching |= Phaser.Types.DOWN; - } - } - } - } - // Then adjust their positions and velocities accordingly (if there was any overlap) - if(this._overlap != 0) { - this._obj1Velocity = body1.velocity.y; - this._obj2Velocity = body2.velocity.y; - /** - * Dynamic = gives and receives impacts - * Static = gives but doesn't receive impacts, cannot be moved by physics - * Kinematic = gives impacts, but never receives, can be moved by physics - */ - if(body1.type == Phaser.Types.BODY_DYNAMIC && body2.type == Phaser.Types.BODY_DYNAMIC) { - this._overlap *= 0.5; - body1.position.y = body1.position.y - this._overlap; - body2.position.y += this._overlap; - this._obj1NewVelocity = Math.sqrt((this._obj2Velocity * this._obj2Velocity * body2.mass) / body1.mass) * ((this._obj2Velocity > 0) ? 1 : -1); - this._obj2NewVelocity = Math.sqrt((this._obj1Velocity * this._obj1Velocity * body1.mass) / body2.mass) * ((this._obj1Velocity > 0) ? 1 : -1); - var average = (this._obj1NewVelocity + this._obj2NewVelocity) * 0.5; - this._obj1NewVelocity -= average; - this._obj2NewVelocity -= average; - body1.velocity.y = average + this._obj1NewVelocity * body1.bounce.y; - body2.velocity.y = average + this._obj2NewVelocity * body2.bounce.y; - } else if(body2.type != Phaser.Types.BODY_DYNAMIC) { - this._overlap *= 2; - body1.position.y -= this._overlap; - body1.velocity.y = this._obj2Velocity - this._obj1Velocity * body1.bounce.y; - // This is special case code that handles things like horizontal moving platforms you can ride - //if (body2.parent.active && body2.moves && (body1.deltaY > body2.deltaY)) - if(body2.sprite.active && (body1.deltaY > body2.deltaY)) { - body1.position.x += body2.position.x - body2.oldPosition.x; - } - } else if(body1.type != Phaser.Types.BODY_DYNAMIC) { - this._overlap *= 2; - body2.position.y += this._overlap; - body2.velocity.y = this._obj1Velocity - this._obj2Velocity * body2.bounce.y; - // This is special case code that handles things like horizontal moving platforms you can ride - //if (object1.active && body1.moves && (body1.deltaY < body2.deltaY)) - if(body1.sprite.active && (body1.deltaY < body2.deltaY)) { - body2.position.x += body1.position.x - body1.oldPosition.x; - } - } - return true; - } else { - return false; - } - }; - ArcadePhysics.prototype.overlap = /* - private TILEseparate(shapeA: IPhysicsShape, shapeB: IPhysicsShape, distance: Vec2, tangent: Vec2) { - - if (tangent.x == 1) - { - console.log('1 The left side of ShapeA hit the right side of ShapeB', Math.floor(distance.x)); - shapeA.physics.touching |= Phaser.Types.LEFT; - shapeB.physics.touching |= Phaser.Types.RIGHT; - } - else if (tangent.x == -1) - { - console.log('2 The right side of ShapeA hit the left side of ShapeB', Math.floor(distance.x)); - shapeA.physics.touching |= Phaser.Types.RIGHT; - shapeB.physics.touching |= Phaser.Types.LEFT; - } - - if (tangent.y == 1) - { - console.log('3 The top of ShapeA hit the bottom of ShapeB', Math.floor(distance.y)); - shapeA.physics.touching |= Phaser.Types.UP; - shapeB.physics.touching |= Phaser.Types.DOWN; - } - else if (tangent.y == -1) - { - console.log('4 The bottom of ShapeA hit the top of ShapeB', Math.floor(distance.y)); - shapeA.physics.touching |= Phaser.Types.DOWN; - shapeB.physics.touching |= Phaser.Types.UP; - } - - - // only apply collision response forces if the object is travelling into, and not out of, the collision - var dot = Vec2Utils.dot(shapeA.physics.velocity, tangent); - - if (dot < 0) - { - console.log('in to', dot); - - // Apply horizontal bounce - if (shapeA.physics.bounce.x > 0) - { - shapeA.physics.velocity.x *= -(shapeA.physics.bounce.x); - } - else - { - shapeA.physics.velocity.x = 0; - } - // Apply horizontal bounce - if (shapeA.physics.bounce.y > 0) - { - shapeA.physics.velocity.y *= -(shapeA.physics.bounce.y); - } - else - { - shapeA.physics.velocity.y = 0; - } - } - else - { - console.log('out of', dot); - } - - shapeA.position.x += Math.floor(distance.x); - //shapeA.bounds.x += Math.floor(distance.x); - - shapeA.position.y += Math.floor(distance.y); - //shapeA.bounds.y += distance.y; - - console.log('------------------------------------------------'); - - } - - private collideWorld(shape:IPhysicsShape) { - - // Collide on the x-axis - this._distance.x = shape.world.bounds.x - (shape.position.x - shape.bounds.halfWidth); - - if (0 < this._distance.x) - { - // Hit Left - this._tangent.setTo(1, 0); - this.separateXWall(shape, this._distance, this._tangent); - } - else - { - this._distance.x = (shape.position.x + shape.bounds.halfWidth) - shape.world.bounds.right; - - if (0 < this._distance.x) - { - // Hit Right - this._tangent.setTo(-1, 0); - this._distance.reverse(); - this.separateXWall(shape, this._distance, this._tangent); - } - } - - // Collide on the y-axis - this._distance.y = shape.world.bounds.y - (shape.position.y - shape.bounds.halfHeight); - - if (0 < this._distance.y) - { - // Hit Top - this._tangent.setTo(0, 1); - this.separateYWall(shape, this._distance, this._tangent); - } - else - { - this._distance.y = (shape.position.y + shape.bounds.halfHeight) - shape.world.bounds.bottom; - - if (0 < this._distance.y) - { - // Hit Bottom - this._tangent.setTo(0, -1); - this._distance.reverse(); - this.separateYWall(shape, this._distance, this._tangent); - } - } - - } - - private separateX(shapeA: IPhysicsShape, shapeB: IPhysicsShape, distance: Vec2, tangent: Vec2) { - - if (tangent.x == 1) - { - console.log('The left side of ShapeA hit the right side of ShapeB', distance.x); - shapeA.physics.touching |= Phaser.Types.LEFT; - shapeB.physics.touching |= Phaser.Types.RIGHT; - } - else - { - console.log('The right side of ShapeA hit the left side of ShapeB', distance.x); - shapeA.physics.touching |= Phaser.Types.RIGHT; - shapeB.physics.touching |= Phaser.Types.LEFT; - } - - // collision edges - //shapeA.oH = tangent.x; - - // only apply collision response forces if the object is travelling into, and not out of, the collision - if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) - { - // Apply horizontal bounce - if (shapeA.physics.bounce.x > 0) - { - shapeA.physics.velocity.x *= -(shapeA.physics.bounce.x); - } - else - { - shapeA.physics.velocity.x = 0; - } - } - - shapeA.position.x += distance.x; - shapeA.bounds.x += distance.x; - - } - - private separateY(shapeA: IPhysicsShape, shapeB: IPhysicsShape, distance: Vec2, tangent: Vec2) { - - if (tangent.y == 1) - { - console.log('The top of ShapeA hit the bottom of ShapeB', distance.y); - shapeA.physics.touching |= Phaser.Types.UP; - shapeB.physics.touching |= Phaser.Types.DOWN; - } - else - { - console.log('The bottom of ShapeA hit the top of ShapeB', distance.y); - shapeA.physics.touching |= Phaser.Types.DOWN; - shapeB.physics.touching |= Phaser.Types.UP; - } - - // collision edges - //shapeA.oV = tangent.y; - - // only apply collision response forces if the object is travelling into, and not out of, the collision - if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) - { - // Apply horizontal bounce - if (shapeA.physics.bounce.y > 0) - { - shapeA.physics.velocity.y *= -(shapeA.physics.bounce.y); - } - else - { - shapeA.physics.velocity.y = 0; - } - } - - shapeA.position.y += distance.y; - shapeA.bounds.y += distance.y; - - } - - private separateXWall(shapeA: IPhysicsShape, distance: Vec2, tangent: Vec2) { - - if (tangent.x == 1) - { - console.log('The left side of ShapeA hit the right side of ShapeB', distance.x); - shapeA.physics.touching |= Phaser.Types.LEFT; - } - else - { - console.log('The right side of ShapeA hit the left side of ShapeB', distance.x); - shapeA.physics.touching |= Phaser.Types.RIGHT; - } - - // collision edges - //shapeA.oH = tangent.x; - - // only apply collision response forces if the object is travelling into, and not out of, the collision - if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) - { - // Apply horizontal bounce - if (shapeA.physics.bounce.x > 0) - { - shapeA.physics.velocity.x *= -(shapeA.physics.bounce.x); - } - else - { - shapeA.physics.velocity.x = 0; - } - } - - shapeA.position.x += distance.x; - - } - - private separateYWall(shapeA: IPhysicsShape, distance: Vec2, tangent: Vec2) { - - if (tangent.y == 1) - { - console.log('The top of ShapeA hit the bottom of ShapeB', distance.y); - shapeA.physics.touching |= Phaser.Types.UP; - } - else - { - console.log('The bottom of ShapeA hit the top of ShapeB', distance.y); - shapeA.physics.touching |= Phaser.Types.DOWN; - } - - // collision edges - //shapeA.oV = tangent.y; - - // only apply collision response forces if the object is travelling into, and not out of, the collision - if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) - { - // Apply horizontal bounce - if (shapeA.physics.bounce.y > 0) - { - shapeA.physics.velocity.y *= -(shapeA.physics.bounce.y); - } - else - { - shapeA.physics.velocity.y = 0; - } - } - - shapeA.position.y += distance.y; - - } - */ - /** - * Checks for overlaps between two objects using the world QuadTree. Can be Sprite vs. Sprite, Sprite vs. Group or Group vs. Group. - * Note: Does not take the objects scrollFactor into account. All overlaps are check in world space. - * @param object1 The first Sprite or Group to check. If null the world.group is used. - * @param object2 The second Sprite or Group to check. - * @param notifyCallback A callback function that is called if the objects overlap. The two objects will be passed to this function in the same order in which you passed them to Collision.overlap. - * @param processCallback A callback function that lets you perform additional checks against the two objects if they overlap. If this is set then notifyCallback will only be called if processCallback returns true. - * @param context The context in which the callbacks will be called - * @returns {boolean} true if the objects overlap, otherwise false. - */ - function (object1, object2, notifyCallback, processCallback, context) { - if (typeof object1 === "undefined") { object1 = null; } - if (typeof object2 === "undefined") { object2 = null; } - if (typeof notifyCallback === "undefined") { notifyCallback = null; } - if (typeof processCallback === "undefined") { processCallback = null; } - if (typeof context === "undefined") { context = null; } - /* - if (object1 == null) - { - object1 = this.game.world.group; - } - - if (object2 == object1) - { - object2 = null; - } - - QuadTree.divisions = this.worldDivisions; - - this._quadTree = new Phaser.QuadTree(this, this.bounds.x, this.bounds.y, this.bounds.width, this.bounds.height); - - this._quadTree.load(object1, object2, notifyCallback, processCallback, context); - - this._quadTreeResult = this._quadTree.execute(); - - console.log('over', this._quadTreeResult); - - this._quadTree.destroy(); - - this._quadTree = null; - - return this._quadTreeResult; - */ - return false; - }; - ArcadePhysics.prototype.separateTile = /** - * Collision resolution specifically for GameObjects vs. Tiles. - * @param object The GameObject to separate - * @param tile The Tile to separate - * @returns {boolean} Whether the objects in fact touched and were separated - */ - function (object, x, y, width, height, mass, collideLeft, collideRight, collideUp, collideDown, separateX, separateY) { - //var separatedX: bool = this.separateTileX(object, x, y, width, height, mass, collideLeft, collideRight, separateX); - //var separatedY: bool = this.separateTileY(object, x, y, width, height, mass, collideUp, collideDown, separateY); - //return separatedX || separatedY; - return false; - }; - return ArcadePhysics; - })(); - Physics.ArcadePhysics = ArcadePhysics; - /** - * Separates the two objects on their x axis - * @param object The GameObject to separate - * @param tile The Tile to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the X axis. - */ - /* - public separateTileX(object:Sprite, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool, separate: bool): bool { - - // Can't separate two immovable objects (tiles are always immovable) - if (object.immovable) - { - return false; - } - - // First, get the object delta - var overlap: number = 0; - var objDelta: number = object.x - object.last.x; - //var objDelta: number = object.collisionMask.deltaX; - - if (objDelta != 0) - { - // Check if the X hulls actually overlap - var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; - //var objDeltaAbs: number = object.collisionMask.deltaXAbs; - var objBounds: Rectangle = new Rectangle(object.x - ((objDelta > 0) ? objDelta : 0), object.last.y, object.width + ((objDelta > 0) ? objDelta : -objDelta), object.height); - - if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) - { - var maxOverlap: number = objDeltaAbs + Collision.OVERLAP_BIAS; - - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if (objDelta > 0) - { - overlap = object.x + object.width - x; - - if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.RIGHT) || collideLeft == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.RIGHT; - } - } - else if (objDelta < 0) - { - overlap = object.x - width - x; - - if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.LEFT) || collideRight == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.LEFT; - } - - } - - } - } - - // Then adjust their positions and velocities accordingly (if there was any overlap) - if (overlap != 0) - { - if (separate == true) - { - //console.log(' - object.x = object.x - overlap; - object.velocity.x = -(object.velocity.x * object.elasticity); - } - - Collision.TILE_OVERLAP = true; - return true; - } - else - { - return false; - } - - } - */ - /** - * Separates the two objects on their y axis - * @param object The first GameObject to separate - * @param tile The second GameObject to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis. - */ - /* - public separateTileY(object: Sprite, x: number, y: number, width: number, height: number, mass: number, collideUp: bool, collideDown: bool, separate: bool): bool { - - // Can't separate two immovable objects (tiles are always immovable) - if (object.immovable) - { - return false; - } - - // First, get the two object deltas - var overlap: number = 0; - var objDelta: number = object.y - object.last.y; - - if (objDelta != 0) - { - // Check if the Y hulls actually overlap - var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; - var objBounds: Rectangle = new Rectangle(object.x, object.y - ((objDelta > 0) ? objDelta : 0), object.width, object.height + objDeltaAbs); - - if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) - { - var maxOverlap: number = objDeltaAbs + Collision.OVERLAP_BIAS; - - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if (objDelta > 0) - { - overlap = object.y + object.height - y; - - if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.DOWN) || collideUp == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.DOWN; - } - } - else if (objDelta < 0) - { - overlap = object.y - height - y; - - if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.UP) || collideDown == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.UP; - } - } - } - } - - // TODO - with super low velocities you get lots of stuttering, set some kind of base minimum here - - // Then adjust their positions and velocities accordingly (if there was any overlap) - if (overlap != 0) - { - if (separate == true) - { - object.y = object.y - overlap; - object.velocity.y = -(object.velocity.y * object.elasticity); - } - - Collision.TILE_OVERLAP = true; - return true; - } - else - { - return false; - } - } - */ - /** - * Separates the two objects on their x axis - * @param object The GameObject to separate - * @param tile The Tile to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the X axis. - */ - /* - public static NEWseparateTileX(object:Sprite, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool, separate: bool): bool { - - // Can't separate two immovable objects (tiles are always immovable) - if (object.immovable) - { - return false; - } - - // First, get the object delta - var overlap: number = 0; - - if (object.collisionMask.deltaX != 0) - { - // Check if the X hulls actually overlap - //var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; - //var objBounds: Rectangle = new Rectangle(object.x - ((objDelta > 0) ? objDelta : 0), object.last.y, object.width + ((objDelta > 0) ? objDelta : -objDelta), object.height); - - //if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) - if (object.collisionMask.intersectsRaw(x, x + width, y, y + height)) - { - var maxOverlap: number = object.collisionMask.deltaXAbs + Collision.OVERLAP_BIAS; - - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if (object.collisionMask.deltaX > 0) - { - //overlap = object.x + object.width - x; - overlap = object.collisionMask.right - x; - - if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.RIGHT) || collideLeft == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.RIGHT; - } - } - else if (object.collisionMask.deltaX < 0) - { - //overlap = object.x - width - x; - overlap = object.collisionMask.x - width - x; - - if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.LEFT) || collideRight == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.LEFT; - } - - } - - } - } - - // Then adjust their positions and velocities accordingly (if there was any overlap) - if (overlap != 0) - { - if (separate == true) - { - object.x = object.x - overlap; - object.velocity.x = -(object.velocity.x * object.elasticity); - } - - Collision.TILE_OVERLAP = true; - return true; - } - else - { - return false; - } - - } - */ - /** - * Separates the two objects on their y axis - * @param object The first GameObject to separate - * @param tile The second GameObject to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis. - */ - /* - public NEWseparateTileY(object: Sprite, x: number, y: number, width: number, height: number, mass: number, collideUp: bool, collideDown: bool, separate: bool): bool { - - // Can't separate two immovable objects (tiles are always immovable) - if (object.immovable) - { - return false; - } - - // First, get the two object deltas - var overlap: number = 0; - //var objDelta: number = object.y - object.last.y; - - if (object.collisionMask.deltaY != 0) - { - // Check if the Y hulls actually overlap - //var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; - //var objBounds: Rectangle = new Rectangle(object.x, object.y - ((objDelta > 0) ? objDelta : 0), object.width, object.height + objDeltaAbs); - - //if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) - if (object.collisionMask.intersectsRaw(x, x + width, y, y + height)) - { - //var maxOverlap: number = objDeltaAbs + Collision.OVERLAP_BIAS; - var maxOverlap: number = object.collisionMask.deltaYAbs + Collision.OVERLAP_BIAS; - - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if (object.collisionMask.deltaY > 0) - { - //overlap = object.y + object.height - y; - overlap = object.collisionMask.bottom - y; - - if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.DOWN) || collideUp == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.DOWN; - } - } - else if (object.collisionMask.deltaY < 0) - { - //overlap = object.y - height - y; - overlap = object.collisionMask.y - height - y; - - if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.UP) || collideDown == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.UP; - } - } - } - } - - // TODO - with super low velocities you get lots of stuttering, set some kind of base minimum here - - // Then adjust their positions and velocities accordingly (if there was any overlap) - if (overlap != 0) - { - if (separate == true) - { - object.y = object.y - overlap; - object.velocity.y = -(object.velocity.y * object.elasticity); - } - - Collision.TILE_OVERLAP = true; - return true; - } - else - { - return false; - } - } - */ - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - (function (Physics) { - /// - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - Joint - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Advanced) { - var Joint = (function () { - function Joint(type, body1, body2, collideConnected) { - this.id = Phaser.Physics.Advanced.Manager.jointCounter++; - this.type = type; - this.body1 = body1; - this.body2 = body2; - this.collideConnected = collideConnected; - this.maxForce = 9999999999; - this.breakable = false; - } - Joint.prototype.getWorldAnchor1 = function () { - return this.body1.getWorldPoint(this.anchor1); - }; - Joint.prototype.getWorldAnchor2 = function () { - return this.body2.getWorldPoint(this.anchor2); - }; - Joint.prototype.setWorldAnchor1 = function (anchor1) { - this.anchor1 = this.body1.getLocalPoint(anchor1); - }; - Joint.prototype.setWorldAnchor2 = function (anchor2) { - this.anchor2 = this.body2.getLocalPoint(anchor2); - }; - return Joint; - })(); - Advanced.Joint = Joint; - })(Physics.Advanced || (Physics.Advanced = {})); - var Advanced = Physics.Advanced; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - (function (Physics) { - /// - /// - /// - /** - * Phaser - Advanced Physics Manager - * - * Your game only has one PhysicsManager instance and it's responsible for looking after, creating and colliding - * all of the physics objects in the world. - */ - (function (Advanced) { - var Manager = (function () { - function Manager(game) { - this.lastTime = Date.now(); - this.frameRateHz = 60; - this.timeDelta = 0; - //public paused: bool = false; - //public step: bool = false; // step through the simulation (i.e. per click) - this.paused = true; - this.step = 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; - Manager.SHAPE_NUM_TYPES = 3; - Manager.JOINT_TYPE_ANGLE = 0; - Manager.JOINT_TYPE_REVOLUTE = 1; - Manager.JOINT_TYPE_WELD = 2; - Manager.JOINT_TYPE_WHEEL = 3; - Manager.JOINT_TYPE_PRISMATIC = 4; - Manager.JOINT_TYPE_DISTANCE = 5; - Manager.JOINT_TYPE_ROPE = 6; - Manager.JOINT_TYPE_MOUSE = 7; - Manager.JOINT_LINEAR_SLOP = 0.0008; - Manager.JOINT_ANGULAR_SLOP = 2 * Phaser.GameMath.DEG_TO_RAD; - Manager.JOINT_MAX_LINEAR_CORRECTION = 0.5; - Manager.JOINT_MAX_ANGULAR_CORRECTION = 8 * Phaser.GameMath.DEG_TO_RAD; - Manager.JOINT_LIMIT_STATE_INACTIVE = 0; - Manager.JOINT_LIMIT_STATE_AT_LOWER = 1; - Manager.JOINT_LIMIT_STATE_AT_UPPER = 2; - Manager.JOINT_LIMIT_STATE_EQUAL_LIMITS = 3; - Manager.CONTACT_SOLVER_COLLISION_SLOP = 0.0008; - Manager.CONTACT_SOLVER_BAUMGARTE = 0.28; - Manager.CONTACT_SOLVER_MAX_LINEAR_CORRECTION = 1; - Manager.bodyCounter = 0; - Manager.jointCounter = 0; - Manager.shapeCounter = 0; - Manager.prototype.update = function () { - var time = Date.now(); - var frameTime = (time - this.lastTime) / 1000; - this.lastTime = time; - // if rAf - why? - frameTime = Math.floor(frameTime * 60 + 0.5) / 60; - //if (!mouseDown) - //{ - // var p = canvasToWorld(mousePosition); - // var body = space.findBodyByPoint(p); - // //domCanvas.style.cursor = body ? "pointer" : "default"; - //} - if(!this.paused || this.step) { - Manager.clear(); - var h = 1 / this.frameRateHz; - this.timeDelta += frameTime; - if(this.step) { - this.step = false; - this.timeDelta = h; - } - for(var maxSteps = 4; maxSteps > 0 && this.timeDelta >= h; maxSteps--) { - this.space.step(h, this.velocityIterations, this.positionIterations, this.warmStarting, this.allowSleep); - this.timeDelta -= h; - } - if(this.timeDelta > h) { - this.timeDelta = 0; - } - } - //frameCount++; - }; - Manager.prototype.pixelsToMeters = function (value) { - return value * 0.02; - }; - Manager.prototype.metersToPixels = function (value) { - return value * 50; - }; - Manager.pixelsToMeters = function pixelsToMeters(value) { - return value * 0.02; - }; - Manager.metersToPixels = function metersToPixels(value) { - return value * 50; - }; - Manager.p2m = function p2m(value) { - return value * 0.02; - }; - Manager.m2p = function m2p(value) { - return value * 50; - }; - Manager.areaForCircle = function areaForCircle(radius_outer, radius_inner) { - return Math.PI * (radius_outer * radius_outer - radius_inner * radius_inner); - }; - Manager.inertiaForCircle = function inertiaForCircle(mass, center, radius_outer, radius_inner) { - return mass * ((radius_outer * radius_outer + radius_inner * radius_inner) * 0.5 + center.lengthSq()); - }; - Manager.areaForSegment = function areaForSegment(a, b, radius) { - return radius * (Math.PI * radius + 2 * Phaser.Vec2Utils.distance(a, b)); - }; - Manager.centroidForSegment = function centroidForSegment(a, b) { - return Phaser.Vec2Utils.scale(Phaser.Vec2Utils.add(a, b), 0.5); - }; - Manager.inertiaForSegment = function inertiaForSegment(mass, a, b) { - var distsq = Phaser.Vec2Utils.distanceSq(b, a); - var offset = Phaser.Vec2Utils.scale(Phaser.Vec2Utils.add(a, b), 0.5); - return mass * (distsq / 12 + offset.lengthSq()); - }; - Manager.areaForPoly = function areaForPoly(verts) { - var area = 0; - for(var i = 0; i < verts.length; i++) { - area += Phaser.Vec2Utils.cross(verts[i], verts[(i + 1) % verts.length]); - } - return area / 2; - }; - Manager.centroidForPoly = function centroidForPoly(verts) { - var area = 0; - var vsum = new Phaser.Vec2(); - for(var i = 0; i < verts.length; i++) { - var v1 = verts[i]; - var v2 = verts[(i + 1) % verts.length]; - var cross = Phaser.Vec2Utils.cross(v1, v2); - area += cross; - // SO many vecs created here - unroll these bad boys - vsum.add(Phaser.Vec2Utils.scale(Phaser.Vec2Utils.add(v1, v2), cross)); - } - return Phaser.Vec2Utils.scale(vsum, 1 / (3 * area)); - }; - Manager.inertiaForPoly = function inertiaForPoly(mass, verts, offset) { - var sum1 = 0; - var sum2 = 0; - for(var i = 0; i < verts.length; i++) { - var v1 = Phaser.Vec2Utils.add(verts[i], offset); - var v2 = Phaser.Vec2Utils.add(verts[(i + 1) % verts.length], offset); - var a = Phaser.Vec2Utils.cross(v2, v1); - var b = Phaser.Vec2Utils.dot(v1, v1) + Phaser.Vec2Utils.dot(v1, v2) + Phaser.Vec2Utils.dot(v2, v2); - sum1 += a * b; - sum2 += a; - } - return (mass * sum1) / (6 * sum2); - }; - Manager.inertiaForBox = function inertiaForBox(mass, w, h) { - return mass * (w * w + h * h) / 12; - }; - Manager.createConvexHull = // Create the convex hull using the Gift wrapping algorithm (http://en.wikipedia.org/wiki/Gift_wrapping_algorithm) - function createConvexHull(points) { - // Find the right most point on the hull - var i0 = 0; - var x0 = points[0].x; - for(var i = 1; i < points.length; i++) { - var x = points[i].x; - if(x > x0 || (x == x0 && points[i].y < points[i0].y)) { - i0 = i; - x0 = x; - } - } - var n = points.length; - var hull = []; - var m = 0; - var ih = i0; - while(1) { - hull[m] = ih; - var ie = 0; - for(var j = 1; j < n; j++) { - if(ie == ih) { - ie = j; - continue; - } - var r = Phaser.Vec2Utils.subtract(points[ie], points[hull[m]]); - var v = Phaser.Vec2Utils.subtract(points[j], points[hull[m]]); - var c = Phaser.Vec2Utils.cross(r, v); - if(c < 0) { - ie = j; - } - // Collinearity check - if(c == 0 && v.lengthSq() > r.lengthSq()) { - ie = j; - } - } - m++; - ih = ie; - if(ie == i0) { - break; - } - } - // Copy vertices - var newPoints = []; - for(var i = 0; i < m; ++i) { - newPoints.push(points[hull[i]]); - } - return newPoints; - }; - return Manager; - })(); - Advanced.Manager = Manager; - })(Physics.Advanced || (Physics.Advanced = {})); - var Advanced = Physics.Advanced; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - (function (Physics) { - /// - /// - /// - /** - * Phaser - 2D AABB - * - * A 2D AABB object - */ - (function (Advanced) { - var Bounds = (function () { - /** - * Creates a new 2D AABB object. - * @class Bounds - * @constructor - * @return {Bounds} This object - **/ - function Bounds(mins, maxs) { - if (typeof mins === "undefined") { mins = null; } - if (typeof maxs === "undefined") { maxs = null; } - if(mins) { - this.mins = Phaser.Vec2Utils.clone(mins); - } else { - this.mins = new Phaser.Vec2(999999, 999999); - } - if(maxs) { - this.maxs = Phaser.Vec2Utils.clone(maxs); - } else { - this.maxs = new Phaser.Vec2(999999, 999999); - } - } - Bounds.prototype.toString = function () { - return [ - "mins:", - this.mins.toString(), - "maxs:", - this.maxs.toString() - ].join(" "); - }; - Bounds.prototype.setTo = function (mins, maxs) { - this.mins.setTo(mins.x, mins.y); - this.maxs.setTo(maxs.x, maxs.y); - }; - Bounds.prototype.copy = function (b) { - this.mins.copyFrom(b.mins); - this.maxs.copyFrom(b.maxs); - return this; - }; - Bounds.prototype.clear = function () { - this.mins.setTo(999999, 999999); - this.maxs.setTo(-999999, -999999); - return this; - }; - Object.defineProperty(Bounds.prototype, "x", { - get: function () { - return Phaser.Physics.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); - }; - Bounds.prototype.getPerimeter = /* - public getCenter() { - return vec2.scale(vec2.add(this.mins, this.maxs), 0.5); - } - - public getExtent() { - return vec2.scale(vec2.sub(this.maxs, this.mins), 0.5); - } - */ - function () { - return (this.maxs.x - this.mins.x + this.maxs.y - this.mins.y) * 2; - }; - Bounds.prototype.addPoint = function (p) { - if(this.mins.x > p.x) { - this.mins.x = p.x; - } - if(this.maxs.x < p.x) { - this.maxs.x = p.x; - } - if(this.mins.y > p.y) { - this.mins.y = p.y; - } - if(this.maxs.y < p.y) { - this.maxs.y = p.y; - } - return this; - }; - Bounds.prototype.addBounds = function (b) { - if(this.mins.x > b.mins.x) { - this.mins.x = b.mins.x; - } - if(this.maxs.x < b.maxs.x) { - this.maxs.x = b.maxs.x; - } - if(this.mins.y > b.mins.y) { - this.mins.y = b.mins.y; - } - if(this.maxs.y < b.maxs.y) { - this.maxs.y = b.maxs.y; - } - return this; - }; - Bounds.prototype.addBounds2 = function (mins, maxs) { - if(this.mins.x > mins.x) { - this.mins.x = mins.x; - } - if(this.maxs.x < maxs.x) { - this.maxs.x = maxs.x; - } - if(this.mins.y > mins.y) { - this.mins.y = mins.y; - } - if(this.maxs.y < maxs.y) { - this.maxs.y = maxs.y; - } - return this; - }; - Bounds.prototype.addExtents = function (center, extent_x, extent_y) { - if(this.mins.x > center.x - extent_x) { - this.mins.x = center.x - extent_x; - } - if(this.maxs.x < center.x + extent_x) { - this.maxs.x = center.x + extent_x; - } - if(this.mins.y > center.y - extent_y) { - this.mins.y = center.y - extent_y; - } - if(this.maxs.y < center.y + extent_y) { - this.maxs.y = center.y + extent_y; - } - return this; - }; - Bounds.prototype.expand = function (ax, ay) { - this.mins.x -= ax; - this.mins.y -= ay; - this.maxs.x += ax; - this.maxs.y += ay; - return this; - }; - Bounds.prototype.containPoint = function (p) { - if(p.x < this.mins.x || p.x > this.maxs.x || p.y < this.mins.y || p.y > this.maxs.y) { - return false; - } - return true; - }; - Bounds.prototype.intersectsBounds = function (b) { - if(this.mins.x > b.maxs.x || this.maxs.x < b.mins.x || this.mins.y > b.maxs.y || this.maxs.y < b.mins.y) { - return false; - } - return true; - }; - Bounds.expand = function expand(b, ax, ay) { - var b = new Bounds(b.mins, b.maxs); - b.expand(ax, ay); - return b; - }; - return Bounds; - })(); - Advanced.Bounds = Bounds; - })(Physics.Advanced || (Physics.Advanced = {})); - var Advanced = Physics.Advanced; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - (function (Physics) { - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - (function (Physics) { - /// - /// - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - Shape - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Advanced) { - var Shape = (function () { - function Shape(type) { - this.id = Phaser.Physics.Advanced.Manager.shapeCounter++; - this.type = type; - this.elasticity = 0.0; - this.friction = 1.0; - this.density = 1; - this.bounds = new Advanced.Bounds(); - } - Shape.prototype.findEdgeByPoint = // Over-ridden by ShapePoly - function (p, minDist) { - return -1; - }; - return Shape; - })(); - Advanced.Shape = Shape; - })(Physics.Advanced || (Physics.Advanced = {})); - var Advanced = Physics.Advanced; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - (function (Physics) { - /// - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - Contact - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Advanced) { - var Contact = (function () { - function Contact(p, n, d, hash) { - this.hash = hash; - this.point = p; - this.normal = n; - this.depth = d; - this.lambdaNormal = 0; - this.lambdaTangential = 0; - this.r1 = new Phaser.Vec2(); - this.r2 = new Phaser.Vec2(); - this.r1_local = new Phaser.Vec2(); - this.r2_local = new Phaser.Vec2(); - } - return Contact; - })(); - Advanced.Contact = Contact; - })(Physics.Advanced || (Physics.Advanced = {})); - var Advanced = Physics.Advanced; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - (function (Physics) { - /// - /// - /// - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - ContactSolver - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - //------------------------------------------------------------------------------------------------- - // Contact Constraint - // - // Non-penetration constraint: - // C = dot(p2 - p1, n) - // Cdot = dot(v2 - v1, n) - // J = [ -n, -cross(r1, n), n, cross(r2, n) ] - // - // impulse = JT * lambda = [ -n * lambda, -cross(r1, n) * lambda, n * lambda, cross(r1, n) * lambda ] - // - // Friction constraint: - // C = dot(p2 - p1, t) - // Cdot = dot(v2 - v1, t) - // J = [ -t, -cross(r1, t), t, cross(r2, t) ] - // - // impulse = JT * lambda = [ -t * lambda, -cross(r1, t) * lambda, t * lambda, cross(r1, t) * lambda ] - // - // NOTE: lambda is an impulse in constraint space. - //------------------------------------------------------------------------------------------------- - (function (Advanced) { - var ContactSolver = (function () { - function ContactSolver(shape1, shape2) { - this.shape1 = shape1; - this.shape2 = shape2; - this.contacts = []; - this.elasticity = 1; - this.friction = 1; - } - ContactSolver.prototype.update = function (newContactArr) { - for(var i = 0; i < newContactArr.length; i++) { - var newContact = newContactArr[i]; - var k = -1; - for(var j = 0; j < this.contacts.length; j++) { - if(newContact.hash == this.contacts[j].hash) { - k = j; - break; - } - } - if(k > -1) { - newContact.lambdaNormal = this.contacts[k].lambdaNormal; - newContact.lambdaTangential = this.contacts[k].lambdaTangential; - } - } - this.contacts = newContactArr; - }; - ContactSolver.prototype.initSolver = function (dt_inv) { - var body1 = this.shape1.body; - var body2 = this.shape2.body; - var sum_m_inv = body1.massInverted + body2.massInverted; - for(var i = 0; i < this.contacts.length; i++) { - var con = this.contacts[i]; - //console.log('initSolver con'); - //console.log(con); - // Transformed r1, r2 - Phaser.Vec2Utils.subtract(con.point, body1.position, con.r1); - Phaser.Vec2Utils.subtract(con.point, body2.position, con.r2); - //con.r1 = vec2.sub(con.point, body1.p); - //con.r2 = vec2.sub(con.point, body2.p); - // Local r1, r2 - Phaser.TransformUtils.unrotate(body1.transform, con.r1, con.r1_local); - Phaser.TransformUtils.unrotate(body2.transform, con.r2, con.r2_local); - //con.r1_local = body1.transform.unrotate(con.r1); - //con.r2_local = body2.transform.unrotate(con.r2); - var n = con.normal; - var t = Phaser.Vec2Utils.perp(con.normal); - // invEMn = J * invM * JT - // J = [ -n, -cross(r1, n), n, cross(r2, n) ] - var sn1 = Phaser.Vec2Utils.cross(con.r1, n); - var sn2 = Phaser.Vec2Utils.cross(con.r2, n); - var emn_inv = sum_m_inv + body1.inertiaInverted * sn1 * sn1 + body2.inertiaInverted * sn2 * sn2; - con.emn = emn_inv == 0 ? 0 : 1 / emn_inv; - // invEMt = J * invM * JT - // J = [ -t, -cross(r1, t), t, cross(r2, t) ] - var st1 = Phaser.Vec2Utils.cross(con.r1, t); - var st2 = Phaser.Vec2Utils.cross(con.r2, t); - var emt_inv = sum_m_inv + body1.inertiaInverted * st1 * st1 + body2.inertiaInverted * st2 * st2; - con.emt = emt_inv == 0 ? 0 : 1 / emt_inv; - // Linear velocities at contact point - // in 2D: cross(w, r) = perp(r) * w - var v1 = new Phaser.Vec2(); - var v2 = new Phaser.Vec2(); - Phaser.Vec2Utils.multiplyAdd(body1.velocity, Phaser.Vec2Utils.perp(con.r1), body1.angularVelocity, v1); - Phaser.Vec2Utils.multiplyAdd(body2.velocity, Phaser.Vec2Utils.perp(con.r2), body2.angularVelocity, v2); - //var v1 = vec2.mad(body1.v, vec2.perp(con.r1), body1.w); - //var v2 = vec2.mad(body2.v, vec2.perp(con.r2), body2.w); - // relative velocity at contact point - var rv = new Phaser.Vec2(); - Phaser.Vec2Utils.subtract(v2, v1, rv); - //var rv = vec2.sub(v2, v1); - // bounce velocity dot n - con.bounce = Phaser.Vec2Utils.dot(rv, con.normal) * this.elasticity; - } - }; - ContactSolver.prototype.warmStart = function () { - var body1 = this.shape1.body; - var body2 = this.shape2.body; - for(var i = 0; i < this.contacts.length; i++) { - var con = this.contacts[i]; - var n = con.normal; - var lambda_n = con.lambdaNormal; - var lambda_t = con.lambdaTangential; - // Apply accumulated impulses - //var impulse = vec2.rotate_vec(new vec2(lambda_n, lambda_t), n); - //var impulse = new vec2(lambda_n * n.x - lambda_t * n.y, lambda_t * n.x + lambda_n * n.y); - var impulse = new Phaser.Vec2(lambda_n * n.x - lambda_t * n.y, lambda_t * n.x + lambda_n * n.y); - //console.log('phaser warmStart impulse ' + i + ' = ' + impulse.toString()); - body1.velocity.multiplyAddByScalar(impulse, -body1.massInverted); - //body1.v.mad(impulse, -body1.m_inv); - body1.angularVelocity -= Phaser.Vec2Utils.cross(con.r1, impulse) * body1.inertiaInverted; - //body1.w -= vec2.cross(con.r1, impulse) * body1.i_inv; - body2.velocity.multiplyAddByScalar(impulse, body2.massInverted); - //body2.v.mad(impulse, body2.m_inv); - body2.angularVelocity += Phaser.Vec2Utils.cross(con.r2, impulse) * body2.inertiaInverted; - //body2.w += vec2.cross(con.r2, impulse) * body2.i_inv; - } - }; - ContactSolver.prototype.solveVelocityConstraints = function () { - var body1 = this.shape1.body; - var body2 = this.shape2.body; - 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); - var r1 = con.r1; - var r2 = con.r2; - // Linear velocities at contact point - // in 2D: cross(w, r) = perp(r) * w - var v1 = new Phaser.Vec2(); - var v2 = new Phaser.Vec2(); - Phaser.Vec2Utils.multiplyAdd(body1.velocity, Phaser.Vec2Utils.perp(r1), body1.angularVelocity, v1); - //var v1 = vec2.mad(body1.v, vec2.perp(r1), body1.w); - 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); - // Max friction constraint impulse (Coulomb's Law) - var lambda_t_max = con.lambdaNormal * this.friction; - // Accumulate and clamp - var lambda_t_old = con.lambdaTangential; - con.lambdaTangential = this.clamp(lambda_t_old + lambda_t, -lambda_t_max, lambda_t_max); - lambda_t = con.lambdaTangential - lambda_t_old; - // Apply the final impulses - //var impulse = vec2.rotate_vec(new vec2(lambda_n, lambda_t), n); - var impulse = new Phaser.Vec2(lambda_n * n.x - lambda_t * n.y, lambda_t * n.x + lambda_n * n.y); - 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); - 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; - var i2_inv = body2.inertiaInverted; - var sum_m_inv = m1_inv + m2_inv; - var max_penetration = 0; - for(var i = 0; i < this.contacts.length; i++) { - Advanced.Manager.write('------------- solvePositionConstraints ' + i); - var con = this.contacts[i]; - var n = con.normal; - var r1 = new Phaser.Vec2(); - var r2 = new Phaser.Vec2(); - // Transformed r1, r2 - Phaser.Vec2Utils.rotate(con.r1_local, body1.angle, r1); - //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(); - Phaser.Vec2Utils.add(body1.position, r1, p1); - //var p1 = vec2.add(body1.p, r1); - Phaser.Vec2Utils.add(body2.position, r2, p2); - //var p2 = vec2.add(body2.p, r2); - 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, dp); - //var dp = vec2.sub(p2, p1); - // Position constraint - var c = Phaser.Vec2Utils.dot(dp, n) + con.depth; - var correction = this.clamp(Advanced.Manager.CONTACT_SOLVER_BAUMGARTE * (c + Advanced.Manager.CONTACT_SOLVER_COLLISION_SLOP), -Advanced.Manager.CONTACT_SOLVER_MAX_LINEAR_CORRECTION, 0); - if(correction == 0) { - continue; - } - // We don't need max_penetration less than or equal slop - max_penetration = Math.max(max_penetration, -c); - // Compute lambda for position constraint - // Solve (J * invM * JT) * lambda = -C / dt - var sn1 = Phaser.Vec2Utils.cross(r1, n); - var sn2 = Phaser.Vec2Utils.cross(r2, n); - var em_inv = sum_m_inv + body1.inertiaInverted * sn1 * sn1 + body2.inertiaInverted * sn2 * sn2; - var lambda_dt = em_inv == 0 ? 0 : -correction / em_inv; - // Apply correction impulses - var impulse_dt = new Phaser.Vec2(); - Phaser.Vec2Utils.scale(n, lambda_dt, impulse_dt); - //var impulse_dt = vec2.scale(n, lambda_dt); - body1.position.multiplyAddByScalar(impulse_dt, -m1_inv); - //body1.p.mad(impulse_dt, -m1_inv); - body1.angle -= sn1 * lambda_dt * i1_inv; - body2.position.multiplyAddByScalar(impulse_dt, m2_inv); - //body2.p.mad(impulse_dt, m2_inv); - body2.angle += sn2 * lambda_dt * i2_inv; - 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) { - return v < min ? min : (v > max ? max : v); - }; - return ContactSolver; - })(); - Advanced.ContactSolver = ContactSolver; - })(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 - Shape - Circle - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Shapes) { - var Circle = (function (_super) { - __extends(Circle, _super); - function Circle(radius, x, y) { - if (typeof x === "undefined") { x = 0; } - if (typeof y === "undefined") { y = 0; } - _super.call(this, 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(); - this.finishVerts(); - } - Circle.prototype.finishVerts = function () { - this.radius = Math.abs(this.radius); - }; - Circle.prototype.duplicate = function () { - return new Circle(this.center.x, this.center.y, this.radius); - }; - Circle.prototype.recenter = function (c) { - this.center.subtract(c); - }; - Circle.prototype.transform = function (xf) { - Phaser.TransformUtils.transform(xf, this.center, this.center); - //this.center = xf.transform(this.center); - }; - Circle.prototype.untransform = function (xf) { - Phaser.TransformUtils.untransform(xf, this.center, this.center); - //this.center = xf.untransform(this.center); - }; - Circle.prototype.area = function () { - return Advanced.Manager.areaForCircle(this.radius, 0); - }; - Circle.prototype.centroid = function () { - return Phaser.Vec2Utils.clone(this.center); - }; - Circle.prototype.inertia = function (mass) { - return Advanced.Manager.inertiaForCircle(mass, this.center, this.radius, 0); - }; - Circle.prototype.cacheData = function (xf) { - Phaser.TransformUtils.transform(xf, this.center, this.tc); - //this.tc = xf.transform(this.center); - this.bounds.mins.setTo(this.tc.x - this.radius, this.tc.y - this.radius); - this.bounds.maxs.setTo(this.tc.x + this.radius, this.tc.y + this.radius); - }; - Circle.prototype.pointQuery = function (p) { - //return vec2.distsq(this.tc, p) < (this.r * this.r); - return Phaser.Vec2Utils.distanceSq(this.tc, p) < (this.radius * this.radius); - }; - Circle.prototype.findVertexByPoint = function (p, minDist) { - var dsq = minDist * minDist; - if(Phaser.Vec2Utils.distanceSq(this.tc, p) < dsq) { - return 0; - } - return -1; - }; - Circle.prototype.distanceOnPlane = function (n, d) { - Phaser.Vec2Utils.dot(n, this.tc) - this.radius - d; - }; - return Circle; - })(Phaser.Physics.Advanced.Shape); - Shapes.Circle = Circle; - })(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) { - /// - /// - /// - /// - /** - * 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) { - /// - /// - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - Shapes - Convex Polygon - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Shapes) { - var Poly = (function (_super) { - __extends(Poly, _super); - // Verts is an optional array of objects, the objects must have public x and y properties which will be used - // to seed this polygon (i.e. Vec2 objects, or just straight JS objects) and must wind COUNTER clockwise - function Poly(verts) { - _super.call(this, Advanced.Manager.SHAPE_TYPE_POLY); - this.verts = []; - this.planes = []; - this.tverts = []; - this.tplanes = []; - if(verts) { - for(var i = 0; i < verts.length; i++) { - this.verts[i] = new Phaser.Vec2(verts[i].x, verts[i].y); - this.tverts[i] = this.verts[i]; - //this.tverts[i] = new Phaser.Vec2(verts[i].x, verts[i].y); - this.tplanes[i] = new Phaser.Physics.Advanced.Plane(new Phaser.Vec2(), 0); - } - } - this.finishVerts(); - } - Poly.prototype.finishVerts = function () { - if(this.verts.length < 2) { - this.convexity = false; - this.planes = []; - return; - } - this.convexity = true; - this.tverts = []; - this.tplanes = []; - // Must be counter-clockwise verts - for(var i = 0; i < this.verts.length; i++) { - var a = this.verts[i]; - var b = this.verts[(i + 1) % this.verts.length]; - var n = Phaser.Vec2Utils.normalize(Phaser.Vec2Utils.perp(Phaser.Vec2Utils.subtract(a, b))); - this.planes[i] = new Phaser.Physics.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].normal; - //var d = this.planes[i].d; - if(Phaser.Vec2Utils.dot(this.planes[i].normal, this.verts[(i + 2) % this.verts.length]) - this.planes[i].d > 0) { - this.convexity = false; - } - } - }; - Poly.prototype.duplicate = function () { - return new Phaser.Physics.Advanced.Shapes.Poly(this.verts); - }; - Poly.prototype.recenter = function (c) { - for(var i = 0; i < this.verts.length; i++) { - this.verts[i].subtract(c); - } - }; - Poly.prototype.transform = function (xf) { - for(var i = 0; i < this.verts.length; i++) { - this.verts[i] = Phaser.TransformUtils.transform(xf, this.verts[i]); - //this.verts[i] = xf.transform(this.verts[i]); - } - }; - Poly.prototype.untransform = function (xf) { - for(var i = 0; i < this.verts.length; i++) { - this.verts[i] = Phaser.TransformUtils.untransform(xf, this.verts[i]); - //this.verts[i] = xf.untransform(this.verts[i]); - } - }; - Poly.prototype.area = function () { - return Advanced.Manager.areaForPoly(this.verts); - }; - Poly.prototype.centroid = function () { - return Advanced.Manager.centroidForPoly(this.verts); - }; - Poly.prototype.inertia = function (mass) { - return Advanced.Manager.inertiaForPoly(mass, this.verts, new Phaser.Vec2()); - }; - Poly.prototype.cacheData = function (xf) { - this.bounds.clear(); - var numVerts = this.verts.length; - Advanced.Manager.write('----------- Poly cacheData = ' + numVerts); - if(numVerts == 0) { - return; - } - for(var i = 0; i < numVerts; i++) { - this.tverts[i] = Phaser.TransformUtils.transform(xf, this.verts[i]); - //this.tverts[i] = xf.transform(this.verts[i]); - Advanced.Manager.write('tvert' + i + ' = ' + this.tverts[i].toString()); - } - if(numVerts < 2) { - this.bounds.addPoint(this.tverts[0]); - return; - } - for(var i = 0; i < numVerts; i++) { - var a = this.tverts[i]; - var b = this.tverts[(i + 1) % numVerts]; - var n = Phaser.Vec2Utils.normalize(Phaser.Vec2Utils.perp(Phaser.Vec2Utils.subtract(a, b))); - 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); - } - }; - Poly.prototype.pointQuery = function (p) { - if(!this.bounds.containPoint(p)) { - return false; - } - return this.containPoint(p); - }; - Poly.prototype.findVertexByPoint = function (p, minDist) { - var dsq = minDist * minDist; - for(var i = 0; i < this.tverts.length; i++) { - if(Phaser.Vec2Utils.distanceSq(this.tverts[i], p) < dsq) { - return i; - } - } - return -1; - }; - Poly.prototype.findEdgeByPoint = function (p, minDist) { - var dsq = minDist * minDist; - var numVerts = this.tverts.length; - for(var i = 0; i < this.tverts.length; i++) { - var v1 = this.tverts[i]; - var v2 = this.tverts[(i + 1) % numVerts]; - var n = this.tplanes[i].normal; - var dtv1 = Phaser.Vec2Utils.cross(v1, n); - var dtv2 = Phaser.Vec2Utils.cross(v2, n); - var dt = Phaser.Vec2Utils.cross(p, n); - if(dt > dtv1) { - if(Phaser.Vec2Utils.distanceSq(v1, p) < dsq) { - return i; - } - } else if(dt < dtv2) { - if(Phaser.Vec2Utils.distanceSq(v2, p) < dsq) { - return i; - } - } else { - var dist = Phaser.Vec2Utils.dot(n, p) - Phaser.Vec2Utils.dot(n, v1); - if(dist * dist < dsq) { - return i; - } - } - } - return -1; - }; - Poly.prototype.distanceOnPlane = function (n, d) { - var min = 999999; - for(var i = 0; i < this.verts.length; i++) { - min = Math.min(min, Phaser.Vec2Utils.dot(n, this.tverts[i])); - } - return min - d; - }; - Poly.prototype.containPoint = function (p) { - for(var i = 0; i < this.verts.length; i++) { - var plane = this.tplanes[i]; - if(Phaser.Vec2Utils.dot(plane.normal, p) - plane.d > 0) { - return false; - } - } - return true; - }; - Poly.prototype.containPointPartial = function (p, n) { - for(var i = 0; i < this.verts.length; i++) { - var plane = this.tplanes[i]; - if(Phaser.Vec2Utils.dot(plane.normal, n) < 0.0001) { - continue; - } - if(Phaser.Vec2Utils.dot(plane.normal, p) - plane.d > 0) { - return false; - } - } - return true; - }; - return Poly; - })(Phaser.Physics.Advanced.Shape); - Shapes.Poly = Poly; - })(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 - Segment - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Shapes) { - var Segment = (function (_super) { - __extends(Segment, _super); - function Segment(a, b, radius) { - _super.call(this, Advanced.Manager.SHAPE_TYPE_SEGMENT); - this.a = a.duplicate(); - this.b = b.duplicate(); - this.radius = radius; - this.normal = Phaser.Vec2Utils.perp(Phaser.Vec2Utils.subtract(b, a)); - this.normal.normalize(); - this.ta = new Phaser.Vec2(); - this.tb = new Phaser.Vec2(); - this.tn = new Phaser.Vec2(); - this.finishVerts(); - } - Segment.prototype.finishVerts = function () { - this.normal = Phaser.Vec2Utils.perp(Phaser.Vec2Utils.subtract(this.b, this.a)); - this.normal.normalize(); - this.radius = Math.abs(this.radius); - }; - Segment.prototype.duplicate = function () { - return new Phaser.Physics.Advanced.Shapes.Segment(this.a, this.b, this.radius); - }; - Segment.prototype.recenter = function (c) { - this.a.subtract(c); - this.b.subtract(c); - }; - Segment.prototype.transform = function (xf) { - Phaser.TransformUtils.transform(xf, this.a, this.a); - Phaser.TransformUtils.transform(xf, this.b, this.b); - //this.a = xf.transform(this.a); - //this.b = xf.transform(this.b); - }; - Segment.prototype.untransform = function (xf) { - Phaser.TransformUtils.untransform(xf, this.a, this.a); - Phaser.TransformUtils.untransform(xf, this.b, this.b); - //this.a = xf.untransform(this.a); - //this.b = xf.untransform(this.b); - }; - Segment.prototype.area = function () { - return Advanced.Manager.areaForSegment(this.a, this.b, this.radius); - }; - Segment.prototype.centroid = function () { - return Advanced.Manager.centroidForSegment(this.a, this.b); - }; - Segment.prototype.inertia = function (mass) { - return Advanced.Manager.inertiaForSegment(mass, this.a, this.b); - }; - Segment.prototype.cacheData = function (xf) { - Phaser.TransformUtils.transform(xf, this.a, this.ta); - Phaser.TransformUtils.transform(xf, this.b, this.tb); - //this.ta = xf.transform(this.a); - //this.tb = xf.transform(this.b); - this.tn = Phaser.Vec2Utils.perp(Phaser.Vec2Utils.subtract(this.tb, this.ta)).normalize(); - var l; - var r; - var t; - var b; - if(this.ta.x < this.tb.x) { - l = this.ta.x; - r = this.tb.x; - } else { - l = this.tb.x; - r = this.ta.x; - } - if(this.ta.y < this.tb.y) { - b = this.ta.y; - t = this.tb.y; - } else { - b = this.tb.y; - t = this.ta.y; - } - this.bounds.mins.setTo(l - this.radius, b - this.radius); - this.bounds.maxs.setTo(r + this.radius, t + this.radius); - }; - Segment.prototype.pointQuery = function (p) { - if(!this.bounds.containPoint(p)) { - return false; - } - var dn = Phaser.Vec2Utils.dot(this.tn, p) - Phaser.Vec2Utils.dot(this.ta, this.tn); - var dist = Math.abs(dn); - if(dist > this.radius) { - return false; - } - var dt = Phaser.Vec2Utils.cross(p, this.tn); - var dta = Phaser.Vec2Utils.cross(this.ta, this.tn); - var dtb = Phaser.Vec2Utils.cross(this.tb, this.tn); - if(dt <= dta) { - if(dt < dta - this.radius) { - return false; - } - return Phaser.Vec2Utils.distanceSq(this.ta, p) < (this.radius * this.radius); - } else if(dt > dtb) { - if(dt > dtb + this.radius) { - return false; - } - return Phaser.Vec2Utils.distanceSq(this.tb, p) < (this.radius * this.radius); - } - return true; - }; - Segment.prototype.findVertexByPoint = function (p, minDist) { - var dsq = minDist * minDist; - if(Phaser.Vec2Utils.distanceSq(this.ta, p) < dsq) { - return 0; - } - if(Phaser.Vec2Utils.distanceSq(this.tb, p) < dsq) { - return 1; - } - return -1; - }; - Segment.prototype.distanceOnPlane = function (n, d) { - var a = Phaser.Vec2Utils.dot(n, this.ta) - this.radius; - var b = Phaser.Vec2Utils.dot(n, this.tb) - this.radius; - return Math.min(a, b) - d; - }; - return Segment; - })(Phaser.Physics.Advanced.Shape); - Shapes.Segment = Segment; - })(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) { - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - Collision Handlers - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Advanced) { - var Collision = (function () { - function Collision() { - } - Collision.prototype.collide = function (a, b, contacts) { - // Circle (a is the circle) - if(a.type == Advanced.Manager.SHAPE_TYPE_CIRCLE) { - if(b.type == Advanced.Manager.SHAPE_TYPE_CIRCLE) { - return this.circle2Circle(a, b, contacts); - } else if(b.type == Advanced.Manager.SHAPE_TYPE_SEGMENT) { - return this.circle2Segment(a, b, contacts); - } else if(b.type == Advanced.Manager.SHAPE_TYPE_POLY) { - return this.circle2Poly(a, b, contacts); - } - } - // Segment (a is the segment) - if(a.type == Advanced.Manager.SHAPE_TYPE_SEGMENT) { - if(b.type == Advanced.Manager.SHAPE_TYPE_CIRCLE) { - return this.circle2Segment(b, a, contacts); - } else if(b.type == Advanced.Manager.SHAPE_TYPE_SEGMENT) { - return this.segment2Segment(a, b, contacts); - } else if(b.type == Advanced.Manager.SHAPE_TYPE_POLY) { - return this.segment2Poly(a, b, contacts); - } - } - // Poly (a is the poly) - if(a.type == Advanced.Manager.SHAPE_TYPE_POLY) { - if(b.type == Advanced.Manager.SHAPE_TYPE_CIRCLE) { - return this.circle2Poly(b, a, contacts); - } else if(b.type == Advanced.Manager.SHAPE_TYPE_SEGMENT) { - return this.segment2Poly(b, a, contacts); - } else if(b.type == Advanced.Manager.SHAPE_TYPE_POLY) { - return this.poly2Poly(a, b, contacts); - } - } - }; - Collision.prototype._circle2Circle = function (c1, r1, c2, r2, contactArr) { - var rmax = r1 + r2; - var t = new Phaser.Vec2(); - //var t = vec2.sub(c2, c1); - Phaser.Vec2Utils.subtract(c2, c1, t); - var distsq = t.lengthSq(); - if(distsq > rmax * rmax) { - return 0; - } - var dist = Math.sqrt(distsq); - var p = new Phaser.Vec2(); - Phaser.Vec2Utils.multiplyAdd(c1, t, 0.5 + (r1 - r2) * 0.5 / dist, p); - //var p = vec2.mad(c1, t, 0.5 + (r1 - r2) * 0.5 / dist); - var n = new Phaser.Vec2(); - //var n = (dist != 0) ? vec2.scale(t, 1 / dist) : vec2.zero; - if(dist != 0) { - Phaser.Vec2Utils.scale(t, 1 / dist, n); - } - var d = dist - rmax; - contactArr.push(new Advanced.Contact(p, n, d, 0)); - return 1; - }; - Collision.prototype.circle2Circle = function (circ1, circ2, contactArr) { - return this._circle2Circle(circ1.tc, circ1.radius, circ2.tc, circ2.radius, contactArr); - }; - Collision.prototype.circle2Segment = function (circ, seg, contactArr) { - var rsum = circ.radius + seg.radius; - // Normal distance from segment - var dn = Phaser.Vec2Utils.dot(circ.tc, seg.tn) - Phaser.Vec2Utils.dot(seg.ta, seg.tn); - var dist = (dn < 0 ? dn * -1 : dn) - rsum; - if(dist > 0) { - return 0; - } - // Tangential distance along segment - var dt = Phaser.Vec2Utils.cross(circ.tc, seg.tn); - var dtMin = Phaser.Vec2Utils.cross(seg.ta, seg.tn); - var dtMax = Phaser.Vec2Utils.cross(seg.tb, seg.tn); - if(dt < dtMin) { - if(dt < dtMin - rsum) { - return 0; - } - return this._circle2Circle(circ.tc, circ.radius, seg.ta, seg.radius, contactArr); - } else if(dt > dtMax) { - if(dt > dtMax + rsum) { - return 0; - } - return this._circle2Circle(circ.tc, circ.radius, seg.tb, seg.radius, contactArr); - } - var n = new Phaser.Vec2(); - if(dn > 0) { - n.copyFrom(seg.tn); - } else { - Phaser.Vec2Utils.negative(seg.tn, n); - } - //var n = (dn > 0) ? seg.tn : vec2.neg(seg.tn); - var c1 = new Phaser.Vec2(); - Phaser.Vec2Utils.multiplyAdd(circ.tc, n, -(circ.radius + dist * 0.5), c1); - var c2 = new Phaser.Vec2(); - Phaser.Vec2Utils.negative(n, c2); - contactArr.push(new Advanced.Contact(c1, c2, dist, 0)); - //contactArr.push(new Contact(vec2.mad(circ.tc, n, -(circ.r + dist * 0.5)), vec2.neg(n), dist, 0)); - return 1; - }; - Collision.prototype.circle2Poly = function (circ, poly, contactArr) { - var minDist = -999999; - var minIdx = -1; - for(var i = 0; i < poly.verts.length; i++) { - var plane = poly.tplanes[i]; - var dist = Phaser.Vec2Utils.dot(circ.tc, plane.normal) - plane.d - circ.radius; - if(dist > 0) { - return 0; - } else if(dist > minDist) { - minDist = dist; - minIdx = i; - } - } - var n = poly.tplanes[minIdx].normal; - var a = poly.tverts[minIdx]; - var b = poly.tverts[(minIdx + 1) % poly.verts.length]; - var dta = Phaser.Vec2Utils.cross(a, n); - var dtb = Phaser.Vec2Utils.cross(b, n); - var dt = Phaser.Vec2Utils.cross(circ.tc, n); - if(dt > dta) { - return this._circle2Circle(circ.tc, circ.radius, a, 0, contactArr); - } else if(dt < dtb) { - return this._circle2Circle(circ.tc, circ.radius, b, 0, contactArr); - } - var c1 = new Phaser.Vec2(); - Phaser.Vec2Utils.multiplyAdd(circ.tc, n, -(circ.radius + minDist * 0.5), c1); - var c2 = new Phaser.Vec2(); - Phaser.Vec2Utils.negative(n, c2); - contactArr.push(new Advanced.Contact(c1, c2, minDist, 0)); - //contactArr.push(new Contact(vec2.mad(circ.tc, n, -(circ.r + minDist * 0.5)), vec2.neg(n), minDist, 0)); - return 1; - }; - Collision.prototype.segmentPointDistanceSq = function (seg, p) { - var w = new Phaser.Vec2(); - var d = new Phaser.Vec2(); - Phaser.Vec2Utils.subtract(p, seg.ta, w); - Phaser.Vec2Utils.subtract(seg.tb, seg.ta, d); - //var w = vec2.sub(p, seg.ta); - //var d = vec2.sub(seg.tb, seg.ta); - var proj = w.dot(d); - if(proj <= 0) { - return w.dot(w); - } - var vsq = d.dot(d); - if(proj >= vsq) { - return w.dot(w) - 2 * proj + vsq; - } - return w.dot(w) - proj * proj / vsq; - }; - Collision.prototype.segment2Segment = // FIXME and optimise me lots!!! - function (seg1, seg2, contactArr) { - var d = []; - d[0] = this.segmentPointDistanceSq(seg1, seg2.ta); - d[1] = this.segmentPointDistanceSq(seg1, seg2.tb); - d[2] = this.segmentPointDistanceSq(seg2, seg1.ta); - d[3] = this.segmentPointDistanceSq(seg2, seg1.tb); - var idx1 = d[0] < d[1] ? 0 : 1; - var idx2 = d[2] < d[3] ? 2 : 3; - var idxm = d[idx1] < d[idx2] ? idx1 : idx2; - var s, t; - var u = Phaser.Vec2Utils.subtract(seg1.tb, seg1.ta); - var v = Phaser.Vec2Utils.subtract(seg2.tb, seg2.ta); - switch(idxm) { - case 0: - s = Phaser.Vec2Utils.dot(Phaser.Vec2Utils.subtract(seg2.ta, seg1.ta), u) / Phaser.Vec2Utils.dot(u, u); - s = s < 0 ? 0 : (s > 1 ? 1 : s); - t = 0; - break; - case 1: - s = Phaser.Vec2Utils.dot(Phaser.Vec2Utils.subtract(seg2.tb, seg1.ta), u) / Phaser.Vec2Utils.dot(u, u); - s = s < 0 ? 0 : (s > 1 ? 1 : s); - t = 1; - break; - case 2: - s = 0; - t = Phaser.Vec2Utils.dot(Phaser.Vec2Utils.subtract(seg1.ta, seg2.ta), v) / Phaser.Vec2Utils.dot(v, v); - t = t < 0 ? 0 : (t > 1 ? 1 : t); - break; - case 3: - s = 1; - t = Phaser.Vec2Utils.dot(Phaser.Vec2Utils.subtract(seg1.tb, seg2.ta), v) / Phaser.Vec2Utils.dot(v, v); - t = t < 0 ? 0 : (t > 1 ? 1 : t); - break; - } - var minp1 = Phaser.Vec2Utils.multiplyAdd(seg1.ta, u, s); - var minp2 = Phaser.Vec2Utils.multiplyAdd(seg2.ta, v, t); - return this._circle2Circle(minp1, seg1.radius, minp2, seg2.radius, contactArr); - }; - Collision.prototype.findPointsBehindSeg = // Identify vertexes that have penetrated the segment. - function (contactArr, seg, poly, dist, coef) { - var dta = Phaser.Vec2Utils.cross(seg.tn, seg.ta); - var dtb = Phaser.Vec2Utils.cross(seg.tn, seg.tb); - var n = new Phaser.Vec2(); - Phaser.Vec2Utils.scale(seg.tn, coef, n); - //var n = vec2.scale(seg.tn, coef); - for(var i = 0; i < poly.verts.length; i++) { - var v = poly.tverts[i]; - if(Phaser.Vec2Utils.dot(v, n) < Phaser.Vec2Utils.dot(seg.tn, seg.ta) * coef + seg.radius) { - var dt = Phaser.Vec2Utils.cross(seg.tn, v); - if(dta >= dt && dt >= dtb) { - contactArr.push(new Advanced.Contact(v, n, dist, (poly.id << 16) | i)); - } - } - } - }; - Collision.prototype.segment2Poly = function (seg, poly, contactArr) { - var seg_td = Phaser.Vec2Utils.dot(seg.tn, seg.ta); - var seg_d1 = poly.distanceOnPlane(seg.tn, seg_td) - seg.radius; - if(seg_d1 > 0) { - return 0; - } - var n = new Phaser.Vec2(); - Phaser.Vec2Utils.negative(seg.tn, n); - var seg_d2 = poly.distanceOnPlane(n, -seg_td) - seg.radius; - //var seg_d2 = poly.distanceOnPlane(vec2.neg(seg.tn), -seg_td) - seg.r; - if(seg_d2 > 0) { - return 0; - } - var poly_d = -999999; - var poly_i = -1; - for(var i = 0; i < poly.verts.length; i++) { - var plane = poly.tplanes[i]; - var dist = seg.distanceOnPlane(plane.normal, plane.d); - if(dist > 0) { - return 0; - } - if(dist > poly_d) { - poly_d = dist; - poly_i = i; - } - } - var poly_n = new Phaser.Vec2(); - Phaser.Vec2Utils.negative(poly.tplanes[poly_i].normal, poly_n); - //var poly_n = vec2.neg(poly.tplanes[poly_i].n); - var va = new Phaser.Vec2(); - Phaser.Vec2Utils.multiplyAdd(seg.ta, poly_n, seg.radius, va); - //var va = vec2.mad(seg.ta, poly_n, seg.r); - var vb = new Phaser.Vec2(); - Phaser.Vec2Utils.multiplyAdd(seg.tb, poly_n, seg.radius, vb); - //var vb = vec2.mad(seg.tb, poly_n, seg.r); - if(poly.containPoint(va)) { - contactArr.push(new Advanced.Contact(va, poly_n, poly_d, (seg.id << 16) | 0)); - } - if(poly.containPoint(vb)) { - contactArr.push(new Advanced.Contact(vb, poly_n, poly_d, (seg.id << 16) | 1)); - } - // Floating point precision problems here. - // This will have to do for now. - poly_d -= 0.1; - if(seg_d1 >= poly_d || seg_d2 >= poly_d) { - if(seg_d1 > seg_d2) { - this.findPointsBehindSeg(contactArr, seg, poly, seg_d1, 1); - } else { - this.findPointsBehindSeg(contactArr, seg, poly, seg_d2, -1); - } - } - // If no other collision points are found, try colliding endpoints. - if(contactArr.length == 0) { - var poly_a = poly.tverts[poly_i]; - var poly_b = poly.tverts[(poly_i + 1) % poly.verts.length]; - if(this._circle2Circle(seg.ta, seg.radius, poly_a, 0, contactArr)) { - return 1; - } - if(this._circle2Circle(seg.tb, seg.radius, poly_a, 0, contactArr)) { - return 1; - } - if(this._circle2Circle(seg.ta, seg.radius, poly_b, 0, contactArr)) { - return 1; - } - if(this._circle2Circle(seg.tb, seg.radius, poly_b, 0, contactArr)) { - return 1; - } - } - return contactArr.length; - }; - Collision.prototype.findMSA = // Find the minimum separating axis for the given poly and plane list. - function (poly, planes, num) { - var min_dist = -999999; - var min_index = -1; - for(var i = 0; i < num; i++) { - var dist = poly.distanceOnPlane(planes[i].normal, planes[i].d); - if(dist > 0) { - // no collision - return { - dist: 0, - index: -1 - }; - } else if(dist > min_dist) { - min_dist = dist; - min_index = i; - } - } - // new object - see what we can do here - return { - dist: min_dist, - index: min_index - }; - }; - Collision.prototype.findVertsFallback = function (contactArr, poly1, poly2, n, dist) { - var num = 0; - for(var i = 0; i < poly1.verts.length; i++) { - var v = poly1.tverts[i]; - if(poly2.containPointPartial(v, n)) { - contactArr.push(new Advanced.Contact(v, n, dist, (poly1.id << 16) | i)); - num++; - } - } - for(var i = 0; i < poly2.verts.length; i++) { - var v = poly2.tverts[i]; - if(poly1.containPointPartial(v, n)) { - contactArr.push(new Advanced.Contact(v, n, dist, (poly2.id << 16) | i)); - num++; - } - } - return num; - }; - Collision.prototype.findVerts = // Find the overlapped vertices. - function (contactArr, poly1, poly2, n, dist) { - var num = 0; - for(var i = 0; i < poly1.verts.length; i++) { - var v = poly1.tverts[i]; - if(poly2.containPoint(v)) { - contactArr.push(new Advanced.Contact(v, n, dist, (poly1.id << 16) | i)); - num++; - } - } - for(var i = 0; i < poly2.verts.length; i++) { - var v = poly2.tverts[i]; - if(poly1.containPoint(v)) { - contactArr.push(new Advanced.Contact(v, n, dist, (poly2.id << 16) | i)); - num++; - } - } - return num > 0 ? num : this.findVertsFallback(contactArr, poly1, poly2, n, dist); - }; - Collision.prototype.poly2Poly = function (poly1, poly2, contactArr) { - var msa1 = this.findMSA(poly2, poly1.tplanes, poly1.verts.length); - if(msa1.index == -1) { - console.log('poly2poly 0', msa1); - return 0; - } - var msa2 = this.findMSA(poly1, poly2.tplanes, poly2.verts.length); - if(msa2.index == -1) { - console.log('poly2poly 1', msa2); - return 0; - } - // Penetration normal direction should be from poly1 to poly2 - if(msa1.dist > msa2.dist) { - return this.findVerts(contactArr, poly1, poly2, poly1.tplanes[msa1.index].normal, msa1.dist); - } - return this.findVerts(contactArr, poly1, poly2, Phaser.Vec2Utils.negative(poly2.tplanes[msa2.index].normal), msa2.dist); - }; - return Collision; - })(); - Advanced.Collision = Collision; - })(Physics.Advanced || (Physics.Advanced = {})); - var Advanced = Physics.Advanced; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - (function (Physics) { - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - (function (Physics) { - /// - /// - /// - /// - /// - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - Space - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Advanced) { - var Space = (function () { - function Space() { - this.stepCount = 0; - this.bodies = []; - this.bodyHash = { - }; - this.joints = []; - this.jointHash = { - }; - this.numContacts = 0; - this.contactSolvers = []; - //this.postSolve(arb) { }; - this.gravity = new Phaser.Vec2(0, 10); - this.damping = 0; - this._linTolSqr = Space.SLEEP_LINEAR_TOLERANCE * Space.SLEEP_LINEAR_TOLERANCE; - this._angTolSqr = Space.SLEEP_ANGULAR_TOLERANCE * Space.SLEEP_ANGULAR_TOLERANCE; - } - Space.TIME_TO_SLEEP = 0.5; - Space.SLEEP_LINEAR_TOLERANCE = 0.5; - Space.SLEEP_ANGULAR_TOLERANCE = 2 * Phaser.GameMath.DEG_TO_RAD; - Space.prototype.clear = function () { - Advanced.Manager.shapeCounter = 0; - Advanced.Manager.bodyCounter = 0; - Advanced.Manager.jointCounter = 0; - for(var i = 0; i < this.bodies.length; i++) { - if(this.bodies[i]) { - this.removeBody(this.bodies[i]); - } - } - this.bodies = []; - this.bodyHash = { - }; - this.joints = []; - this.jointHash = { - }; - this.contactSolvers = []; - this.stepCount = 0; - }; - Space.prototype.addBody = function (body) { - if(this.bodyHash[body.id] != undefined) { - return; - } - var index = this.bodies.push(body) - 1; - this.bodyHash[body.id] = index; - body.awake(true); - body.space = this; - body.cacheData('addBody'); - }; - Space.prototype.removeBody = function (body) { - if(this.bodyHash[body.id] == undefined) { - return; - } - // Remove linked joints - for(var i = 0; i < body.joints.length; i++) { - if(body.joints[i]) { - this.removeJoint(body.joints[i]); - } - } - body.space = null; - var index = this.bodyHash[body.id]; - delete this.bodyHash[body.id]; - delete this.bodies[index]; - }; - Space.prototype.addJoint = function (joint) { - if(this.jointHash[joint.id] != undefined) { - return; - } - joint.body1.awake(true); - joint.body2.awake(true); - var index = this.joints.push(joint) - 1; - this.jointHash[joint.id] = index; - var index = joint.body1.joints.push(joint) - 1; - joint.body1.jointHash[joint.id] = index; - var index = joint.body2.joints.push(joint) - 1; - joint.body2.jointHash[joint.id] = index; - }; - Space.prototype.removeJoint = function (joint) { - if(this.jointHash[joint.id] == undefined) { - return; - } - joint.body1.awake(true); - joint.body2.awake(true); - var index = joint.body1.jointHash[joint.id]; - delete joint.body1.jointHash[joint.id]; - delete joint.body1.joints[index]; - var index = joint.body2.jointHash[joint.id]; - delete joint.body2.jointHash[joint.id]; - delete joint.body2.joints[index]; - var index = this.jointHash[joint.id]; - delete this.jointHash[joint.id]; - delete this.joints[index]; - }; - Space.prototype.findShapeByPoint = function (p, refShape) { - var firstShape; - for(var i = 0; i < this.bodies.length; i++) { - var body = this.bodies[i]; - if(!body) { - continue; - } - for(var j = 0; j < body.shapes.length; j++) { - var shape = body.shapes[j]; - if(shape.pointQuery(p)) { - if(!refShape) { - return shape; - } - if(!firstShape) { - firstShape = shape; - } - if(shape == refShape) { - refShape = null; - } - } - } - } - return firstShape; - }; - Space.prototype.findBodyByPoint = function (p, refBody) { - var firstBody; - for(var i = 0; i < this.bodies.length; i++) { - var body = this.bodies[i]; - if(!body) { - continue; - } - for(var j = 0; j < body.shapes.length; j++) { - var shape = body.shapes[j]; - if(shape.pointQuery(p)) { - if(!refBody) { - return shape.body; - } - if(!firstBody) { - firstBody = shape.body; - } - if(shape.body == refBody) { - refBody = null; - } - break; - } - } - } - return firstBody; - }; - Space.prototype.shapeById = function (id) { - var shape; - for(var i = 0; i < this.bodies.length; i++) { - var body = this.bodies[i]; - if(!body) { - continue; - } - for(var j = 0; j < body.shapes.length; j++) { - if(body.shapes[j].id == id) { - return body.shapes[j]; - } - } - } - return null; - }; - Space.prototype.jointById = function (id) { - var index = this.jointHash[id]; - if(index != undefined) { - return this.joints[index]; - } - return null; - }; - Space.prototype.findVertexByPoint = function (p, minDist, refVertexId) { - var firstVertexId = -1; - refVertexId = refVertexId || -1; - for(var i = 0; i < this.bodies.length; i++) { - var body = this.bodies[i]; - if(!body) { - continue; - } - for(var j = 0; j < body.shapes.length; j++) { - var shape = body.shapes[j]; - var index = shape.findVertexByPoint(p, minDist); - if(index != -1) { - var vertex = (shape.id << 16) | index; - if(refVertexId == -1) { - return vertex; - } - if(firstVertexId == -1) { - firstVertexId = vertex; - } - if(vertex == refVertexId) { - refVertexId = -1; - } - } - } - } - return firstVertexId; - }; - Space.prototype.findEdgeByPoint = function (p, minDist, refEdgeId) { - var firstEdgeId = -1; - refEdgeId = refEdgeId || -1; - for(var i = 0; i < this.bodies.length; i++) { - var body = this.bodies[i]; - if(!body) { - continue; - } - for(var j = 0; j < body.shapes.length; j++) { - var shape = body.shapes[j]; - if(shape.type != Advanced.Manager.SHAPE_TYPE_POLY) { - continue; - } - var index = shape.findEdgeByPoint(p, minDist); - if(index != -1) { - var edge = (shape.id << 16) | index; - if(refEdgeId == -1) { - return edge; - } - if(firstEdgeId == -1) { - firstEdgeId = edge; - } - if(edge == refEdgeId) { - refEdgeId = -1; - } - } - } - } - return firstEdgeId; - }; - Space.prototype.findJointByPoint = function (p, minDist, refJointId) { - var firstJointId = -1; - var dsq = minDist * minDist; - refJointId = refJointId || -1; - for(var i = 0; i < this.joints.length; i++) { - var joint = this.joints[i]; - if(!joint) { - continue; - } - var jointId = -1; - if(Phaser.Vec2Utils.distanceSq(p, joint.getWorldAnchor1()) < dsq) { - jointId = (joint.id << 16 | 0); - } else if(Phaser.Vec2Utils.distanceSq(p, joint.getWorldAnchor2()) < dsq) { - jointId = (joint.id << 16 | 1); - } - if(jointId != -1) { - if(refJointId == -1) { - return jointId; - } - if(firstJointId == -1) { - firstJointId = jointId; - } - if(jointId == refJointId) { - refJointId = -1; - } - } - } - return firstJointId; - }; - Space.prototype.findContactSolver = function (shape1, shape2) { - Advanced.Manager.write('findContactSolver. Length: ' + this._cl); - for(var i = 0; i < this._cl; i++) { - var contactSolver = this.contactSolvers[i]; - if(shape1 == contactSolver.shape1 && shape2 == contactSolver.shape2) { - return contactSolver; - } - } - return null; - }; - Space.prototype.genTemporalContactSolvers = function () { - Advanced.Manager.write('genTemporalContactSolvers'); - this._cl = 0; - this.contactSolvers.length = 0; - this.numContacts = 0; - for(var body1Index = 0; body1Index < this._bl; body1Index++) { - if(!this.bodies[body1Index]) { - continue; - } - this.bodies[body1Index].stepCount = this.stepCount; - for(var body2Index = 0; body2Index < this._bl; body2Index++) { - if(this.bodies[body1Index].inContact(this.bodies[body2Index]) == false) { - continue; - } - Advanced.Manager.write('body1 and body2 intersect'); - for(var i = 0; i < this.bodies[body1Index].shapesLength; i++) { - for(var j = 0; j < this.bodies[body2Index].shapesLength; j++) { - this._shape1 = this.bodies[body1Index].shapes[i]; - this._shape2 = this.bodies[body2Index].shapes[j]; - var contactArr = []; - if(!Advanced.Manager.collision.collide(this._shape1, this._shape2, contactArr)) { - continue; - } - if(this._shape1.type > this._shape2.type) { - var temp = this._shape1; - this._shape1 = this._shape2; - this._shape2 = temp; - } - this.numContacts += contactArr.length; - // Result stored in this._contactSolver (see what we can do about generating some re-usable solvers) - var contactSolver = this.findContactSolver(this._shape1, this._shape2); - Advanced.Manager.write('findContactSolver result: ' + contactSolver); - if(contactSolver) { - contactSolver.update(contactArr); - this.contactSolvers.push(contactSolver); - } else { - Advanced.Manager.write('awake both bodies'); - this.bodies[body1Index].awake(true); - this.bodies[body2Index].awake(true); - var newContactSolver = new Advanced.ContactSolver(this._shape1, this._shape2); - newContactSolver.contacts = contactArr; - newContactSolver.elasticity = Math.max(this._shape1.elasticity, this._shape2.elasticity); - newContactSolver.friction = Math.sqrt(this._shape1.friction * this._shape2.friction); - this.contactSolvers.push(newContactSolver); - Advanced.Manager.write('new contact solver'); - } - } - } - } - } - this._cl = this.contactSolvers.length; - }; - Space.prototype.initSolver = function (warmStarting) { - Advanced.Manager.write('initSolver'); - Advanced.Manager.write('contactSolvers.length: ' + this._cl); - // Initialize contact solvers - for(var c = 0; c < this._cl; c++) { - this.contactSolvers[c].initSolver(this._deltaInv); - // Warm starting (apply cached impulse) - if(warmStarting) { - this.contactSolvers[c].warmStart(); - } - } - // Initialize joint solver - for(var j = 0; j < this.joints.length; j++) { - if(this.joints[j]) { - this.joints[j].initSolver(this._delta, warmStarting); - } - } - // Warm starting (apply cached impulse) - /* - if (warmStarting) - { - for (var c = 0; c < this._cl; c++) - { - this.contactSolvers[c].warmStart(); - } - } - */ - }; - Space.prototype.velocitySolver = function (iterations) { - Advanced.Manager.write('velocitySolver, iterations: ' + iterations + ' csa len: ' + this._cl); - for(var i = 0; i < iterations; i++) { - for(var j = 0; j < this._jl; j++) { - if(this.joints[j]) { - this.joints[j].solveVelocityConstraints(); - } - } - for(var c = 0; c < this._cl; c++) { - this.contactSolvers[c].solveVelocityConstraints(); - } - } - }; - Space.prototype.positionSolver = function (iterations) { - this._positionSolved = false; - for(var i = 0; i < iterations; i++) { - this._contactsOk = true; - this._jointsOk = true; - for(var c = 0; c < this._cl; c++) { - this._contactsOk = this.contactSolvers[c].solvePositionConstraints() && this._contactsOk; - } - for(var j = 0; j < this._jl; j++) { - if(this.joints[j]) { - this._jointsOk = this.joints[j].solvePositionConstraints() && this._jointsOk; - } - } - if(this._contactsOk && this._jointsOk) { - // exit early if the position errors are small - this._positionSolved = true; - break; - } - } - return this._positionSolved; - }; - Space.prototype.step = // Step through the physics simulation - function (dt, velocityIterations, positionIterations, warmStarting, allowSleep) { - Advanced.Manager.clear(); - Advanced.Manager.write('Space step ' + this.stepCount); - this._delta = dt; - this._deltaInv = 1 / dt; - this._bl = this.bodies.length; - this._jl = this.joints.length; - this.stepCount++; - // 1) Generate Contact Solvers (into the this.contactSolvers array) - this.genTemporalContactSolvers(); - Advanced.Manager.dump("Contact Solvers", this.bodies[1]); - // 2) Initialize the Contact Solvers - this.initSolver(warmStarting); - Advanced.Manager.dump("Init Solver", this.bodies[1]); - // 3) Intergrate velocity - for(var i = 0; i < this._bl; i++) { - if(this.bodies[i] && this.bodies[i].isDynamic && this.bodies[i].isAwake) { - this.bodies[i].updateVelocity(this.gravity, this._delta, this.damping); - } - } - Advanced.Manager.dump("Update Velocity", this.bodies[1]); - // 4) Awaken bodies via joints - for(var j = 0; i < this._jl; j++) { - if(!this.joints[j]) { - continue; - } - // combine - var awake1 = this.joints[j].body1.isAwake && !this.joints[j].body1.isStatic; - var awake2 = this.joints[j].body2.isAwake && !this.joints[j].body2.isStatic; - if(awake1 ^ awake2) { - if(!awake1) { - this.joints[j].body1.awake(true); - } - if(!awake2) { - this.joints[j].body2.awake(true); - } - } - } - // 5) Iterative velocity constraints solver - this.velocitySolver(velocityIterations); - Advanced.Manager.dump("Velocity Solvers", this.bodies[1]); - // 6) Intergrate position - for(var i = 0; i < this._bl; i++) { - if(this.bodies[i] && this.bodies[i].isDynamic && this.bodies[i].isAwake) { - this.bodies[i].updatePosition(this._delta); - } - } - Advanced.Manager.dump("Update Position", this.bodies[1]); - // 7) Process breakable joint - for(var i = 0; i < this._jl; i++) { - if(this.joints[i] && this.joints[i].breakable && (this.joints[i].getReactionForce(this._deltaInv).lengthSq() >= this.joints[i].maxForce * this.joints[i].maxForce)) { - this.removeJoint(this.joints[i]); - } - } - // 8) Iterative position constraints solver (result stored in this._positionSolved) - this.positionSolver(positionIterations); - Advanced.Manager.dump("Position Solver", this.bodies[1]); - // 9) Sync the Transforms - for(var i = 0; i < this._bl; i++) { - if(this.bodies[i]) { - this.bodies[i].syncTransform(); - } - } - Advanced.Manager.dump("Sync Transform", this.bodies[1]); - // 10) Post solve collision callback - if(this.postSolve) { - for(var i = 0; i < this._cl; i++) { - this.postSolve(this.contactSolvers[i]); - } - } - // 11) Cache Body Data - for(var i = 0; i < this._bl; i++) { - if(this.bodies[i] && this.bodies[i].isDynamic && this.bodies[i].isAwake) { - this.bodies[i].cacheData('post solve collision callback'); - } - } - Advanced.Manager.dump("Cache Data", this.bodies[1]); - Advanced.Manager.writeAll(); - // 12) Process sleeping - if(allowSleep) { - this._minSleepTime = 999999; - for(var i = 0; i < this._bl; i++) { - if(!this.bodies[i] || this.bodies[i].isDynamic == false) { - continue; - } - if(this.bodies[i].angularVelocity * this.bodies[i].angularVelocity > this._angTolSqr || this.bodies[i].velocity.dot(this.bodies[i].velocity) > this._linTolSqr) { - this.bodies[i].sleepTime = 0; - this._minSleepTime = 0; - } else { - this.bodies[i].sleepTime += this._delta; - this._minSleepTime = Math.min(this._minSleepTime, this.bodies[i].sleepTime); - } - } - if(this._positionSolved && this._minSleepTime >= Space.TIME_TO_SLEEP) { - for(var i = 0; i < this._bl; i++) { - if(this.bodies[i]) { - this.bodies[i].awake(false); - } - } - } - } - }; - return Space; - })(); - Advanced.Space = Space; - })(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(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 = 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, [ - { - 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) { - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - Body - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Advanced) { - var Body = (function () { - 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 - this.joints = []; - this.jointHash = { - }; - this.fixedRotation = false; - this.categoryBits = 0x0001; - this.maskBits = 0xFFFF; - this.stepCount = 0; - this.id = Phaser.Physics.Advanced.Manager.bodyCounter++; - this.name = 'body' + this.id; - this.type = type; - if(sprite) { - this.sprite = sprite; - this.game = sprite.game; - this.position = new Phaser.Vec2(Phaser.Physics.Advanced.Manager.pixelsToMeters(sprite.x), Phaser.Physics.Advanced.Manager.pixelsToMeters(sprite.y)); - this.angle = sprite.rotation; - } else { - 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); - this.centroid = new Phaser.Vec2(); - this.velocity = new Phaser.Vec2(); - this.force = new Phaser.Vec2(); - this.angularVelocity = 0; - this.torque = 0; - this.linearDamping = 0; - this.angularDamping = 0; - this.sleepTime = 0; - this.awaked = false; - this.shapes = []; - this.joints = []; - this.jointHash = { - }; - this.bounds = new Advanced.Bounds(); - this.fixedRotation = false; - this.categoryBits = 0x0001; - 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); - //for (var i = 0; i < this.shapes.length; i++) - //{ - // body.addShape(this.shapes[i].duplicate()); - //} - //body.resetMassData(); - //return body; - }; - Object.defineProperty(Body.prototype, "isDisabled", { - get: function () { - return this.type == Phaser.Types.BODY_DISABLED ? true : false; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Body.prototype, "isStatic", { - get: function () { - return this.type == Phaser.Types.BODY_STATIC ? true : false; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Body.prototype, "isKinetic", { - get: function () { - return this.type == Phaser.Types.BODY_KINETIC ? true : false; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Body.prototype, "isDynamic", { - get: function () { - return this.type == Phaser.Types.BODY_DYNAMIC ? true : false; - }, - enumerable: true, - configurable: true - }); - Body.prototype.setType = function (type) { - if(type == this.type) { - return; - } - this.force.setTo(0, 0); - this.velocity.setTo(0, 0); - this.torque = 0; - this.angularVelocity = 0; - this.type = type; - this.awake(true); - }; - Body.prototype.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; - this.shapes.push(shape); - this.shapesLength = this.shapes.length; - return shape; - }; - Body.prototype.removeShape = function (shape) { - var index = this.shapes.indexOf(shape); - if(index != -1) { - this.shapes.splice(index, 1); - shape.body = undefined; - } - this.shapesLength = this.shapes.length; - }; - Body.prototype.setMass = function (mass) { - this.mass = mass; - this.massInverted = mass > 0 ? 1 / mass : 0; - }; - Body.prototype.setInertia = function (inertia) { - this.inertia = inertia; - this.inertiaInverted = inertia > 0 ? 1 / inertia : 0; - }; - Body.prototype.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); - // 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 - return Phaser.TransformUtils.transform(this.transform, p); - }; - Body.prototype.getWorldVector = function (v) { - // OPTIMISE: Creating new vector - return Phaser.TransformUtils.rotate(this.transform, v); - }; - Body.prototype.getLocalPoint = function (p) { - // OPTIMISE: Creating new vector - return Phaser.TransformUtils.untransform(this.transform, p); - }; - Body.prototype.getLocalVector = function (v) { - // OPTIMISE: Creating new vector - return Phaser.TransformUtils.unrotate(this.transform, v); - }; - Body.prototype.setFixedRotation = function (flag) { - this.fixedRotation = flag; - this.resetMassData(); - }; - Body.prototype.resetMassData = function () { - this.centroid.setTo(0, 0); - this.mass = 0; - this.massInverted = 0; - this.inertia = 0; - this.inertiaInverted = 0; - if(this.isDynamic == false) { - Phaser.TransformUtils.transform(this.transform, this.centroid, this.position); - //this.position.copyFrom(this.transform.transform(this.centroid)); - return; - } - var totalMassCentroid = new Phaser.Vec2(0, 0); - var totalMass = 0; - var totalInertia = 0; - for(var i = 0; i < this.shapes.length; i++) { - var shape = this.shapes[i]; - var centroid = shape.centroid(); - var mass = shape.area() * shape.density; - var inertia = shape.inertia(mass); - //console.log('rmd', centroid, shape); - totalMassCentroid.multiplyAddByScalar(centroid, mass); - totalMass += mass; - totalInertia += inertia; - } - //this.centroid.copy(vec2.scale(totalMassCentroid, 1 / totalMass)); - Phaser.Vec2Utils.scale(totalMassCentroid, 1 / totalMass, this.centroid); - this.setMass(totalMass); - if(!this.fixedRotation) { - //this.setInertia(totalInertia - totalMass * vec2.dot(this.centroid, this.centroid)); - this.setInertia(totalInertia - totalMass * Phaser.Vec2Utils.dot(this.centroid, this.centroid)); - } - //console.log("mass = " + this.m + " inertia = " + this.i); - // Move center of mass - var oldPosition = Phaser.Vec2Utils.clone(this.position); - //this.position.copyFrom(this.transform.transform(this.centroid)); - Phaser.TransformUtils.transform(this.transform, this.centroid, this.position); - // Update center of mass velocity - //this.velocity.mad(vec2.perp(vec2.sub(this.position, old_p)), this.angularVelocity); - oldPosition.subtract(this.position); - this.velocity.multiplyAddByScalar(Phaser.Vec2Utils.perp(oldPosition, oldPosition), this.angularVelocity); - }; - Body.prototype.resetJointAnchors = function () { - for(var i = 0; i < this.joints.length; i++) { - var joint = this.joints[i]; - if(!joint) { - continue; - } - var anchor1 = joint.getWorldAnchor1(); - var anchor2 = joint.getWorldAnchor2(); - joint.setWorldAnchor1(anchor1); - joint.setWorldAnchor2(anchor2); - } - }; - Body.prototype.cacheData = function (source) { - if (typeof source === "undefined") { source = ''; } - 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); - Phaser.Vec2Utils.multiplyAdd(gravity, this.force, this.massInverted, this._tempVec2); - Phaser.Vec2Utils.multiplyAdd(this.velocity, this._tempVec2, dt, this.velocity); - this.angularVelocity = this.angularVelocity + this.torque * this.inertiaInverted * dt; - // Apply damping. - // ODE: dv/dt + c * v = 0 - // Solution: v(t) = v0 * exp(-c * t) - // Time step: v(t + dt) = v0 * exp(-c * (t + dt)) = v0 * exp(-c * t) * exp(-c * dt) = v * exp(-c * dt) - // v2 = exp(-c * dt) * v1 - // Taylor expansion: - // v2 = (1.0f - c * dt) * v1 - this.velocity.scale(this.clamp(1 - dt * (damping + this.linearDamping), 0, 1)); - this.angularVelocity *= this.clamp(1 - dt * (damping + this.angularDamping), 0, 1); - this.force.setTo(0, 0); - this.torque = 0; - }; - Body.prototype.inContact = function (body2) { - if(!body2 || this.stepCount == body2.stepCount) { - return false; - } - if(!(this.isAwake && this.isStatic == false) && !(body2.isAwake && body2.isStatic == false)) { - return false; - } - if(this.isCollidable(body2) == false) { - return false; - } - if(!this.bounds.intersectsBounds(body2.bounds)) { - return false; - } - return true; - }; - Body.prototype.clamp = function (v, min, max) { - return v < min ? min : (v > max ? max : v); - }; - Body.prototype.updatePosition = function (dt) { - //console.log('body update pos', this.position.y); - //console.log('pre add temp', this._tempVec2.y); - //this.position.addself(vec2.scale(this.velocity, dt)); - this.position.add(Phaser.Vec2Utils.scale(this.velocity, dt, this._tempVec2)); - //console.log('post add temp', this._tempVec2.y); - //console.log('post add', this.position.y); - this.angle += this.angularVelocity * dt; - }; - Body.prototype.resetForce = function () { - this.force.setTo(0, 0); - this.torque = 0; - }; - Body.prototype.applyForce = function (force, p) { - if(this.isDynamic == false) { - return; - } - if(this.isAwake == false) { - this.awake(true); - } - this.force.add(force); - // this.f.addself(force); - // this.torque += vec2.cross(vec2.sub(p, this.p), force); - Phaser.Vec2Utils.subtract(p, this.position, this._tempVec2); - this.torque += Phaser.Vec2Utils.cross(this._tempVec2, force); - }; - Body.prototype.applyForceToCenter = function (force) { - if(this.isDynamic == false) { - return; - } - if(this.isAwake == false) { - this.awake(true); - } - this.force.add(force); - }; - Body.prototype.applyTorque = function (torque) { - if(this.isDynamic == false) { - return; - } - if(this.isAwake == false) { - this.awake(true); - } - this.torque += torque; - }; - Body.prototype.applyLinearImpulse = function (impulse, p) { - if(this.isDynamic == false) { - return; - } - if(this.isAwake == false) { - this.awake(true); - } - this.velocity.multiplyAddByScalar(impulse, this.massInverted); - // 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; - }; - Body.prototype.applyAngularImpulse = function (impulse) { - if(this.isDynamic == false) { - return; - } - if(this.isAwake == false) { - this.awake(true); - } - this.angularVelocity += impulse * this.inertiaInverted; - }; - Body.prototype.kineticEnergy = function () { - var vsq = this.velocity.dot(this.velocity); - var wsq = this.angularVelocity * this.angularVelocity; - return 0.5 * (this.mass * vsq + this.inertia * wsq); - }; - Object.defineProperty(Body.prototype, "isAwake", { - get: function () { - return this.awaked; - }, - enumerable: true, - configurable: true - }); - Body.prototype.awake = function (flag) { - this.awaked = flag; - if(flag) { - this.sleepTime = 0; - } else { - this.velocity.setTo(0, 0); - this.angularVelocity = 0; - this.force.setTo(0, 0); - this.torque = 0; - } - }; - Body.prototype.isCollidable = function (other) { - if(this == other) { - return false; - } - if(this.isDynamic == false && other.isDynamic == false) { - return false; - } - if(!(this.maskBits & other.categoryBits) || !(other.maskBits & this.categoryBits)) { - return false; - } - for(var i = 0; i < this.joints.length; i++) { - var joint = this.joints[i]; - if(!this.joints[i] || (!this.joints[i].collideConnected && other.jointHash[this.joints[i].id] != undefined)) { - return false; - } - } - return true; - }; - return Body; - })(); - Advanced.Body = Body; - })(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 53aebce0..903c0f87 100644 --- a/Tests/physics/body1.js +++ b/Tests/physics/body1.js @@ -18,13 +18,6 @@ var walls; var t; function create() { - //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); diff --git a/Tests/physics/body1.ts b/Tests/physics/body1.ts index 6e87f57d..86cb69df 100644 --- a/Tests/physics/body1.ts +++ b/Tests/physics/body1.ts @@ -26,14 +26,6 @@ function create() { - //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 diff --git a/Tests/physics/simple test 1.js b/Tests/physics/simple test 1.js new file mode 100644 index 00000000..7ecb0802 --- /dev/null +++ b/Tests/physics/simple test 1.js @@ -0,0 +1,25 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, null, render); + function init() { + // Using Phasers asset loader we load up a PNG from the assets folder + game.load.image('atari', 'assets/sprites/atari130xe.png'); + game.load.image('ball', 'assets/sprites/shinyball.png'); + game.load.start(); + } + var atari; + var ball; + function create() { + // Add some gravity to the world, otherwise nothing will actually happen + game.physics.gravity.setTo(0, 10); + //atari = game.add.physicsSprite(220/2, 450, 'atari'); + atari = game.add.physicsSprite(320, 450, 'atari'); + // We'll make the atari sprite a static body, so it won't be influenced by gravity or other forces + atari.body.type = Phaser.Types.BODY_STATIC; + ball = game.add.physicsSprite(330, 0, 'ball', null, 0); + } + function render() { + Phaser.DebugUtils.renderPhysicsBody(atari.body); + Phaser.DebugUtils.renderPhysicsBody(ball.body); + } +})(); diff --git a/Tests/physics/simple test 1.ts b/Tests/physics/simple test 1.ts new file mode 100644 index 00000000..c35cc3c1 --- /dev/null +++ b/Tests/physics/simple test 1.ts @@ -0,0 +1,40 @@ +/// + +(function () { + + var game = new Phaser.Game(this, 'game', 800, 600, init, create, null, render); + + function init() { + + // Using Phasers asset loader we load up a PNG from the assets folder + game.load.image('atari', 'assets/sprites/atari130xe.png'); + game.load.image('ball', 'assets/sprites/shinyball.png'); + game.load.start(); + + } + + var atari: Phaser.Sprite; + var ball: Phaser.Sprite; + + function create() { + + // Add some gravity to the world, otherwise nothing will actually happen + game.physics.gravity.setTo(0, 10); + + //atari = game.add.physicsSprite(220/2, 450, 'atari'); + atari = game.add.physicsSprite(320, 450, 'atari'); + // We'll make the atari sprite a static body, so it won't be influenced by gravity or other forces + atari.body.type = Phaser.Types.BODY_STATIC; + + ball = game.add.physicsSprite(330, 0, 'ball', null, 0); + + } + + function render() { + + Phaser.DebugUtils.renderPhysicsBody(atari.body); + Phaser.DebugUtils.renderPhysicsBody(ball.body); + + } + +})(); diff --git a/Tests/scrollzones/blasteroids.js b/Tests/scrollzones/blasteroids.js index 580e2761..cfdfe9cd 100644 --- a/Tests/scrollzones/blasteroids.js +++ b/Tests/scrollzones/blasteroids.js @@ -77,8 +77,8 @@ } } function render() { - ship.body.renderDebugInfo(32, 32); - } + //ship.body.renderDebugInfo(32, 32); + } function recycleBullet(bullet) { if(bullet.exists && bullet.x < -40 || bullet.x > 840 || bullet.y < -40 || bullet.y > 640) { bullet.exists = false; diff --git a/Tests/scrollzones/blasteroids.ts b/Tests/scrollzones/blasteroids.ts index 84bad9e4..df050c54 100644 --- a/Tests/scrollzones/blasteroids.ts +++ b/Tests/scrollzones/blasteroids.ts @@ -122,7 +122,7 @@ function render() { - ship.body.renderDebugInfo(32, 32); + //ship.body.renderDebugInfo(32, 32); } diff --git a/Tests/sprites/create sprite 1.js b/Tests/sprites/create sprite 1.js index 2b5be685..31a73b0c 100644 --- a/Tests/sprites/create sprite 1.js +++ b/Tests/sprites/create sprite 1.js @@ -9,10 +9,7 @@ function create() { // This will create a Sprite positioned at the top-left of the game (0,0) // Try changing the 0, 0 values - game.add.sprite(200, 100, 'bunny'); + game.add.sprite(0, 0, 'bunny'); game.camera.texture.alpha = 0.5; - //game.world.group.texture.flippedX = true; - //game.world.group.transform.origin.setTo(game.stage.centerX, game.stage.centerY); - //game.world.group.transform.skew.x = 1.2; - } + } })(); diff --git a/Tests/sprites/create sprite 1.ts b/Tests/sprites/create sprite 1.ts index 6ea3aebf..a6d1bbb2 100644 --- a/Tests/sprites/create sprite 1.ts +++ b/Tests/sprites/create sprite 1.ts @@ -16,12 +16,9 @@ // This will create a Sprite positioned at the top-left of the game (0,0) // Try changing the 0, 0 values - game.add.sprite(200, 100, 'bunny'); + game.add.sprite(0, 0, 'bunny'); game.camera.texture.alpha = 0.5; - //game.world.group.texture.flippedX = true; - //game.world.group.transform.origin.setTo(game.stage.centerX, game.stage.centerY); - //game.world.group.transform.skew.x = 1.2; } diff --git a/build/phaser.d.ts b/build/phaser.d.ts index 782a3b9c..d09681a8 100644 --- a/build/phaser.d.ts +++ b/build/phaser.d.ts @@ -316,7 +316,7 @@ module Phaser { * @param {Number} height Desired height of this node. * @param {Number} parent The parent branch or node. Pass null to create a root. */ - constructor(manager: Physics.PhysicsManager, x: number, y: number, width: number, height: number, parent?: QuadTree); + constructor(manager: Physics.Manager, x: number, y: number, width: number, height: number, parent?: QuadTree); private _iterator; private _ot; private _i; @@ -325,7 +325,7 @@ module Phaser { private _l; private _overlapProcessed; private _checkObject; - static physics: Physics.PhysicsManager; + static physics: Physics.Manager; /** * Flag for specifying that you want to add an object to the A list. */ @@ -2555,11 +2555,502 @@ module Phaser { } } /** -* Phaser - Physics - Body +* Phaser - 2D Transform +* +* A 2D Transform +*/ +module Phaser { + class Transform { + /** + * Creates a new 2D Transform object. + * @class Transform + * @constructor + * @return {Transform} This object + **/ + constructor(pos: Vec2, angle: number); + public t: Vec2; + public c: number; + public s: number; + public angle: number; + public toString(): string; + public setTo(pos: Vec2, angle: number): Transform; + public setRotation(angle: number): Transform; + public setPosition(p: Vec2): Transform; + public identity(): Transform; + } +} +/** +* Phaser - TransformUtils +* +* A collection of methods useful for manipulating and performing operations on 2D Transforms. +* +*/ +module Phaser { + class TransformUtils { + static rotate(t: Transform, v: Vec2, out?: Vec2): Vec2; + static unrotate(t: Transform, v: Vec2, out?: Vec2): Vec2; + static transform(t: Transform, v: Vec2, out?: Vec2): Vec2; + static untransform(t: Transform, v: Vec2, out?: Vec2): Vec2; + } +} +/** +* Phaser - Advanced Physics - Joint +* +* Based on the work Ju Hyung Lee started in JS PhyRus. +*/ +module Phaser.Physics { + class Joint { + constructor(type: number, body1: Body, body2: Body, collideConnected); + public id: number; + public type: number; + public body1: Body; + public body2: Body; + public collideConnected; + public maxForce: number; + public breakable: bool; + public anchor1: Vec2; + public anchor2: Vec2; + public getWorldAnchor1(): Vec2; + public getWorldAnchor2(): Vec2; + public setWorldAnchor1(anchor1): void; + public setWorldAnchor2(anchor2): void; + } +} +/** +* Phaser - Physics Manager +* +* The Physics Manager is responsible for looking after, creating and colliding +* all of the physics bodies and joints in the world. +*/ +module Phaser.Physics { + class Manager { + constructor(game: Game); + /** + * 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; + static SHAPE_TYPE_POLY: number; + static SHAPE_NUM_TYPES: number; + static JOINT_TYPE_ANGLE: number; + static JOINT_TYPE_REVOLUTE: number; + static JOINT_TYPE_WELD: number; + static JOINT_TYPE_WHEEL: number; + static JOINT_TYPE_PRISMATIC: number; + static JOINT_TYPE_DISTANCE: number; + static JOINT_TYPE_ROPE: number; + static JOINT_TYPE_MOUSE: number; + static JOINT_LINEAR_SLOP: number; + static JOINT_ANGULAR_SLOP: number; + static JOINT_MAX_LINEAR_CORRECTION: number; + static JOINT_MAX_ANGULAR_CORRECTION: number; + static JOINT_LIMIT_STATE_INACTIVE: number; + static JOINT_LIMIT_STATE_AT_LOWER: number; + static JOINT_LIMIT_STATE_AT_UPPER: number; + static JOINT_LIMIT_STATE_EQUAL_LIMITS: number; + static CONTACT_SOLVER_COLLISION_SLOP: number; + static CONTACT_SOLVER_BAUMGARTE: number; + static CONTACT_SOLVER_MAX_LINEAR_CORRECTION: number; + static bodyCounter: number; + static jointCounter: number; + static shapeCounter: number; + public space: Space; + public lastTime: number; + public frameRateHz: number; + public timeDelta: number; + public paused: bool; + public step: bool; + public velocityIterations: number; + public positionIterations: number; + public allowSleep: bool; + public warmStarting: bool; + public gravity: Vec2; + public update(): void; + public addBody(body: Body): void; + public removeBody(body: Body): void; + public addJoint(joint: IJoint): void; + public removeJoint(joint: IJoint): void; + public pixelsToMeters(value: number): number; + public metersToPixels(value: number): number; + static pixelsToMeters(value: number): number; + static metersToPixels(value: number): number; + static p2m(value: number): number; + static m2p(value: number): number; + static areaForCircle(radius_outer: number, radius_inner: number): number; + static inertiaForCircle(mass: number, center: Vec2, radius_outer: number, radius_inner: number): number; + static areaForSegment(a: Vec2, b: Vec2, radius: number): number; + static centroidForSegment(a: Vec2, b: Vec2): Vec2; + static inertiaForSegment(mass: number, a: Vec2, b: Vec2): number; + static areaForPoly(verts: Vec2[]): number; + static centroidForPoly(verts: Vec2[]): Vec2; + static inertiaForPoly(mass: number, verts: Vec2[], offset: Vec2): number; + static inertiaForBox(mass: number, w: number, h: number): number; + static createConvexHull(points): any[]; + } +} +/** +* Phaser - 2D AABB +* +* A 2D AABB object +*/ +module Phaser.Physics { + class Bounds { + /** + * Creates a new 2D AABB object. + * @class Bounds + * @constructor + * @return {Bounds} This object + **/ + constructor(mins?: Vec2, maxs?: Vec2); + public mins: Vec2; + public maxs: Vec2; + public toString(): string; + public setTo(mins: Vec2, maxs: Vec2): void; + public copy(b: Bounds): Bounds; + public clear(): Bounds; + public x : number; + public y : number; + public width : number; + public height : number; + public right : number; + public bottom : number; + public isEmpty(): bool; + public getPerimeter(): number; + public addPoint(p: Vec2): Bounds; + public addBounds(b: Bounds): Bounds; + public addBounds2(mins, maxs): Bounds; + public addExtents(center: Vec2, extent_x: number, extent_y: number): Bounds; + public expand(ax: number, ay: number): Bounds; + public containPoint(p: Vec2): bool; + public intersectsBounds(b: Bounds): bool; + static expand(b: Bounds, ax, ay); + } +} +/** +* Phaser - Advanced Physics - IShape +* +* Based on the work Ju Hyung Lee started in JS PhyRus. +*/ +module Phaser.Physics { + interface IShape { + id: number; + type: number; + elasticity: number; + friction: number; + density: number; + body: Body; + bounds: Bounds; + area(): number; + centroid(): Vec2; + inertia(mass: number): number; + cacheData(xf: Transform); + pointQuery(p: Vec2): bool; + findEdgeByPoint(p: Vec2, minDist: number): number; + findVertexByPoint(p: Vec2, minDist: number): number; + verts: Vec2[]; + planes: Plane[]; + tverts: Vec2[]; + tplanes: Plane[]; + convexity: bool; + } +} +/** +* Phaser - Advanced Physics - Shape +* +* Based on the work Ju Hyung Lee started in JS PhyRus. +*/ +module Phaser.Physics { + class Shape { + constructor(type: number); + public id: number; + public type: number; + public body: Body; + public verts: Vec2[]; + public planes: Plane[]; + public tverts: Vec2[]; + public tplanes: Plane[]; + public convexity: bool; + public elasticity: number; + public friction: number; + public density: number; + public bounds: Bounds; + public findEdgeByPoint(p: Vec2, minDist: number): number; + } +} +/** +* Phaser - Advanced Physics - Contact +* +* Based on the work Ju Hyung Lee started in JS PhyRus. +*/ +module Phaser.Physics { + class Contact { + constructor(p, n, d, hash); + public hash; + public r1: Vec2; + public r2: Vec2; + public r1_local: Vec2; + public r2_local: Vec2; + public bounce: number; + public emn: number; + public emt: number; + public point; + public normal: Vec2; + public depth; + public lambdaNormal; + public lambdaTangential; + } +} +module Phaser.Physics { + class ContactSolver { + constructor(shape1, shape2); + public shape1; + public shape2; + public contacts: Contact[]; + public elasticity: number; + public friction: number; + public update(newContactArr: Contact[]): void; + public initSolver(dt_inv): void; + public warmStart(): void; + public solveVelocityConstraints(): void; + public solvePositionConstraints(): bool; + public clamp(v, min, max); + } +} +/** +* Phaser - Advanced Physics - Shape - Circle +* +* Based on the work Ju Hyung Lee started in JS PhyRus. +*/ +module Phaser.Physics.Shapes { + class Circle extends Shape implements IShape { + constructor(radius: number, x?: number, y?: number); + public radius: number; + public center: Vec2; + public tc: Vec2; + public finishVerts(): void; + public duplicate(): Circle; + public recenter(c: Vec2): void; + public transform(xf: Transform): void; + public untransform(xf: Transform): void; + public area(): number; + public centroid(): Vec2; + public inertia(mass: number): number; + public cacheData(xf: Transform): void; + public pointQuery(p: Vec2): bool; + public findVertexByPoint(p: Vec2, minDist: number): number; + public distanceOnPlane(n, d): void; + } +} +/** +* Phaser - Advanced Physics - Plane +* +* Based on the work Ju Hyung Lee started in JS PhyRus. +*/ +module Phaser.Physics { + class Plane { + constructor(normal: Vec2, d: number); + public normal: Vec2; + public d: number; + } +} +/** +* Phaser - Advanced Physics - Shapes - Convex Polygon +* +* Based on the work Ju Hyung Lee started in JS PhyRus. +*/ +module Phaser.Physics.Shapes { + class Poly extends Shape implements IShape { + constructor(verts?); + public finishVerts(): void; + public duplicate(): Poly; + public recenter(c): void; + public transform(xf: Transform): void; + public untransform(xf: Transform): void; + public area(): number; + public centroid(): Vec2; + public inertia(mass: number): number; + public cacheData(xf: Transform): void; + public pointQuery(p: Vec2): bool; + public findVertexByPoint(p: Vec2, minDist: number): number; + public findEdgeByPoint(p: Vec2, minDist: number): number; + public distanceOnPlane(n: Vec2, d: number): number; + public containPoint(p: Vec2): bool; + public containPointPartial(p, n): bool; + } +} +/** +* Phaser - Advanced Physics - Shapes - Segment +* +* Based on the work Ju Hyung Lee started in JS PhyRus. +*/ +module Phaser.Physics.Shapes { + class Segment extends Shape implements IShape { + constructor(a, b, radius: number); + public a: Vec2; + public b: Vec2; + public radius: number; + public normal: Vec2; + public ta: Vec2; + public tb: Vec2; + public tn: Vec2; + public finishVerts(): void; + public duplicate(): Segment; + public recenter(c): void; + public transform(xf: Transform): void; + public untransform(xf: Transform): void; + public area(): number; + public centroid(): Vec2; + public inertia(mass: number): number; + public cacheData(xf: Transform): void; + public pointQuery(p: Vec2): bool; + public findVertexByPoint(p: Vec2, minDist: number): number; + public distanceOnPlane(n, d): number; + } +} +/** +* Phaser - Advanced Physics - Collision Handlers +* +* Based on the work Ju Hyung Lee started in JS PhyRus. +*/ +module Phaser.Physics { + class Collision { + public collide(a, b, contacts: Contact[]): number; + private _circle2Circle(c1, r1, c2, r2, contactArr); + public circle2Circle(circ1: Shapes.Circle, circ2: Shapes.Circle, contactArr: Contact[]): number; + public circle2Segment(circ: Shapes.Circle, seg: Shapes.Segment, contactArr: Contact[]): number; + public circle2Poly(circ: Shapes.Circle, poly: Shapes.Poly, contactArr: Contact[]): number; + public segmentPointDistanceSq(seg: Shapes.Segment, p): number; + public segment2Segment(seg1: Shapes.Segment, seg2: Shapes.Segment, contactArr: Contact[]): number; + public findPointsBehindSeg(contactArr: Contact[], seg: Shapes.Segment, poly: Shapes.Poly, dist: number, coef: number): void; + public segment2Poly(seg: Shapes.Segment, poly: Shapes.Poly, contactArr: Contact[]): number; + public findMSA(poly: Shapes.Poly, planes: Plane[], num: number): { + dist: number; + index: number; + }; + public findVertsFallback(contactArr: Contact[], poly1: Shapes.Poly, poly2: Shapes.Poly, n, dist: number): number; + public findVerts(contactArr: Contact[], poly1: Shapes.Poly, poly2: Shapes.Poly, n, dist: number): number; + public poly2Poly(poly1: Shapes.Poly, poly2: Shapes.Poly, contactArr: Contact[]): number; + } +} +/** +* Phaser - Advanced Physics - Joint +* +* Based on the work Ju Hyung Lee started in JS PhyRus. +*/ +module Phaser.Physics { + interface IJoint { + id: number; + type: number; + body1: Body; + body2: Body; + collideConnected; + maxForce: number; + breakable: bool; + anchor1: Vec2; + anchor2: Vec2; + getWorldAnchor1(); + getWorldAnchor2(); + setWorldAnchor1(anchor1); + setWorldAnchor2(anchor2); + initSolver(dt, warmStarting); + solveVelocityConstraints(); + solvePositionConstraints(); + getReactionForce(dt_inv); + } +} +/** +* Phaser - Advanced Physics - Space +* +* Based on the work Ju Hyung Lee started in JS PhyRus. +*/ +module Phaser.Physics { + class Space { + constructor(manager: Manager); + private _manager; + private _delta; + private _deltaInv; + private _bl; + private _jl; + private _cl; + private _linTolSqr; + private _angTolSqr; + private _minSleepTime; + private _positionSolved; + private _shape1; + private _shape2; + private _contactsOk; + private _jointsOk; + private bodyHash; + private jointHash; + static TIME_TO_SLEEP: number; + static SLEEP_LINEAR_TOLERANCE: number; + static SLEEP_ANGULAR_TOLERANCE: number; + public bodies: Body[]; + public joints: IJoint[]; + public numContacts: number; + public contactSolvers: ContactSolver[]; + public postSolve; + public gravity: Vec2; + public damping: number; + public stepCount: number; + public clear(): void; + public addBody(body: Body): void; + public removeBody(body: Body): void; + public addJoint(joint: IJoint): void; + public removeJoint(joint: IJoint): void; + public findShapeByPoint(p, refShape); + public findBodyByPoint(p, refBody: Body); + public shapeById(id): IShape; + public jointById(id): IJoint; + public findVertexByPoint(p, minDist, refVertexId): number; + public findEdgeByPoint(p, minDist, refEdgeId): number; + public findJointByPoint(p, minDist, refJointId): number; + private findContactSolver(shape1, shape2); + private genTemporalContactSolvers(); + private initSolver(warmStarting); + private velocitySolver(iterations); + private positionSolver(iterations); + public step(dt: number, velocityIterations: number, positionIterations: number, warmStarting: bool, allowSleep: bool): void; + } +} +/** +* Phaser - Advanced Physics - Shapes - Triangle +* +* Based on the work Ju Hyung Lee started in JS PhyRus. +*/ +module Phaser.Physics.Shapes { + class Triangle extends Poly { + constructor(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number); + } +} +/** +* Phaser - Advanced Physics - Shapes - Box +* +* Based on the work Ju Hyung Lee started in JS PhyRus. +*/ +module Phaser.Physics.Shapes { + class Box extends Poly { + constructor(x, y, width, height); + } +} +/** +* Phaser - Advanced Physics - Body +* +* Based on the work Ju Hyung Lee started in JS PhyRus. */ module Phaser.Physics { class Body { - constructor(sprite: Sprite, type: number); + constructor(sprite: Sprite, type: number, x?: number, y?: number, shapeType?: number); + public toString(): string; + private _tempVec2; /** * Reference to Phaser.Game */ @@ -2569,6 +3060,14 @@ module Phaser.Physics { */ public sprite: Sprite; /** + * The Body ID + */ + public id: number; + /** + * The Body name + */ + public name: string; + /** * The type of Body (disabled, dynamic, static or kinematic) * Disabled = skips all physics operations / tests (default) * Dynamic = gives and receives impacts @@ -2577,53 +3076,71 @@ module Phaser.Physics { * @type {number} */ public type: number; - public gravity: Vec2; - public bounce: Vec2; - public velocity: Vec2; - public acceleration: Vec2; - public drag: Vec2; - public maxVelocity: Vec2; - public angularVelocity: number; - public angularAcceleration: number; - public angularDrag: number; - public maxAngular: number; - /** - * Orientation of the object. - * @type {number} - */ - public facing: number; - public touching: number; - public allowCollisions: number; - public wasTouching: number; - public mass: number; + public angle: number; + public transform: Transform; + public centroid: Vec2; public position: Vec2; - public oldPosition: Vec2; - public offset: Vec2; - public bounds: Rectangle; - private _width; - private _height; - public x : number; - public y : number; - public width : number; - public height : number; - public preUpdate(): void; - public postUpdate(): void; - public hullWidth : number; - public hullHeight : number; - public hullX : number; - public hullY : number; - public deltaXAbs : number; - public deltaYAbs : number; - public deltaX : number; - public deltaY : number; - public render(context: CanvasRenderingContext2D): void; - /** - * Render debug infos. (including name, bounds info, position and some other properties) - * @param x {number} X position of the debug info to be rendered. - * @param y {number} Y position of the debug info to be rendered. - * @param [color] {number} color of the debug info to be rendered. (format is css color string) - */ - public renderDebugInfo(x: number, y: number, color?: string): void; + public velocity: Vec2; + public force: Vec2; + public angularVelocity: number; + public torque: number; + public linearDamping: number; + public angularDamping: number; + public sleepTime: number; + public awaked: bool; + public allowCollisions: number; + public shapes: IShape[]; + public shapesLength: number; + 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; + public stepCount: number; + public space: Space; + public duplicate(): void; + public isDisabled : bool; + public isStatic : bool; + public isKinetic : bool; + public isDynamic : bool; + public setType(type: number): void; + public addPoly(verts, elasticity?: number, friction?: number, density?: number): Shapes.Poly; + public addTriangle(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, elasticity?: number, friction?: number, density?: number): Shapes.Triangle; + public addBox(x: number, y: number, width: number, height: number, elasticity?: number, friction?: number, density?: number): Shapes.Box; + public addCircle(radius: number, x?: number, y?: number, elasticity?: number, friction?: number, density?: number): Shapes.Circle; + public addShape(shape); + public removeShape(shape): void; + private setMass(mass); + private setInertia(inertia); + public setTransform(pos, angle): void; + public syncTransform(): void; + public getWorldPoint(p: Vec2): Vec2; + public getWorldVector(v: Vec2): Vec2; + public getLocalPoint(p: Vec2): Vec2; + public getLocalVector(v: Vec2): Vec2; + public setFixedRotation(flag): void; + public resetMassData(): void; + public resetJointAnchors(): void; + public cacheData(source?: string): void; + public updateVelocity(gravity, dt, damping): void; + public inContact(body2: Body): bool; + public clamp(v, min, max); + public updatePosition(dt: number): void; + public resetForce(): void; + public applyForce(force: Vec2, p: Vec2): void; + public applyForceToCenter(force: Vec2): void; + public applyTorque(torque: number): void; + public applyLinearImpulse(impulse: Vec2, p: Vec2): void; + public applyAngularImpulse(impulse: number): void; + public kineticEnergy(): number; + public isAwake : bool; + public awake(flag): void; + public isCollidable(other: Body): bool; } } /** @@ -2638,9 +3155,10 @@ module Phaser { * @param [x] {number} the initial x position of the sprite. * @param [y] {number} the initial y position of the sprite. * @param [key] {string} Key of the graphic you want to load for this sprite. - * @param [bodyType] {number} The physics body type of the object (defaults to BODY_DYNAMIC) + * @param [bodyType] {number} The physics body type of the object (defaults to BODY_DISABLED) + * @param [shapeType] {number} The physics shape the body will consist of (either Box (0) or Circle (1), for custom types see body.addShape) */ - constructor(game: Game, x?: number, y?: number, key?: string, frame?, bodyType?: number); + constructor(game: Game, x?: number, y?: number, key?: string, frame?, bodyType?: number, shapeType?: number); /** * Reference to the main game object */ @@ -2767,7 +3285,7 @@ module Phaser { */ public preUpdate(): void; /** - * Override this function to update your class's position and appearance. + * Override this function to update your sprites position and appearance. */ public update(): void; /** @@ -5192,14 +5710,7 @@ module Phaser { */ public lifespan: number; /** - * Determines how quickly the particles come to rest on the ground. - * Only used if the particle has gravity-like acceleration applied. - * @default 500 - */ - public friction: number; - /** - * The particle's main update logic. Basically it checks to see if it should - * be dead yet, and then has some special bounce behavior if there is some gravity on it. + * The particle's main update logic. Basically it checks to see if it should be dead yet. */ public update(): void; /** @@ -6149,6 +6660,17 @@ module Phaser { */ public sprite(x: number, y: number, key?: string, frame?, bodyType?: number): Sprite; /** + * Create a new Sprite with the physics automatically created and set to DYNAMIC. The Sprite position offset is set to its center. + * + * @param x {number} X position of the new sprite. + * @param y {number} Y position of the new sprite. + * @param [key] {string} The image key as defined in the Game.Cache to use as the texture for this sprite + * @param [frame] {string|number} If the sprite uses an image from a texture atlas or sprite sheet you can pass the frame here. Either a number for a frame ID or a string for a frame name. + * @param [shapeType] The default body shape is either 0 for a Box or 1 for a Circle. See Sprite.body.addShape for custom shapes (polygons, etc) + * @returns {Sprite} The newly created sprite object. + */ + public physicsSprite(x: number, y: number, key?: string, frame?, shapeType?: number): Sprite; + /** * Create a new DynamicTexture with specific size. * * @param width {number} Width of the texture. @@ -7040,196 +7562,6 @@ module Phaser { } } /** -* Phaser - CircleUtils -* -* A collection of methods useful for manipulating and comparing Circle objects. -* -* TODO: -*/ -module Phaser { - class CircleUtils { - /** - * Returns a new Circle object with the same values for the x, y, width, and height properties as the original Circle object. - * @method clone - * @param {Circle} a - The Circle object. - * @param {Circle} [optional] out Optional Circle object. If given the values will be set into the object, otherwise a brand new Circle object will be created and returned. - * @return {Phaser.Circle} - **/ - static clone(a: Circle, out?: Circle): Circle; - /** - * Return true if the given x/y coordinates are within the Circle object. - * If you need details about the intersection then use Phaser.Intersect.circleContainsPoint instead. - * @method contains - * @param {Circle} a - The Circle object. - * @param {Number} The X value of the coordinate to test. - * @param {Number} The Y value of the coordinate to test. - * @return {Boolean} True if the coordinates are within this circle, otherwise false. - **/ - static contains(a: Circle, x: number, y: number): bool; - /** - * Return true if the coordinates of the given Point object are within this Circle object. - * If you need details about the intersection then use Phaser.Intersect.circleContainsPoint instead. - * @method containsPoint - * @param {Circle} a - The Circle object. - * @param {Point} The Point object to test. - * @return {Boolean} True if the coordinates are within this circle, otherwise false. - **/ - static containsPoint(a: Circle, point: Point): bool; - /** - * Return true if the given Circle is contained entirely within this Circle object. - * If you need details about the intersection then use Phaser.Intersect.circleToCircle instead. - * @method containsCircle - * @param {Circle} The Circle object to test. - * @return {Boolean} True if the coordinates are within this circle, otherwise false. - **/ - static containsCircle(a: Circle, b: Circle): bool; - /** - * Returns the distance from the center of the Circle object to the given object (can be Circle, Point or anything with x/y properties) - * @method distanceBetween - * @param {Circle} a - The Circle object. - * @param {Circle} b - The target object. Must have visible x and y properties that represent the center of the object. - * @param {Boolean} [optional] round - Round the distance to the nearest integer (default false) - * @return {Number} The distance between this Point object and the destination Point object. - **/ - static distanceBetween(a: Circle, target: any, round?: bool): number; - /** - * Determines whether the two Circle objects match. This method compares the x, y and diameter properties. - * @method equals - * @param {Circle} a - The first Circle object. - * @param {Circle} b - The second Circle object. - * @return {Boolean} A value of true if the object has exactly the same values for the x, y and diameter properties as this Circle object; otherwise false. - **/ - static equals(a: Circle, b: Circle): bool; - /** - * Determines whether the two Circle objects intersect. - * This method checks the radius distances between the two Circle objects to see if they intersect. - * @method intersects - * @param {Circle} a - The first Circle object. - * @param {Circle} b - The second Circle object. - * @return {Boolean} A value of true if the specified object intersects with this Circle object; otherwise false. - **/ - static intersects(a: Circle, b: Circle): bool; - /** - * Returns a Point object containing the coordinates of a point on the circumference of the Circle based on the given angle. - * @method circumferencePoint - * @param {Circle} a - The first Circle object. - * @param {Number} angle The angle in radians (unless asDegrees is true) to return the point from. - * @param {Boolean} asDegrees Is the given angle in radians (false) or degrees (true)? - * @param {Phaser.Point} [optional] output An optional Point object to put the result in to. If none specified a new Point object will be created. - * @return {Phaser.Point} The Point object holding the result. - **/ - static circumferencePoint(a: Circle, angle: number, asDegrees?: bool, out?: Point): Point; - static intersectsRectangle(c: Circle, r: Rectangle): bool; - } -} -/** -* Phaser - PhysicsManager -* -* Your game only has one PhysicsManager instance and it's responsible for looking after, creating and colliding -* all of the physics objects in the world. -*/ -module Phaser.Physics { - class PhysicsManager { - constructor(game: Game, width: number, height: number); - /** - * Local private reference to Game. - */ - public game: Game; - /** - * Physics object pool - */ - public members: Group; - private _drag; - private _delta; - private _velocityDelta; - private _length; - private _distance; - private _tangent; - private _separatedX; - private _separatedY; - private _overlap; - private _maxOverlap; - private _obj1Velocity; - private _obj2Velocity; - private _obj1NewVelocity; - private _obj2NewVelocity; - private _average; - private _quadTree; - private _quadTreeResult; - public bounds: Rectangle; - public gravity: Vec2; - public drag: Vec2; - public bounce: Vec2; - public angularDrag: number; - /** - * The overlap bias is used when calculating hull overlap before separation - change it if you have especially small or large GameObjects - * @type {number} - */ - static OVERLAP_BIAS: number; - /** - * The overlap bias is used when calculating hull overlap before separation - change it if you have especially small or large GameObjects - * @type {number} - */ - static TILE_OVERLAP: bool; - /** - * @type {number} - */ - public worldDivisions: number; - public updateMotion(body: Body): void; - /** - * A tween-like function that takes a starting velocity and some other factors and returns an altered velocity. - * - * @param {number} Velocity Any component of velocity (e.g. 20). - * @param {number} Acceleration Rate at which the velocity is changing. - * @param {number} Drag Really kind of a deceleration, this is how much the velocity changes if Acceleration is not set. - * @param {number} Max An absolute value cap for the velocity. - * - * @return {number} The altered Velocity value. - */ - public computeVelocity(velocity: number, gravity?: number, acceleration?: number, drag?: number, max?: number): number; - /** - * The core Collision separation method. - * @param body1 The first Physics.Body to separate - * @param body2 The second Physics.Body to separate - * @returns {boolean} Returns true if the bodies were separated, otherwise false. - */ - public separate(body1: Body, body2: Body): bool; - public checkHullIntersection(body1: Body, body2: Body): bool; - /** - * Separates the two objects on their x axis - * @param object1 The first GameObject to separate - * @param object2 The second GameObject to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the X axis. - */ - public separateBodyX(body1: Body, body2: Body): bool; - /** - * Separates the two objects on their y axis - * @param object1 The first GameObject to separate - * @param object2 The second GameObject to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis. - */ - public separateBodyY(body1: Body, body2: Body): bool; - /** - * Checks for overlaps between two objects using the world QuadTree. Can be Sprite vs. Sprite, Sprite vs. Group or Group vs. Group. - * Note: Does not take the objects scrollFactor into account. All overlaps are check in world space. - * @param object1 The first Sprite or Group to check. If null the world.group is used. - * @param object2 The second Sprite or Group to check. - * @param notifyCallback A callback function that is called if the objects overlap. The two objects will be passed to this function in the same order in which you passed them to Collision.overlap. - * @param processCallback A callback function that lets you perform additional checks against the two objects if they overlap. If this is set then notifyCallback will only be called if processCallback returns true. - * @param context The context in which the callbacks will be called - * @returns {boolean} true if the objects overlap, otherwise false. - */ - public overlap(object1?, object2?, notifyCallback?, processCallback?, context?): bool; - /** - * Collision resolution specifically for GameObjects vs. Tiles. - * @param object The GameObject to separate - * @param tile The Tile to separate - * @returns {boolean} Whether the objects in fact touched and were separated - */ - public separateTile(object: Sprite, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool, collideUp: bool, collideDown: bool, separateX: bool, separateY: bool): bool; - } -} -/** * Phaser - World * * "This world is but a canvas to our imagination." - Henry David Thoreau @@ -7268,10 +7600,10 @@ module Phaser { */ public bounds: Rectangle; /** - * Reference to the physics manager. - * @type {Physics.PhysicsManager} + * The Gravity of the World (defaults to 0,0, or no gravity at all) + * @type {Vec2} */ - public physics: Physics.PhysicsManager; + public gravity: Vec2; /** * Object container stores every object created with `create*` methods. * @type {Group} @@ -7301,7 +7633,7 @@ module Phaser { * @param height {number} New height of the world. * @param [updateCameraBounds] {boolean} Update camera bounds automatically or not. Default to true. */ - public setSize(width: number, height: number, updateCameraBounds?: bool, updatePhysicsBounds?: bool): void; + public setSize(width: number, height: number, updateCameraBounds?: bool): void; public width : number; public height : number; public centerX : number; @@ -8957,6 +9289,11 @@ module Phaser { class DebugUtils { static game: Game; /** + * Render context of stage's canvas. + * @type {CanvasRenderingContext2D} + */ + static context: CanvasRenderingContext2D; + /** * Render debug infos. (including name, bounds info, position and some other properties) * @param x {number} X position of the debug info to be rendered. * @param y {number} Y position of the debug info to be rendered. @@ -8964,7 +9301,7 @@ module Phaser { */ static renderSpriteInfo(sprite: Sprite, x: number, y: number, color?: string): void; static renderSpriteBounds(sprite: Sprite, camera?: Camera, color?: string): void; - static renderSpritePhysicsBody(sprite: Sprite, camera?: Camera, color?: string): void; + static renderPhysicsBody(body: Physics.Body, lineWidth?: number, fillStyle?: string, sleepStyle?: string): void; } } /** @@ -8999,16 +9336,6 @@ module Phaser { */ public _raf: RequestAnimationFrame; /** - * Max allowable accumulation. - * @type {number} - */ - private _maxAccumulation; - /** - * Total number of milliseconds elapsed since last update loop. - * @type {number} - */ - private _accumulator; - /** * Milliseconds of time per step of the game loop. * @type {number} */ @@ -9123,6 +9450,11 @@ module Phaser { */ public world: World; /** + * Reference to the physics manager. + * @type {Physics.Manager} + */ + public physics: Physics.Manager; + /** * Instance of repeatable random data generator helper. * @type {RandomDataGenerator} */ @@ -9196,7 +9528,6 @@ module Phaser { */ public destroy(): void; public paused : bool; - public framerate : number; /** * Checks for overlaps between two objects using the world QuadTree. Can be GameObject vs. GameObject, GameObject vs. Group or Group vs. Group. * Note: Does not take the objects scrollFactor into account. All overlaps are check in world space. @@ -9392,6 +9723,89 @@ module Phaser { } } /** +* Phaser - CircleUtils +* +* A collection of methods useful for manipulating and comparing Circle objects. +* +* TODO: +*/ +module Phaser { + class CircleUtils { + /** + * Returns a new Circle object with the same values for the x, y, width, and height properties as the original Circle object. + * @method clone + * @param {Circle} a - The Circle object. + * @param {Circle} [optional] out Optional Circle object. If given the values will be set into the object, otherwise a brand new Circle object will be created and returned. + * @return {Phaser.Circle} + **/ + static clone(a: Circle, out?: Circle): Circle; + /** + * Return true if the given x/y coordinates are within the Circle object. + * If you need details about the intersection then use Phaser.Intersect.circleContainsPoint instead. + * @method contains + * @param {Circle} a - The Circle object. + * @param {Number} The X value of the coordinate to test. + * @param {Number} The Y value of the coordinate to test. + * @return {Boolean} True if the coordinates are within this circle, otherwise false. + **/ + static contains(a: Circle, x: number, y: number): bool; + /** + * Return true if the coordinates of the given Point object are within this Circle object. + * If you need details about the intersection then use Phaser.Intersect.circleContainsPoint instead. + * @method containsPoint + * @param {Circle} a - The Circle object. + * @param {Point} The Point object to test. + * @return {Boolean} True if the coordinates are within this circle, otherwise false. + **/ + static containsPoint(a: Circle, point: Point): bool; + /** + * Return true if the given Circle is contained entirely within this Circle object. + * If you need details about the intersection then use Phaser.Intersect.circleToCircle instead. + * @method containsCircle + * @param {Circle} The Circle object to test. + * @return {Boolean} True if the coordinates are within this circle, otherwise false. + **/ + static containsCircle(a: Circle, b: Circle): bool; + /** + * Returns the distance from the center of the Circle object to the given object (can be Circle, Point or anything with x/y properties) + * @method distanceBetween + * @param {Circle} a - The Circle object. + * @param {Circle} b - The target object. Must have visible x and y properties that represent the center of the object. + * @param {Boolean} [optional] round - Round the distance to the nearest integer (default false) + * @return {Number} The distance between this Point object and the destination Point object. + **/ + static distanceBetween(a: Circle, target: any, round?: bool): number; + /** + * Determines whether the two Circle objects match. This method compares the x, y and diameter properties. + * @method equals + * @param {Circle} a - The first Circle object. + * @param {Circle} b - The second Circle object. + * @return {Boolean} A value of true if the object has exactly the same values for the x, y and diameter properties as this Circle object; otherwise false. + **/ + static equals(a: Circle, b: Circle): bool; + /** + * Determines whether the two Circle objects intersect. + * This method checks the radius distances between the two Circle objects to see if they intersect. + * @method intersects + * @param {Circle} a - The first Circle object. + * @param {Circle} b - The second Circle object. + * @return {Boolean} A value of true if the specified object intersects with this Circle object; otherwise false. + **/ + static intersects(a: Circle, b: Circle): bool; + /** + * Returns a Point object containing the coordinates of a point on the circumference of the Circle based on the given angle. + * @method circumferencePoint + * @param {Circle} a - The first Circle object. + * @param {Number} angle The angle in radians (unless asDegrees is true) to return the point from. + * @param {Boolean} asDegrees Is the given angle in radians (false) or degrees (true)? + * @param {Phaser.Point} [optional] output An optional Point object to put the result in to. If none specified a new Point object will be created. + * @return {Phaser.Point} The Point object holding the result. + **/ + static circumferencePoint(a: Circle, angle: number, asDegrees?: bool, out?: Point): Point; + static intersectsRectangle(c: Circle, r: Rectangle): bool; + } +} +/** * Phaser - Mat3Utils * * A collection of methods useful for manipulating and performing operations on Mat3 objects. @@ -9424,694 +9838,6 @@ module Phaser { } } /** -* Phaser - 2D Transform -* -* A 2D Transform -*/ -module Phaser { - class Transform { - /** - * Creates a new 2D Transform object. - * @class Transform - * @constructor - * @return {Transform} This object - **/ - constructor(pos: Vec2, angle: number); - public t: Vec2; - public c: number; - public s: number; - public angle: number; - public toString(): string; - public setTo(pos: Vec2, angle: number): Transform; - public setRotation(angle: number): Transform; - public setPosition(p: Vec2): Transform; - public identity(): Transform; - } -} -/** -* Phaser - TransformUtils -* -* A collection of methods useful for manipulating and performing operations on 2D Transforms. -* -*/ -module Phaser { - class TransformUtils { - static rotate(t: Transform, v: Vec2, out?: Vec2): Vec2; - static unrotate(t: Transform, v: Vec2, out?: Vec2): Vec2; - static transform(t: Transform, v: Vec2, out?: Vec2): Vec2; - static untransform(t: Transform, v: Vec2, out?: Vec2): Vec2; - } -} -/** -* Phaser - PhysicsManager -* -* Your game only has one PhysicsManager instance and it's responsible for looking after, creating and colliding -* all of the physics objects in the world. -*/ -module Phaser.Physics { - class ArcadePhysics { - constructor(game: Game, width: number, height: number); - /** - * Local private reference to Game. - */ - public game: Game; - /** - * Physics object pool - */ - public members: Group; - private _drag; - private _delta; - private _velocityDelta; - private _length; - private _distance; - private _tangent; - private _separatedX; - private _separatedY; - private _overlap; - private _maxOverlap; - private _obj1Velocity; - private _obj2Velocity; - private _obj1NewVelocity; - private _obj2NewVelocity; - private _average; - private _quadTree; - private _quadTreeResult; - public bounds: Rectangle; - public gravity: Vec2; - public drag: Vec2; - public bounce: Vec2; - public angularDrag: number; - /** - * The overlap bias is used when calculating hull overlap before separation - change it if you have especially small or large GameObjects - * @type {number} - */ - static OVERLAP_BIAS: number; - /** - * The overlap bias is used when calculating hull overlap before separation - change it if you have especially small or large GameObjects - * @type {number} - */ - static TILE_OVERLAP: bool; - /** - * @type {number} - */ - public worldDivisions: number; - public updateMotion(body: Body): void; - /** - * A tween-like function that takes a starting velocity and some other factors and returns an altered velocity. - * - * @param {number} Velocity Any component of velocity (e.g. 20). - * @param {number} Acceleration Rate at which the velocity is changing. - * @param {number} Drag Really kind of a deceleration, this is how much the velocity changes if Acceleration is not set. - * @param {number} Max An absolute value cap for the velocity. - * - * @return {number} The altered Velocity value. - */ - public computeVelocity(velocity: number, gravity?: number, acceleration?: number, drag?: number, max?: number): number; - /** - * The core Collision separation method. - * @param body1 The first Physics.Body to separate - * @param body2 The second Physics.Body to separate - * @returns {boolean} Returns true if the bodies were separated, otherwise false. - */ - public separate(body1: Body, body2: Body): bool; - public checkHullIntersection(body1: Body, body2: Body): bool; - /** - * Separates the two objects on their x axis - * @param object1 The first GameObject to separate - * @param object2 The second GameObject to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the X axis. - */ - public separateBodyX(body1: Body, body2: Body): bool; - /** - * Separates the two objects on their y axis - * @param object1 The first GameObject to separate - * @param object2 The second GameObject to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis. - */ - public separateBodyY(body1: Body, body2: Body): bool; - /** - * Checks for overlaps between two objects using the world QuadTree. Can be Sprite vs. Sprite, Sprite vs. Group or Group vs. Group. - * Note: Does not take the objects scrollFactor into account. All overlaps are check in world space. - * @param object1 The first Sprite or Group to check. If null the world.group is used. - * @param object2 The second Sprite or Group to check. - * @param notifyCallback A callback function that is called if the objects overlap. The two objects will be passed to this function in the same order in which you passed them to Collision.overlap. - * @param processCallback A callback function that lets you perform additional checks against the two objects if they overlap. If this is set then notifyCallback will only be called if processCallback returns true. - * @param context The context in which the callbacks will be called - * @returns {boolean} true if the objects overlap, otherwise false. - */ - public overlap(object1?, object2?, notifyCallback?, processCallback?, context?): bool; - /** - * Collision resolution specifically for GameObjects vs. Tiles. - * @param object The GameObject to separate - * @param tile The Tile to separate - * @returns {boolean} Whether the objects in fact touched and were separated - */ - public separateTile(object: Sprite, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool, collideUp: bool, collideDown: bool, separateX: bool, separateY: bool): bool; - } -} -/** -* Phaser - Advanced Physics - Joint -* -* Based on the work Ju Hyung Lee started in JS PhyRus. -*/ -module Phaser.Physics.Advanced { - class Joint { - constructor(type: number, body1: Body, body2: Body, collideConnected); - public id: number; - public type: number; - public body1: Body; - public body2: Body; - public collideConnected; - public maxForce: number; - public breakable: bool; - public anchor1: Vec2; - public anchor2: Vec2; - public getWorldAnchor1(): Vec2; - public getWorldAnchor2(): Vec2; - public setWorldAnchor1(anchor1): void; - public setWorldAnchor2(anchor2): void; - } -} -/** -* Phaser - Advanced Physics Manager -* -* Your game only has one PhysicsManager instance and it's responsible for looking after, creating and colliding -* all of the physics objects in the world. -*/ -module Phaser.Physics.Advanced { - class Manager { - constructor(game: Game); - /** - * Local reference to Game. - */ - public game: Game; - static debug: HTMLTextAreaElement; - static clear(): void; - static write(s: string): void; - static writeAll(): void; - static log: any[]; - static dump(phase: string, body: Body): void; - static collision: Collision; - static SHAPE_TYPE_CIRCLE: number; - static SHAPE_TYPE_SEGMENT: number; - static SHAPE_TYPE_POLY: number; - static SHAPE_NUM_TYPES: number; - static JOINT_TYPE_ANGLE: number; - static JOINT_TYPE_REVOLUTE: number; - static JOINT_TYPE_WELD: number; - static JOINT_TYPE_WHEEL: number; - static JOINT_TYPE_PRISMATIC: number; - static JOINT_TYPE_DISTANCE: number; - static JOINT_TYPE_ROPE: number; - static JOINT_TYPE_MOUSE: number; - static JOINT_LINEAR_SLOP: number; - static JOINT_ANGULAR_SLOP: number; - static JOINT_MAX_LINEAR_CORRECTION: number; - static JOINT_MAX_ANGULAR_CORRECTION: number; - static JOINT_LIMIT_STATE_INACTIVE: number; - static JOINT_LIMIT_STATE_AT_LOWER: number; - static JOINT_LIMIT_STATE_AT_UPPER: number; - static JOINT_LIMIT_STATE_EQUAL_LIMITS: number; - static CONTACT_SOLVER_COLLISION_SLOP: number; - static CONTACT_SOLVER_BAUMGARTE: number; - static CONTACT_SOLVER_MAX_LINEAR_CORRECTION: number; - static bodyCounter: number; - static jointCounter: number; - static shapeCounter: number; - public space: Space; - public lastTime: number; - public frameRateHz: number; - public timeDelta: number; - public paused: bool; - public step: bool; - public velocityIterations: number; - public positionIterations: number; - public allowSleep: bool; - public warmStarting: bool; - public update(): void; - public pixelsToMeters(value: number): number; - public metersToPixels(value: number): number; - static pixelsToMeters(value: number): number; - static metersToPixels(value: number): number; - static p2m(value: number): number; - static m2p(value: number): number; - static areaForCircle(radius_outer: number, radius_inner: number): number; - static inertiaForCircle(mass: number, center: Vec2, radius_outer: number, radius_inner: number): number; - static areaForSegment(a: Vec2, b: Vec2, radius: number): number; - static centroidForSegment(a: Vec2, b: Vec2): Vec2; - static inertiaForSegment(mass: number, a: Vec2, b: Vec2): number; - static areaForPoly(verts: Vec2[]): number; - static centroidForPoly(verts: Vec2[]): Vec2; - static inertiaForPoly(mass: number, verts: Vec2[], offset: Vec2): number; - static inertiaForBox(mass: number, w: number, h: number): number; - static createConvexHull(points): any[]; - } -} -/** -* Phaser - 2D AABB -* -* A 2D AABB object -*/ -module Phaser.Physics.Advanced { - class Bounds { - /** - * Creates a new 2D AABB object. - * @class Bounds - * @constructor - * @return {Bounds} This object - **/ - constructor(mins?: Vec2, maxs?: Vec2); - public mins: Vec2; - public maxs: Vec2; - public toString(): string; - public setTo(mins: Vec2, maxs: Vec2): void; - public copy(b: Bounds): Bounds; - public clear(): Bounds; - public x : number; - public y : number; - public width : number; - public height : number; - public isEmpty(): bool; - public getPerimeter(): number; - public addPoint(p: Vec2): Bounds; - public addBounds(b: Bounds): Bounds; - public addBounds2(mins, maxs): Bounds; - public addExtents(center: Vec2, extent_x: number, extent_y: number): Bounds; - public expand(ax: number, ay: number): Bounds; - public containPoint(p: Vec2): bool; - public intersectsBounds(b: Bounds): bool; - static expand(b: Bounds, ax, ay); - } -} -/** -* Phaser - Advanced Physics - IShape -* -* Based on the work Ju Hyung Lee started in JS PhyRus. -*/ -module Phaser.Physics.Advanced { - interface IShape { - id: number; - type: number; - elasticity: number; - friction: number; - density: number; - body: Body; - bounds: Bounds; - area(): number; - centroid(): Vec2; - inertia(mass: number): number; - cacheData(xf: Transform); - pointQuery(p: Vec2): bool; - findEdgeByPoint(p: Vec2, minDist: number): number; - findVertexByPoint(p: Vec2, minDist: number): number; - verts: Vec2[]; - planes: Plane[]; - tverts: Vec2[]; - tplanes: Plane[]; - convexity: bool; - } -} -/** -* Phaser - Advanced Physics - Shape -* -* Based on the work Ju Hyung Lee started in JS PhyRus. -*/ -module Phaser.Physics.Advanced { - class Shape { - constructor(type: number); - public id: number; - public type: number; - public body: Body; - public verts: Vec2[]; - public planes: Plane[]; - public tverts: Vec2[]; - public tplanes: Plane[]; - public convexity: bool; - public elasticity: number; - public friction: number; - public density: number; - public bounds: Bounds; - public findEdgeByPoint(p: Vec2, minDist: number): number; - } -} -/** -* Phaser - Advanced Physics - Contact -* -* Based on the work Ju Hyung Lee started in JS PhyRus. -*/ -module Phaser.Physics.Advanced { - class Contact { - constructor(p, n, d, hash); - public hash; - public r1: Vec2; - public r2: Vec2; - public r1_local: Vec2; - public r2_local: Vec2; - public bounce: number; - public emn: number; - public emt: number; - public point; - public normal: Vec2; - public depth; - public lambdaNormal; - public lambdaTangential; - } -} -module Phaser.Physics.Advanced { - class ContactSolver { - constructor(shape1, shape2); - public shape1; - public shape2; - public contacts: Contact[]; - public elasticity: number; - public friction: number; - public update(newContactArr: Contact[]): void; - public initSolver(dt_inv): void; - public warmStart(): void; - public solveVelocityConstraints(): void; - public solvePositionConstraints(): bool; - public clamp(v, min, max); - } -} -/** -* Phaser - Advanced Physics - Shape - Circle -* -* Based on the work Ju Hyung Lee started in JS PhyRus. -*/ -module Phaser.Physics.Advanced.Shapes { - class Circle extends Shape implements IShape { - constructor(radius: number, x?: number, y?: number); - public radius: number; - public center: Vec2; - public tc: Vec2; - public finishVerts(): void; - public duplicate(): Circle; - public recenter(c: Vec2): void; - public transform(xf: Transform): void; - public untransform(xf: Transform): void; - public area(): number; - public centroid(): Vec2; - public inertia(mass: number): number; - public cacheData(xf: Transform): void; - public pointQuery(p: Vec2): bool; - public findVertexByPoint(p: Vec2, minDist: number): number; - public distanceOnPlane(n, d): void; - } -} -/** -* Phaser - Advanced Physics - 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. -*/ -module Phaser.Physics.Advanced.Shapes { - class Poly extends Shape implements IShape { - constructor(verts?); - public finishVerts(): void; - public duplicate(): Poly; - public recenter(c): void; - public transform(xf: Transform): void; - public untransform(xf: Transform): void; - public area(): number; - public centroid(): Vec2; - public inertia(mass: number): number; - public cacheData(xf: Transform): void; - public pointQuery(p: Vec2): bool; - public findVertexByPoint(p: Vec2, minDist: number): number; - public findEdgeByPoint(p: Vec2, minDist: number): number; - public distanceOnPlane(n: Vec2, d: number): number; - public containPoint(p: Vec2): bool; - public containPointPartial(p, n): bool; - } -} -/** -* Phaser - Advanced Physics - Shapes - Segment -* -* Based on the work Ju Hyung Lee started in JS PhyRus. -*/ -module Phaser.Physics.Advanced.Shapes { - class Segment extends Shape implements IShape { - constructor(a, b, radius: number); - public a: Vec2; - public b: Vec2; - public radius: number; - public normal: Vec2; - public ta: Vec2; - public tb: Vec2; - public tn: Vec2; - public finishVerts(): void; - public duplicate(): Segment; - public recenter(c): void; - public transform(xf: Transform): void; - public untransform(xf: Transform): void; - public area(): number; - public centroid(): Vec2; - public inertia(mass: number): number; - public cacheData(xf: Transform): void; - public pointQuery(p: Vec2): bool; - public findVertexByPoint(p: Vec2, minDist: number): number; - public distanceOnPlane(n, d): number; - } -} -/** -* Phaser - Advanced Physics - Collision Handlers -* -* Based on the work Ju Hyung Lee started in JS PhyRus. -*/ -module Phaser.Physics.Advanced { - class Collision { - constructor(); - public collide(a, b, contacts: Contact[]): number; - private _circle2Circle(c1, r1, c2, r2, contactArr); - public circle2Circle(circ1: Shapes.Circle, circ2: Shapes.Circle, contactArr: Contact[]): number; - public circle2Segment(circ: Shapes.Circle, seg: Shapes.Segment, contactArr: Contact[]): number; - public circle2Poly(circ: Shapes.Circle, poly: Shapes.Poly, contactArr: Contact[]): number; - public segmentPointDistanceSq(seg: Shapes.Segment, p): number; - public segment2Segment(seg1: Shapes.Segment, seg2: Shapes.Segment, contactArr: Contact[]): number; - public findPointsBehindSeg(contactArr: Contact[], seg: Shapes.Segment, poly: Shapes.Poly, dist: number, coef: number): void; - public segment2Poly(seg: Shapes.Segment, poly: Shapes.Poly, contactArr: Contact[]): number; - public findMSA(poly: Shapes.Poly, planes: Plane[], num: number): { - dist: number; - index: number; - }; - public findVertsFallback(contactArr: Contact[], poly1: Shapes.Poly, poly2: Shapes.Poly, n, dist: number): number; - public findVerts(contactArr: Contact[], poly1: Shapes.Poly, poly2: Shapes.Poly, n, dist: number): number; - public poly2Poly(poly1: Shapes.Poly, poly2: Shapes.Poly, contactArr: Contact[]): number; - } -} -/** -* Phaser - Advanced Physics - Joint -* -* Based on the work Ju Hyung Lee started in JS PhyRus. -*/ -module Phaser.Physics.Advanced { - interface IJoint { - id: number; - type: number; - body1: Body; - body2: Body; - collideConnected; - maxForce: number; - breakable: bool; - anchor1: Vec2; - anchor2: Vec2; - getWorldAnchor1(); - getWorldAnchor2(); - setWorldAnchor1(anchor1); - setWorldAnchor2(anchor2); - initSolver(dt, warmStarting); - solveVelocityConstraints(); - solvePositionConstraints(); - getReactionForce(dt_inv); - } -} -/** -* Phaser - Advanced Physics - Space -* -* Based on the work Ju Hyung Lee started in JS PhyRus. -*/ -module Phaser.Physics.Advanced { - class Space { - constructor(); - private _delta; - private _deltaInv; - private _bl; - private _jl; - private _cl; - private _linTolSqr; - private _angTolSqr; - private _minSleepTime; - private _positionSolved; - private _shape1; - private _shape2; - private _contactsOk; - private _jointsOk; - static TIME_TO_SLEEP: number; - static SLEEP_LINEAR_TOLERANCE: number; - static SLEEP_ANGULAR_TOLERANCE: number; - public bodies: Body[]; - private bodyHash; - public joints: IJoint[]; - private jointHash; - public numContacts: number; - public contactSolvers: ContactSolver[]; - public postSolve; - public gravity: Vec2; - public damping: number; - public stepCount: number; - public clear(): void; - public addBody(body: Body): void; - public removeBody(body: Body): void; - public addJoint(joint: IJoint): void; - public removeJoint(joint: IJoint): void; - public findShapeByPoint(p, refShape); - public findBodyByPoint(p, refBody: Body); - public shapeById(id): IShape; - public jointById(id): IJoint; - public findVertexByPoint(p, minDist, refVertexId): number; - public findEdgeByPoint(p, minDist, refEdgeId): number; - public findJointByPoint(p, minDist, refJointId): number; - private findContactSolver(shape1, shape2); - private genTemporalContactSolvers(); - private initSolver(warmStarting); - private velocitySolver(iterations); - private positionSolver(iterations); - public step(dt: number, velocityIterations: number, positionIterations: number, warmStarting: bool, allowSleep: bool): void; - } -} -/** -* 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. -*/ -module Phaser.Physics.Advanced { - class Body { - constructor(sprite: Sprite, type: number, x?: number, y?: number); - public toString(): string; - private _tempVec2; - /** - * Reference to Phaser.Game - */ - public game: Game; - /** - * Reference to the parent Sprite - */ - public sprite: Sprite; - /** - * The Body ID - */ - public id: number; - /** - * The Body name - */ - public name: string; - /** - * The type of Body (disabled, dynamic, static or kinematic) - * Disabled = skips all physics operations / tests (default) - * Dynamic = gives and receives impacts - * Static = gives but doesn't receive impacts, cannot be moved by physics - * Kinematic = gives impacts, but never receives, can be moved by physics - * @type {number} - */ - public type: number; - public angle: number; - public transform: Transform; - public centroid: Vec2; - public position: Vec2; - public velocity: Vec2; - public force: Vec2; - public angularVelocity: number; - public torque: number; - public linearDamping: number; - public angularDamping: number; - public sleepTime: number; - public awaked: bool; - public shapes: IShape[]; - public shapesLength: number; - 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; - public stepCount: number; - public space: Space; - public duplicate(): void; - public isDisabled : bool; - public isStatic : bool; - public isKinetic : bool; - public isDynamic : bool; - public setType(type: number): void; - public addPoly(verts, elasticity?: number, friction?: number, density?: number): Shapes.Poly; - public addTriangle(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, elasticity?: number, friction?: number, density?: number): Shapes.Triangle; - public addBox(x: number, y: number, width: number, height: number, elasticity?: number, friction?: number, density?: number): Shapes.Box; - public addCircle(radius: number, x?: number, y?: number, elasticity?: number, friction?: number, density?: number): Shapes.Circle; - public addShape(shape); - public removeShape(shape): void; - private setMass(mass); - private setInertia(inertia); - public setTransform(pos, angle): void; - public syncTransform(): void; - public getWorldPoint(p: Vec2): Vec2; - public getWorldVector(v: Vec2): Vec2; - public getLocalPoint(p: Vec2): Vec2; - public getLocalVector(v: Vec2): Vec2; - public setFixedRotation(flag): void; - public resetMassData(): void; - public resetJointAnchors(): void; - public cacheData(source?: string): void; - public updateVelocity(gravity, dt, damping): void; - public inContact(body2: Body): bool; - public clamp(v, min, max); - public updatePosition(dt: number): void; - public resetForce(): void; - public applyForce(force: Vec2, p: Vec2): void; - public applyForceToCenter(force: Vec2): void; - public applyTorque(torque: number): void; - public applyLinearImpulse(impulse: Vec2, p: Vec2): void; - public applyAngularImpulse(impulse: number): void; - public kineticEnergy(): number; - public isAwake : bool; - public awake(flag): void; - public isCollidable(other: Body): bool; - } -} -/** * Phaser - PixelUtils * * A collection of methods useful for manipulating pixels. diff --git a/build/phaser.js b/build/phaser.js index 96d3a9b8..661e4d30 100644 --- a/build/phaser.js +++ b/build/phaser.js @@ -708,20 +708,28 @@ var Phaser; QuadTree._iterator = QuadTree._iterator.next; continue; } - //if (QuadTree._object.body.bounds.checkHullIntersection(this._checkObject.body.bounds)) - if(QuadTree.physics.checkHullIntersection(QuadTree._object.body, this._checkObject.body)) { - //Execute callback functions if they exist - if((QuadTree._processingCallback == null) || QuadTree._processingCallback(QuadTree._object, this._checkObject)) { - this._overlapProcessed = true; - } - if(this._overlapProcessed && (QuadTree._notifyCallback != null)) { - if(QuadTree._callbackContext !== null) { - QuadTree._notifyCallback.call(QuadTree._callbackContext, QuadTree._object, this._checkObject); - } else { - QuadTree._notifyCallback(QuadTree._object, this._checkObject); - } - } + /* + if (QuadTree.physics.checkHullIntersection(QuadTree._object.body, this._checkObject.body)) + { + //Execute callback functions if they exist + if ((QuadTree._processingCallback == null) || QuadTree._processingCallback(QuadTree._object, this._checkObject)) + { + this._overlapProcessed = true; } + + if (this._overlapProcessed && (QuadTree._notifyCallback != null)) + { + if (QuadTree._callbackContext !== null) + { + QuadTree._notifyCallback.call(QuadTree._callbackContext, QuadTree._object, this._checkObject); + } + else + { + QuadTree._notifyCallback(QuadTree._object, this._checkObject); + } + } + } + */ QuadTree._iterator = QuadTree._iterator.next; } return this._overlapProcessed; @@ -1587,7 +1595,7 @@ var Phaser; if (typeof threshold === "undefined") { threshold = 30; } var hsv = ColorUtils.RGBtoHSV(color); if(threshold >= 359 || threshold <= 0) { - throw Error("FlxColor Warning: Invalid threshold given to getSplitComplementHarmony()"); + throw Error("ColorUtils Warning: Invalid threshold given to getSplitComplementHarmony()"); } var opposite = ColorUtils.game.math.wrapValue(hsv.hue, 180, 359); var warmer = ColorUtils.game.math.wrapValue(hsv.hue, opposite - threshold, 359); @@ -3195,7 +3203,7 @@ var Phaser; this._prevRotation = this.rotation; dirty = true; } - // If it has moved, updated the edges and center + // If it has moved, update the edges and center if(dirty || this.parent.x != this._pos.x || this.parent.y != this._pos.y) { this.center.x = this.parent.x + this._distance * this._scA.y; this.center.y = this.parent.y + this._distance * this._scA.x; @@ -4260,231 +4268,2817 @@ var Phaser; } */ })(Phaser || (Phaser = {})); +/// +/// +/** +* Phaser - 2D Transform +* +* A 2D Transform +*/ +var Phaser; +(function (Phaser) { + var Transform = (function () { + /** + * Creates a new 2D Transform object. + * @class Transform + * @constructor + * @return {Transform} This object + **/ + function Transform(pos, angle) { + this.t = Phaser.Vec2Utils.clone(pos); + this.c = Math.cos(angle); + this.s = Math.sin(angle); + this.angle = angle; + } + Transform.prototype.toString = function () { + return 't=' + this.t.toString() + ' c=' + this.c + ' s=' + this.s + ' a=' + this.angle; + }; + Transform.prototype.setTo = function (pos, angle) { + this.t.copyFrom(pos); + this.c = Math.cos(angle); + this.s = Math.sin(angle); + return this; + }; + Transform.prototype.setRotation = function (angle) { + if(angle !== this.angle) { + this.c = Math.cos(angle); + this.s = Math.sin(angle); + this.angle = angle; + } + return this; + }; + Transform.prototype.setPosition = function (p) { + this.t.copyFrom(p); + return this; + }; + Transform.prototype.identity = function () { + this.t.setTo(0, 0); + this.c = 1; + this.s = 0; + return this; + }; + return Transform; + })(); + Phaser.Transform = Transform; +})(Phaser || (Phaser = {})); +/// +/// +/// +/** +* Phaser - TransformUtils +* +* A collection of methods useful for manipulating and performing operations on 2D Transforms. +* +*/ +var Phaser; +(function (Phaser) { + var TransformUtils = (function () { + function TransformUtils() { } + TransformUtils.rotate = function rotate(t, v, out) { + if (typeof out === "undefined") { out = new Phaser.Vec2(); } + //return new vec2(v.x * this.c - v.y * this.s, v.x * this.s + v.y * this.c); + return out.setTo(v.x * t.c - v.y * t.s, v.x * t.s + v.y * t.c); + }; + TransformUtils.unrotate = function unrotate(t, v, out) { + if (typeof out === "undefined") { out = new Phaser.Vec2(); } + //return new vec2(v.x * this.c + v.y * this.s, -v.x * this.s + v.y * this.c); + return out.setTo(v.x * t.c + v.y * t.s, -v.x * t.s + v.y * t.c); + }; + TransformUtils.transform = function transform(t, v, out) { + if (typeof out === "undefined") { out = new Phaser.Vec2(); } + //return new vec2(v.x * this.c - v.y * this.s + this.t.x, v.x * this.s + v.y * this.c + this.t.y); + return out.setTo(v.x * t.c - v.y * t.s + t.t.x, v.x * t.s + v.y * t.c + t.t.y); + }; + TransformUtils.untransform = function untransform(t, v, out) { + if (typeof out === "undefined") { out = new Phaser.Vec2(); } + var px = v.x - t.t.x; + var py = v.y - t.t.y; + //return new vec2(px * this.c + py * this.s, -px * this.s + py * this.c); + return out.setTo(px * t.c + py * t.s, -px * t.s + py * t.c); + }; + return TransformUtils; + })(); + Phaser.TransformUtils = TransformUtils; +})(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + /// + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Joint + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + (function (Physics) { + var Joint = (function () { + function Joint(type, body1, body2, collideConnected) { + this.id = Phaser.Physics.Manager.jointCounter++; + this.type = type; + this.body1 = body1; + this.body2 = body2; + this.collideConnected = collideConnected; + this.maxForce = 9999999999; + this.breakable = false; + } + Joint.prototype.getWorldAnchor1 = function () { + return this.body1.getWorldPoint(this.anchor1); + }; + Joint.prototype.getWorldAnchor2 = function () { + return this.body2.getWorldPoint(this.anchor2); + }; + Joint.prototype.setWorldAnchor1 = function (anchor1) { + this.anchor1 = this.body1.getLocalPoint(anchor1); + }; + Joint.prototype.setWorldAnchor2 = function (anchor2) { + this.anchor2 = this.body2.getLocalPoint(anchor2); + }; + return Joint; + })(); + Physics.Joint = Joint; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + /// + /// + /// + /** + * Phaser - Physics Manager + * + * The Physics Manager is responsible for looking after, creating and colliding + * all of the physics bodies and joints in the world. + */ + (function (Physics) { + var Manager = (function () { + function Manager(game) { + this.lastTime = Date.now(); + this.frameRateHz = 60; + this.timeDelta = 0; + this.paused = false; + this.step = false; + // step through the simulation (i.e. per click) + //public paused: bool = true; + //public step: bool = false; // step through the simulation (i.e. per click) + this.velocityIterations = 8; + this.positionIterations = 4; + this.allowSleep = true; + this.warmStarting = true; + this.game = game; + this.gravity = new Phaser.Vec2(); + this.space = new Physics.Space(this); + Manager.collision = new Physics.Collision(); + } + Manager.clear = function clear() { + //Manager.debug.textContent = ""; + Manager.log = []; + }; + Manager.write = function write(s) { + //Manager.debug.textContent += s + "\n"; + }; + Manager.writeAll = function writeAll() { + for(var i = 0; i < Manager.log.length; i++) { + //Manager.debug.textContent += Manager.log[i]; + } + }; + Manager.log = []; + Manager.dump = function dump(phase, body) { + /* + var s = "\n\nPhase: " + phase + "\n"; + s += "Position: " + body.position.toString() + "\n"; + s += "Velocity: " + body.velocity.toString() + "\n"; + s += "Angle: " + body.angle + "\n"; + s += "Force: " + body.force.toString() + "\n"; + s += "Torque: " + body.torque + "\n"; + s += "Bounds: " + body.bounds.toString() + "\n"; + s += "Shape ***\n"; + s += "Vert 0: " + body.shapes[0].verts[0].toString() + "\n"; + s += "Vert 1: " + body.shapes[0].verts[1].toString() + "\n"; + s += "Vert 2: " + body.shapes[0].verts[2].toString() + "\n"; + s += "Vert 3: " + body.shapes[0].verts[3].toString() + "\n"; + s += "TVert 0: " + body.shapes[0].tverts[0].toString() + "\n"; + s += "TVert 1: " + body.shapes[0].tverts[1].toString() + "\n"; + s += "TVert 2: " + body.shapes[0].tverts[2].toString() + "\n"; + s += "TVert 3: " + body.shapes[0].tverts[3].toString() + "\n"; + s += "Plane 0: " + body.shapes[0].planes[0].normal.toString() + "\n"; + s += "Plane 1: " + body.shapes[0].planes[1].normal.toString() + "\n"; + s += "Plane 2: " + body.shapes[0].planes[2].normal.toString() + "\n"; + s += "Plane 3: " + body.shapes[0].planes[3].normal.toString() + "\n"; + s += "TPlane 0: " + body.shapes[0].tplanes[0].normal.toString() + "\n"; + s += "TPlane 1: " + body.shapes[0].tplanes[1].normal.toString() + "\n"; + s += "TPlane 2: " + body.shapes[0].tplanes[2].normal.toString() + "\n"; + s += "TPlane 3: " + body.shapes[0].tplanes[3].normal.toString() + "\n"; + + Manager.log.push(s); + */ + }; + Manager.SHAPE_TYPE_CIRCLE = 0; + Manager.SHAPE_TYPE_SEGMENT = 1; + Manager.SHAPE_TYPE_POLY = 2; + Manager.SHAPE_NUM_TYPES = 3; + Manager.JOINT_TYPE_ANGLE = 0; + Manager.JOINT_TYPE_REVOLUTE = 1; + Manager.JOINT_TYPE_WELD = 2; + Manager.JOINT_TYPE_WHEEL = 3; + Manager.JOINT_TYPE_PRISMATIC = 4; + Manager.JOINT_TYPE_DISTANCE = 5; + Manager.JOINT_TYPE_ROPE = 6; + Manager.JOINT_TYPE_MOUSE = 7; + Manager.JOINT_LINEAR_SLOP = 0.0008; + Manager.JOINT_ANGULAR_SLOP = 2 * 0.017453292519943294444444444444444; + Manager.JOINT_MAX_LINEAR_CORRECTION = 0.5; + Manager.JOINT_MAX_ANGULAR_CORRECTION = 8 * 0.017453292519943294444444444444444; + Manager.JOINT_LIMIT_STATE_INACTIVE = 0; + Manager.JOINT_LIMIT_STATE_AT_LOWER = 1; + Manager.JOINT_LIMIT_STATE_AT_UPPER = 2; + Manager.JOINT_LIMIT_STATE_EQUAL_LIMITS = 3; + Manager.CONTACT_SOLVER_COLLISION_SLOP = 0.0008; + Manager.CONTACT_SOLVER_BAUMGARTE = 0.28; + Manager.CONTACT_SOLVER_MAX_LINEAR_CORRECTION = 1; + Manager.bodyCounter = 0; + Manager.jointCounter = 0; + Manager.shapeCounter = 0; + Manager.prototype.update = function () { + // Get these from Phaser.Time instead + var time = Date.now(); + var frameTime = (time - this.lastTime) / 1000; + this.lastTime = time; + // if rAf - why? + frameTime = Math.floor(frameTime * 60 + 0.5) / 60; + //if (!mouseDown) + //{ + // var p = canvasToWorld(mousePosition); + // var body = space.findBodyByPoint(p); + // //domCanvas.style.cursor = body ? "pointer" : "default"; + //} + if(!this.paused || this.step) { + Manager.clear(); + var h = 1 / this.frameRateHz; + this.timeDelta += frameTime; + if(this.step) { + this.step = false; + this.timeDelta = h; + } + for(var maxSteps = 4; maxSteps > 0 && this.timeDelta >= h; maxSteps--) { + this.space.step(h, this.velocityIterations, this.positionIterations, this.warmStarting, this.allowSleep); + this.timeDelta -= h; + } + if(this.timeDelta > h) { + this.timeDelta = 0; + } + } + //frameCount++; + }; + Manager.prototype.addBody = function (body) { + this.space.addBody(body); + }; + Manager.prototype.removeBody = function (body) { + this.space.removeBody(body); + }; + Manager.prototype.addJoint = function (joint) { + this.space.addJoint(joint); + }; + Manager.prototype.removeJoint = function (joint) { + this.space.removeJoint(joint); + }; + Manager.prototype.pixelsToMeters = function (value) { + return value * 0.02; + }; + Manager.prototype.metersToPixels = function (value) { + return value * 50; + }; + Manager.pixelsToMeters = function pixelsToMeters(value) { + return value * 0.02; + }; + Manager.metersToPixels = function metersToPixels(value) { + return value * 50; + }; + Manager.p2m = function p2m(value) { + return value * 0.02; + }; + Manager.m2p = function m2p(value) { + return value * 50; + }; + Manager.areaForCircle = function areaForCircle(radius_outer, radius_inner) { + return Math.PI * (radius_outer * radius_outer - radius_inner * radius_inner); + }; + Manager.inertiaForCircle = function inertiaForCircle(mass, center, radius_outer, radius_inner) { + return mass * ((radius_outer * radius_outer + radius_inner * radius_inner) * 0.5 + center.lengthSq()); + }; + Manager.areaForSegment = function areaForSegment(a, b, radius) { + return radius * (Math.PI * radius + 2 * Phaser.Vec2Utils.distance(a, b)); + }; + Manager.centroidForSegment = function centroidForSegment(a, b) { + return Phaser.Vec2Utils.scale(Phaser.Vec2Utils.add(a, b), 0.5); + }; + Manager.inertiaForSegment = function inertiaForSegment(mass, a, b) { + var distsq = Phaser.Vec2Utils.distanceSq(b, a); + var offset = Phaser.Vec2Utils.scale(Phaser.Vec2Utils.add(a, b), 0.5); + return mass * (distsq / 12 + offset.lengthSq()); + }; + Manager.areaForPoly = function areaForPoly(verts) { + var area = 0; + for(var i = 0; i < verts.length; i++) { + area += Phaser.Vec2Utils.cross(verts[i], verts[(i + 1) % verts.length]); + } + return area / 2; + }; + Manager.centroidForPoly = function centroidForPoly(verts) { + var area = 0; + var vsum = new Phaser.Vec2(); + for(var i = 0; i < verts.length; i++) { + var v1 = verts[i]; + var v2 = verts[(i + 1) % verts.length]; + var cross = Phaser.Vec2Utils.cross(v1, v2); + area += cross; + // SO many vecs created here - unroll these bad boys + vsum.add(Phaser.Vec2Utils.scale(Phaser.Vec2Utils.add(v1, v2), cross)); + } + return Phaser.Vec2Utils.scale(vsum, 1 / (3 * area)); + }; + Manager.inertiaForPoly = function inertiaForPoly(mass, verts, offset) { + var sum1 = 0; + var sum2 = 0; + for(var i = 0; i < verts.length; i++) { + var v1 = Phaser.Vec2Utils.add(verts[i], offset); + var v2 = Phaser.Vec2Utils.add(verts[(i + 1) % verts.length], offset); + var a = Phaser.Vec2Utils.cross(v2, v1); + var b = Phaser.Vec2Utils.dot(v1, v1) + Phaser.Vec2Utils.dot(v1, v2) + Phaser.Vec2Utils.dot(v2, v2); + sum1 += a * b; + sum2 += a; + } + return (mass * sum1) / (6 * sum2); + }; + Manager.inertiaForBox = function inertiaForBox(mass, w, h) { + return mass * (w * w + h * h) / 12; + }; + Manager.createConvexHull = // Create the convex hull using the Gift wrapping algorithm (http://en.wikipedia.org/wiki/Gift_wrapping_algorithm) + function createConvexHull(points) { + // Find the right most point on the hull + var i0 = 0; + var x0 = points[0].x; + for(var i = 1; i < points.length; i++) { + var x = points[i].x; + if(x > x0 || (x == x0 && points[i].y < points[i0].y)) { + i0 = i; + x0 = x; + } + } + var n = points.length; + var hull = []; + var m = 0; + var ih = i0; + while(1) { + hull[m] = ih; + var ie = 0; + for(var j = 1; j < n; j++) { + if(ie == ih) { + ie = j; + continue; + } + var r = Phaser.Vec2Utils.subtract(points[ie], points[hull[m]]); + var v = Phaser.Vec2Utils.subtract(points[j], points[hull[m]]); + var c = Phaser.Vec2Utils.cross(r, v); + if(c < 0) { + ie = j; + } + // Collinearity check + if(c == 0 && v.lengthSq() > r.lengthSq()) { + ie = j; + } + } + m++; + ih = ie; + if(ie == i0) { + break; + } + } + // Copy vertices + var newPoints = []; + for(var i = 0; i < m; ++i) { + newPoints.push(points[hull[i]]); + } + return newPoints; + }; + return Manager; + })(); + Physics.Manager = Manager; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + /// + /// + /// + /** + * Phaser - 2D AABB + * + * A 2D AABB object + */ + (function (Physics) { + var Bounds = (function () { + /** + * Creates a new 2D AABB object. + * @class Bounds + * @constructor + * @return {Bounds} This object + **/ + function Bounds(mins, maxs) { + if (typeof mins === "undefined") { mins = null; } + if (typeof maxs === "undefined") { maxs = null; } + if(mins) { + this.mins = Phaser.Vec2Utils.clone(mins); + } else { + this.mins = new Phaser.Vec2(999999, 999999); + } + if(maxs) { + this.maxs = Phaser.Vec2Utils.clone(maxs); + } else { + this.maxs = new Phaser.Vec2(999999, 999999); + } + } + Bounds.prototype.toString = function () { + return [ + "mins:", + this.mins.toString(), + "maxs:", + this.maxs.toString() + ].join(" "); + }; + Bounds.prototype.setTo = function (mins, maxs) { + this.mins.setTo(mins.x, mins.y); + this.maxs.setTo(maxs.x, maxs.y); + }; + Bounds.prototype.copy = function (b) { + this.mins.copyFrom(b.mins); + this.maxs.copyFrom(b.maxs); + return this; + }; + Bounds.prototype.clear = function () { + this.mins.setTo(999999, 999999); + this.maxs.setTo(-999999, -999999); + return this; + }; + Object.defineProperty(Bounds.prototype, "x", { + get: function () { + return Phaser.Physics.Manager.metersToPixels(this.mins.x); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Bounds.prototype, "y", { + get: function () { + return Phaser.Physics.Manager.metersToPixels(this.mins.y); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Bounds.prototype, "width", { + get: function () { + return Phaser.Physics.Manager.metersToPixels(this.maxs.x - this.mins.x); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Bounds.prototype, "height", { + get: function () { + return Phaser.Physics.Manager.metersToPixels(this.maxs.y - this.mins.y); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Bounds.prototype, "right", { + get: function () { + return this.x + this.width; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Bounds.prototype, "bottom", { + get: function () { + return this.y + this.height; + }, + enumerable: true, + configurable: true + }); + Bounds.prototype.isEmpty = function () { + return (this.mins.x > this.maxs.x || this.mins.y > this.maxs.y); + }; + Bounds.prototype.getPerimeter = /* + public getCenter() { + return vec2.scale(vec2.add(this.mins, this.maxs), 0.5); + } + + public getExtent() { + return vec2.scale(vec2.sub(this.maxs, this.mins), 0.5); + } + */ + function () { + return (this.maxs.x - this.mins.x + this.maxs.y - this.mins.y) * 2; + }; + Bounds.prototype.addPoint = function (p) { + if(this.mins.x > p.x) { + this.mins.x = p.x; + } + if(this.maxs.x < p.x) { + this.maxs.x = p.x; + } + if(this.mins.y > p.y) { + this.mins.y = p.y; + } + if(this.maxs.y < p.y) { + this.maxs.y = p.y; + } + return this; + }; + Bounds.prototype.addBounds = function (b) { + if(this.mins.x > b.mins.x) { + this.mins.x = b.mins.x; + } + if(this.maxs.x < b.maxs.x) { + this.maxs.x = b.maxs.x; + } + if(this.mins.y > b.mins.y) { + this.mins.y = b.mins.y; + } + if(this.maxs.y < b.maxs.y) { + this.maxs.y = b.maxs.y; + } + return this; + }; + Bounds.prototype.addBounds2 = function (mins, maxs) { + if(this.mins.x > mins.x) { + this.mins.x = mins.x; + } + if(this.maxs.x < maxs.x) { + this.maxs.x = maxs.x; + } + if(this.mins.y > mins.y) { + this.mins.y = mins.y; + } + if(this.maxs.y < maxs.y) { + this.maxs.y = maxs.y; + } + return this; + }; + Bounds.prototype.addExtents = function (center, extent_x, extent_y) { + if(this.mins.x > center.x - extent_x) { + this.mins.x = center.x - extent_x; + } + if(this.maxs.x < center.x + extent_x) { + this.maxs.x = center.x + extent_x; + } + if(this.mins.y > center.y - extent_y) { + this.mins.y = center.y - extent_y; + } + if(this.maxs.y < center.y + extent_y) { + this.maxs.y = center.y + extent_y; + } + return this; + }; + Bounds.prototype.expand = function (ax, ay) { + this.mins.x -= ax; + this.mins.y -= ay; + this.maxs.x += ax; + this.maxs.y += ay; + return this; + }; + Bounds.prototype.containPoint = function (p) { + if(p.x < this.mins.x || p.x > this.maxs.x || p.y < this.mins.y || p.y > this.maxs.y) { + return false; + } + return true; + }; + Bounds.prototype.intersectsBounds = function (b) { + if(this.mins.x > b.maxs.x || this.maxs.x < b.mins.x || this.mins.y > b.maxs.y || this.maxs.y < b.mins.y) { + return false; + } + return true; + }; + Bounds.expand = function expand(b, ax, ay) { + var b = new Bounds(b.mins, b.maxs); + b.expand(ax, ay); + return b; + }; + return Bounds; + })(); + Physics.Bounds = Bounds; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + })(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + /// + /// + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Shape + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + (function (Physics) { + var Shape = (function () { + function Shape(type) { + this.id = Phaser.Physics.Manager.shapeCounter++; + this.type = type; + this.elasticity = 0.0; + this.friction = 1.0; + this.density = 1; + this.bounds = new Physics.Bounds(); + } + Shape.prototype.findEdgeByPoint = // Over-ridden by ShapePoly + function (p, minDist) { + return -1; + }; + return Shape; + })(); + Physics.Shape = Shape; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + /// + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Contact + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + (function (Physics) { + var Contact = (function () { + function Contact(p, n, d, hash) { + this.hash = hash; + this.point = p; + this.normal = n; + this.depth = d; + this.lambdaNormal = 0; + this.lambdaTangential = 0; + this.r1 = new Phaser.Vec2(); + this.r2 = new Phaser.Vec2(); + this.r1_local = new Phaser.Vec2(); + this.r2_local = new Phaser.Vec2(); + } + return Contact; + })(); + Physics.Contact = Contact; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); var Phaser; (function (Phaser) { /// /// /// + /// + /// + /// + /// /** - * Phaser - Physics - Body + * Phaser - Advanced Physics - ContactSolver + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + //------------------------------------------------------------------------------------------------- + // Contact Constraint + // + // Non-penetration constraint: + // C = dot(p2 - p1, n) + // Cdot = dot(v2 - v1, n) + // J = [ -n, -cross(r1, n), n, cross(r2, n) ] + // + // impulse = JT * lambda = [ -n * lambda, -cross(r1, n) * lambda, n * lambda, cross(r1, n) * lambda ] + // + // Friction constraint: + // C = dot(p2 - p1, t) + // Cdot = dot(v2 - v1, t) + // J = [ -t, -cross(r1, t), t, cross(r2, t) ] + // + // impulse = JT * lambda = [ -t * lambda, -cross(r1, t) * lambda, t * lambda, cross(r1, t) * lambda ] + // + // NOTE: lambda is an impulse in constraint space. + //------------------------------------------------------------------------------------------------- + (function (Physics) { + var ContactSolver = (function () { + function ContactSolver(shape1, shape2) { + this.shape1 = shape1; + this.shape2 = shape2; + this.contacts = []; + this.elasticity = 1; + this.friction = 1; + } + ContactSolver.prototype.update = function (newContactArr) { + for(var i = 0; i < newContactArr.length; i++) { + var newContact = newContactArr[i]; + var k = -1; + for(var j = 0; j < this.contacts.length; j++) { + if(newContact.hash == this.contacts[j].hash) { + k = j; + break; + } + } + if(k > -1) { + newContact.lambdaNormal = this.contacts[k].lambdaNormal; + newContact.lambdaTangential = this.contacts[k].lambdaTangential; + } + } + this.contacts = newContactArr; + }; + ContactSolver.prototype.initSolver = function (dt_inv) { + var body1 = this.shape1.body; + var body2 = this.shape2.body; + var sum_m_inv = body1.massInverted + body2.massInverted; + for(var i = 0; i < this.contacts.length; i++) { + var con = this.contacts[i]; + //console.log('initSolver con'); + //console.log(con); + // Transformed r1, r2 + Phaser.Vec2Utils.subtract(con.point, body1.position, con.r1); + Phaser.Vec2Utils.subtract(con.point, body2.position, con.r2); + //con.r1 = vec2.sub(con.point, body1.p); + //con.r2 = vec2.sub(con.point, body2.p); + // Local r1, r2 + Phaser.TransformUtils.unrotate(body1.transform, con.r1, con.r1_local); + Phaser.TransformUtils.unrotate(body2.transform, con.r2, con.r2_local); + //con.r1_local = body1.transform.unrotate(con.r1); + //con.r2_local = body2.transform.unrotate(con.r2); + var n = con.normal; + var t = Phaser.Vec2Utils.perp(con.normal); + // invEMn = J * invM * JT + // J = [ -n, -cross(r1, n), n, cross(r2, n) ] + var sn1 = Phaser.Vec2Utils.cross(con.r1, n); + var sn2 = Phaser.Vec2Utils.cross(con.r2, n); + var emn_inv = sum_m_inv + body1.inertiaInverted * sn1 * sn1 + body2.inertiaInverted * sn2 * sn2; + con.emn = emn_inv == 0 ? 0 : 1 / emn_inv; + // invEMt = J * invM * JT + // J = [ -t, -cross(r1, t), t, cross(r2, t) ] + var st1 = Phaser.Vec2Utils.cross(con.r1, t); + var st2 = Phaser.Vec2Utils.cross(con.r2, t); + var emt_inv = sum_m_inv + body1.inertiaInverted * st1 * st1 + body2.inertiaInverted * st2 * st2; + con.emt = emt_inv == 0 ? 0 : 1 / emt_inv; + // Linear velocities at contact point + // in 2D: cross(w, r) = perp(r) * w + var v1 = new Phaser.Vec2(); + var v2 = new Phaser.Vec2(); + Phaser.Vec2Utils.multiplyAdd(body1.velocity, Phaser.Vec2Utils.perp(con.r1), body1.angularVelocity, v1); + Phaser.Vec2Utils.multiplyAdd(body2.velocity, Phaser.Vec2Utils.perp(con.r2), body2.angularVelocity, v2); + //var v1 = vec2.mad(body1.v, vec2.perp(con.r1), body1.w); + //var v2 = vec2.mad(body2.v, vec2.perp(con.r2), body2.w); + // relative velocity at contact point + var rv = new Phaser.Vec2(); + Phaser.Vec2Utils.subtract(v2, v1, rv); + //var rv = vec2.sub(v2, v1); + // bounce velocity dot n + con.bounce = Phaser.Vec2Utils.dot(rv, con.normal) * this.elasticity; + } + }; + ContactSolver.prototype.warmStart = function () { + var body1 = this.shape1.body; + var body2 = this.shape2.body; + for(var i = 0; i < this.contacts.length; i++) { + var con = this.contacts[i]; + var n = con.normal; + var lambda_n = con.lambdaNormal; + var lambda_t = con.lambdaTangential; + // Apply accumulated impulses + //var impulse = vec2.rotate_vec(new vec2(lambda_n, lambda_t), n); + //var impulse = new vec2(lambda_n * n.x - lambda_t * n.y, lambda_t * n.x + lambda_n * n.y); + var impulse = new Phaser.Vec2(lambda_n * n.x - lambda_t * n.y, lambda_t * n.x + lambda_n * n.y); + //console.log('phaser warmStart impulse ' + i + ' = ' + impulse.toString()); + body1.velocity.multiplyAddByScalar(impulse, -body1.massInverted); + //body1.v.mad(impulse, -body1.m_inv); + body1.angularVelocity -= Phaser.Vec2Utils.cross(con.r1, impulse) * body1.inertiaInverted; + //body1.w -= vec2.cross(con.r1, impulse) * body1.i_inv; + body2.velocity.multiplyAddByScalar(impulse, body2.massInverted); + //body2.v.mad(impulse, body2.m_inv); + body2.angularVelocity += Phaser.Vec2Utils.cross(con.r2, impulse) * body2.inertiaInverted; + //body2.w += vec2.cross(con.r2, impulse) * body2.i_inv; + } + }; + ContactSolver.prototype.solveVelocityConstraints = function () { + var body1 = this.shape1.body; + var body2 = this.shape2.body; + Physics.Manager.write('solveVelocityConstraints. Body1: ' + body1.name + ' Body2: ' + body2.name); + Physics.Manager.write('Shape 1: ' + this.shape1.type + ' Shape 2: ' + this.shape2.type); + var m1_inv = body1.massInverted; + var i1_inv = body1.inertiaInverted; + var m2_inv = body2.massInverted; + var i2_inv = body2.inertiaInverted; + Physics.Manager.write('m1_inv: ' + m1_inv); + Physics.Manager.write('i1_inv: ' + i1_inv); + Physics.Manager.write('m2_inv: ' + m2_inv); + Physics.Manager.write('i2_inv: ' + i2_inv); + for(var i = 0; i < this.contacts.length; i++) { + Physics.Manager.write('------------ solve con ' + i); + var con = this.contacts[i]; + var n = con.normal; + var t = Phaser.Vec2Utils.perp(n); + var r1 = con.r1; + var r2 = con.r2; + // Linear velocities at contact point + // in 2D: cross(w, r) = perp(r) * w + var v1 = new Phaser.Vec2(); + var v2 = new Phaser.Vec2(); + Phaser.Vec2Utils.multiplyAdd(body1.velocity, Phaser.Vec2Utils.perp(r1), body1.angularVelocity, v1); + //var v1 = vec2.mad(body1.v, vec2.perp(r1), body1.w); + Physics.Manager.write('v1 ' + v1.toString()); + Phaser.Vec2Utils.multiplyAdd(body2.velocity, Phaser.Vec2Utils.perp(r2), body2.angularVelocity, v2); + //var v2 = vec2.mad(body2.v, vec2.perp(r2), body2.w); + Physics.Manager.write('v2 ' + v2.toString()); + // Relative velocity at contact point + var rv = new Phaser.Vec2(); + Phaser.Vec2Utils.subtract(v2, v1, rv); + //var rv = vec2.sub(v2, v1); + Physics.Manager.write('rv ' + rv.toString()); + // Compute normal constraint impulse + adding bounce as a velocity bias + // lambda_n = -EMn * J * V + var lambda_n = -con.emn * (Phaser.Vec2Utils.dot(n, rv) + con.bounce); + Physics.Manager.write('lambda_n: ' + lambda_n); + // Accumulate and clamp + var lambda_n_old = con.lambdaNormal; + con.lambdaNormal = Math.max(lambda_n_old + lambda_n, 0); + //con.lambdaNormal = this.clamp(lambda_n_old + lambda_n, 0); + lambda_n = con.lambdaNormal - lambda_n_old; + Physics.Manager.write('lambda_n clamped: ' + lambda_n); + // Compute frictional constraint impulse + // lambda_t = -EMt * J * V + var lambda_t = -con.emt * Phaser.Vec2Utils.dot(t, rv); + // Max friction constraint impulse (Coulomb's Law) + var lambda_t_max = con.lambdaNormal * this.friction; + // Accumulate and clamp + var lambda_t_old = con.lambdaTangential; + con.lambdaTangential = this.clamp(lambda_t_old + lambda_t, -lambda_t_max, lambda_t_max); + lambda_t = con.lambdaTangential - lambda_t_old; + // Apply the final impulses + //var impulse = vec2.rotate_vec(new vec2(lambda_n, lambda_t), n); + var impulse = new Phaser.Vec2(lambda_n * n.x - lambda_t * n.y, lambda_t * n.x + lambda_n * n.y); + Physics.Manager.write('impulse: ' + impulse.toString()); + body1.velocity.multiplyAddByScalar(impulse, -m1_inv); + //body1.v.mad(impulse, -m1_inv); + body1.angularVelocity -= Phaser.Vec2Utils.cross(r1, impulse) * i1_inv; + //body1.w -= vec2.cross(r1, impulse) * i1_inv; + body2.velocity.multiplyAddByScalar(impulse, m2_inv); + //body2.v.mad(impulse, m2_inv); + body2.angularVelocity += Phaser.Vec2Utils.cross(r2, impulse) * i2_inv; + //body2.w += vec2.cross(r2, impulse) * i2_inv; + Physics.Manager.write('body1: ' + body1.toString()); + Physics.Manager.write('body2: ' + body2.toString()); + } + }; + ContactSolver.prototype.solvePositionConstraints = function () { + var body1 = this.shape1.body; + var body2 = this.shape2.body; + Physics.Manager.write('solvePositionConstraints'); + var m1_inv = body1.massInverted; + var i1_inv = body1.inertiaInverted; + var m2_inv = body2.massInverted; + var i2_inv = body2.inertiaInverted; + var sum_m_inv = m1_inv + m2_inv; + var max_penetration = 0; + for(var i = 0; i < this.contacts.length; i++) { + Physics.Manager.write('------------- solvePositionConstraints ' + i); + var con = this.contacts[i]; + var n = con.normal; + var r1 = new Phaser.Vec2(); + var r2 = new Phaser.Vec2(); + // Transformed r1, r2 + Phaser.Vec2Utils.rotate(con.r1_local, body1.angle, r1); + //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); + Physics.Manager.write('r1_local.x = ' + con.r1_local.x + ' r1_local.y = ' + con.r1_local.y + ' angle: ' + body1.angle); + Physics.Manager.write('r1 rotated: r1.x = ' + r1.x + ' r1.y = ' + r1.y); + Physics.Manager.write('r2_local.x = ' + con.r2_local.x + ' r2_local.y = ' + con.r2_local.y + ' angle: ' + body2.angle); + Physics.Manager.write('r2 rotated: r2.x = ' + r2.x + ' r2.y = ' + r2.y); + // Contact points (corrected) + var p1 = new Phaser.Vec2(); + var p2 = new Phaser.Vec2(); + Phaser.Vec2Utils.add(body1.position, r1, p1); + //var p1 = vec2.add(body1.p, r1); + Phaser.Vec2Utils.add(body2.position, r2, p2); + //var p2 = vec2.add(body2.p, r2); + Physics.Manager.write('body1.pos.x=' + body1.position.x + ' y=' + body1.position.y); + Physics.Manager.write('body2.pos.x=' + body2.position.x + ' y=' + body2.position.y); + // Corrected delta vector + var dp = new Phaser.Vec2(); + Phaser.Vec2Utils.subtract(p2, p1, dp); + //var dp = vec2.sub(p2, p1); + // Position constraint + var c = Phaser.Vec2Utils.dot(dp, n) + con.depth; + var correction = this.clamp(Physics.Manager.CONTACT_SOLVER_BAUMGARTE * (c + Physics.Manager.CONTACT_SOLVER_COLLISION_SLOP), -Physics.Manager.CONTACT_SOLVER_MAX_LINEAR_CORRECTION, 0); + if(correction == 0) { + continue; + } + // We don't need max_penetration less than or equal slop + max_penetration = Math.max(max_penetration, -c); + // Compute lambda for position constraint + // Solve (J * invM * JT) * lambda = -C / dt + var sn1 = Phaser.Vec2Utils.cross(r1, n); + var sn2 = Phaser.Vec2Utils.cross(r2, n); + var em_inv = sum_m_inv + body1.inertiaInverted * sn1 * sn1 + body2.inertiaInverted * sn2 * sn2; + var lambda_dt = em_inv == 0 ? 0 : -correction / em_inv; + // Apply correction impulses + var impulse_dt = new Phaser.Vec2(); + Phaser.Vec2Utils.scale(n, lambda_dt, impulse_dt); + //var impulse_dt = vec2.scale(n, lambda_dt); + body1.position.multiplyAddByScalar(impulse_dt, -m1_inv); + //body1.p.mad(impulse_dt, -m1_inv); + body1.angle -= sn1 * lambda_dt * i1_inv; + body2.position.multiplyAddByScalar(impulse_dt, m2_inv); + //body2.p.mad(impulse_dt, m2_inv); + body2.angle += sn2 * lambda_dt * i2_inv; + Physics.Manager.write('body1.pos.x=' + body1.position.x + ' y=' + body1.position.y); + Physics.Manager.write('body2.pos.x=' + body2.position.x + ' y=' + body2.position.y); + } + Physics.Manager.write('max_penetration: ' + max_penetration); + return max_penetration <= Physics.Manager.CONTACT_SOLVER_COLLISION_SLOP * 3; + }; + ContactSolver.prototype.clamp = function (v, min, max) { + return v < min ? min : (v > max ? max : v); + }; + return ContactSolver; + })(); + Physics.ContactSolver = ContactSolver; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + (function (Physics) { + /// + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Shape - Circle + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + (function (Shapes) { + var Circle = (function (_super) { + __extends(Circle, _super); + function Circle(radius, x, y) { + if (typeof x === "undefined") { x = 0; } + if (typeof y === "undefined") { y = 0; } + _super.call(this, Physics.Manager.SHAPE_TYPE_CIRCLE); + x = Physics.Manager.pixelsToMeters(x); + y = Physics.Manager.pixelsToMeters(y); + radius = Physics.Manager.pixelsToMeters(radius); + this.center = new Phaser.Vec2(x, y); + this.radius = radius; + this.tc = new Phaser.Vec2(); + this.finishVerts(); + } + Circle.prototype.finishVerts = function () { + this.radius = Math.abs(this.radius); + }; + Circle.prototype.duplicate = function () { + return new Circle(this.center.x, this.center.y, this.radius); + }; + Circle.prototype.recenter = function (c) { + this.center.subtract(c); + }; + Circle.prototype.transform = function (xf) { + Phaser.TransformUtils.transform(xf, this.center, this.center); + //this.center = xf.transform(this.center); + }; + Circle.prototype.untransform = function (xf) { + Phaser.TransformUtils.untransform(xf, this.center, this.center); + //this.center = xf.untransform(this.center); + }; + Circle.prototype.area = function () { + return Physics.Manager.areaForCircle(this.radius, 0); + }; + Circle.prototype.centroid = function () { + return Phaser.Vec2Utils.clone(this.center); + }; + Circle.prototype.inertia = function (mass) { + return Physics.Manager.inertiaForCircle(mass, this.center, this.radius, 0); + }; + Circle.prototype.cacheData = function (xf) { + Phaser.TransformUtils.transform(xf, this.center, this.tc); + //this.tc = xf.transform(this.center); + this.bounds.mins.setTo(this.tc.x - this.radius, this.tc.y - this.radius); + this.bounds.maxs.setTo(this.tc.x + this.radius, this.tc.y + this.radius); + }; + Circle.prototype.pointQuery = function (p) { + //return vec2.distsq(this.tc, p) < (this.r * this.r); + return Phaser.Vec2Utils.distanceSq(this.tc, p) < (this.radius * this.radius); + }; + Circle.prototype.findVertexByPoint = function (p, minDist) { + var dsq = minDist * minDist; + if(Phaser.Vec2Utils.distanceSq(this.tc, p) < dsq) { + return 0; + } + return -1; + }; + Circle.prototype.distanceOnPlane = function (n, d) { + Phaser.Vec2Utils.dot(n, this.tc) - this.radius - d; + }; + return Circle; + })(Phaser.Physics.Shape); + Shapes.Circle = Circle; + })(Physics.Shapes || (Physics.Shapes = {})); + var Shapes = Physics.Shapes; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Plane + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + (function (Physics) { + var Plane = (function () { + function Plane(normal, d) { + this.normal = normal; + this.d = d; + } + return Plane; + })(); + Physics.Plane = Plane; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + (function (Physics) { + /// + /// + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Shapes - Convex Polygon + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + (function (Shapes) { + var Poly = (function (_super) { + __extends(Poly, _super); + // Verts is an optional array of objects, the objects must have public x and y properties which will be used + // to seed this polygon (i.e. Vec2 objects, or just straight JS objects) and must wind COUNTER clockwise + function Poly(verts) { + _super.call(this, Physics.Manager.SHAPE_TYPE_POLY); + this.verts = []; + this.planes = []; + this.tverts = []; + this.tplanes = []; + if(verts) { + for(var i = 0; i < verts.length; i++) { + this.verts[i] = new Phaser.Vec2(verts[i].x, verts[i].y); + this.tverts[i] = this.verts[i]; + //this.tverts[i] = new Phaser.Vec2(verts[i].x, verts[i].y); + this.tplanes[i] = new Phaser.Physics.Plane(new Phaser.Vec2(), 0); + } + } + this.finishVerts(); + } + Poly.prototype.finishVerts = function () { + if(this.verts.length < 2) { + this.convexity = false; + this.planes = []; + return; + } + this.convexity = true; + this.tverts = []; + this.tplanes = []; + // Must be counter-clockwise verts + for(var i = 0; i < this.verts.length; i++) { + var a = this.verts[i]; + var b = this.verts[(i + 1) % this.verts.length]; + var n = Phaser.Vec2Utils.normalize(Phaser.Vec2Utils.perp(Phaser.Vec2Utils.subtract(a, b))); + this.planes[i] = new Phaser.Physics.Plane(n, Phaser.Vec2Utils.dot(n, a)); + this.tverts[i] = Phaser.Vec2Utils.clone(this.verts[i])// reference??? + ; + //this.tverts[i] = this.verts[i]; // reference??? + this.tplanes[i] = new Phaser.Physics.Plane(new Phaser.Vec2(), 0); + } + for(var i = 0; i < this.verts.length; i++) { + //var b = this.verts[(i + 2) % this.verts.length]; + //var n = this.planes[i].normal; + //var d = this.planes[i].d; + if(Phaser.Vec2Utils.dot(this.planes[i].normal, this.verts[(i + 2) % this.verts.length]) - this.planes[i].d > 0) { + this.convexity = false; + } + } + }; + Poly.prototype.duplicate = function () { + return new Phaser.Physics.Shapes.Poly(this.verts); + }; + Poly.prototype.recenter = function (c) { + for(var i = 0; i < this.verts.length; i++) { + this.verts[i].subtract(c); + } + }; + Poly.prototype.transform = function (xf) { + for(var i = 0; i < this.verts.length; i++) { + this.verts[i] = Phaser.TransformUtils.transform(xf, this.verts[i]); + //this.verts[i] = xf.transform(this.verts[i]); + } + }; + Poly.prototype.untransform = function (xf) { + for(var i = 0; i < this.verts.length; i++) { + this.verts[i] = Phaser.TransformUtils.untransform(xf, this.verts[i]); + //this.verts[i] = xf.untransform(this.verts[i]); + } + }; + Poly.prototype.area = function () { + return Physics.Manager.areaForPoly(this.verts); + }; + Poly.prototype.centroid = function () { + return Physics.Manager.centroidForPoly(this.verts); + }; + Poly.prototype.inertia = function (mass) { + return Physics.Manager.inertiaForPoly(mass, this.verts, new Phaser.Vec2()); + }; + Poly.prototype.cacheData = function (xf) { + this.bounds.clear(); + var numVerts = this.verts.length; + Physics.Manager.write('----------- Poly cacheData = ' + numVerts); + if(numVerts == 0) { + return; + } + for(var i = 0; i < numVerts; i++) { + this.tverts[i] = Phaser.TransformUtils.transform(xf, this.verts[i]); + //this.tverts[i] = xf.transform(this.verts[i]); + Physics.Manager.write('tvert' + i + ' = ' + this.tverts[i].toString()); + } + if(numVerts < 2) { + this.bounds.addPoint(this.tverts[0]); + return; + } + for(var i = 0; i < numVerts; i++) { + var a = this.tverts[i]; + var b = this.tverts[(i + 1) % numVerts]; + var n = Phaser.Vec2Utils.normalize(Phaser.Vec2Utils.perp(Phaser.Vec2Utils.subtract(a, b))); + Physics.Manager.write('a = ' + a.toString()); + Physics.Manager.write('b = ' + b.toString()); + Physics.Manager.write('n = ' + n.toString()); + this.tplanes[i].normal = n; + this.tplanes[i].d = Phaser.Vec2Utils.dot(n, a); + Physics.Manager.write('tplanes' + i + ' n = ' + this.tplanes[i].normal.toString()); + Physics.Manager.write('tplanes' + i + ' d = ' + this.tplanes[i].d.toString()); + this.bounds.addPoint(a); + } + }; + Poly.prototype.pointQuery = function (p) { + if(!this.bounds.containPoint(p)) { + return false; + } + return this.containPoint(p); + }; + Poly.prototype.findVertexByPoint = function (p, minDist) { + var dsq = minDist * minDist; + for(var i = 0; i < this.tverts.length; i++) { + if(Phaser.Vec2Utils.distanceSq(this.tverts[i], p) < dsq) { + return i; + } + } + return -1; + }; + Poly.prototype.findEdgeByPoint = function (p, minDist) { + var dsq = minDist * minDist; + var numVerts = this.tverts.length; + for(var i = 0; i < this.tverts.length; i++) { + var v1 = this.tverts[i]; + var v2 = this.tverts[(i + 1) % numVerts]; + var n = this.tplanes[i].normal; + var dtv1 = Phaser.Vec2Utils.cross(v1, n); + var dtv2 = Phaser.Vec2Utils.cross(v2, n); + var dt = Phaser.Vec2Utils.cross(p, n); + if(dt > dtv1) { + if(Phaser.Vec2Utils.distanceSq(v1, p) < dsq) { + return i; + } + } else if(dt < dtv2) { + if(Phaser.Vec2Utils.distanceSq(v2, p) < dsq) { + return i; + } + } else { + var dist = Phaser.Vec2Utils.dot(n, p) - Phaser.Vec2Utils.dot(n, v1); + if(dist * dist < dsq) { + return i; + } + } + } + return -1; + }; + Poly.prototype.distanceOnPlane = function (n, d) { + var min = 999999; + for(var i = 0; i < this.verts.length; i++) { + min = Math.min(min, Phaser.Vec2Utils.dot(n, this.tverts[i])); + } + return min - d; + }; + Poly.prototype.containPoint = function (p) { + for(var i = 0; i < this.verts.length; i++) { + var plane = this.tplanes[i]; + if(Phaser.Vec2Utils.dot(plane.normal, p) - plane.d > 0) { + return false; + } + } + return true; + }; + Poly.prototype.containPointPartial = function (p, n) { + for(var i = 0; i < this.verts.length; i++) { + var plane = this.tplanes[i]; + if(Phaser.Vec2Utils.dot(plane.normal, n) < 0.0001) { + continue; + } + if(Phaser.Vec2Utils.dot(plane.normal, p) - plane.d > 0) { + return false; + } + } + return true; + }; + return Poly; + })(Phaser.Physics.Shape); + Shapes.Poly = Poly; + })(Physics.Shapes || (Physics.Shapes = {})); + var Shapes = Physics.Shapes; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + (function (Physics) { + /// + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Shapes - Segment + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + (function (Shapes) { + var Segment = (function (_super) { + __extends(Segment, _super); + function Segment(a, b, radius) { + _super.call(this, Physics.Manager.SHAPE_TYPE_SEGMENT); + this.a = a.duplicate(); + this.b = b.duplicate(); + this.radius = radius; + this.normal = Phaser.Vec2Utils.perp(Phaser.Vec2Utils.subtract(b, a)); + this.normal.normalize(); + this.ta = new Phaser.Vec2(); + this.tb = new Phaser.Vec2(); + this.tn = new Phaser.Vec2(); + this.finishVerts(); + } + Segment.prototype.finishVerts = function () { + this.normal = Phaser.Vec2Utils.perp(Phaser.Vec2Utils.subtract(this.b, this.a)); + this.normal.normalize(); + this.radius = Math.abs(this.radius); + }; + Segment.prototype.duplicate = function () { + return new Phaser.Physics.Shapes.Segment(this.a, this.b, this.radius); + }; + Segment.prototype.recenter = function (c) { + this.a.subtract(c); + this.b.subtract(c); + }; + Segment.prototype.transform = function (xf) { + Phaser.TransformUtils.transform(xf, this.a, this.a); + Phaser.TransformUtils.transform(xf, this.b, this.b); + //this.a = xf.transform(this.a); + //this.b = xf.transform(this.b); + }; + Segment.prototype.untransform = function (xf) { + Phaser.TransformUtils.untransform(xf, this.a, this.a); + Phaser.TransformUtils.untransform(xf, this.b, this.b); + //this.a = xf.untransform(this.a); + //this.b = xf.untransform(this.b); + }; + Segment.prototype.area = function () { + return Physics.Manager.areaForSegment(this.a, this.b, this.radius); + }; + Segment.prototype.centroid = function () { + return Physics.Manager.centroidForSegment(this.a, this.b); + }; + Segment.prototype.inertia = function (mass) { + return Physics.Manager.inertiaForSegment(mass, this.a, this.b); + }; + Segment.prototype.cacheData = function (xf) { + Phaser.TransformUtils.transform(xf, this.a, this.ta); + Phaser.TransformUtils.transform(xf, this.b, this.tb); + //this.ta = xf.transform(this.a); + //this.tb = xf.transform(this.b); + this.tn = Phaser.Vec2Utils.perp(Phaser.Vec2Utils.subtract(this.tb, this.ta)).normalize(); + var l; + var r; + var t; + var b; + if(this.ta.x < this.tb.x) { + l = this.ta.x; + r = this.tb.x; + } else { + l = this.tb.x; + r = this.ta.x; + } + if(this.ta.y < this.tb.y) { + b = this.ta.y; + t = this.tb.y; + } else { + b = this.tb.y; + t = this.ta.y; + } + this.bounds.mins.setTo(l - this.radius, b - this.radius); + this.bounds.maxs.setTo(r + this.radius, t + this.radius); + }; + Segment.prototype.pointQuery = function (p) { + if(!this.bounds.containPoint(p)) { + return false; + } + var dn = Phaser.Vec2Utils.dot(this.tn, p) - Phaser.Vec2Utils.dot(this.ta, this.tn); + var dist = Math.abs(dn); + if(dist > this.radius) { + return false; + } + var dt = Phaser.Vec2Utils.cross(p, this.tn); + var dta = Phaser.Vec2Utils.cross(this.ta, this.tn); + var dtb = Phaser.Vec2Utils.cross(this.tb, this.tn); + if(dt <= dta) { + if(dt < dta - this.radius) { + return false; + } + return Phaser.Vec2Utils.distanceSq(this.ta, p) < (this.radius * this.radius); + } else if(dt > dtb) { + if(dt > dtb + this.radius) { + return false; + } + return Phaser.Vec2Utils.distanceSq(this.tb, p) < (this.radius * this.radius); + } + return true; + }; + Segment.prototype.findVertexByPoint = function (p, minDist) { + var dsq = minDist * minDist; + if(Phaser.Vec2Utils.distanceSq(this.ta, p) < dsq) { + return 0; + } + if(Phaser.Vec2Utils.distanceSq(this.tb, p) < dsq) { + return 1; + } + return -1; + }; + Segment.prototype.distanceOnPlane = function (n, d) { + var a = Phaser.Vec2Utils.dot(n, this.ta) - this.radius; + var b = Phaser.Vec2Utils.dot(n, this.tb) - this.radius; + return Math.min(a, b) - d; + }; + return Segment; + })(Phaser.Physics.Shape); + Shapes.Segment = Segment; + })(Physics.Shapes || (Physics.Shapes = {})); + var Shapes = Physics.Shapes; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Collision Handlers + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + (function (Physics) { + var Collision = (function () { + function Collision() { } + Collision.prototype.collide = function (a, b, contacts) { + // Circle (a is the circle) + if(a.type == Physics.Manager.SHAPE_TYPE_CIRCLE) { + if(b.type == Physics.Manager.SHAPE_TYPE_CIRCLE) { + return this.circle2Circle(a, b, contacts); + } else if(b.type == Physics.Manager.SHAPE_TYPE_SEGMENT) { + return this.circle2Segment(a, b, contacts); + } else if(b.type == Physics.Manager.SHAPE_TYPE_POLY) { + return this.circle2Poly(a, b, contacts); + } + } + // Segment (a is the segment) + if(a.type == Physics.Manager.SHAPE_TYPE_SEGMENT) { + if(b.type == Physics.Manager.SHAPE_TYPE_CIRCLE) { + return this.circle2Segment(b, a, contacts); + } else if(b.type == Physics.Manager.SHAPE_TYPE_SEGMENT) { + return this.segment2Segment(a, b, contacts); + } else if(b.type == Physics.Manager.SHAPE_TYPE_POLY) { + return this.segment2Poly(a, b, contacts); + } + } + // Poly (a is the poly) + if(a.type == Physics.Manager.SHAPE_TYPE_POLY) { + if(b.type == Physics.Manager.SHAPE_TYPE_CIRCLE) { + return this.circle2Poly(b, a, contacts); + } else if(b.type == Physics.Manager.SHAPE_TYPE_SEGMENT) { + return this.segment2Poly(b, a, contacts); + } else if(b.type == Physics.Manager.SHAPE_TYPE_POLY) { + return this.poly2Poly(a, b, contacts); + } + } + }; + Collision.prototype._circle2Circle = function (c1, r1, c2, r2, contactArr) { + var rmax = r1 + r2; + var t = new Phaser.Vec2(); + //var t = vec2.sub(c2, c1); + Phaser.Vec2Utils.subtract(c2, c1, t); + var distsq = t.lengthSq(); + if(distsq > rmax * rmax) { + return 0; + } + var dist = Math.sqrt(distsq); + var p = new Phaser.Vec2(); + Phaser.Vec2Utils.multiplyAdd(c1, t, 0.5 + (r1 - r2) * 0.5 / dist, p); + //var p = vec2.mad(c1, t, 0.5 + (r1 - r2) * 0.5 / dist); + var n = new Phaser.Vec2(); + //var n = (dist != 0) ? vec2.scale(t, 1 / dist) : vec2.zero; + if(dist != 0) { + Phaser.Vec2Utils.scale(t, 1 / dist, n); + } + var d = dist - rmax; + contactArr.push(new Physics.Contact(p, n, d, 0)); + return 1; + }; + Collision.prototype.circle2Circle = function (circ1, circ2, contactArr) { + return this._circle2Circle(circ1.tc, circ1.radius, circ2.tc, circ2.radius, contactArr); + }; + Collision.prototype.circle2Segment = function (circ, seg, contactArr) { + var rsum = circ.radius + seg.radius; + // Normal distance from segment + var dn = Phaser.Vec2Utils.dot(circ.tc, seg.tn) - Phaser.Vec2Utils.dot(seg.ta, seg.tn); + var dist = (dn < 0 ? dn * -1 : dn) - rsum; + if(dist > 0) { + return 0; + } + // Tangential distance along segment + var dt = Phaser.Vec2Utils.cross(circ.tc, seg.tn); + var dtMin = Phaser.Vec2Utils.cross(seg.ta, seg.tn); + var dtMax = Phaser.Vec2Utils.cross(seg.tb, seg.tn); + if(dt < dtMin) { + if(dt < dtMin - rsum) { + return 0; + } + return this._circle2Circle(circ.tc, circ.radius, seg.ta, seg.radius, contactArr); + } else if(dt > dtMax) { + if(dt > dtMax + rsum) { + return 0; + } + return this._circle2Circle(circ.tc, circ.radius, seg.tb, seg.radius, contactArr); + } + var n = new Phaser.Vec2(); + if(dn > 0) { + n.copyFrom(seg.tn); + } else { + Phaser.Vec2Utils.negative(seg.tn, n); + } + //var n = (dn > 0) ? seg.tn : vec2.neg(seg.tn); + var c1 = new Phaser.Vec2(); + Phaser.Vec2Utils.multiplyAdd(circ.tc, n, -(circ.radius + dist * 0.5), c1); + var c2 = new Phaser.Vec2(); + Phaser.Vec2Utils.negative(n, c2); + contactArr.push(new Physics.Contact(c1, c2, dist, 0)); + //contactArr.push(new Contact(vec2.mad(circ.tc, n, -(circ.r + dist * 0.5)), vec2.neg(n), dist, 0)); + return 1; + }; + Collision.prototype.circle2Poly = function (circ, poly, contactArr) { + var minDist = -999999; + var minIdx = -1; + for(var i = 0; i < poly.verts.length; i++) { + var plane = poly.tplanes[i]; + var dist = Phaser.Vec2Utils.dot(circ.tc, plane.normal) - plane.d - circ.radius; + if(dist > 0) { + return 0; + } else if(dist > minDist) { + minDist = dist; + minIdx = i; + } + } + var n = poly.tplanes[minIdx].normal; + var a = poly.tverts[minIdx]; + var b = poly.tverts[(minIdx + 1) % poly.verts.length]; + var dta = Phaser.Vec2Utils.cross(a, n); + var dtb = Phaser.Vec2Utils.cross(b, n); + var dt = Phaser.Vec2Utils.cross(circ.tc, n); + if(dt > dta) { + return this._circle2Circle(circ.tc, circ.radius, a, 0, contactArr); + } else if(dt < dtb) { + return this._circle2Circle(circ.tc, circ.radius, b, 0, contactArr); + } + var c1 = new Phaser.Vec2(); + Phaser.Vec2Utils.multiplyAdd(circ.tc, n, -(circ.radius + minDist * 0.5), c1); + var c2 = new Phaser.Vec2(); + Phaser.Vec2Utils.negative(n, c2); + contactArr.push(new Physics.Contact(c1, c2, minDist, 0)); + //contactArr.push(new Contact(vec2.mad(circ.tc, n, -(circ.r + minDist * 0.5)), vec2.neg(n), minDist, 0)); + return 1; + }; + Collision.prototype.segmentPointDistanceSq = function (seg, p) { + var w = new Phaser.Vec2(); + var d = new Phaser.Vec2(); + Phaser.Vec2Utils.subtract(p, seg.ta, w); + Phaser.Vec2Utils.subtract(seg.tb, seg.ta, d); + //var w = vec2.sub(p, seg.ta); + //var d = vec2.sub(seg.tb, seg.ta); + var proj = w.dot(d); + if(proj <= 0) { + return w.dot(w); + } + var vsq = d.dot(d); + if(proj >= vsq) { + return w.dot(w) - 2 * proj + vsq; + } + return w.dot(w) - proj * proj / vsq; + }; + Collision.prototype.segment2Segment = // FIXME and optimise me lots!!! + function (seg1, seg2, contactArr) { + var d = []; + d[0] = this.segmentPointDistanceSq(seg1, seg2.ta); + d[1] = this.segmentPointDistanceSq(seg1, seg2.tb); + d[2] = this.segmentPointDistanceSq(seg2, seg1.ta); + d[3] = this.segmentPointDistanceSq(seg2, seg1.tb); + var idx1 = d[0] < d[1] ? 0 : 1; + var idx2 = d[2] < d[3] ? 2 : 3; + var idxm = d[idx1] < d[idx2] ? idx1 : idx2; + var s, t; + var u = Phaser.Vec2Utils.subtract(seg1.tb, seg1.ta); + var v = Phaser.Vec2Utils.subtract(seg2.tb, seg2.ta); + switch(idxm) { + case 0: + s = Phaser.Vec2Utils.dot(Phaser.Vec2Utils.subtract(seg2.ta, seg1.ta), u) / Phaser.Vec2Utils.dot(u, u); + s = s < 0 ? 0 : (s > 1 ? 1 : s); + t = 0; + break; + case 1: + s = Phaser.Vec2Utils.dot(Phaser.Vec2Utils.subtract(seg2.tb, seg1.ta), u) / Phaser.Vec2Utils.dot(u, u); + s = s < 0 ? 0 : (s > 1 ? 1 : s); + t = 1; + break; + case 2: + s = 0; + t = Phaser.Vec2Utils.dot(Phaser.Vec2Utils.subtract(seg1.ta, seg2.ta), v) / Phaser.Vec2Utils.dot(v, v); + t = t < 0 ? 0 : (t > 1 ? 1 : t); + break; + case 3: + s = 1; + t = Phaser.Vec2Utils.dot(Phaser.Vec2Utils.subtract(seg1.tb, seg2.ta), v) / Phaser.Vec2Utils.dot(v, v); + t = t < 0 ? 0 : (t > 1 ? 1 : t); + break; + } + var minp1 = Phaser.Vec2Utils.multiplyAdd(seg1.ta, u, s); + var minp2 = Phaser.Vec2Utils.multiplyAdd(seg2.ta, v, t); + return this._circle2Circle(minp1, seg1.radius, minp2, seg2.radius, contactArr); + }; + Collision.prototype.findPointsBehindSeg = // Identify vertexes that have penetrated the segment. + function (contactArr, seg, poly, dist, coef) { + var dta = Phaser.Vec2Utils.cross(seg.tn, seg.ta); + var dtb = Phaser.Vec2Utils.cross(seg.tn, seg.tb); + var n = new Phaser.Vec2(); + Phaser.Vec2Utils.scale(seg.tn, coef, n); + //var n = vec2.scale(seg.tn, coef); + for(var i = 0; i < poly.verts.length; i++) { + var v = poly.tverts[i]; + if(Phaser.Vec2Utils.dot(v, n) < Phaser.Vec2Utils.dot(seg.tn, seg.ta) * coef + seg.radius) { + var dt = Phaser.Vec2Utils.cross(seg.tn, v); + if(dta >= dt && dt >= dtb) { + contactArr.push(new Physics.Contact(v, n, dist, (poly.id << 16) | i)); + } + } + } + }; + Collision.prototype.segment2Poly = function (seg, poly, contactArr) { + var seg_td = Phaser.Vec2Utils.dot(seg.tn, seg.ta); + var seg_d1 = poly.distanceOnPlane(seg.tn, seg_td) - seg.radius; + if(seg_d1 > 0) { + return 0; + } + var n = new Phaser.Vec2(); + Phaser.Vec2Utils.negative(seg.tn, n); + var seg_d2 = poly.distanceOnPlane(n, -seg_td) - seg.radius; + //var seg_d2 = poly.distanceOnPlane(vec2.neg(seg.tn), -seg_td) - seg.r; + if(seg_d2 > 0) { + return 0; + } + var poly_d = -999999; + var poly_i = -1; + for(var i = 0; i < poly.verts.length; i++) { + var plane = poly.tplanes[i]; + var dist = seg.distanceOnPlane(plane.normal, plane.d); + if(dist > 0) { + return 0; + } + if(dist > poly_d) { + poly_d = dist; + poly_i = i; + } + } + var poly_n = new Phaser.Vec2(); + Phaser.Vec2Utils.negative(poly.tplanes[poly_i].normal, poly_n); + //var poly_n = vec2.neg(poly.tplanes[poly_i].n); + var va = new Phaser.Vec2(); + Phaser.Vec2Utils.multiplyAdd(seg.ta, poly_n, seg.radius, va); + //var va = vec2.mad(seg.ta, poly_n, seg.r); + var vb = new Phaser.Vec2(); + Phaser.Vec2Utils.multiplyAdd(seg.tb, poly_n, seg.radius, vb); + //var vb = vec2.mad(seg.tb, poly_n, seg.r); + if(poly.containPoint(va)) { + contactArr.push(new Physics.Contact(va, poly_n, poly_d, (seg.id << 16) | 0)); + } + if(poly.containPoint(vb)) { + contactArr.push(new Physics.Contact(vb, poly_n, poly_d, (seg.id << 16) | 1)); + } + // Floating point precision problems here. + // This will have to do for now. + poly_d -= 0.1; + if(seg_d1 >= poly_d || seg_d2 >= poly_d) { + if(seg_d1 > seg_d2) { + this.findPointsBehindSeg(contactArr, seg, poly, seg_d1, 1); + } else { + this.findPointsBehindSeg(contactArr, seg, poly, seg_d2, -1); + } + } + // If no other collision points are found, try colliding endpoints. + if(contactArr.length == 0) { + var poly_a = poly.tverts[poly_i]; + var poly_b = poly.tverts[(poly_i + 1) % poly.verts.length]; + if(this._circle2Circle(seg.ta, seg.radius, poly_a, 0, contactArr)) { + return 1; + } + if(this._circle2Circle(seg.tb, seg.radius, poly_a, 0, contactArr)) { + return 1; + } + if(this._circle2Circle(seg.ta, seg.radius, poly_b, 0, contactArr)) { + return 1; + } + if(this._circle2Circle(seg.tb, seg.radius, poly_b, 0, contactArr)) { + return 1; + } + } + return contactArr.length; + }; + Collision.prototype.findMSA = // Find the minimum separating axis for the given poly and plane list. + function (poly, planes, num) { + var min_dist = -999999; + var min_index = -1; + for(var i = 0; i < num; i++) { + var dist = poly.distanceOnPlane(planes[i].normal, planes[i].d); + if(dist > 0) { + // no collision + return { + dist: 0, + index: -1 + }; + } else if(dist > min_dist) { + min_dist = dist; + min_index = i; + } + } + // new object - see what we can do here + return { + dist: min_dist, + index: min_index + }; + }; + Collision.prototype.findVertsFallback = function (contactArr, poly1, poly2, n, dist) { + var num = 0; + for(var i = 0; i < poly1.verts.length; i++) { + var v = poly1.tverts[i]; + if(poly2.containPointPartial(v, n)) { + contactArr.push(new Physics.Contact(v, n, dist, (poly1.id << 16) | i)); + num++; + } + } + for(var i = 0; i < poly2.verts.length; i++) { + var v = poly2.tverts[i]; + if(poly1.containPointPartial(v, n)) { + contactArr.push(new Physics.Contact(v, n, dist, (poly2.id << 16) | i)); + num++; + } + } + return num; + }; + Collision.prototype.findVerts = // Find the overlapped vertices. + function (contactArr, poly1, poly2, n, dist) { + var num = 0; + for(var i = 0; i < poly1.verts.length; i++) { + var v = poly1.tverts[i]; + if(poly2.containPoint(v)) { + contactArr.push(new Physics.Contact(v, n, dist, (poly1.id << 16) | i)); + num++; + } + } + for(var i = 0; i < poly2.verts.length; i++) { + var v = poly2.tverts[i]; + if(poly1.containPoint(v)) { + contactArr.push(new Physics.Contact(v, n, dist, (poly2.id << 16) | i)); + num++; + } + } + return num > 0 ? num : this.findVertsFallback(contactArr, poly1, poly2, n, dist); + }; + Collision.prototype.poly2Poly = function (poly1, poly2, contactArr) { + var msa1 = this.findMSA(poly2, poly1.tplanes, poly1.verts.length); + if(msa1.index == -1) { + console.log('poly2poly 0', msa1); + return 0; + } + var msa2 = this.findMSA(poly1, poly2.tplanes, poly2.verts.length); + if(msa2.index == -1) { + console.log('poly2poly 1', msa2); + return 0; + } + // Penetration normal direction should be from poly1 to poly2 + if(msa1.dist > msa2.dist) { + return this.findVerts(contactArr, poly1, poly2, poly1.tplanes[msa1.index].normal, msa1.dist); + } + return this.findVerts(contactArr, poly1, poly2, Phaser.Vec2Utils.negative(poly2.tplanes[msa2.index].normal), msa2.dist); + }; + return Collision; + })(); + Physics.Collision = Collision; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + })(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + /// + /// + /// + /// + /// + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Space + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + (function (Physics) { + var Space = (function () { + function Space(manager) { + this.postSolve = null; + this.stepCount = 0; + this._manager = manager; + this.bodies = []; + this.bodyHash = { + }; + this.joints = []; + this.jointHash = { + }; + this.numContacts = 0; + this.contactSolvers = []; + this.gravity = this._manager.gravity; + this.damping = 0; + this._linTolSqr = Space.SLEEP_LINEAR_TOLERANCE * Space.SLEEP_LINEAR_TOLERANCE; + this._angTolSqr = Space.SLEEP_ANGULAR_TOLERANCE * Space.SLEEP_ANGULAR_TOLERANCE; + } + Space.TIME_TO_SLEEP = 0.5; + Space.SLEEP_LINEAR_TOLERANCE = 0.5; + Space.SLEEP_ANGULAR_TOLERANCE = 2 * 0.017453292519943294444444444444444; + Space.prototype.clear = function () { + Physics.Manager.shapeCounter = 0; + Physics.Manager.bodyCounter = 0; + Physics.Manager.jointCounter = 0; + for(var i = 0; i < this.bodies.length; i++) { + if(this.bodies[i]) { + this.removeBody(this.bodies[i]); + } + } + this.bodies = []; + this.bodyHash = { + }; + this.joints = []; + this.jointHash = { + }; + this.contactSolvers = []; + this.stepCount = 0; + }; + Space.prototype.addBody = function (body) { + if(this.bodyHash[body.id] != undefined) { + return; + } + var index = this.bodies.push(body) - 1; + this.bodyHash[body.id] = index; + body.awake(true); + body.space = this; + body.cacheData('addBody'); + }; + Space.prototype.removeBody = function (body) { + if(this.bodyHash[body.id] == undefined) { + return; + } + // Remove linked joints + for(var i = 0; i < body.joints.length; i++) { + if(body.joints[i]) { + this.removeJoint(body.joints[i]); + } + } + body.space = null; + var index = this.bodyHash[body.id]; + delete this.bodyHash[body.id]; + delete this.bodies[index]; + }; + Space.prototype.addJoint = function (joint) { + if(this.jointHash[joint.id] != undefined) { + return; + } + joint.body1.awake(true); + joint.body2.awake(true); + var index = this.joints.push(joint) - 1; + this.jointHash[joint.id] = index; + var index = joint.body1.joints.push(joint) - 1; + joint.body1.jointHash[joint.id] = index; + var index = joint.body2.joints.push(joint) - 1; + joint.body2.jointHash[joint.id] = index; + }; + Space.prototype.removeJoint = function (joint) { + if(this.jointHash[joint.id] == undefined) { + return; + } + joint.body1.awake(true); + joint.body2.awake(true); + var index = joint.body1.jointHash[joint.id]; + delete joint.body1.jointHash[joint.id]; + delete joint.body1.joints[index]; + var index = joint.body2.jointHash[joint.id]; + delete joint.body2.jointHash[joint.id]; + delete joint.body2.joints[index]; + var index = this.jointHash[joint.id]; + delete this.jointHash[joint.id]; + delete this.joints[index]; + }; + Space.prototype.findShapeByPoint = function (p, refShape) { + var firstShape; + for(var i = 0; i < this.bodies.length; i++) { + var body = this.bodies[i]; + if(!body) { + continue; + } + for(var j = 0; j < body.shapes.length; j++) { + var shape = body.shapes[j]; + if(shape.pointQuery(p)) { + if(!refShape) { + return shape; + } + if(!firstShape) { + firstShape = shape; + } + if(shape == refShape) { + refShape = null; + } + } + } + } + return firstShape; + }; + Space.prototype.findBodyByPoint = function (p, refBody) { + var firstBody; + for(var i = 0; i < this.bodies.length; i++) { + var body = this.bodies[i]; + if(!body) { + continue; + } + for(var j = 0; j < body.shapes.length; j++) { + var shape = body.shapes[j]; + if(shape.pointQuery(p)) { + if(!refBody) { + return shape.body; + } + if(!firstBody) { + firstBody = shape.body; + } + if(shape.body == refBody) { + refBody = null; + } + break; + } + } + } + return firstBody; + }; + Space.prototype.shapeById = function (id) { + var shape; + for(var i = 0; i < this.bodies.length; i++) { + var body = this.bodies[i]; + if(!body) { + continue; + } + for(var j = 0; j < body.shapes.length; j++) { + if(body.shapes[j].id == id) { + return body.shapes[j]; + } + } + } + return null; + }; + Space.prototype.jointById = function (id) { + var index = this.jointHash[id]; + if(index != undefined) { + return this.joints[index]; + } + return null; + }; + Space.prototype.findVertexByPoint = function (p, minDist, refVertexId) { + var firstVertexId = -1; + refVertexId = refVertexId || -1; + for(var i = 0; i < this.bodies.length; i++) { + var body = this.bodies[i]; + if(!body) { + continue; + } + for(var j = 0; j < body.shapes.length; j++) { + var shape = body.shapes[j]; + var index = shape.findVertexByPoint(p, minDist); + if(index != -1) { + var vertex = (shape.id << 16) | index; + if(refVertexId == -1) { + return vertex; + } + if(firstVertexId == -1) { + firstVertexId = vertex; + } + if(vertex == refVertexId) { + refVertexId = -1; + } + } + } + } + return firstVertexId; + }; + Space.prototype.findEdgeByPoint = function (p, minDist, refEdgeId) { + var firstEdgeId = -1; + refEdgeId = refEdgeId || -1; + for(var i = 0; i < this.bodies.length; i++) { + var body = this.bodies[i]; + if(!body) { + continue; + } + for(var j = 0; j < body.shapes.length; j++) { + var shape = body.shapes[j]; + if(shape.type != Physics.Manager.SHAPE_TYPE_POLY) { + continue; + } + var index = shape.findEdgeByPoint(p, minDist); + if(index != -1) { + var edge = (shape.id << 16) | index; + if(refEdgeId == -1) { + return edge; + } + if(firstEdgeId == -1) { + firstEdgeId = edge; + } + if(edge == refEdgeId) { + refEdgeId = -1; + } + } + } + } + return firstEdgeId; + }; + Space.prototype.findJointByPoint = function (p, minDist, refJointId) { + var firstJointId = -1; + var dsq = minDist * minDist; + refJointId = refJointId || -1; + for(var i = 0; i < this.joints.length; i++) { + var joint = this.joints[i]; + if(!joint) { + continue; + } + var jointId = -1; + if(Phaser.Vec2Utils.distanceSq(p, joint.getWorldAnchor1()) < dsq) { + jointId = (joint.id << 16 | 0); + } else if(Phaser.Vec2Utils.distanceSq(p, joint.getWorldAnchor2()) < dsq) { + jointId = (joint.id << 16 | 1); + } + if(jointId != -1) { + if(refJointId == -1) { + return jointId; + } + if(firstJointId == -1) { + firstJointId = jointId; + } + if(jointId == refJointId) { + refJointId = -1; + } + } + } + return firstJointId; + }; + Space.prototype.findContactSolver = function (shape1, shape2) { + Physics.Manager.write('findContactSolver. Length: ' + this._cl); + for(var i = 0; i < this._cl; i++) { + var contactSolver = this.contactSolvers[i]; + if(shape1 == contactSolver.shape1 && shape2 == contactSolver.shape2) { + return contactSolver; + } + } + return null; + }; + Space.prototype.genTemporalContactSolvers = function () { + Physics.Manager.write('genTemporalContactSolvers'); + this._cl = 0; + this.contactSolvers.length = 0; + this.numContacts = 0; + for(var body1Index = 0; body1Index < this._bl; body1Index++) { + if(!this.bodies[body1Index]) { + continue; + } + this.bodies[body1Index].stepCount = this.stepCount; + for(var body2Index = 0; body2Index < this._bl; body2Index++) { + if(this.bodies[body1Index].inContact(this.bodies[body2Index]) == false) { + continue; + } + Physics.Manager.write('body1 and body2 intersect'); + for(var i = 0; i < this.bodies[body1Index].shapesLength; i++) { + for(var j = 0; j < this.bodies[body2Index].shapesLength; j++) { + this._shape1 = this.bodies[body1Index].shapes[i]; + this._shape2 = this.bodies[body2Index].shapes[j]; + var contactArr = []; + if(!Physics.Manager.collision.collide(this._shape1, this._shape2, contactArr)) { + continue; + } + if(this._shape1.type > this._shape2.type) { + var temp = this._shape1; + this._shape1 = this._shape2; + this._shape2 = temp; + } + this.numContacts += contactArr.length; + // Result stored in this._contactSolver (see what we can do about generating some re-usable solvers) + var contactSolver = this.findContactSolver(this._shape1, this._shape2); + Physics.Manager.write('findContactSolver result: ' + contactSolver); + if(contactSolver) { + contactSolver.update(contactArr); + this.contactSolvers.push(contactSolver); + } else { + Physics.Manager.write('awake both bodies'); + this.bodies[body1Index].awake(true); + this.bodies[body2Index].awake(true); + var newContactSolver = new Physics.ContactSolver(this._shape1, this._shape2); + newContactSolver.contacts = contactArr; + newContactSolver.elasticity = Math.max(this._shape1.elasticity, this._shape2.elasticity); + newContactSolver.friction = Math.sqrt(this._shape1.friction * this._shape2.friction); + this.contactSolvers.push(newContactSolver); + Physics.Manager.write('new contact solver'); + } + } + } + } + } + this._cl = this.contactSolvers.length; + }; + Space.prototype.initSolver = function (warmStarting) { + Physics.Manager.write('initSolver'); + Physics.Manager.write('contactSolvers.length: ' + this._cl); + // Initialize contact solvers + for(var c = 0; c < this._cl; c++) { + this.contactSolvers[c].initSolver(this._deltaInv); + // Warm starting (apply cached impulse) + if(warmStarting) { + this.contactSolvers[c].warmStart(); + } + } + // Initialize joint solver + for(var j = 0; j < this.joints.length; j++) { + if(this.joints[j]) { + this.joints[j].initSolver(this._delta, warmStarting); + } + } + // Warm starting (apply cached impulse) + /* + if (warmStarting) + { + for (var c = 0; c < this._cl; c++) + { + this.contactSolvers[c].warmStart(); + } + } + */ + }; + Space.prototype.velocitySolver = function (iterations) { + Physics.Manager.write('velocitySolver, iterations: ' + iterations + ' csa len: ' + this._cl); + for(var i = 0; i < iterations; i++) { + for(var j = 0; j < this._jl; j++) { + if(this.joints[j]) { + this.joints[j].solveVelocityConstraints(); + } + } + for(var c = 0; c < this._cl; c++) { + this.contactSolvers[c].solveVelocityConstraints(); + } + } + }; + Space.prototype.positionSolver = function (iterations) { + this._positionSolved = false; + for(var i = 0; i < iterations; i++) { + this._contactsOk = true; + this._jointsOk = true; + for(var c = 0; c < this._cl; c++) { + this._contactsOk = this.contactSolvers[c].solvePositionConstraints() && this._contactsOk; + } + for(var j = 0; j < this._jl; j++) { + if(this.joints[j]) { + this._jointsOk = this.joints[j].solvePositionConstraints() && this._jointsOk; + } + } + if(this._contactsOk && this._jointsOk) { + // exit early if the position errors are small + this._positionSolved = true; + break; + } + } + return this._positionSolved; + }; + Space.prototype.step = // Step through the physics simulation + function (dt, velocityIterations, positionIterations, warmStarting, allowSleep) { + Physics.Manager.clear(); + Physics.Manager.write('Space step ' + this.stepCount); + this._delta = dt; + this._deltaInv = 1 / dt; + this._bl = this.bodies.length; + this._jl = this.joints.length; + this.stepCount++; + // 1) Generate Contact Solvers (into the this.contactSolvers array) + this.genTemporalContactSolvers(); + Physics.Manager.dump("Contact Solvers", this.bodies[1]); + // 2) Initialize the Contact Solvers + this.initSolver(warmStarting); + Physics.Manager.dump("Init Solver", this.bodies[1]); + // 3) Intergrate velocity + for(var i = 0; i < this._bl; i++) { + if(this.bodies[i] && this.bodies[i].isDynamic && this.bodies[i].isAwake) { + this.bodies[i].updateVelocity(this.gravity, this._delta, this.damping); + } + } + Physics.Manager.dump("Update Velocity", this.bodies[1]); + // 4) Awaken bodies via joints + for(var j = 0; i < this._jl; j++) { + if(!this.joints[j]) { + continue; + } + // combine + var awake1 = this.joints[j].body1.isAwake && !this.joints[j].body1.isStatic; + var awake2 = this.joints[j].body2.isAwake && !this.joints[j].body2.isStatic; + if(awake1 ^ awake2) { + if(!awake1) { + this.joints[j].body1.awake(true); + } + if(!awake2) { + this.joints[j].body2.awake(true); + } + } + } + // 5) Iterative velocity constraints solver + this.velocitySolver(velocityIterations); + Physics.Manager.dump("Velocity Solvers", this.bodies[1]); + // 6) Intergrate position + for(var i = 0; i < this._bl; i++) { + if(this.bodies[i] && this.bodies[i].isDynamic && this.bodies[i].isAwake) { + this.bodies[i].updatePosition(this._delta); + } + } + Physics.Manager.dump("Update Position", this.bodies[1]); + // 7) Process breakable joint + for(var i = 0; i < this._jl; i++) { + if(this.joints[i] && this.joints[i].breakable && (this.joints[i].getReactionForce(this._deltaInv).lengthSq() >= this.joints[i].maxForce * this.joints[i].maxForce)) { + this.removeJoint(this.joints[i]); + } + } + // 8) Iterative position constraints solver (result stored in this._positionSolved) + this.positionSolver(positionIterations); + Physics.Manager.dump("Position Solver", this.bodies[1]); + // 9) Sync the Transforms + for(var i = 0; i < this._bl; i++) { + if(this.bodies[i]) { + this.bodies[i].syncTransform(); + } + } + Physics.Manager.dump("Sync Transform", this.bodies[1]); + // 10) Post solve collision callback + if(this.postSolve) { + for(var i = 0; i < this._cl; i++) { + this.postSolve(this.contactSolvers[i]); + } + } + // 11) Cache Body Data + for(var i = 0; i < this._bl; i++) { + if(this.bodies[i] && this.bodies[i].isDynamic && this.bodies[i].isAwake) { + this.bodies[i].cacheData('post solve collision callback'); + } + } + Physics.Manager.dump("Cache Data", this.bodies[1]); + Physics.Manager.writeAll(); + // 12) Process sleeping + if(allowSleep) { + this._minSleepTime = 999999; + for(var i = 0; i < this._bl; i++) { + if(!this.bodies[i] || this.bodies[i].isDynamic == false) { + continue; + } + if(this.bodies[i].angularVelocity * this.bodies[i].angularVelocity > this._angTolSqr || this.bodies[i].velocity.dot(this.bodies[i].velocity) > this._linTolSqr) { + this.bodies[i].sleepTime = 0; + this._minSleepTime = 0; + } else { + this.bodies[i].sleepTime += this._delta; + this._minSleepTime = Math.min(this._minSleepTime, this.bodies[i].sleepTime); + } + } + if(this._positionSolved && this._minSleepTime >= Space.TIME_TO_SLEEP) { + for(var i = 0; i < this._bl; i++) { + if(this.bodies[i]) { + this.bodies[i].awake(false); + } + } + } + } + }; + return Space; + })(); + Physics.Space = Space; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + (function (Physics) { + /// + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Shapes - Triangle + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + (function (Shapes) { + var Triangle = (function (_super) { + __extends(Triangle, _super); + function Triangle(x1, y1, x2, y2, x3, y3) { + x1 = Physics.Manager.pixelsToMeters(x1); + y1 = Physics.Manager.pixelsToMeters(y1); + x2 = Physics.Manager.pixelsToMeters(x2); + y2 = Physics.Manager.pixelsToMeters(y2); + x3 = Physics.Manager.pixelsToMeters(x3); + y3 = Physics.Manager.pixelsToMeters(y3); + _super.call(this, [ + { + x: x1, + y: y1 + }, + { + x: x2, + y: y2 + }, + { + x: x3, + y: y3 + } + ]); + } + return Triangle; + })(Phaser.Physics.Shapes.Poly); + Shapes.Triangle = Triangle; + })(Physics.Shapes || (Physics.Shapes = {})); + var Shapes = Physics.Shapes; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + (function (Physics) { + /// + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Shapes - Box + * + * Based on the work Ju Hyung Lee started in JS PhyRus. + */ + (function (Shapes) { + var Box = (function (_super) { + __extends(Box, _super); + // Give in pixels + function Box(x, y, width, height) { + x = Physics.Manager.pixelsToMeters(x); + y = Physics.Manager.pixelsToMeters(y); + width = Physics.Manager.pixelsToMeters(width); + height = Physics.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.Shapes.Poly); + Shapes.Box = Box; + })(Physics.Shapes || (Physics.Shapes = {})); + var Shapes = Physics.Shapes; + })(Phaser.Physics || (Phaser.Physics = {})); + var Physics = Phaser.Physics; +})(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /** + * Phaser - Advanced Physics - Body + * + * Based on the work Ju Hyung Lee started in JS PhyRus. */ (function (Physics) { var Body = (function () { - function Body(sprite, type) { - this.angularVelocity = 0; - this.angularAcceleration = 0; - this.angularDrag = 0; - this.maxAngular = 10000; - this.mass = 1; - this._width = 0; - this._height = 0; - this.sprite = sprite; - this.game = sprite.game; + function Body(sprite, type, x, y, shapeType) { + if (typeof x === "undefined") { x = 0; } + if (typeof y === "undefined") { y = 0; } + if (typeof shapeType === "undefined") { shapeType = 0; } + this._tempVec2 = new Phaser.Vec2(); + // Shapes + this.shapes = []; + // Joints + this.joints = []; + this.jointHash = { + }; + this.fixedRotation = false; + this.categoryBits = 0x0001; + this.maskBits = 0xFFFF; + this.stepCount = 0; + this.id = Phaser.Physics.Manager.bodyCounter++; + this.name = 'body' + this.id; this.type = type; - // Fixture properties - // Will extend into its own class at a later date - can move the fixture defs there and add shape support, but this will do for 1.0 release - this.bounds = new Phaser.Rectangle(); - this._width = sprite.width; - this._height = sprite.height; - // Body properties - this.gravity = Phaser.Vec2Utils.clone(this.game.world.physics.gravity); - this.bounce = Phaser.Vec2Utils.clone(this.game.world.physics.bounce); + if(sprite) { + this.sprite = sprite; + this.game = sprite.game; + this.position = new Phaser.Vec2(Phaser.Physics.Manager.pixelsToMeters(sprite.x), Phaser.Physics.Manager.pixelsToMeters(sprite.y)); + this.angle = sprite.rotation; + } else { + this.position = new Phaser.Vec2(Phaser.Physics.Manager.pixelsToMeters(x), Phaser.Physics.Manager.pixelsToMeters(y)); + this.angle = 0; + } + this.transform = new Phaser.Transform(this.position, this.angle); + this.centroid = new Phaser.Vec2(); this.velocity = new Phaser.Vec2(); - this.acceleration = new Phaser.Vec2(); - this.drag = Phaser.Vec2Utils.clone(this.game.world.physics.drag); - this.maxVelocity = new Phaser.Vec2(10000, 10000); + this.force = new Phaser.Vec2(); this.angularVelocity = 0; - this.angularAcceleration = 0; - this.angularDrag = 0; - this.touching = Phaser.Types.NONE; - this.wasTouching = Phaser.Types.NONE; + this.torque = 0; + this.linearDamping = 0; + this.angularDamping = 0; + this.sleepTime = 0; + this.awaked = false; + this.shapes = []; + this.joints = []; + this.jointHash = { + }; + this.bounds = new Physics.Bounds(); this.allowCollisions = Phaser.Types.ANY; - this.position = new Phaser.Vec2(sprite.x + this.bounds.halfWidth, sprite.y + this.bounds.halfHeight); - this.oldPosition = new Phaser.Vec2(sprite.x + this.bounds.halfWidth, sprite.y + this.bounds.halfHeight); - this.offset = new Phaser.Vec2(); + this.fixedRotation = false; + this.categoryBits = 0x0001; + this.maskBits = 0xFFFF; + this.stepCount = 0; + if(sprite) { + if(shapeType == 0) { + this.addBox(0, 0, this.sprite.width, this.sprite.height, 1, 1, 1); + } else { + this.addCircle(Math.max(this.sprite.width, this.sprite.height) / 2, 0, 0, 1, 1, 1); + } + } } - Object.defineProperty(Body.prototype, "x", { - get: function () { - return this.sprite.x + this.offset.x; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Body.prototype, "y", { - get: function () { - return this.sprite.y + this.offset.y; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Body.prototype, "width", { - get: function () { - return this._width * this.sprite.transform.scale.x; - }, - set: function (value) { - this._width = value; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Body.prototype, "height", { - get: function () { - return this._height * this.sprite.transform.scale.y; - }, - set: function (value) { - this._height = value; - }, - enumerable: true, - configurable: true - }); - Body.prototype.preUpdate = function () { - this.oldPosition.copyFrom(this.position); - this.bounds.x = this.x; - this.bounds.y = this.y; - this.bounds.width = this.width; - this.bounds.height = this.height; + Body.prototype.toString = function () { + return "[{Body (name=" + this.name + " velocity=" + this.velocity.toString() + " angularVelocity: " + this.angularVelocity + ")}]"; }; - Body.prototype.postUpdate = // Shall we do this? Or just update the values directly in the separate functions? But then the bounds will be out of sync - as long as - // the bounds are updated and used in calculations then we can do one final sprite movement here I guess? - function () { - // if this is all it does maybe move elsewhere? Sprite postUpdate? - if(this.type !== Phaser.Types.BODY_DISABLED) { - this.game.world.physics.updateMotion(this); - this.wasTouching = this.touching; - this.touching = Phaser.Types.NONE; + Body.prototype.duplicate = function () { + console.log('body duplicate called'); + //var body = new Body(this.type, this.transform.t, this.angle); + //for (var i = 0; i < this.shapes.length; i++) + //{ + // body.addShape(this.shapes[i].duplicate()); + //} + //body.resetMassData(); + //return body; + }; + Object.defineProperty(Body.prototype, "isDisabled", { + get: function () { + return this.type == Phaser.Types.BODY_DISABLED ? true : false; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Body.prototype, "isStatic", { + get: function () { + return this.type == Phaser.Types.BODY_STATIC ? true : false; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Body.prototype, "isKinetic", { + get: function () { + return this.type == Phaser.Types.BODY_KINETIC ? true : false; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Body.prototype, "isDynamic", { + get: function () { + return this.type == Phaser.Types.BODY_DYNAMIC ? true : false; + }, + enumerable: true, + configurable: true + }); + Body.prototype.setType = function (type) { + if(type == this.type) { + return; } - this.position.setTo(this.x, this.y); + this.force.setTo(0, 0); + this.velocity.setTo(0, 0); + this.torque = 0; + this.angularVelocity = 0; + this.type = type; + this.awake(true); }; - Object.defineProperty(Body.prototype, "hullWidth", { - get: function () { - if(this.deltaX > 0) { - return this.bounds.width + this.deltaX; - } else { - return this.bounds.width - this.deltaX; - } - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Body.prototype, "hullHeight", { - get: function () { - if(this.deltaY > 0) { - return this.bounds.height + this.deltaY; - } else { - return this.bounds.height - this.deltaY; - } - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Body.prototype, "hullX", { - get: function () { - if(this.position.x < this.oldPosition.x) { - return this.position.x; - } else { - return this.oldPosition.x; - } - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Body.prototype, "hullY", { - get: function () { - if(this.position.y < this.oldPosition.y) { - return this.position.y; - } else { - return this.oldPosition.y; - } - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Body.prototype, "deltaXAbs", { - get: function () { - return (this.deltaX > 0 ? this.deltaX : -this.deltaX); - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Body.prototype, "deltaYAbs", { - get: function () { - return (this.deltaY > 0 ? this.deltaY : -this.deltaY); - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Body.prototype, "deltaX", { - get: function () { - return this.position.x - this.oldPosition.x; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Body.prototype, "deltaY", { - get: function () { - return this.position.y - this.oldPosition.y; - }, - enumerable: true, - configurable: true - }); - Body.prototype.render = // MOVE THESE TO A UTIL - function (context) { - context.beginPath(); - context.strokeStyle = 'rgb(0,255,0)'; - context.strokeRect(this.position.x - this.bounds.halfWidth, this.position.y - this.bounds.halfHeight, this.bounds.width, this.bounds.height); - context.stroke(); - context.closePath(); - // center point - context.fillStyle = 'rgb(0,255,0)'; - context.fillRect(this.position.x, this.position.y, 2, 2); - if(this.touching & Phaser.Types.LEFT) { - context.beginPath(); - context.strokeStyle = 'rgb(255,0,0)'; - context.moveTo(this.position.x - this.bounds.halfWidth, this.position.y - this.bounds.halfHeight); - context.lineTo(this.position.x - this.bounds.halfWidth, this.position.y + this.bounds.halfHeight); - context.stroke(); - context.closePath(); + Body.prototype.addPoly = function (verts, elasticity, friction, density) { + if (typeof elasticity === "undefined") { elasticity = 1; } + if (typeof friction === "undefined") { friction = 1; } + if (typeof density === "undefined") { density = 1; } + var poly = new Phaser.Physics.Shapes.Poly(verts); + poly.elasticity = elasticity; + poly.friction = friction; + poly.density = density; + this.addShape(poly); + this.resetMassData(); + return poly; + }; + Body.prototype.addTriangle = function (x1, y1, x2, y2, x3, y3, elasticity, friction, density) { + if (typeof elasticity === "undefined") { elasticity = 1; } + if (typeof friction === "undefined") { friction = 1; } + if (typeof density === "undefined") { density = 1; } + var tri = new Phaser.Physics.Shapes.Triangle(x1, y1, x2, y2, x3, y3); + tri.elasticity = elasticity; + tri.friction = friction; + tri.density = density; + this.addShape(tri); + this.resetMassData(); + return tri; + }; + Body.prototype.addBox = function (x, y, width, height, elasticity, friction, density) { + if (typeof elasticity === "undefined") { elasticity = 1; } + if (typeof friction === "undefined") { friction = 1; } + if (typeof density === "undefined") { density = 1; } + var box = new Phaser.Physics.Shapes.Box(x, y, width, height); + box.elasticity = elasticity; + box.friction = friction; + box.density = density; + this.addShape(box); + this.resetMassData(); + return box; + }; + Body.prototype.addCircle = function (radius, x, y, elasticity, friction, density) { + if (typeof x === "undefined") { x = 0; } + if (typeof y === "undefined") { y = 0; } + if (typeof elasticity === "undefined") { elasticity = 1; } + if (typeof friction === "undefined") { friction = 1; } + if (typeof density === "undefined") { density = 1; } + var circle = new Phaser.Physics.Shapes.Circle(radius, x, y); + circle.elasticity = elasticity; + circle.friction = friction; + circle.density = density; + this.addShape(circle); + this.resetMassData(); + return circle; + }; + Body.prototype.addShape = function (shape) { + // Check not already part of this body + shape.body = this; + this.shapes.push(shape); + this.shapesLength = this.shapes.length; + return shape; + }; + Body.prototype.removeShape = function (shape) { + var index = this.shapes.indexOf(shape); + if(index != -1) { + this.shapes.splice(index, 1); + shape.body = undefined; } - if(this.touching & Phaser.Types.RIGHT) { - context.beginPath(); - context.strokeStyle = 'rgb(255,0,0)'; - context.moveTo(this.position.x + this.bounds.halfWidth, this.position.y - this.bounds.halfHeight); - context.lineTo(this.position.x + this.bounds.halfWidth, this.position.y + this.bounds.halfHeight); - context.stroke(); - context.closePath(); + this.shapesLength = this.shapes.length; + }; + Body.prototype.setMass = function (mass) { + this.mass = mass; + this.massInverted = mass > 0 ? 1 / mass : 0; + }; + Body.prototype.setInertia = function (inertia) { + this.inertia = inertia; + this.inertiaInverted = inertia > 0 ? 1 / inertia : 0; + }; + Body.prototype.setTransform = function (pos, angle) { + // inject the transform into this.position + this.transform.setTo(pos, angle); + Physics.Manager.write('setTransform: ' + this.position.toString()); + Physics.Manager.write('centroid: ' + this.centroid.toString()); + Phaser.TransformUtils.transform(this.transform, this.centroid, this.position); + Physics.Manager.write('post setTransform: ' + this.position.toString()); + //this.position.copyFrom(this.transform.transform(this.centroid)); + this.angle = angle; + }; + Body.prototype.syncTransform = function () { + Physics.Manager.write('syncTransform:'); + Physics.Manager.write('p: ' + this.position.toString()); + Physics.Manager.write('centroid: ' + this.centroid.toString()); + Physics.Manager.write('xf: ' + this.transform.toString()); + Physics.Manager.write('a: ' + this.angle); + this.transform.setRotation(this.angle); + // OPTIMISE: Creating new vector + Phaser.Vec2Utils.subtract(this.position, Phaser.TransformUtils.rotate(this.transform, this.centroid), this.transform.t); + Physics.Manager.write('--------------------'); + Physics.Manager.write('xf: ' + this.transform.toString()); + Physics.Manager.write('--------------------'); + }; + Body.prototype.getWorldPoint = function (p) { + // OPTIMISE: Creating new vector + return Phaser.TransformUtils.transform(this.transform, p); + }; + Body.prototype.getWorldVector = function (v) { + // OPTIMISE: Creating new vector + return Phaser.TransformUtils.rotate(this.transform, v); + }; + Body.prototype.getLocalPoint = function (p) { + // OPTIMISE: Creating new vector + return Phaser.TransformUtils.untransform(this.transform, p); + }; + Body.prototype.getLocalVector = function (v) { + // OPTIMISE: Creating new vector + return Phaser.TransformUtils.unrotate(this.transform, v); + }; + Body.prototype.setFixedRotation = function (flag) { + this.fixedRotation = flag; + this.resetMassData(); + }; + Body.prototype.resetMassData = function () { + this.centroid.setTo(0, 0); + this.mass = 0; + this.massInverted = 0; + this.inertia = 0; + this.inertiaInverted = 0; + if(this.isDynamic == false) { + Phaser.TransformUtils.transform(this.transform, this.centroid, this.position); + //this.position.copyFrom(this.transform.transform(this.centroid)); + return; } - if(this.touching & Phaser.Types.UP) { - context.beginPath(); - context.strokeStyle = 'rgb(255,0,0)'; - context.moveTo(this.position.x - this.bounds.halfWidth, this.position.y - this.bounds.halfHeight); - context.lineTo(this.position.x + this.bounds.halfWidth, this.position.y - this.bounds.halfHeight); - context.stroke(); - context.closePath(); + var totalMassCentroid = new Phaser.Vec2(0, 0); + var totalMass = 0; + var totalInertia = 0; + for(var i = 0; i < this.shapes.length; i++) { + var shape = this.shapes[i]; + var centroid = shape.centroid(); + var mass = shape.area() * shape.density; + var inertia = shape.inertia(mass); + //console.log('rmd', centroid, shape); + totalMassCentroid.multiplyAddByScalar(centroid, mass); + totalMass += mass; + totalInertia += inertia; } - if(this.touching & Phaser.Types.DOWN) { - context.beginPath(); - context.strokeStyle = 'rgb(255,0,0)'; - context.moveTo(this.position.x - this.bounds.halfWidth, this.position.y + this.bounds.halfHeight); - context.lineTo(this.position.x + this.bounds.halfWidth, this.position.y + this.bounds.halfHeight); - context.stroke(); - context.closePath(); + //this.centroid.copy(vec2.scale(totalMassCentroid, 1 / totalMass)); + Phaser.Vec2Utils.scale(totalMassCentroid, 1 / totalMass, this.centroid); + this.setMass(totalMass); + if(!this.fixedRotation) { + this.setInertia(totalInertia - totalMass * Phaser.Vec2Utils.dot(this.centroid, this.centroid)); + } + // Move center of mass + var oldPosition = Phaser.Vec2Utils.clone(this.position); + Phaser.TransformUtils.transform(this.transform, this.centroid, this.position); + // Update center of mass velocity + oldPosition.subtract(this.position); + this.velocity.multiplyAddByScalar(Phaser.Vec2Utils.perp(oldPosition, oldPosition), this.angularVelocity); + }; + Body.prototype.resetJointAnchors = function () { + for(var i = 0; i < this.joints.length; i++) { + var joint = this.joints[i]; + if(!joint) { + continue; + } + var anchor1 = joint.getWorldAnchor1(); + var anchor2 = joint.getWorldAnchor2(); + joint.setWorldAnchor1(anchor1); + joint.setWorldAnchor2(anchor2); } }; - Body.prototype.renderDebugInfo = /** - * Render debug infos. (including name, bounds info, position and some other properties) - * @param x {number} X position of the debug info to be rendered. - * @param y {number} Y position of the debug info to be rendered. - * @param [color] {number} color of the debug info to be rendered. (format is css color string) - */ - function (x, y, color) { - if (typeof color === "undefined") { color = 'rgb(255,255,255)'; } - this.sprite.texture.context.fillStyle = color; - this.sprite.texture.context.fillText('Sprite: (' + this.sprite.width + ' x ' + this.sprite.height + ')', x, y); - //this.sprite.texture.context.fillText('x: ' + this._sprite.frameBounds.x.toFixed(1) + ' y: ' + this._sprite.frameBounds.y.toFixed(1) + ' rotation: ' + this._sprite.rotation.toFixed(1), x, y + 14); - this.sprite.texture.context.fillText('x: ' + this.bounds.x.toFixed(1) + ' y: ' + this.bounds.y.toFixed(1) + ' rotation: ' + this.sprite.transform.rotation.toFixed(0), x, y + 14); - this.sprite.texture.context.fillText('vx: ' + this.velocity.x.toFixed(1) + ' vy: ' + this.velocity.y.toFixed(1), x, y + 28); - this.sprite.texture.context.fillText('acx: ' + this.acceleration.x.toFixed(1) + ' acy: ' + this.acceleration.y.toFixed(1), x, y + 42); - this.sprite.texture.context.fillText('angVx: ' + this.angularVelocity.toFixed(1) + ' angAc: ' + this.angularAcceleration.toFixed(1), x, y + 56); + Body.prototype.cacheData = function (source) { + if (typeof source === "undefined") { source = ''; } + Physics.Manager.write('cacheData -- start'); + Physics.Manager.write('p: ' + this.position.toString()); + Physics.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); + } + Physics.Manager.write('bounds: ' + this.bounds.toString()); + Physics.Manager.write('p: ' + this.position.toString()); + Physics.Manager.write('xf: ' + this.transform.toString()); + Physics.Manager.write('cacheData -- stop'); + }; + Body.prototype.updateVelocity = function (gravity, dt, damping) { + Phaser.Vec2Utils.multiplyAdd(gravity, this.force, this.massInverted, this._tempVec2); + Phaser.Vec2Utils.multiplyAdd(this.velocity, this._tempVec2, dt, this.velocity); + this.angularVelocity = this.angularVelocity + this.torque * this.inertiaInverted * dt; + // Apply damping. + // ODE: dv/dt + c * v = 0 + // Solution: v(t) = v0 * exp(-c * t) + // Time step: v(t + dt) = v0 * exp(-c * (t + dt)) = v0 * exp(-c * t) * exp(-c * dt) = v * exp(-c * dt) + // v2 = exp(-c * dt) * v1 + // Taylor expansion: + // v2 = (1.0f - c * dt) * v1 + this.velocity.scale(this.clamp(1 - dt * (damping + this.linearDamping), 0, 1)); + this.angularVelocity *= this.clamp(1 - dt * (damping + this.angularDamping), 0, 1); + this.force.setTo(0, 0); + this.torque = 0; + }; + Body.prototype.inContact = function (body2) { + if(!body2 || this.stepCount == body2.stepCount) { + return false; + } + if(!(this.isAwake && this.isStatic == false) && !(body2.isAwake && body2.isStatic == false)) { + return false; + } + if(this.isCollidable(body2) == false) { + return false; + } + if(!this.bounds.intersectsBounds(body2.bounds)) { + return false; + } + return true; + }; + Body.prototype.clamp = function (v, min, max) { + return v < min ? min : (v > max ? max : v); + }; + Body.prototype.updatePosition = function (dt) { + this.position.add(Phaser.Vec2Utils.scale(this.velocity, dt, this._tempVec2)); + this.angle += this.angularVelocity * dt; + if(this.sprite) { + this.sprite.x = this.position.x * 50; + this.sprite.y = this.position.y * 50; + // Obey fixed rotation? + this.sprite.rotation = this.game.math.radiansToDegrees(this.angle); + } + }; + Body.prototype.resetForce = function () { + this.force.setTo(0, 0); + this.torque = 0; + }; + Body.prototype.applyForce = function (force, p) { + if(this.isDynamic == false) { + return; + } + if(this.isAwake == false) { + this.awake(true); + } + this.force.add(force); + Phaser.Vec2Utils.subtract(p, this.position, this._tempVec2); + this.torque += Phaser.Vec2Utils.cross(this._tempVec2, force); + }; + Body.prototype.applyForceToCenter = function (force) { + if(this.isDynamic == false) { + return; + } + if(this.isAwake == false) { + this.awake(true); + } + this.force.add(force); + }; + Body.prototype.applyTorque = function (torque) { + if(this.isDynamic == false) { + return; + } + if(this.isAwake == false) { + this.awake(true); + } + this.torque += torque; + }; + Body.prototype.applyLinearImpulse = function (impulse, p) { + if(this.isDynamic == false) { + return; + } + if(this.isAwake == false) { + this.awake(true); + } + this.velocity.multiplyAddByScalar(impulse, this.massInverted); + Phaser.Vec2Utils.subtract(p, this.position, this._tempVec2); + this.angularVelocity += Phaser.Vec2Utils.cross(this._tempVec2, impulse) * this.inertiaInverted; + }; + Body.prototype.applyAngularImpulse = function (impulse) { + if(this.isDynamic == false) { + return; + } + if(this.isAwake == false) { + this.awake(true); + } + this.angularVelocity += impulse * this.inertiaInverted; + }; + Body.prototype.kineticEnergy = function () { + var vsq = this.velocity.dot(this.velocity); + var wsq = this.angularVelocity * this.angularVelocity; + return 0.5 * (this.mass * vsq + this.inertia * wsq); + }; + Object.defineProperty(Body.prototype, "isAwake", { + get: function () { + return this.awaked; + }, + enumerable: true, + configurable: true + }); + Body.prototype.awake = function (flag) { + this.awaked = flag; + if(flag) { + this.sleepTime = 0; + } else { + this.velocity.setTo(0, 0); + this.angularVelocity = 0; + this.force.setTo(0, 0); + this.torque = 0; + } + }; + Body.prototype.isCollidable = function (other) { + if(this == other) { + return false; + } + if(this.isDynamic == false && other.isDynamic == false) { + return false; + } + if(!(this.maskBits & other.categoryBits) || !(other.maskBits & this.categoryBits)) { + return false; + } + for(var i = 0; i < this.joints.length; i++) { + var joint = this.joints[i]; + if(!this.joints[i] || (!this.joints[i].collideConnected && other.jointHash[this.joints[i].id] != undefined)) { + return false; + } + } + return true; }; return Body; })(); @@ -4514,14 +7108,20 @@ var Phaser; * @param [x] {number} the initial x position of the sprite. * @param [y] {number} the initial y position of the sprite. * @param [key] {string} Key of the graphic you want to load for this sprite. - * @param [bodyType] {number} The physics body type of the object (defaults to BODY_DYNAMIC) + * @param [bodyType] {number} The physics body type of the object (defaults to BODY_DISABLED) + * @param [shapeType] {number} The physics shape the body will consist of (either Box (0) or Circle (1), for custom types see body.addShape) */ - function Sprite(game, x, y, key, frame, bodyType) { + function Sprite(game, x, y, key, frame, bodyType, shapeType) { if (typeof x === "undefined") { x = 0; } if (typeof y === "undefined") { y = 0; } if (typeof key === "undefined") { key = null; } if (typeof frame === "undefined") { frame = null; } - if (typeof bodyType === "undefined") { bodyType = Phaser.Types.BODY_DYNAMIC; } + if (typeof bodyType === "undefined") { bodyType = Phaser.Types.BODY_DISABLED; } + if (typeof shapeType === "undefined") { shapeType = 0; } + /** + * Sprite physics body. + */ + this.body = null; /** * A boolean representing if the Sprite has been modified in any way via a scale, rotate, flip or skew. */ @@ -4569,7 +7169,11 @@ var Phaser; this.frame = frame; } } - this.body = new Phaser.Physics.Body(this, bodyType); + if(bodyType !== Phaser.Types.BODY_DISABLED) { + this.body = new Phaser.Physics.Body(this, bodyType, 0, 0, shapeType); + this.game.physics.addBody(this.body); + this.transform.origin.setTo(0.5, 0.5); + } this.worldView = new Phaser.Rectangle(x, y, this.width, this.height); this.cameraView = new Phaser.Rectangle(x, y, this.width, this.height); this.transform.setCache(); @@ -4654,8 +7258,6 @@ var Phaser; this.transform.update(); this.worldView.x = (this.x * this.transform.scrollFactor.x) - (this.width * this.transform.origin.x); this.worldView.y = (this.y * this.transform.scrollFactor.y) - (this.height * this.transform.origin.y); - //this.worldView.x = this.x * this.transform.scrollFactor.x; - //this.worldView.y = this.y * this.transform.scrollFactor.y; this.worldView.width = this.width; this.worldView.height = this.height; if(this.modified == false && (!this.transform.scale.equals(1) || !this.transform.skew.equals(0) || this.transform.rotation != 0 || this.transform.rotationOffset != 0 || this.texture.flippedX || this.texture.flippedY)) { @@ -4663,7 +7265,7 @@ var Phaser; } }; Sprite.prototype.update = /** - * Override this function to update your class's position and appearance. + * Override this function to update your sprites position and appearance. */ function () { }; @@ -4672,7 +7274,6 @@ var Phaser; */ function () { this.animations.update(); - this.body.postUpdate(); /* if (this.worldBounds != null) { @@ -4960,8 +7561,8 @@ var Phaser; */ function reset(sprite, x, y) { sprite.revive(); - sprite.body.touching = Phaser.Types.NONE; - sprite.body.wasTouching = Phaser.Types.NONE; + //sprite.body.touching = Types.NONE; + //sprite.body.wasTouching = Types.NONE; sprite.x = x; sprite.y = y; sprite.body.velocity.x = 0; @@ -9436,11 +12037,9 @@ var Phaser; _super.call(this, game); this.body.type = Phaser.Types.BODY_DYNAMIC; this.lifespan = 0; - this.friction = 500; } Particle.prototype.update = /** - * The particle's main update logic. Basically it checks to see if it should - * be dead yet, and then has some special bounce behavior if there is some gravity on it. + * The particle's main update logic. Basically it checks to see if it should be dead yet. */ function () { // Lifespan behavior @@ -9451,30 +12050,6 @@ var Phaser; if(this.lifespan <= 0) { this.kill(); } - //simpler bounce/spin behavior for now - if(this.body.touching) { - if(this.body.angularVelocity != 0) { - this.body.angularVelocity = -this.body.angularVelocity; - } - } - if(this.body.acceleration.y > 0)//special behavior for particles with gravity - { - if(this.body.touching & Phaser.Types.FLOOR) { - this.body.drag.x = this.friction; - if(!(this.body.wasTouching & Phaser.Types.FLOOR)) { - if(this.body.velocity.y < -this.body.bounce.y * 10) { - if(this.body.angularVelocity != 0) { - this.body.angularVelocity *= -this.body.bounce.y; - } - } else { - this.body.velocity.y = 0; - this.body.angularVelocity = 0; - } - } - } else { - this.body.drag.x = 0; - } - } }; Particle.prototype.onEmit = /** * Triggered whenever this object is launched by a Emitter. @@ -9591,16 +12166,16 @@ var Phaser; } } if(collide > 0) { - particle.body.allowCollisions = Phaser.Types.ANY; + //particle.body.allowCollisions = Types.ANY; particle.body.type = Phaser.Types.BODY_DYNAMIC; particle.width *= collide; particle.height *= collide; } else { - particle.body.allowCollisions = Phaser.Types.NONE; - } + //particle.body.allowCollisions = Types.NONE; + } particle.exists = false; // Center the origin for rotation assistance - particle.transform.origin.setTo(particle.body.bounds.halfWidth, particle.body.bounds.halfHeight); + //particle.transform.origin.setTo(particle.body.bounds.halfWidth, particle.body.bounds.halfHeight); this.add(particle); i++; } @@ -9686,7 +12261,7 @@ var Phaser; function () { var particle = this.recycle(Phaser.Particle); particle.lifespan = this.lifespan; - particle.body.bounce.setTo(this.bounce, this.bounce); + //particle.body.bounce.setTo(this.bounce, this.bounce); Phaser.SpriteUtils.reset(particle, this.x - (particle.width >> 1) + this.game.math.random() * this.width, this.y - (particle.height >> 1) + this.game.math.random() * this.height); particle.visible = true; if(this.minParticleSpeed.x != this.maxParticleSpeed.x) { @@ -9699,7 +12274,7 @@ var Phaser; } else { particle.body.velocity.y = this.minParticleSpeed.y; } - particle.body.acceleration.y = this.gravity; + //particle.body.acceleration.y = this.gravity; if(this.minRotation != this.maxRotation && this.minRotation !== 0 && this.maxRotation !== 0) { particle.body.angularVelocity = this.minRotation + this.game.math.random() * (this.maxRotation - this.minRotation); } else { @@ -9708,8 +12283,8 @@ var Phaser; if(particle.body.angularVelocity != 0) { particle.rotation = this.game.math.random() * 360 - 180; } - particle.body.drag.x = this.particleDrag.x; - particle.body.drag.y = this.particleDrag.y; + //particle.body.drag.x = this.particleDrag.x; + //particle.body.drag.y = this.particleDrag.y; particle.onEmit(); }; Emitter.prototype.setSize = /** @@ -9764,9 +12339,9 @@ var Phaser; * @param Object {object} The Object that you want to sync up with. */ function (object) { - this.x = object.body.bounds.halfWidth - (this.width >> 1); - this.y = object.body.bounds.halfHeight - (this.height >> 1); - }; + //this.x = object.body.bounds.halfWidth - (this.width >> 1); + //this.y = object.body.bounds.halfHeight - (this.height >> 1); + }; return Emitter; })(Phaser.Group); Phaser.Emitter = Emitter; @@ -10275,16 +12850,15 @@ var Phaser; // Loop through the tiles we've got and check overlaps accordingly (the results are stored in this._tempTileBlock) this._tempBlockResults = []; this.getTempBlock(this._tempTileX, this._tempTileY, this._tempTileW, this._tempTileH, true); - Phaser.Physics.PhysicsManager.TILE_OVERLAP = false; - for(var r = 0; r < this._tempTileBlock.length; r++) { - if(this._game.world.physics.separateTile(object, this._tempTileBlock[r].x * this.tileWidth, this._tempTileBlock[r].y * this.tileHeight, this.tileWidth, this.tileHeight, this._tempTileBlock[r].tile.mass, this._tempTileBlock[r].tile.collideLeft, this._tempTileBlock[r].tile.collideRight, this._tempTileBlock[r].tile.collideUp, this._tempTileBlock[r].tile.collideDown, this._tempTileBlock[r].tile.separateX, this._tempTileBlock[r].tile.separateY) == true) { - this._tempBlockResults.push({ - x: this._tempTileBlock[r].x, - y: this._tempTileBlock[r].y, - tile: this._tempTileBlock[r].tile - }); - } + /* + for (var r = 0; r < this._tempTileBlock.length; r++) + { + if (this._game.world.physics.separateTile(object, this._tempTileBlock[r].x * this.tileWidth, this._tempTileBlock[r].y * this.tileHeight, this.tileWidth, this.tileHeight, this._tempTileBlock[r].tile.mass, this._tempTileBlock[r].tile.collideLeft, this._tempTileBlock[r].tile.collideRight, this._tempTileBlock[r].tile.collideUp, this._tempTileBlock[r].tile.collideDown, this._tempTileBlock[r].tile.separateX, this._tempTileBlock[r].tile.separateY) == true) + { + this._tempBlockResults.push({ x: this._tempTileBlock[r].x, y: this._tempTileBlock[r].y, tile: this._tempTileBlock[r].tile }); } + } + */ return this._tempBlockResults; }; TilemapLayer.prototype.getTempBlock = /** @@ -10989,9 +13563,25 @@ var Phaser; function (x, y, key, frame, bodyType) { if (typeof key === "undefined") { key = ''; } if (typeof frame === "undefined") { frame = null; } - if (typeof bodyType === "undefined") { bodyType = Phaser.Types.BODY_DYNAMIC; } + if (typeof bodyType === "undefined") { bodyType = Phaser.Types.BODY_DISABLED; } return this._world.group.add(new Phaser.Sprite(this._game, x, y, key, frame, bodyType)); }; + GameObjectFactory.prototype.physicsSprite = /** + * Create a new Sprite with the physics automatically created and set to DYNAMIC. The Sprite position offset is set to its center. + * + * @param x {number} X position of the new sprite. + * @param y {number} Y position of the new sprite. + * @param [key] {string} The image key as defined in the Game.Cache to use as the texture for this sprite + * @param [frame] {string|number} If the sprite uses an image from a texture atlas or sprite sheet you can pass the frame here. Either a number for a frame ID or a string for a frame name. + * @param [shapeType] The default body shape is either 0 for a Box or 1 for a Circle. See Sprite.body.addShape for custom shapes (polygons, etc) + * @returns {Sprite} The newly created sprite object. + */ + function (x, y, key, frame, shapeType) { + if (typeof key === "undefined") { key = ''; } + if (typeof frame === "undefined") { frame = null; } + if (typeof shapeType === "undefined") { shapeType = 0; } + return this._world.group.add(new Phaser.Sprite(this._game, x, y, key, frame, Phaser.Types.BODY_DYNAMIC, shapeType)); + }; GameObjectFactory.prototype.dynamicTexture = /** * Create a new DynamicTexture with specific size. * @@ -12476,1111 +15066,11 @@ var Phaser; })(); Phaser.TweenManager = TweenManager; })(Phaser || (Phaser = {})); -/// -/// -/// -/// -/** -* Phaser - CircleUtils -* -* A collection of methods useful for manipulating and comparing Circle objects. -* -* TODO: -*/ -var Phaser; -(function (Phaser) { - var CircleUtils = (function () { - function CircleUtils() { } - CircleUtils.clone = /** - * Returns a new Circle object with the same values for the x, y, width, and height properties as the original Circle object. - * @method clone - * @param {Circle} a - The Circle object. - * @param {Circle} [optional] out Optional Circle object. If given the values will be set into the object, otherwise a brand new Circle object will be created and returned. - * @return {Phaser.Circle} - **/ - function clone(a, out) { - if (typeof out === "undefined") { out = new Phaser.Circle(); } - return out.setTo(a.x, a.y, a.diameter); - }; - CircleUtils.contains = /** - * Return true if the given x/y coordinates are within the Circle object. - * If you need details about the intersection then use Phaser.Intersect.circleContainsPoint instead. - * @method contains - * @param {Circle} a - The Circle object. - * @param {Number} The X value of the coordinate to test. - * @param {Number} The Y value of the coordinate to test. - * @return {Boolean} True if the coordinates are within this circle, otherwise false. - **/ - function contains(a, x, y) { - //return (a.radius * a.radius >= Collision.distanceSquared(a.x, a.y, x, y)); - return true; - }; - CircleUtils.containsPoint = /** - * Return true if the coordinates of the given Point object are within this Circle object. - * If you need details about the intersection then use Phaser.Intersect.circleContainsPoint instead. - * @method containsPoint - * @param {Circle} a - The Circle object. - * @param {Point} The Point object to test. - * @return {Boolean} True if the coordinates are within this circle, otherwise false. - **/ - function containsPoint(a, point) { - return CircleUtils.contains(a, point.x, point.y); - }; - CircleUtils.containsCircle = /** - * Return true if the given Circle is contained entirely within this Circle object. - * If you need details about the intersection then use Phaser.Intersect.circleToCircle instead. - * @method containsCircle - * @param {Circle} The Circle object to test. - * @return {Boolean} True if the coordinates are within this circle, otherwise false. - **/ - function containsCircle(a, b) { - //return ((a.radius + b.radius) * (a.radius + b.radius)) >= Collision.distanceSquared(a.x, a.y, b.x, b.y); - return true; - }; - CircleUtils.distanceBetween = /** - * Returns the distance from the center of the Circle object to the given object (can be Circle, Point or anything with x/y properties) - * @method distanceBetween - * @param {Circle} a - The Circle object. - * @param {Circle} b - The target object. Must have visible x and y properties that represent the center of the object. - * @param {Boolean} [optional] round - Round the distance to the nearest integer (default false) - * @return {Number} The distance between this Point object and the destination Point object. - **/ - function distanceBetween(a, target, round) { - if (typeof round === "undefined") { round = false; } - var dx = a.x - target.x; - var dy = a.y - target.y; - if(round === true) { - return Math.round(Math.sqrt(dx * dx + dy * dy)); - } else { - return Math.sqrt(dx * dx + dy * dy); - } - }; - CircleUtils.equals = /** - * Determines whether the two Circle objects match. This method compares the x, y and diameter properties. - * @method equals - * @param {Circle} a - The first Circle object. - * @param {Circle} b - The second Circle object. - * @return {Boolean} A value of true if the object has exactly the same values for the x, y and diameter properties as this Circle object; otherwise false. - **/ - function equals(a, b) { - return (a.x == b.x && a.y == b.y && a.diameter == b.diameter); - }; - CircleUtils.intersects = /** - * Determines whether the two Circle objects intersect. - * This method checks the radius distances between the two Circle objects to see if they intersect. - * @method intersects - * @param {Circle} a - The first Circle object. - * @param {Circle} b - The second Circle object. - * @return {Boolean} A value of true if the specified object intersects with this Circle object; otherwise false. - **/ - function intersects(a, b) { - return (CircleUtils.distanceBetween(a, b) <= (a.radius + b.radius)); - }; - CircleUtils.circumferencePoint = /** - * Returns a Point object containing the coordinates of a point on the circumference of the Circle based on the given angle. - * @method circumferencePoint - * @param {Circle} a - The first Circle object. - * @param {Number} angle The angle in radians (unless asDegrees is true) to return the point from. - * @param {Boolean} asDegrees Is the given angle in radians (false) or degrees (true)? - * @param {Phaser.Point} [optional] output An optional Point object to put the result in to. If none specified a new Point object will be created. - * @return {Phaser.Point} The Point object holding the result. - **/ - function circumferencePoint(a, angle, asDegrees, out) { - if (typeof asDegrees === "undefined") { asDegrees = false; } - if (typeof out === "undefined") { out = new Phaser.Point(); } - if(asDegrees === true) { - angle = angle * Phaser.GameMath.DEG_TO_RAD; - } - return out.setTo(a.x + a.radius * Math.cos(angle), a.y + a.radius * Math.sin(angle)); - }; - CircleUtils.intersectsRectangle = /* - public static boolean intersect(Rectangle r, Circle c) - { - float cx = Math.abs(c.x - r.x - r.halfWidth); - float xDist = r.halfWidth + c.radius; - if (cx > xDist) - return false; - float cy = Math.abs(c.y - r.y - r.halfHeight); - float yDist = r.halfHeight + c.radius; - if (cy > yDist) - return false; - if (cx <= r.halfWidth || cy <= r.halfHeight) - return true; - float xCornerDist = cx - r.halfWidth; - float yCornerDist = cy - r.halfHeight; - float xCornerDistSq = xCornerDist * xCornerDist; - float yCornerDistSq = yCornerDist * yCornerDist; - float maxCornerDistSq = c.radius * c.radius; - return xCornerDistSq + yCornerDistSq <= maxCornerDistSq; - } - */ - function intersectsRectangle(c, r) { - var cx = Math.abs(c.x - r.x - r.halfWidth); - var xDist = r.halfWidth + c.radius; - if(cx > xDist) { - return false; - } - var cy = Math.abs(c.y - r.y - r.halfHeight); - var yDist = r.halfHeight + c.radius; - if(cy > yDist) { - return false; - } - if(cx <= r.halfWidth || cy <= r.halfHeight) { - return true; - } - var xCornerDist = cx - r.halfWidth; - var yCornerDist = cy - r.halfHeight; - var xCornerDistSq = xCornerDist * xCornerDist; - var yCornerDistSq = yCornerDist * yCornerDist; - var maxCornerDistSq = c.radius * c.radius; - return xCornerDistSq + yCornerDistSq <= maxCornerDistSq; - }; - return CircleUtils; - })(); - Phaser.CircleUtils = CircleUtils; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - /// - /// - /// - /// - /// - /** - * Phaser - PhysicsManager - * - * Your game only has one PhysicsManager instance and it's responsible for looking after, creating and colliding - * all of the physics objects in the world. - */ - (function (Physics) { - var PhysicsManager = (function () { - function PhysicsManager(game, width, height) { - this._length = 0; - /** - * @type {number} - */ - this.worldDivisions = 6; - this.game = game; - this.gravity = new Phaser.Vec2(); - this.drag = new Phaser.Vec2(); - this.bounce = new Phaser.Vec2(); - this.angularDrag = 0; - this.bounds = new Phaser.Rectangle(0, 0, width, height); - this._distance = new Phaser.Vec2(); - this._tangent = new Phaser.Vec2(); - this.members = new Phaser.Group(game); - } - PhysicsManager.OVERLAP_BIAS = 4; - PhysicsManager.TILE_OVERLAP = false; - PhysicsManager.prototype.updateMotion = /* - public update() { - - this._length = this._objects.length; - - for (var i = 0; i < this._length; i++) - { - if (this._objects[i]) - { - this._objects[i].preUpdate(); - this.updateMotion(this._objects[i]); - this.collideWorld(this._objects[i]); - - for (var x = 0; x < this._length; x++) - { - if (this._objects[x] && this._objects[x] !== this._objects[i]) - { - //this.collideShapes(this._objects[i], this._objects[x]); - var r = this.NEWseparate(this._objects[i], this._objects[x]); - //console.log('sep', r); - } - } - - } - } - - } - - public render() { - - // iterate through the objects here, updating and colliding - for (var i = 0; i < this._length; i++) - { - if (this._objects[i]) - { - this._objects[i].render(this.game.stage.context); - } - } - - } - */ - function (body) { - if(body.type == Phaser.Types.BODY_DISABLED) { - return; - } - this._velocityDelta = (this.computeVelocity(body.angularVelocity, body.gravity.x, body.angularAcceleration, body.angularDrag, body.maxAngular) - body.angularVelocity) / 2; - body.angularVelocity += this._velocityDelta; - body.sprite.transform.rotation += body.angularVelocity * this.game.time.elapsed; - body.angularVelocity += this._velocityDelta; - this._velocityDelta = (this.computeVelocity(body.velocity.x, body.gravity.x, body.acceleration.x, body.drag.x) - body.velocity.x) / 2; - body.velocity.x += this._velocityDelta; - this._delta = body.velocity.x * this.game.time.elapsed; - body.velocity.x += this._velocityDelta; - //body.position.x += this._delta; - body.sprite.x += this._delta; - this._velocityDelta = (this.computeVelocity(body.velocity.y, body.gravity.y, body.acceleration.y, body.drag.y) - body.velocity.y) / 2; - body.velocity.y += this._velocityDelta; - this._delta = body.velocity.y * this.game.time.elapsed; - body.velocity.y += this._velocityDelta; - //body.position.y += this._delta; - body.sprite.y += this._delta; - }; - PhysicsManager.prototype.computeVelocity = /** - * A tween-like function that takes a starting velocity and some other factors and returns an altered velocity. - * - * @param {number} Velocity Any component of velocity (e.g. 20). - * @param {number} Acceleration Rate at which the velocity is changing. - * @param {number} Drag Really kind of a deceleration, this is how much the velocity changes if Acceleration is not set. - * @param {number} Max An absolute value cap for the velocity. - * - * @return {number} The altered Velocity value. - */ - function (velocity, gravity, acceleration, drag, max) { - if (typeof gravity === "undefined") { gravity = 0; } - if (typeof acceleration === "undefined") { acceleration = 0; } - if (typeof drag === "undefined") { drag = 0; } - if (typeof max === "undefined") { max = 10000; } - if(acceleration !== 0) { - velocity += (acceleration + gravity) * this.game.time.elapsed; - } else if(drag !== 0) { - this._drag = drag * this.game.time.elapsed; - if(velocity - this._drag > 0) { - velocity = velocity - this._drag; - } else if(velocity + this._drag < 0) { - velocity += this._drag; - } else { - velocity = 0; - } - velocity += gravity; - } - if((velocity != 0) && (max != 10000)) { - if(velocity > max) { - velocity = max; - } else if(velocity < -max) { - velocity = -max; - } - } - return velocity; - }; - PhysicsManager.prototype.separate = /** - * The core Collision separation method. - * @param body1 The first Physics.Body to separate - * @param body2 The second Physics.Body to separate - * @returns {boolean} Returns true if the bodies were separated, otherwise false. - */ - function (body1, body2) { - this._separatedX = this.separateBodyX(body1, body2); - this._separatedY = this.separateBodyY(body1, body2); - return this._separatedX || this._separatedY; - }; - PhysicsManager.prototype.checkHullIntersection = function (body1, body2) { - return ((body1.hullX + body1.hullWidth > body2.hullX) && (body1.hullX < body2.hullX + body2.hullWidth) && (body1.hullY + body1.hullHeight > body2.hullY) && (body1.hullY < body2.hullY + body2.hullHeight)); - }; - PhysicsManager.prototype.separateBodyX = /** - * Separates the two objects on their x axis - * @param object1 The first GameObject to separate - * @param object2 The second GameObject to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the X axis. - */ - function (body1, body2) { - // Can't separate two disabled or static objects - if((body1.type == Phaser.Types.BODY_DISABLED || body1.type == Phaser.Types.BODY_STATIC) && (body2.type == Phaser.Types.BODY_DISABLED || body2.type == Phaser.Types.BODY_STATIC)) { - return false; - } - // First, get the two object deltas - this._overlap = 0; - if(body1.deltaX != body2.deltaX) { - if(Phaser.RectangleUtils.intersects(body1.bounds, body2.bounds)) { - this._maxOverlap = body1.deltaXAbs + body2.deltaXAbs + PhysicsManager.OVERLAP_BIAS; - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if(body1.deltaX > body2.deltaX) { - this._overlap = body1.bounds.right - body2.bounds.x; - if((this._overlap > this._maxOverlap) || !(body1.allowCollisions & Phaser.Types.RIGHT) || !(body2.allowCollisions & Phaser.Types.LEFT)) { - this._overlap = 0; - } else { - body1.touching |= Phaser.Types.RIGHT; - body2.touching |= Phaser.Types.LEFT; - } - } else if(body1.deltaX < body2.deltaX) { - this._overlap = body1.bounds.x - body2.bounds.width - body2.bounds.x; - if((-this._overlap > this._maxOverlap) || !(body1.allowCollisions & Phaser.Types.LEFT) || !(body2.allowCollisions & Phaser.Types.RIGHT)) { - this._overlap = 0; - } else { - body1.touching |= Phaser.Types.LEFT; - body2.touching |= Phaser.Types.RIGHT; - } - } - } - } - // Then adjust their positions and velocities accordingly (if there was any overlap) - if(this._overlap != 0) { - this._obj1Velocity = body1.velocity.x; - this._obj2Velocity = body2.velocity.x; - /** - * Dynamic = gives and receives impacts - * Static = gives but doesn't receive impacts, cannot be moved by physics - * Kinematic = gives impacts, but never receives, can be moved by physics - */ - // 2 dynamic bodies will exchange velocities - if(body1.type == Phaser.Types.BODY_DYNAMIC && body2.type == Phaser.Types.BODY_DYNAMIC) { - this._overlap *= 0.5; - body1.position.x = body1.position.x - this._overlap; - body2.position.x += this._overlap; - this._obj1NewVelocity = Math.sqrt((this._obj2Velocity * this._obj2Velocity * body2.mass) / body1.mass) * ((this._obj2Velocity > 0) ? 1 : -1); - this._obj2NewVelocity = Math.sqrt((this._obj1Velocity * this._obj1Velocity * body1.mass) / body2.mass) * ((this._obj1Velocity > 0) ? 1 : -1); - this._average = (this._obj1NewVelocity + this._obj2NewVelocity) * 0.5; - this._obj1NewVelocity -= this._average; - this._obj2NewVelocity -= this._average; - body1.velocity.x = this._average + this._obj1NewVelocity * body1.bounce.x; - body2.velocity.x = this._average + this._obj2NewVelocity * body2.bounce.x; - } else if(body2.type != Phaser.Types.BODY_DYNAMIC) { - // Body 2 is Static or Kinematic - this._overlap *= 2; - body1.position.x -= this._overlap; - body1.velocity.x = this._obj2Velocity - this._obj1Velocity * body1.bounce.x; - } else if(body1.type != Phaser.Types.BODY_DYNAMIC) { - // Body 1 is Static or Kinematic - this._overlap *= 2; - body2.position.x += this._overlap; - body2.velocity.x = this._obj1Velocity - this._obj2Velocity * body2.bounce.x; - } - return true; - } else { - return false; - } - }; - PhysicsManager.prototype.separateBodyY = /** - * Separates the two objects on their y axis - * @param object1 The first GameObject to separate - * @param object2 The second GameObject to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis. - */ - function (body1, body2) { - // Can't separate two immovable objects - if((body1.type == Phaser.Types.BODY_DISABLED || body1.type == Phaser.Types.BODY_STATIC) && (body2.type == Phaser.Types.BODY_DISABLED || body2.type == Phaser.Types.BODY_STATIC)) { - return false; - } - // First, get the two object deltas - this._overlap = 0; - if(body1.deltaY != body2.deltaY) { - if(Phaser.RectangleUtils.intersects(body1.bounds, body2.bounds)) { - // This is the only place to use the DeltaAbs values - this._maxOverlap = body1.deltaYAbs + body2.deltaYAbs + PhysicsManager.OVERLAP_BIAS; - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if(body1.deltaY > body2.deltaY) { - this._overlap = body1.bounds.bottom - body2.bounds.y; - if((this._overlap > this._maxOverlap) || !(body1.allowCollisions & Phaser.Types.DOWN) || !(body2.allowCollisions & Phaser.Types.UP)) { - this._overlap = 0; - } else { - body1.touching |= Phaser.Types.DOWN; - body2.touching |= Phaser.Types.UP; - } - } else if(body1.deltaY < body2.deltaY) { - this._overlap = body1.bounds.y - body2.bounds.height - body2.bounds.y; - if((-this._overlap > this._maxOverlap) || !(body1.allowCollisions & Phaser.Types.UP) || !(body2.allowCollisions & Phaser.Types.DOWN)) { - this._overlap = 0; - } else { - body1.touching |= Phaser.Types.UP; - body2.touching |= Phaser.Types.DOWN; - } - } - } - } - // Then adjust their positions and velocities accordingly (if there was any overlap) - if(this._overlap != 0) { - this._obj1Velocity = body1.velocity.y; - this._obj2Velocity = body2.velocity.y; - /** - * Dynamic = gives and receives impacts - * Static = gives but doesn't receive impacts, cannot be moved by physics - * Kinematic = gives impacts, but never receives, can be moved by physics - */ - if(body1.type == Phaser.Types.BODY_DYNAMIC && body2.type == Phaser.Types.BODY_DYNAMIC) { - this._overlap *= 0.5; - body1.position.y = body1.position.y - this._overlap; - body2.position.y += this._overlap; - this._obj1NewVelocity = Math.sqrt((this._obj2Velocity * this._obj2Velocity * body2.mass) / body1.mass) * ((this._obj2Velocity > 0) ? 1 : -1); - this._obj2NewVelocity = Math.sqrt((this._obj1Velocity * this._obj1Velocity * body1.mass) / body2.mass) * ((this._obj1Velocity > 0) ? 1 : -1); - var average = (this._obj1NewVelocity + this._obj2NewVelocity) * 0.5; - this._obj1NewVelocity -= average; - this._obj2NewVelocity -= average; - body1.velocity.y = average + this._obj1NewVelocity * body1.bounce.y; - body2.velocity.y = average + this._obj2NewVelocity * body2.bounce.y; - } else if(body2.type != Phaser.Types.BODY_DYNAMIC) { - this._overlap *= 2; - body1.position.y -= this._overlap; - body1.velocity.y = this._obj2Velocity - this._obj1Velocity * body1.bounce.y; - // This is special case code that handles things like horizontal moving platforms you can ride - //if (body2.parent.active && body2.moves && (body1.deltaY > body2.deltaY)) - if(body2.sprite.active && (body1.deltaY > body2.deltaY)) { - body1.position.x += body2.position.x - body2.oldPosition.x; - } - } else if(body1.type != Phaser.Types.BODY_DYNAMIC) { - this._overlap *= 2; - body2.position.y += this._overlap; - body2.velocity.y = this._obj1Velocity - this._obj2Velocity * body2.bounce.y; - // This is special case code that handles things like horizontal moving platforms you can ride - //if (object1.active && body1.moves && (body1.deltaY < body2.deltaY)) - if(body1.sprite.active && (body1.deltaY < body2.deltaY)) { - body2.position.x += body1.position.x - body1.oldPosition.x; - } - } - return true; - } else { - return false; - } - }; - PhysicsManager.prototype.overlap = /* - private TILEseparate(shapeA: IPhysicsShape, shapeB: IPhysicsShape, distance: Vec2, tangent: Vec2) { - - if (tangent.x == 1) - { - console.log('1 The left side of ShapeA hit the right side of ShapeB', Math.floor(distance.x)); - shapeA.physics.touching |= Phaser.Types.LEFT; - shapeB.physics.touching |= Phaser.Types.RIGHT; - } - else if (tangent.x == -1) - { - console.log('2 The right side of ShapeA hit the left side of ShapeB', Math.floor(distance.x)); - shapeA.physics.touching |= Phaser.Types.RIGHT; - shapeB.physics.touching |= Phaser.Types.LEFT; - } - - if (tangent.y == 1) - { - console.log('3 The top of ShapeA hit the bottom of ShapeB', Math.floor(distance.y)); - shapeA.physics.touching |= Phaser.Types.UP; - shapeB.physics.touching |= Phaser.Types.DOWN; - } - else if (tangent.y == -1) - { - console.log('4 The bottom of ShapeA hit the top of ShapeB', Math.floor(distance.y)); - shapeA.physics.touching |= Phaser.Types.DOWN; - shapeB.physics.touching |= Phaser.Types.UP; - } - - - // only apply collision response forces if the object is travelling into, and not out of, the collision - var dot = Vec2Utils.dot(shapeA.physics.velocity, tangent); - - if (dot < 0) - { - console.log('in to', dot); - - // Apply horizontal bounce - if (shapeA.physics.bounce.x > 0) - { - shapeA.physics.velocity.x *= -(shapeA.physics.bounce.x); - } - else - { - shapeA.physics.velocity.x = 0; - } - // Apply horizontal bounce - if (shapeA.physics.bounce.y > 0) - { - shapeA.physics.velocity.y *= -(shapeA.physics.bounce.y); - } - else - { - shapeA.physics.velocity.y = 0; - } - } - else - { - console.log('out of', dot); - } - - shapeA.position.x += Math.floor(distance.x); - //shapeA.bounds.x += Math.floor(distance.x); - - shapeA.position.y += Math.floor(distance.y); - //shapeA.bounds.y += distance.y; - - console.log('------------------------------------------------'); - - } - - private collideWorld(shape:IPhysicsShape) { - - // Collide on the x-axis - this._distance.x = shape.world.bounds.x - (shape.position.x - shape.bounds.halfWidth); - - if (0 < this._distance.x) - { - // Hit Left - this._tangent.setTo(1, 0); - this.separateXWall(shape, this._distance, this._tangent); - } - else - { - this._distance.x = (shape.position.x + shape.bounds.halfWidth) - shape.world.bounds.right; - - if (0 < this._distance.x) - { - // Hit Right - this._tangent.setTo(-1, 0); - this._distance.reverse(); - this.separateXWall(shape, this._distance, this._tangent); - } - } - - // Collide on the y-axis - this._distance.y = shape.world.bounds.y - (shape.position.y - shape.bounds.halfHeight); - - if (0 < this._distance.y) - { - // Hit Top - this._tangent.setTo(0, 1); - this.separateYWall(shape, this._distance, this._tangent); - } - else - { - this._distance.y = (shape.position.y + shape.bounds.halfHeight) - shape.world.bounds.bottom; - - if (0 < this._distance.y) - { - // Hit Bottom - this._tangent.setTo(0, -1); - this._distance.reverse(); - this.separateYWall(shape, this._distance, this._tangent); - } - } - - } - - private separateX(shapeA: IPhysicsShape, shapeB: IPhysicsShape, distance: Vec2, tangent: Vec2) { - - if (tangent.x == 1) - { - console.log('The left side of ShapeA hit the right side of ShapeB', distance.x); - shapeA.physics.touching |= Phaser.Types.LEFT; - shapeB.physics.touching |= Phaser.Types.RIGHT; - } - else - { - console.log('The right side of ShapeA hit the left side of ShapeB', distance.x); - shapeA.physics.touching |= Phaser.Types.RIGHT; - shapeB.physics.touching |= Phaser.Types.LEFT; - } - - // collision edges - //shapeA.oH = tangent.x; - - // only apply collision response forces if the object is travelling into, and not out of, the collision - if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) - { - // Apply horizontal bounce - if (shapeA.physics.bounce.x > 0) - { - shapeA.physics.velocity.x *= -(shapeA.physics.bounce.x); - } - else - { - shapeA.physics.velocity.x = 0; - } - } - - shapeA.position.x += distance.x; - shapeA.bounds.x += distance.x; - - } - - private separateY(shapeA: IPhysicsShape, shapeB: IPhysicsShape, distance: Vec2, tangent: Vec2) { - - if (tangent.y == 1) - { - console.log('The top of ShapeA hit the bottom of ShapeB', distance.y); - shapeA.physics.touching |= Phaser.Types.UP; - shapeB.physics.touching |= Phaser.Types.DOWN; - } - else - { - console.log('The bottom of ShapeA hit the top of ShapeB', distance.y); - shapeA.physics.touching |= Phaser.Types.DOWN; - shapeB.physics.touching |= Phaser.Types.UP; - } - - // collision edges - //shapeA.oV = tangent.y; - - // only apply collision response forces if the object is travelling into, and not out of, the collision - if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) - { - // Apply horizontal bounce - if (shapeA.physics.bounce.y > 0) - { - shapeA.physics.velocity.y *= -(shapeA.physics.bounce.y); - } - else - { - shapeA.physics.velocity.y = 0; - } - } - - shapeA.position.y += distance.y; - shapeA.bounds.y += distance.y; - - } - - private separateXWall(shapeA: IPhysicsShape, distance: Vec2, tangent: Vec2) { - - if (tangent.x == 1) - { - console.log('The left side of ShapeA hit the right side of ShapeB', distance.x); - shapeA.physics.touching |= Phaser.Types.LEFT; - } - else - { - console.log('The right side of ShapeA hit the left side of ShapeB', distance.x); - shapeA.physics.touching |= Phaser.Types.RIGHT; - } - - // collision edges - //shapeA.oH = tangent.x; - - // only apply collision response forces if the object is travelling into, and not out of, the collision - if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) - { - // Apply horizontal bounce - if (shapeA.physics.bounce.x > 0) - { - shapeA.physics.velocity.x *= -(shapeA.physics.bounce.x); - } - else - { - shapeA.physics.velocity.x = 0; - } - } - - shapeA.position.x += distance.x; - - } - - private separateYWall(shapeA: IPhysicsShape, distance: Vec2, tangent: Vec2) { - - if (tangent.y == 1) - { - console.log('The top of ShapeA hit the bottom of ShapeB', distance.y); - shapeA.physics.touching |= Phaser.Types.UP; - } - else - { - console.log('The bottom of ShapeA hit the top of ShapeB', distance.y); - shapeA.physics.touching |= Phaser.Types.DOWN; - } - - // collision edges - //shapeA.oV = tangent.y; - - // only apply collision response forces if the object is travelling into, and not out of, the collision - if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) - { - // Apply horizontal bounce - if (shapeA.physics.bounce.y > 0) - { - shapeA.physics.velocity.y *= -(shapeA.physics.bounce.y); - } - else - { - shapeA.physics.velocity.y = 0; - } - } - - shapeA.position.y += distance.y; - - } - */ - /** - * Checks for overlaps between two objects using the world QuadTree. Can be Sprite vs. Sprite, Sprite vs. Group or Group vs. Group. - * Note: Does not take the objects scrollFactor into account. All overlaps are check in world space. - * @param object1 The first Sprite or Group to check. If null the world.group is used. - * @param object2 The second Sprite or Group to check. - * @param notifyCallback A callback function that is called if the objects overlap. The two objects will be passed to this function in the same order in which you passed them to Collision.overlap. - * @param processCallback A callback function that lets you perform additional checks against the two objects if they overlap. If this is set then notifyCallback will only be called if processCallback returns true. - * @param context The context in which the callbacks will be called - * @returns {boolean} true if the objects overlap, otherwise false. - */ - function (object1, object2, notifyCallback, processCallback, context) { - if (typeof object1 === "undefined") { object1 = null; } - if (typeof object2 === "undefined") { object2 = null; } - if (typeof notifyCallback === "undefined") { notifyCallback = null; } - if (typeof processCallback === "undefined") { processCallback = null; } - if (typeof context === "undefined") { context = null; } - if(object1 == null) { - object1 = this.game.world.group; - } - if(object2 == object1) { - object2 = null; - } - Phaser.QuadTree.divisions = this.worldDivisions; - this._quadTree = new Phaser.QuadTree(this, this.bounds.x, this.bounds.y, this.bounds.width, this.bounds.height); - this._quadTree.load(object1, object2, notifyCallback, processCallback, context); - this._quadTreeResult = this._quadTree.execute(); - console.log('over', this._quadTreeResult); - this._quadTree.destroy(); - this._quadTree = null; - return this._quadTreeResult; - }; - PhysicsManager.prototype.separateTile = /** - * Collision resolution specifically for GameObjects vs. Tiles. - * @param object The GameObject to separate - * @param tile The Tile to separate - * @returns {boolean} Whether the objects in fact touched and were separated - */ - function (object, x, y, width, height, mass, collideLeft, collideRight, collideUp, collideDown, separateX, separateY) { - //var separatedX: bool = this.separateTileX(object, x, y, width, height, mass, collideLeft, collideRight, separateX); - //var separatedY: bool = this.separateTileY(object, x, y, width, height, mass, collideUp, collideDown, separateY); - //return separatedX || separatedY; - return false; - }; - return PhysicsManager; - })(); - Physics.PhysicsManager = PhysicsManager; - /** - * Separates the two objects on their x axis - * @param object The GameObject to separate - * @param tile The Tile to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the X axis. - */ - /* - public separateTileX(object:Sprite, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool, separate: bool): bool { - - // Can't separate two immovable objects (tiles are always immovable) - if (object.immovable) - { - return false; - } - - // First, get the object delta - var overlap: number = 0; - var objDelta: number = object.x - object.last.x; - //var objDelta: number = object.collisionMask.deltaX; - - if (objDelta != 0) - { - // Check if the X hulls actually overlap - var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; - //var objDeltaAbs: number = object.collisionMask.deltaXAbs; - var objBounds: Rectangle = new Rectangle(object.x - ((objDelta > 0) ? objDelta : 0), object.last.y, object.width + ((objDelta > 0) ? objDelta : -objDelta), object.height); - - if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) - { - var maxOverlap: number = objDeltaAbs + Collision.OVERLAP_BIAS; - - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if (objDelta > 0) - { - overlap = object.x + object.width - x; - - if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.RIGHT) || collideLeft == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.RIGHT; - } - } - else if (objDelta < 0) - { - overlap = object.x - width - x; - - if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.LEFT) || collideRight == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.LEFT; - } - - } - - } - } - - // Then adjust their positions and velocities accordingly (if there was any overlap) - if (overlap != 0) - { - if (separate == true) - { - //console.log(' - object.x = object.x - overlap; - object.velocity.x = -(object.velocity.x * object.elasticity); - } - - Collision.TILE_OVERLAP = true; - return true; - } - else - { - return false; - } - - } - */ - /** - * Separates the two objects on their y axis - * @param object The first GameObject to separate - * @param tile The second GameObject to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis. - */ - /* - public separateTileY(object: Sprite, x: number, y: number, width: number, height: number, mass: number, collideUp: bool, collideDown: bool, separate: bool): bool { - - // Can't separate two immovable objects (tiles are always immovable) - if (object.immovable) - { - return false; - } - - // First, get the two object deltas - var overlap: number = 0; - var objDelta: number = object.y - object.last.y; - - if (objDelta != 0) - { - // Check if the Y hulls actually overlap - var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; - var objBounds: Rectangle = new Rectangle(object.x, object.y - ((objDelta > 0) ? objDelta : 0), object.width, object.height + objDeltaAbs); - - if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) - { - var maxOverlap: number = objDeltaAbs + Collision.OVERLAP_BIAS; - - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if (objDelta > 0) - { - overlap = object.y + object.height - y; - - if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.DOWN) || collideUp == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.DOWN; - } - } - else if (objDelta < 0) - { - overlap = object.y - height - y; - - if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.UP) || collideDown == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.UP; - } - } - } - } - - // TODO - with super low velocities you get lots of stuttering, set some kind of base minimum here - - // Then adjust their positions and velocities accordingly (if there was any overlap) - if (overlap != 0) - { - if (separate == true) - { - object.y = object.y - overlap; - object.velocity.y = -(object.velocity.y * object.elasticity); - } - - Collision.TILE_OVERLAP = true; - return true; - } - else - { - return false; - } - } - */ - /** - * Separates the two objects on their x axis - * @param object The GameObject to separate - * @param tile The Tile to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the X axis. - */ - /* - public static NEWseparateTileX(object:Sprite, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool, separate: bool): bool { - - // Can't separate two immovable objects (tiles are always immovable) - if (object.immovable) - { - return false; - } - - // First, get the object delta - var overlap: number = 0; - - if (object.collisionMask.deltaX != 0) - { - // Check if the X hulls actually overlap - //var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; - //var objBounds: Rectangle = new Rectangle(object.x - ((objDelta > 0) ? objDelta : 0), object.last.y, object.width + ((objDelta > 0) ? objDelta : -objDelta), object.height); - - //if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) - if (object.collisionMask.intersectsRaw(x, x + width, y, y + height)) - { - var maxOverlap: number = object.collisionMask.deltaXAbs + Collision.OVERLAP_BIAS; - - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if (object.collisionMask.deltaX > 0) - { - //overlap = object.x + object.width - x; - overlap = object.collisionMask.right - x; - - if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.RIGHT) || collideLeft == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.RIGHT; - } - } - else if (object.collisionMask.deltaX < 0) - { - //overlap = object.x - width - x; - overlap = object.collisionMask.x - width - x; - - if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.LEFT) || collideRight == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.LEFT; - } - - } - - } - } - - // Then adjust their positions and velocities accordingly (if there was any overlap) - if (overlap != 0) - { - if (separate == true) - { - object.x = object.x - overlap; - object.velocity.x = -(object.velocity.x * object.elasticity); - } - - Collision.TILE_OVERLAP = true; - return true; - } - else - { - return false; - } - - } - */ - /** - * Separates the two objects on their y axis - * @param object The first GameObject to separate - * @param tile The second GameObject to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis. - */ - /* - public NEWseparateTileY(object: Sprite, x: number, y: number, width: number, height: number, mass: number, collideUp: bool, collideDown: bool, separate: bool): bool { - - // Can't separate two immovable objects (tiles are always immovable) - if (object.immovable) - { - return false; - } - - // First, get the two object deltas - var overlap: number = 0; - //var objDelta: number = object.y - object.last.y; - - if (object.collisionMask.deltaY != 0) - { - // Check if the Y hulls actually overlap - //var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; - //var objBounds: Rectangle = new Rectangle(object.x, object.y - ((objDelta > 0) ? objDelta : 0), object.width, object.height + objDeltaAbs); - - //if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) - if (object.collisionMask.intersectsRaw(x, x + width, y, y + height)) - { - //var maxOverlap: number = objDeltaAbs + Collision.OVERLAP_BIAS; - var maxOverlap: number = object.collisionMask.deltaYAbs + Collision.OVERLAP_BIAS; - - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if (object.collisionMask.deltaY > 0) - { - //overlap = object.y + object.height - y; - overlap = object.collisionMask.bottom - y; - - if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.DOWN) || collideUp == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.DOWN; - } - } - else if (object.collisionMask.deltaY < 0) - { - //overlap = object.y - height - y; - overlap = object.collisionMask.y - height - y; - - if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.UP) || collideDown == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.UP; - } - } - } - } - - // TODO - with super low velocities you get lots of stuttering, set some kind of base minimum here - - // Then adjust their positions and velocities accordingly (if there was any overlap) - if (overlap != 0) - { - if (separate == true) - { - object.y = object.y - overlap; - object.velocity.y = -(object.velocity.y * object.elasticity); - } - - Collision.TILE_OVERLAP = true; - return true; - } - else - { - return false; - } - } - */ - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); /// /// /// /// -/// +/// /** * Phaser - World * @@ -13618,13 +15108,11 @@ var Phaser; */ function () { this.group = new Phaser.Group(this._game, 0); - this.physics = new Phaser.Physics.PhysicsManager(this._game, this.width, this.height); }; World.prototype.update = /** * This is called automatically every frame, and is where main logic happens. */ function () { - //this.physics.update(); this.group.update(); this.cameras.update(); }; @@ -13632,7 +15120,6 @@ var Phaser; * This is called automatically every frame, and is where main logic happens. */ function () { - //this.physics.postUpdate(); this.group.postUpdate(); this.cameras.postUpdate(); }; @@ -13640,7 +15127,6 @@ var Phaser; * Clean up memory. */ function () { - //this.physics.destroy(); this.group.destroy(); this.cameras.destroy(); }; @@ -13651,17 +15137,13 @@ var Phaser; * @param height {number} New height of the world. * @param [updateCameraBounds] {boolean} Update camera bounds automatically or not. Default to true. */ - function (width, height, updateCameraBounds, updatePhysicsBounds) { + function (width, height, updateCameraBounds) { if (typeof updateCameraBounds === "undefined") { updateCameraBounds = true; } - if (typeof updatePhysicsBounds === "undefined") { updatePhysicsBounds = true; } this.bounds.width = width; this.bounds.height = height; if(updateCameraBounds == true) { this._game.camera.setBounds(0, 0, width, height); } - if(updatePhysicsBounds == true) { - //this.physics.bounds.copyFrom(this.bounds); - } // dispatch world resize event }; Object.defineProperty(World.prototype, "width", { @@ -13789,14 +15271,19 @@ var Phaser; * @param {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically */ function (source, dest, speed, xSpeedMax, ySpeedMax) { - var a = this.angleBetween(source, dest); + /* + var a: number = this.angleBetween(source, dest); + source.body.velocity.x = 0; source.body.velocity.y = 0; + source.body.acceleration.x = Math.cos(a) * speed; source.body.acceleration.y = Math.sin(a) * speed; + source.body.maxVelocity.x = xSpeedMax; source.body.maxVelocity.y = ySpeedMax; - }; + */ + }; Motion.prototype.moveTowardsMouse = /** * Move the given Sprite towards the mouse pointer coordinates at a steady velocity * If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds.
@@ -13830,14 +15317,19 @@ var Phaser; * @param {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically */ function (source, speed, xSpeedMax, ySpeedMax) { - var a = this.angleBetweenMouse(source); + /* + var a: number = this.angleBetweenMouse(source); + source.body.velocity.x = 0; source.body.velocity.y = 0; + source.body.acceleration.x = Math.cos(a) * speed; source.body.acceleration.y = Math.sin(a) * speed; + source.body.maxVelocity.x = xSpeedMax; source.body.maxVelocity.y = ySpeedMax; - }; + */ + }; Motion.prototype.moveTowardsPoint = /** * Sets the x/y velocity on the source Sprite so it will move towards the target coordinates at the speed given (in pixels per second)
* If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds.
@@ -13873,14 +15365,19 @@ var Phaser; * @param {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically */ function (source, target, speed, xSpeedMax, ySpeedMax) { - var a = this.angleBetweenPoint(source, target); + /* + var a: number = this.angleBetweenPoint(source, target); + source.body.velocity.x = 0; source.body.velocity.y = 0; + source.body.acceleration.x = Math.cos(a) * speed; source.body.acceleration.y = Math.sin(a) * speed; + source.body.maxVelocity.x = xSpeedMax; source.body.maxVelocity.y = ySpeedMax; - }; + */ + }; Motion.prototype.distanceBetween = /** * Find the distance between two Sprites, taking their origin into account * @@ -13963,17 +15460,29 @@ var Phaser; * @return {Point} An Point where Point.x contains the velocity x value and Point.y contains the velocity y value */ function (parent, speed) { - var a; - if(parent.body.facing == Phaser.Types.LEFT) { - a = this.game.math.degreesToRadians(180); - } else if(parent.body.facing == Phaser.Types.RIGHT) { - a = this.game.math.degreesToRadians(0); - } else if(parent.body.facing == Phaser.Types.UP) { - a = this.game.math.degreesToRadians(-90); - } else if(parent.body.facing == Phaser.Types.DOWN) { - a = this.game.math.degreesToRadians(90); + /* + var a: number; + + if (parent.body.facing == Types.LEFT) + { + a = this.game.math.degreesToRadians(180); } - return new Phaser.Point(Math.cos(a) * speed, Math.sin(a) * speed); + else if (parent.body.facing == Types.RIGHT) + { + a = this.game.math.degreesToRadians(0); + } + else if (parent.body.facing == Types.UP) + { + a = this.game.math.degreesToRadians(-90); + } + else if (parent.body.facing == Types.DOWN) + { + a = this.game.math.degreesToRadians(90); + } + + return new Point(Math.cos(a) * speed, Math.sin(a) * speed); + */ + return new Phaser.Point(); }; Motion.prototype.angleBetweenMouse = /** * Find the angle (in radians) between an Sprite and the mouse, taking their x/y and origin into account. @@ -17064,14 +18573,14 @@ var Phaser; */ function renderSpriteInfo(sprite, x, y, color) { if (typeof color === "undefined") { color = 'rgb(255,255,255)'; } - DebugUtils.game.stage.context.fillStyle = color; - DebugUtils.game.stage.context.fillText('Sprite: ' + ' (' + sprite.width + ' x ' + sprite.height + ') origin: ' + sprite.transform.origin.x + ' x ' + sprite.transform.origin.y, x, y); - DebugUtils.game.stage.context.fillText('x: ' + sprite.x.toFixed(1) + ' y: ' + sprite.y.toFixed(1) + ' rotation: ' + sprite.rotation.toFixed(1), x, y + 14); - DebugUtils.game.stage.context.fillText('wx: ' + sprite.worldView.x + ' wy: ' + sprite.worldView.y + ' ww: ' + sprite.worldView.width.toFixed(1) + ' wh: ' + sprite.worldView.height.toFixed(1) + ' wb: ' + sprite.worldView.bottom + ' wr: ' + sprite.worldView.right, x, y + 28); - DebugUtils.game.stage.context.fillText('sx: ' + sprite.transform.scale.x.toFixed(1) + ' sy: ' + sprite.transform.scale.y.toFixed(1), x, y + 42); - DebugUtils.game.stage.context.fillText('tx: ' + sprite.texture.width.toFixed(1) + ' ty: ' + sprite.texture.height.toFixed(1), x, y + 56); - DebugUtils.game.stage.context.fillText('cx: ' + sprite.cameraView.x + ' cy: ' + sprite.cameraView.y + ' cw: ' + sprite.cameraView.width + ' ch: ' + sprite.cameraView.height + ' cb: ' + sprite.cameraView.bottom + ' cr: ' + sprite.cameraView.right, x, y + 70); - DebugUtils.game.stage.context.fillText('inCamera: ' + DebugUtils.game.renderer.inCamera(DebugUtils.game.camera, sprite), x, y + 84); + DebugUtils.context.fillStyle = color; + DebugUtils.context.fillText('Sprite: ' + ' (' + sprite.width + ' x ' + sprite.height + ') origin: ' + sprite.transform.origin.x + ' x ' + sprite.transform.origin.y, x, y); + DebugUtils.context.fillText('x: ' + sprite.x.toFixed(1) + ' y: ' + sprite.y.toFixed(1) + ' rotation: ' + sprite.rotation.toFixed(1), x, y + 14); + DebugUtils.context.fillText('wx: ' + sprite.worldView.x + ' wy: ' + sprite.worldView.y + ' ww: ' + sprite.worldView.width.toFixed(1) + ' wh: ' + sprite.worldView.height.toFixed(1) + ' wb: ' + sprite.worldView.bottom + ' wr: ' + sprite.worldView.right, x, y + 28); + DebugUtils.context.fillText('sx: ' + sprite.transform.scale.x.toFixed(1) + ' sy: ' + sprite.transform.scale.y.toFixed(1), x, y + 42); + DebugUtils.context.fillText('tx: ' + sprite.texture.width.toFixed(1) + ' ty: ' + sprite.texture.height.toFixed(1), x, y + 56); + DebugUtils.context.fillText('cx: ' + sprite.cameraView.x + ' cy: ' + sprite.cameraView.y + ' cw: ' + sprite.cameraView.width + ' ch: ' + sprite.cameraView.height + ' cb: ' + sprite.cameraView.bottom + ' cr: ' + sprite.cameraView.right, x, y + 70); + DebugUtils.context.fillText('inCamera: ' + DebugUtils.game.renderer.inCamera(DebugUtils.game.camera, sprite), x, y + 84); }; DebugUtils.renderSpriteBounds = function renderSpriteBounds(sprite, camera, color) { if (typeof camera === "undefined") { camera = null; } @@ -17079,23 +18588,36 @@ var Phaser; if(camera == null) { camera = DebugUtils.game.camera; } - //var dx = (camera.screenView.x * sprite.transform.scrollFactor.x) + sprite.x - (camera.worldView.x * sprite.transform.scrollFactor.x); - //var dy = (camera.screenView.y * sprite.transform.scrollFactor.y) + sprite.y - (camera.worldView.y * sprite.transform.scrollFactor.y); var dx = sprite.worldView.x; var dy = sprite.worldView.y; - DebugUtils.game.stage.context.fillStyle = color; - DebugUtils.game.stage.context.fillRect(dx, dy, sprite.width, sprite.height); + DebugUtils.context.fillStyle = color; + DebugUtils.context.fillRect(dx, dy, sprite.width, sprite.height); }; - DebugUtils.renderSpritePhysicsBody = function renderSpritePhysicsBody(sprite, camera, color) { - if (typeof camera === "undefined") { camera = null; } - if (typeof color === "undefined") { color = 'rgba(255,0,0,0.2)'; } - if(camera == null) { - camera = DebugUtils.game.camera; + DebugUtils.renderPhysicsBody = function renderPhysicsBody(body, lineWidth, fillStyle, sleepStyle) { + if (typeof lineWidth === "undefined") { lineWidth = 1; } + if (typeof fillStyle === "undefined") { fillStyle = 'rgba(0,255,0,0.2)'; } + if (typeof sleepStyle === "undefined") { sleepStyle = 'rgba(100,100,100,0.2)'; } + for(var s = 0; s < body.shapes.length; s++) { + DebugUtils.context.beginPath(); + if(body.shapes[s].type == Phaser.Physics.Manager.SHAPE_TYPE_POLY) { + var verts = body.shapes[s].tverts; + DebugUtils.context.moveTo((body.position.x + verts[0].x) * 50, (body.position.y + verts[0].y) * 50); + for(var i = 0; i < verts.length; i++) { + DebugUtils.context.lineTo((body.position.x + verts[i].x) * 50, (body.position.y + verts[i].y) * 50); + } + DebugUtils.context.lineTo((body.position.x + verts[verts.length - 1].x) * 50, (body.position.y + verts[verts.length - 1].y) * 50); + } else if(body.shapes[s].type == Phaser.Physics.Manager.SHAPE_TYPE_CIRCLE) { + var circle = body.shapes[s]; + DebugUtils.context.arc(circle.tc.x * 50, circle.tc.y * 50, circle.radius * 50, 0, Math.PI * 2, false); + } + DebugUtils.context.closePath(); + if(body.isAwake) { + DebugUtils.context.fillStyle = fillStyle; + } else { + DebugUtils.context.fillStyle = sleepStyle; + } + DebugUtils.context.fill(); } - var dx = (camera.screenView.x * sprite.transform.scrollFactor.x) + sprite.body.x - (camera.worldView.x * sprite.transform.scrollFactor.x); - var dy = (camera.screenView.y * sprite.transform.scrollFactor.y) + sprite.body.y - (camera.worldView.y * sprite.transform.scrollFactor.y); - DebugUtils.game.stage.context.fillStyle = color; - DebugUtils.game.stage.context.fillRect(dx, dy, sprite.body.width, sprite.body.height); }; return DebugUtils; })(); @@ -17167,16 +18689,6 @@ var Phaser; if (typeof destroyCallback === "undefined") { destroyCallback = null; } var _this = this; /** - * Max allowable accumulation. - * @type {number} - */ - this._maxAccumulation = 32; - /** - * Total number of milliseconds elapsed since last update loop. - * @type {number} - */ - this._accumulator = 0; - /** * Milliseconds of time per step of the game loop. * @type {number} */ @@ -17291,15 +18803,16 @@ var Phaser; this.rnd = new Phaser.RandomDataGenerator([ (Date.now() * Math.random()).toString() ]); + this.physics = new Phaser.Physics.Manager(this); this.setRenderer(Phaser.Types.RENDERER_CANVAS); this.world.boot(); this.stage.boot(); this.input.boot(); - this.framerate = 60; this.isBooted = true; // Set-up some static helper references Phaser.DebugUtils.game = this; Phaser.ColorUtils.game = this; + Phaser.DebugUtils.context = this.stage.context; // Display the default game screen? if(this.onInitCallback == null && this.onCreateCallback == null && this.onUpdateCallback == null && this.onRenderCallback == null && this._pendingState == null) { this._raf = new Phaser.RequestAnimationFrame(this, this.bootLoop); @@ -17359,15 +18872,8 @@ var Phaser; this.tweens.update(); this.input.update(); this.stage.update(); - this._accumulator += this.time.delta; - if(this._accumulator > this._maxAccumulation) { - this._accumulator = this._maxAccumulation; - } - while(this._accumulator >= this._step) { - this.time.elapsed = this.time.timeScale * (this._step / 1000); - this.world.update(); - this._accumulator = this._accumulator - this._step; - } + this.physics.update(); + this.world.update(); if(this._loadComplete && this.onUpdateCallback) { this.onUpdateCallback.call(this.callbackContext); } @@ -17523,19 +19029,6 @@ var Phaser; enumerable: true, configurable: true }); - Object.defineProperty(Game.prototype, "framerate", { - get: function () { - return 1000 / this._step; - }, - set: function (value) { - this._step = 1000 / value; - if(this._maxAccumulation < this._step) { - this._maxAccumulation = this._step; - } - }, - enumerable: true, - configurable: true - }); Game.prototype.collide = /** * Checks for overlaps between two objects using the world QuadTree. Can be GameObject vs. GameObject, GameObject vs. Group or Group vs. Group. * Note: Does not take the objects scrollFactor into account. All overlaps are check in world space. @@ -17551,7 +19044,8 @@ var Phaser; if (typeof objectOrGroup2 === "undefined") { objectOrGroup2 = null; } if (typeof notifyCallback === "undefined") { notifyCallback = null; } if (typeof context === "undefined") { context = this.callbackContext; } - return this.world.physics.overlap(objectOrGroup1, objectOrGroup2, notifyCallback, this.world.physics.separate, context); + //return this.world.physics.overlap(objectOrGroup1, objectOrGroup2, notifyCallback, this.world.physics.separate, context); + return false; }; Object.defineProperty(Game.prototype, "camera", { get: function () { @@ -17906,6 +19400,169 @@ var Phaser; Phaser.Line = Line; })(Phaser || (Phaser = {})); /// +/// +/// +/// +/** +* Phaser - CircleUtils +* +* A collection of methods useful for manipulating and comparing Circle objects. +* +* TODO: +*/ +var Phaser; +(function (Phaser) { + var CircleUtils = (function () { + function CircleUtils() { } + CircleUtils.clone = /** + * Returns a new Circle object with the same values for the x, y, width, and height properties as the original Circle object. + * @method clone + * @param {Circle} a - The Circle object. + * @param {Circle} [optional] out Optional Circle object. If given the values will be set into the object, otherwise a brand new Circle object will be created and returned. + * @return {Phaser.Circle} + **/ + function clone(a, out) { + if (typeof out === "undefined") { out = new Phaser.Circle(); } + return out.setTo(a.x, a.y, a.diameter); + }; + CircleUtils.contains = /** + * Return true if the given x/y coordinates are within the Circle object. + * If you need details about the intersection then use Phaser.Intersect.circleContainsPoint instead. + * @method contains + * @param {Circle} a - The Circle object. + * @param {Number} The X value of the coordinate to test. + * @param {Number} The Y value of the coordinate to test. + * @return {Boolean} True if the coordinates are within this circle, otherwise false. + **/ + function contains(a, x, y) { + //return (a.radius * a.radius >= Collision.distanceSquared(a.x, a.y, x, y)); + return true; + }; + CircleUtils.containsPoint = /** + * Return true if the coordinates of the given Point object are within this Circle object. + * If you need details about the intersection then use Phaser.Intersect.circleContainsPoint instead. + * @method containsPoint + * @param {Circle} a - The Circle object. + * @param {Point} The Point object to test. + * @return {Boolean} True if the coordinates are within this circle, otherwise false. + **/ + function containsPoint(a, point) { + return CircleUtils.contains(a, point.x, point.y); + }; + CircleUtils.containsCircle = /** + * Return true if the given Circle is contained entirely within this Circle object. + * If you need details about the intersection then use Phaser.Intersect.circleToCircle instead. + * @method containsCircle + * @param {Circle} The Circle object to test. + * @return {Boolean} True if the coordinates are within this circle, otherwise false. + **/ + function containsCircle(a, b) { + //return ((a.radius + b.radius) * (a.radius + b.radius)) >= Collision.distanceSquared(a.x, a.y, b.x, b.y); + return true; + }; + CircleUtils.distanceBetween = /** + * Returns the distance from the center of the Circle object to the given object (can be Circle, Point or anything with x/y properties) + * @method distanceBetween + * @param {Circle} a - The Circle object. + * @param {Circle} b - The target object. Must have visible x and y properties that represent the center of the object. + * @param {Boolean} [optional] round - Round the distance to the nearest integer (default false) + * @return {Number} The distance between this Point object and the destination Point object. + **/ + function distanceBetween(a, target, round) { + if (typeof round === "undefined") { round = false; } + var dx = a.x - target.x; + var dy = a.y - target.y; + if(round === true) { + return Math.round(Math.sqrt(dx * dx + dy * dy)); + } else { + return Math.sqrt(dx * dx + dy * dy); + } + }; + CircleUtils.equals = /** + * Determines whether the two Circle objects match. This method compares the x, y and diameter properties. + * @method equals + * @param {Circle} a - The first Circle object. + * @param {Circle} b - The second Circle object. + * @return {Boolean} A value of true if the object has exactly the same values for the x, y and diameter properties as this Circle object; otherwise false. + **/ + function equals(a, b) { + return (a.x == b.x && a.y == b.y && a.diameter == b.diameter); + }; + CircleUtils.intersects = /** + * Determines whether the two Circle objects intersect. + * This method checks the radius distances between the two Circle objects to see if they intersect. + * @method intersects + * @param {Circle} a - The first Circle object. + * @param {Circle} b - The second Circle object. + * @return {Boolean} A value of true if the specified object intersects with this Circle object; otherwise false. + **/ + function intersects(a, b) { + return (CircleUtils.distanceBetween(a, b) <= (a.radius + b.radius)); + }; + CircleUtils.circumferencePoint = /** + * Returns a Point object containing the coordinates of a point on the circumference of the Circle based on the given angle. + * @method circumferencePoint + * @param {Circle} a - The first Circle object. + * @param {Number} angle The angle in radians (unless asDegrees is true) to return the point from. + * @param {Boolean} asDegrees Is the given angle in radians (false) or degrees (true)? + * @param {Phaser.Point} [optional] output An optional Point object to put the result in to. If none specified a new Point object will be created. + * @return {Phaser.Point} The Point object holding the result. + **/ + function circumferencePoint(a, angle, asDegrees, out) { + if (typeof asDegrees === "undefined") { asDegrees = false; } + if (typeof out === "undefined") { out = new Phaser.Point(); } + if(asDegrees === true) { + angle = angle * Phaser.GameMath.DEG_TO_RAD; + } + return out.setTo(a.x + a.radius * Math.cos(angle), a.y + a.radius * Math.sin(angle)); + }; + CircleUtils.intersectsRectangle = /* + public static boolean intersect(Rectangle r, Circle c) + { + float cx = Math.abs(c.x - r.x - r.halfWidth); + float xDist = r.halfWidth + c.radius; + if (cx > xDist) + return false; + float cy = Math.abs(c.y - r.y - r.halfHeight); + float yDist = r.halfHeight + c.radius; + if (cy > yDist) + return false; + if (cx <= r.halfWidth || cy <= r.halfHeight) + return true; + float xCornerDist = cx - r.halfWidth; + float yCornerDist = cy - r.halfHeight; + float xCornerDistSq = xCornerDist * xCornerDist; + float yCornerDistSq = yCornerDist * yCornerDist; + float maxCornerDistSq = c.radius * c.radius; + return xCornerDistSq + yCornerDistSq <= maxCornerDistSq; + } + */ + function intersectsRectangle(c, r) { + var cx = Math.abs(c.x - r.x - r.halfWidth); + var xDist = r.halfWidth + c.radius; + if(cx > xDist) { + return false; + } + var cy = Math.abs(c.y - r.y - r.halfHeight); + var yDist = r.halfHeight + c.radius; + if(cy > yDist) { + return false; + } + if(cx <= r.halfWidth || cy <= r.halfHeight) { + return true; + } + var xCornerDist = cx - r.halfWidth; + var yCornerDist = cy - r.halfHeight; + var xCornerDistSq = xCornerDist * xCornerDist; + var yCornerDistSq = yCornerDist * yCornerDist; + var maxCornerDistSq = c.radius * c.radius; + return xCornerDistSq + yCornerDistSq <= maxCornerDistSq; + }; + return CircleUtils; + })(); + Phaser.CircleUtils = CircleUtils; +})(Phaser || (Phaser = {})); +/// /// /// /** @@ -18061,3795 +19718,6 @@ var Phaser; Phaser.Mat3Utils = Mat3Utils; })(Phaser || (Phaser = {})); /// -/// -/** -* Phaser - 2D Transform -* -* A 2D Transform -*/ -var Phaser; -(function (Phaser) { - var Transform = (function () { - /** - * Creates a new 2D Transform object. - * @class Transform - * @constructor - * @return {Transform} This object - **/ - function Transform(pos, angle) { - this.t = Phaser.Vec2Utils.clone(pos); - this.c = Math.cos(angle); - this.s = Math.sin(angle); - this.angle = angle; - } - Transform.prototype.toString = function () { - return 't=' + this.t.toString() + ' c=' + this.c + ' s=' + this.s + ' a=' + this.angle; - }; - Transform.prototype.setTo = function (pos, angle) { - this.t.copyFrom(pos); - this.c = Math.cos(angle); - this.s = Math.sin(angle); - return this; - }; - Transform.prototype.setRotation = function (angle) { - if(angle !== this.angle) { - this.c = Math.cos(angle); - this.s = Math.sin(angle); - this.angle = angle; - } - return this; - }; - Transform.prototype.setPosition = function (p) { - this.t.copyFrom(p); - return this; - }; - Transform.prototype.identity = function () { - this.t.setTo(0, 0); - this.c = 1; - this.s = 0; - return this; - }; - return Transform; - })(); - Phaser.Transform = Transform; -})(Phaser || (Phaser = {})); -/// -/// -/// -/** -* Phaser - TransformUtils -* -* A collection of methods useful for manipulating and performing operations on 2D Transforms. -* -*/ -var Phaser; -(function (Phaser) { - var TransformUtils = (function () { - function TransformUtils() { } - TransformUtils.rotate = function rotate(t, v, out) { - if (typeof out === "undefined") { out = new Phaser.Vec2(); } - //return new vec2(v.x * this.c - v.y * this.s, v.x * this.s + v.y * this.c); - return out.setTo(v.x * t.c - v.y * t.s, v.x * t.s + v.y * t.c); - }; - TransformUtils.unrotate = function unrotate(t, v, out) { - if (typeof out === "undefined") { out = new Phaser.Vec2(); } - //return new vec2(v.x * this.c + v.y * this.s, -v.x * this.s + v.y * this.c); - return out.setTo(v.x * t.c + v.y * t.s, -v.x * t.s + v.y * t.c); - }; - TransformUtils.transform = function transform(t, v, out) { - if (typeof out === "undefined") { out = new Phaser.Vec2(); } - //return new vec2(v.x * this.c - v.y * this.s + this.t.x, v.x * this.s + v.y * this.c + this.t.y); - return out.setTo(v.x * t.c - v.y * t.s + t.t.x, v.x * t.s + v.y * t.c + t.t.y); - }; - TransformUtils.untransform = function untransform(t, v, out) { - if (typeof out === "undefined") { out = new Phaser.Vec2(); } - var px = v.x - t.t.x; - var py = v.y - t.t.y; - //return new vec2(px * this.c + py * this.s, -px * this.s + py * this.c); - return out.setTo(px * t.c + py * t.s, -px * t.s + py * t.c); - }; - return TransformUtils; - })(); - Phaser.TransformUtils = TransformUtils; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - /// - /// - /// - /// - /// - /** - * Phaser - PhysicsManager - * - * Your game only has one PhysicsManager instance and it's responsible for looking after, creating and colliding - * all of the physics objects in the world. - */ - (function (Physics) { - var ArcadePhysics = (function () { - function ArcadePhysics(game, width, height) { - this._length = 0; - /** - * @type {number} - */ - this.worldDivisions = 6; - this.game = game; - this.gravity = new Phaser.Vec2(); - this.drag = new Phaser.Vec2(); - this.bounce = new Phaser.Vec2(); - this.angularDrag = 0; - this.bounds = new Phaser.Rectangle(0, 0, width, height); - this._distance = new Phaser.Vec2(); - this._tangent = new Phaser.Vec2(); - this.members = new Phaser.Group(game); - } - ArcadePhysics.OVERLAP_BIAS = 4; - ArcadePhysics.TILE_OVERLAP = false; - ArcadePhysics.prototype.updateMotion = /* - public update() { - - this._length = this._objects.length; - - for (var i = 0; i < this._length; i++) - { - if (this._objects[i]) - { - this._objects[i].preUpdate(); - this.updateMotion(this._objects[i]); - this.collideWorld(this._objects[i]); - - for (var x = 0; x < this._length; x++) - { - if (this._objects[x] && this._objects[x] !== this._objects[i]) - { - //this.collideShapes(this._objects[i], this._objects[x]); - var r = this.NEWseparate(this._objects[i], this._objects[x]); - //console.log('sep', r); - } - } - - } - } - - } - - public render() { - - // iterate through the objects here, updating and colliding - for (var i = 0; i < this._length; i++) - { - if (this._objects[i]) - { - this._objects[i].render(this.game.stage.context); - } - } - - } - */ - function (body) { - if(body.type == Phaser.Types.BODY_DISABLED) { - return; - } - this._velocityDelta = (this.computeVelocity(body.angularVelocity, body.gravity.x, body.angularAcceleration, body.angularDrag, body.maxAngular) - body.angularVelocity) / 2; - body.angularVelocity += this._velocityDelta; - body.sprite.transform.rotation += body.angularVelocity * this.game.time.elapsed; - body.angularVelocity += this._velocityDelta; - this._velocityDelta = (this.computeVelocity(body.velocity.x, body.gravity.x, body.acceleration.x, body.drag.x) - body.velocity.x) / 2; - body.velocity.x += this._velocityDelta; - this._delta = body.velocity.x * this.game.time.elapsed; - body.velocity.x += this._velocityDelta; - //body.position.x += this._delta; - body.sprite.x += this._delta; - this._velocityDelta = (this.computeVelocity(body.velocity.y, body.gravity.y, body.acceleration.y, body.drag.y) - body.velocity.y) / 2; - body.velocity.y += this._velocityDelta; - this._delta = body.velocity.y * this.game.time.elapsed; - body.velocity.y += this._velocityDelta; - //body.position.y += this._delta; - body.sprite.y += this._delta; - }; - ArcadePhysics.prototype.computeVelocity = /** - * A tween-like function that takes a starting velocity and some other factors and returns an altered velocity. - * - * @param {number} Velocity Any component of velocity (e.g. 20). - * @param {number} Acceleration Rate at which the velocity is changing. - * @param {number} Drag Really kind of a deceleration, this is how much the velocity changes if Acceleration is not set. - * @param {number} Max An absolute value cap for the velocity. - * - * @return {number} The altered Velocity value. - */ - function (velocity, gravity, acceleration, drag, max) { - if (typeof gravity === "undefined") { gravity = 0; } - if (typeof acceleration === "undefined") { acceleration = 0; } - if (typeof drag === "undefined") { drag = 0; } - if (typeof max === "undefined") { max = 10000; } - if(acceleration !== 0) { - velocity += (acceleration + gravity) * this.game.time.elapsed; - } else if(drag !== 0) { - this._drag = drag * this.game.time.elapsed; - if(velocity - this._drag > 0) { - velocity = velocity - this._drag; - } else if(velocity + this._drag < 0) { - velocity += this._drag; - } else { - velocity = 0; - } - velocity += gravity; - } - if((velocity != 0) && (max != 10000)) { - if(velocity > max) { - velocity = max; - } else if(velocity < -max) { - velocity = -max; - } - } - return velocity; - }; - ArcadePhysics.prototype.separate = /** - * The core Collision separation method. - * @param body1 The first Physics.Body to separate - * @param body2 The second Physics.Body to separate - * @returns {boolean} Returns true if the bodies were separated, otherwise false. - */ - function (body1, body2) { - this._separatedX = this.separateBodyX(body1, body2); - this._separatedY = this.separateBodyY(body1, body2); - return this._separatedX || this._separatedY; - }; - ArcadePhysics.prototype.checkHullIntersection = function (body1, body2) { - return ((body1.hullX + body1.hullWidth > body2.hullX) && (body1.hullX < body2.hullX + body2.hullWidth) && (body1.hullY + body1.hullHeight > body2.hullY) && (body1.hullY < body2.hullY + body2.hullHeight)); - }; - ArcadePhysics.prototype.separateBodyX = /** - * Separates the two objects on their x axis - * @param object1 The first GameObject to separate - * @param object2 The second GameObject to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the X axis. - */ - function (body1, body2) { - // Can't separate two disabled or static objects - if((body1.type == Phaser.Types.BODY_DISABLED || body1.type == Phaser.Types.BODY_STATIC) && (body2.type == Phaser.Types.BODY_DISABLED || body2.type == Phaser.Types.BODY_STATIC)) { - return false; - } - // First, get the two object deltas - this._overlap = 0; - if(body1.deltaX != body2.deltaX) { - if(Phaser.RectangleUtils.intersects(body1.bounds, body2.bounds)) { - this._maxOverlap = body1.deltaXAbs + body2.deltaXAbs + Physics.PhysicsManager.OVERLAP_BIAS; - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if(body1.deltaX > body2.deltaX) { - this._overlap = body1.bounds.right - body2.bounds.x; - if((this._overlap > this._maxOverlap) || !(body1.allowCollisions & Phaser.Types.RIGHT) || !(body2.allowCollisions & Phaser.Types.LEFT)) { - this._overlap = 0; - } else { - body1.touching |= Phaser.Types.RIGHT; - body2.touching |= Phaser.Types.LEFT; - } - } else if(body1.deltaX < body2.deltaX) { - this._overlap = body1.bounds.x - body2.bounds.width - body2.bounds.x; - if((-this._overlap > this._maxOverlap) || !(body1.allowCollisions & Phaser.Types.LEFT) || !(body2.allowCollisions & Phaser.Types.RIGHT)) { - this._overlap = 0; - } else { - body1.touching |= Phaser.Types.LEFT; - body2.touching |= Phaser.Types.RIGHT; - } - } - } - } - // Then adjust their positions and velocities accordingly (if there was any overlap) - if(this._overlap != 0) { - this._obj1Velocity = body1.velocity.x; - this._obj2Velocity = body2.velocity.x; - /** - * Dynamic = gives and receives impacts - * Static = gives but doesn't receive impacts, cannot be moved by physics - * Kinematic = gives impacts, but never receives, can be moved by physics - */ - // 2 dynamic bodies will exchange velocities - if(body1.type == Phaser.Types.BODY_DYNAMIC && body2.type == Phaser.Types.BODY_DYNAMIC) { - this._overlap *= 0.5; - body1.position.x = body1.position.x - this._overlap; - body2.position.x += this._overlap; - this._obj1NewVelocity = Math.sqrt((this._obj2Velocity * this._obj2Velocity * body2.mass) / body1.mass) * ((this._obj2Velocity > 0) ? 1 : -1); - this._obj2NewVelocity = Math.sqrt((this._obj1Velocity * this._obj1Velocity * body1.mass) / body2.mass) * ((this._obj1Velocity > 0) ? 1 : -1); - this._average = (this._obj1NewVelocity + this._obj2NewVelocity) * 0.5; - this._obj1NewVelocity -= this._average; - this._obj2NewVelocity -= this._average; - body1.velocity.x = this._average + this._obj1NewVelocity * body1.bounce.x; - body2.velocity.x = this._average + this._obj2NewVelocity * body2.bounce.x; - } else if(body2.type != Phaser.Types.BODY_DYNAMIC) { - // Body 2 is Static or Kinematic - this._overlap *= 2; - body1.position.x -= this._overlap; - body1.velocity.x = this._obj2Velocity - this._obj1Velocity * body1.bounce.x; - } else if(body1.type != Phaser.Types.BODY_DYNAMIC) { - // Body 1 is Static or Kinematic - this._overlap *= 2; - body2.position.x += this._overlap; - body2.velocity.x = this._obj1Velocity - this._obj2Velocity * body2.bounce.x; - } - return true; - } else { - return false; - } - }; - ArcadePhysics.prototype.separateBodyY = /** - * Separates the two objects on their y axis - * @param object1 The first GameObject to separate - * @param object2 The second GameObject to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis. - */ - function (body1, body2) { - // Can't separate two immovable objects - if((body1.type == Phaser.Types.BODY_DISABLED || body1.type == Phaser.Types.BODY_STATIC) && (body2.type == Phaser.Types.BODY_DISABLED || body2.type == Phaser.Types.BODY_STATIC)) { - return false; - } - // First, get the two object deltas - this._overlap = 0; - if(body1.deltaY != body2.deltaY) { - if(Phaser.RectangleUtils.intersects(body1.bounds, body2.bounds)) { - // This is the only place to use the DeltaAbs values - this._maxOverlap = body1.deltaYAbs + body2.deltaYAbs + Physics.PhysicsManager.OVERLAP_BIAS; - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if(body1.deltaY > body2.deltaY) { - this._overlap = body1.bounds.bottom - body2.bounds.y; - if((this._overlap > this._maxOverlap) || !(body1.allowCollisions & Phaser.Types.DOWN) || !(body2.allowCollisions & Phaser.Types.UP)) { - this._overlap = 0; - } else { - body1.touching |= Phaser.Types.DOWN; - body2.touching |= Phaser.Types.UP; - } - } else if(body1.deltaY < body2.deltaY) { - this._overlap = body1.bounds.y - body2.bounds.height - body2.bounds.y; - if((-this._overlap > this._maxOverlap) || !(body1.allowCollisions & Phaser.Types.UP) || !(body2.allowCollisions & Phaser.Types.DOWN)) { - this._overlap = 0; - } else { - body1.touching |= Phaser.Types.UP; - body2.touching |= Phaser.Types.DOWN; - } - } - } - } - // Then adjust their positions and velocities accordingly (if there was any overlap) - if(this._overlap != 0) { - this._obj1Velocity = body1.velocity.y; - this._obj2Velocity = body2.velocity.y; - /** - * Dynamic = gives and receives impacts - * Static = gives but doesn't receive impacts, cannot be moved by physics - * Kinematic = gives impacts, but never receives, can be moved by physics - */ - if(body1.type == Phaser.Types.BODY_DYNAMIC && body2.type == Phaser.Types.BODY_DYNAMIC) { - this._overlap *= 0.5; - body1.position.y = body1.position.y - this._overlap; - body2.position.y += this._overlap; - this._obj1NewVelocity = Math.sqrt((this._obj2Velocity * this._obj2Velocity * body2.mass) / body1.mass) * ((this._obj2Velocity > 0) ? 1 : -1); - this._obj2NewVelocity = Math.sqrt((this._obj1Velocity * this._obj1Velocity * body1.mass) / body2.mass) * ((this._obj1Velocity > 0) ? 1 : -1); - var average = (this._obj1NewVelocity + this._obj2NewVelocity) * 0.5; - this._obj1NewVelocity -= average; - this._obj2NewVelocity -= average; - body1.velocity.y = average + this._obj1NewVelocity * body1.bounce.y; - body2.velocity.y = average + this._obj2NewVelocity * body2.bounce.y; - } else if(body2.type != Phaser.Types.BODY_DYNAMIC) { - this._overlap *= 2; - body1.position.y -= this._overlap; - body1.velocity.y = this._obj2Velocity - this._obj1Velocity * body1.bounce.y; - // This is special case code that handles things like horizontal moving platforms you can ride - //if (body2.parent.active && body2.moves && (body1.deltaY > body2.deltaY)) - if(body2.sprite.active && (body1.deltaY > body2.deltaY)) { - body1.position.x += body2.position.x - body2.oldPosition.x; - } - } else if(body1.type != Phaser.Types.BODY_DYNAMIC) { - this._overlap *= 2; - body2.position.y += this._overlap; - body2.velocity.y = this._obj1Velocity - this._obj2Velocity * body2.bounce.y; - // This is special case code that handles things like horizontal moving platforms you can ride - //if (object1.active && body1.moves && (body1.deltaY < body2.deltaY)) - if(body1.sprite.active && (body1.deltaY < body2.deltaY)) { - body2.position.x += body1.position.x - body1.oldPosition.x; - } - } - return true; - } else { - return false; - } - }; - ArcadePhysics.prototype.overlap = /* - private TILEseparate(shapeA: IPhysicsShape, shapeB: IPhysicsShape, distance: Vec2, tangent: Vec2) { - - if (tangent.x == 1) - { - console.log('1 The left side of ShapeA hit the right side of ShapeB', Math.floor(distance.x)); - shapeA.physics.touching |= Phaser.Types.LEFT; - shapeB.physics.touching |= Phaser.Types.RIGHT; - } - else if (tangent.x == -1) - { - console.log('2 The right side of ShapeA hit the left side of ShapeB', Math.floor(distance.x)); - shapeA.physics.touching |= Phaser.Types.RIGHT; - shapeB.physics.touching |= Phaser.Types.LEFT; - } - - if (tangent.y == 1) - { - console.log('3 The top of ShapeA hit the bottom of ShapeB', Math.floor(distance.y)); - shapeA.physics.touching |= Phaser.Types.UP; - shapeB.physics.touching |= Phaser.Types.DOWN; - } - else if (tangent.y == -1) - { - console.log('4 The bottom of ShapeA hit the top of ShapeB', Math.floor(distance.y)); - shapeA.physics.touching |= Phaser.Types.DOWN; - shapeB.physics.touching |= Phaser.Types.UP; - } - - - // only apply collision response forces if the object is travelling into, and not out of, the collision - var dot = Vec2Utils.dot(shapeA.physics.velocity, tangent); - - if (dot < 0) - { - console.log('in to', dot); - - // Apply horizontal bounce - if (shapeA.physics.bounce.x > 0) - { - shapeA.physics.velocity.x *= -(shapeA.physics.bounce.x); - } - else - { - shapeA.physics.velocity.x = 0; - } - // Apply horizontal bounce - if (shapeA.physics.bounce.y > 0) - { - shapeA.physics.velocity.y *= -(shapeA.physics.bounce.y); - } - else - { - shapeA.physics.velocity.y = 0; - } - } - else - { - console.log('out of', dot); - } - - shapeA.position.x += Math.floor(distance.x); - //shapeA.bounds.x += Math.floor(distance.x); - - shapeA.position.y += Math.floor(distance.y); - //shapeA.bounds.y += distance.y; - - console.log('------------------------------------------------'); - - } - - private collideWorld(shape:IPhysicsShape) { - - // Collide on the x-axis - this._distance.x = shape.world.bounds.x - (shape.position.x - shape.bounds.halfWidth); - - if (0 < this._distance.x) - { - // Hit Left - this._tangent.setTo(1, 0); - this.separateXWall(shape, this._distance, this._tangent); - } - else - { - this._distance.x = (shape.position.x + shape.bounds.halfWidth) - shape.world.bounds.right; - - if (0 < this._distance.x) - { - // Hit Right - this._tangent.setTo(-1, 0); - this._distance.reverse(); - this.separateXWall(shape, this._distance, this._tangent); - } - } - - // Collide on the y-axis - this._distance.y = shape.world.bounds.y - (shape.position.y - shape.bounds.halfHeight); - - if (0 < this._distance.y) - { - // Hit Top - this._tangent.setTo(0, 1); - this.separateYWall(shape, this._distance, this._tangent); - } - else - { - this._distance.y = (shape.position.y + shape.bounds.halfHeight) - shape.world.bounds.bottom; - - if (0 < this._distance.y) - { - // Hit Bottom - this._tangent.setTo(0, -1); - this._distance.reverse(); - this.separateYWall(shape, this._distance, this._tangent); - } - } - - } - - private separateX(shapeA: IPhysicsShape, shapeB: IPhysicsShape, distance: Vec2, tangent: Vec2) { - - if (tangent.x == 1) - { - console.log('The left side of ShapeA hit the right side of ShapeB', distance.x); - shapeA.physics.touching |= Phaser.Types.LEFT; - shapeB.physics.touching |= Phaser.Types.RIGHT; - } - else - { - console.log('The right side of ShapeA hit the left side of ShapeB', distance.x); - shapeA.physics.touching |= Phaser.Types.RIGHT; - shapeB.physics.touching |= Phaser.Types.LEFT; - } - - // collision edges - //shapeA.oH = tangent.x; - - // only apply collision response forces if the object is travelling into, and not out of, the collision - if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) - { - // Apply horizontal bounce - if (shapeA.physics.bounce.x > 0) - { - shapeA.physics.velocity.x *= -(shapeA.physics.bounce.x); - } - else - { - shapeA.physics.velocity.x = 0; - } - } - - shapeA.position.x += distance.x; - shapeA.bounds.x += distance.x; - - } - - private separateY(shapeA: IPhysicsShape, shapeB: IPhysicsShape, distance: Vec2, tangent: Vec2) { - - if (tangent.y == 1) - { - console.log('The top of ShapeA hit the bottom of ShapeB', distance.y); - shapeA.physics.touching |= Phaser.Types.UP; - shapeB.physics.touching |= Phaser.Types.DOWN; - } - else - { - console.log('The bottom of ShapeA hit the top of ShapeB', distance.y); - shapeA.physics.touching |= Phaser.Types.DOWN; - shapeB.physics.touching |= Phaser.Types.UP; - } - - // collision edges - //shapeA.oV = tangent.y; - - // only apply collision response forces if the object is travelling into, and not out of, the collision - if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) - { - // Apply horizontal bounce - if (shapeA.physics.bounce.y > 0) - { - shapeA.physics.velocity.y *= -(shapeA.physics.bounce.y); - } - else - { - shapeA.physics.velocity.y = 0; - } - } - - shapeA.position.y += distance.y; - shapeA.bounds.y += distance.y; - - } - - private separateXWall(shapeA: IPhysicsShape, distance: Vec2, tangent: Vec2) { - - if (tangent.x == 1) - { - console.log('The left side of ShapeA hit the right side of ShapeB', distance.x); - shapeA.physics.touching |= Phaser.Types.LEFT; - } - else - { - console.log('The right side of ShapeA hit the left side of ShapeB', distance.x); - shapeA.physics.touching |= Phaser.Types.RIGHT; - } - - // collision edges - //shapeA.oH = tangent.x; - - // only apply collision response forces if the object is travelling into, and not out of, the collision - if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) - { - // Apply horizontal bounce - if (shapeA.physics.bounce.x > 0) - { - shapeA.physics.velocity.x *= -(shapeA.physics.bounce.x); - } - else - { - shapeA.physics.velocity.x = 0; - } - } - - shapeA.position.x += distance.x; - - } - - private separateYWall(shapeA: IPhysicsShape, distance: Vec2, tangent: Vec2) { - - if (tangent.y == 1) - { - console.log('The top of ShapeA hit the bottom of ShapeB', distance.y); - shapeA.physics.touching |= Phaser.Types.UP; - } - else - { - console.log('The bottom of ShapeA hit the top of ShapeB', distance.y); - shapeA.physics.touching |= Phaser.Types.DOWN; - } - - // collision edges - //shapeA.oV = tangent.y; - - // only apply collision response forces if the object is travelling into, and not out of, the collision - if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) - { - // Apply horizontal bounce - if (shapeA.physics.bounce.y > 0) - { - shapeA.physics.velocity.y *= -(shapeA.physics.bounce.y); - } - else - { - shapeA.physics.velocity.y = 0; - } - } - - shapeA.position.y += distance.y; - - } - */ - /** - * Checks for overlaps between two objects using the world QuadTree. Can be Sprite vs. Sprite, Sprite vs. Group or Group vs. Group. - * Note: Does not take the objects scrollFactor into account. All overlaps are check in world space. - * @param object1 The first Sprite or Group to check. If null the world.group is used. - * @param object2 The second Sprite or Group to check. - * @param notifyCallback A callback function that is called if the objects overlap. The two objects will be passed to this function in the same order in which you passed them to Collision.overlap. - * @param processCallback A callback function that lets you perform additional checks against the two objects if they overlap. If this is set then notifyCallback will only be called if processCallback returns true. - * @param context The context in which the callbacks will be called - * @returns {boolean} true if the objects overlap, otherwise false. - */ - function (object1, object2, notifyCallback, processCallback, context) { - if (typeof object1 === "undefined") { object1 = null; } - if (typeof object2 === "undefined") { object2 = null; } - if (typeof notifyCallback === "undefined") { notifyCallback = null; } - if (typeof processCallback === "undefined") { processCallback = null; } - if (typeof context === "undefined") { context = null; } - /* - if (object1 == null) - { - object1 = this.game.world.group; - } - - if (object2 == object1) - { - object2 = null; - } - - QuadTree.divisions = this.worldDivisions; - - this._quadTree = new Phaser.QuadTree(this, this.bounds.x, this.bounds.y, this.bounds.width, this.bounds.height); - - this._quadTree.load(object1, object2, notifyCallback, processCallback, context); - - this._quadTreeResult = this._quadTree.execute(); - - console.log('over', this._quadTreeResult); - - this._quadTree.destroy(); - - this._quadTree = null; - - return this._quadTreeResult; - */ - return false; - }; - ArcadePhysics.prototype.separateTile = /** - * Collision resolution specifically for GameObjects vs. Tiles. - * @param object The GameObject to separate - * @param tile The Tile to separate - * @returns {boolean} Whether the objects in fact touched and were separated - */ - function (object, x, y, width, height, mass, collideLeft, collideRight, collideUp, collideDown, separateX, separateY) { - //var separatedX: bool = this.separateTileX(object, x, y, width, height, mass, collideLeft, collideRight, separateX); - //var separatedY: bool = this.separateTileY(object, x, y, width, height, mass, collideUp, collideDown, separateY); - //return separatedX || separatedY; - return false; - }; - return ArcadePhysics; - })(); - Physics.ArcadePhysics = ArcadePhysics; - /** - * Separates the two objects on their x axis - * @param object The GameObject to separate - * @param tile The Tile to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the X axis. - */ - /* - public separateTileX(object:Sprite, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool, separate: bool): bool { - - // Can't separate two immovable objects (tiles are always immovable) - if (object.immovable) - { - return false; - } - - // First, get the object delta - var overlap: number = 0; - var objDelta: number = object.x - object.last.x; - //var objDelta: number = object.collisionMask.deltaX; - - if (objDelta != 0) - { - // Check if the X hulls actually overlap - var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; - //var objDeltaAbs: number = object.collisionMask.deltaXAbs; - var objBounds: Rectangle = new Rectangle(object.x - ((objDelta > 0) ? objDelta : 0), object.last.y, object.width + ((objDelta > 0) ? objDelta : -objDelta), object.height); - - if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) - { - var maxOverlap: number = objDeltaAbs + Collision.OVERLAP_BIAS; - - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if (objDelta > 0) - { - overlap = object.x + object.width - x; - - if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.RIGHT) || collideLeft == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.RIGHT; - } - } - else if (objDelta < 0) - { - overlap = object.x - width - x; - - if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.LEFT) || collideRight == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.LEFT; - } - - } - - } - } - - // Then adjust their positions and velocities accordingly (if there was any overlap) - if (overlap != 0) - { - if (separate == true) - { - //console.log(' - object.x = object.x - overlap; - object.velocity.x = -(object.velocity.x * object.elasticity); - } - - Collision.TILE_OVERLAP = true; - return true; - } - else - { - return false; - } - - } - */ - /** - * Separates the two objects on their y axis - * @param object The first GameObject to separate - * @param tile The second GameObject to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis. - */ - /* - public separateTileY(object: Sprite, x: number, y: number, width: number, height: number, mass: number, collideUp: bool, collideDown: bool, separate: bool): bool { - - // Can't separate two immovable objects (tiles are always immovable) - if (object.immovable) - { - return false; - } - - // First, get the two object deltas - var overlap: number = 0; - var objDelta: number = object.y - object.last.y; - - if (objDelta != 0) - { - // Check if the Y hulls actually overlap - var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; - var objBounds: Rectangle = new Rectangle(object.x, object.y - ((objDelta > 0) ? objDelta : 0), object.width, object.height + objDeltaAbs); - - if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) - { - var maxOverlap: number = objDeltaAbs + Collision.OVERLAP_BIAS; - - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if (objDelta > 0) - { - overlap = object.y + object.height - y; - - if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.DOWN) || collideUp == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.DOWN; - } - } - else if (objDelta < 0) - { - overlap = object.y - height - y; - - if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.UP) || collideDown == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.UP; - } - } - } - } - - // TODO - with super low velocities you get lots of stuttering, set some kind of base minimum here - - // Then adjust their positions and velocities accordingly (if there was any overlap) - if (overlap != 0) - { - if (separate == true) - { - object.y = object.y - overlap; - object.velocity.y = -(object.velocity.y * object.elasticity); - } - - Collision.TILE_OVERLAP = true; - return true; - } - else - { - return false; - } - } - */ - /** - * Separates the two objects on their x axis - * @param object The GameObject to separate - * @param tile The Tile to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the X axis. - */ - /* - public static NEWseparateTileX(object:Sprite, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool, separate: bool): bool { - - // Can't separate two immovable objects (tiles are always immovable) - if (object.immovable) - { - return false; - } - - // First, get the object delta - var overlap: number = 0; - - if (object.collisionMask.deltaX != 0) - { - // Check if the X hulls actually overlap - //var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; - //var objBounds: Rectangle = new Rectangle(object.x - ((objDelta > 0) ? objDelta : 0), object.last.y, object.width + ((objDelta > 0) ? objDelta : -objDelta), object.height); - - //if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) - if (object.collisionMask.intersectsRaw(x, x + width, y, y + height)) - { - var maxOverlap: number = object.collisionMask.deltaXAbs + Collision.OVERLAP_BIAS; - - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if (object.collisionMask.deltaX > 0) - { - //overlap = object.x + object.width - x; - overlap = object.collisionMask.right - x; - - if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.RIGHT) || collideLeft == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.RIGHT; - } - } - else if (object.collisionMask.deltaX < 0) - { - //overlap = object.x - width - x; - overlap = object.collisionMask.x - width - x; - - if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.LEFT) || collideRight == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.LEFT; - } - - } - - } - } - - // Then adjust their positions and velocities accordingly (if there was any overlap) - if (overlap != 0) - { - if (separate == true) - { - object.x = object.x - overlap; - object.velocity.x = -(object.velocity.x * object.elasticity); - } - - Collision.TILE_OVERLAP = true; - return true; - } - else - { - return false; - } - - } - */ - /** - * Separates the two objects on their y axis - * @param object The first GameObject to separate - * @param tile The second GameObject to separate - * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis. - */ - /* - public NEWseparateTileY(object: Sprite, x: number, y: number, width: number, height: number, mass: number, collideUp: bool, collideDown: bool, separate: bool): bool { - - // Can't separate two immovable objects (tiles are always immovable) - if (object.immovable) - { - return false; - } - - // First, get the two object deltas - var overlap: number = 0; - //var objDelta: number = object.y - object.last.y; - - if (object.collisionMask.deltaY != 0) - { - // Check if the Y hulls actually overlap - //var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; - //var objBounds: Rectangle = new Rectangle(object.x, object.y - ((objDelta > 0) ? objDelta : 0), object.width, object.height + objDeltaAbs); - - //if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) - if (object.collisionMask.intersectsRaw(x, x + width, y, y + height)) - { - //var maxOverlap: number = objDeltaAbs + Collision.OVERLAP_BIAS; - var maxOverlap: number = object.collisionMask.deltaYAbs + Collision.OVERLAP_BIAS; - - // If they did overlap (and can), figure out by how much and flip the corresponding flags - if (object.collisionMask.deltaY > 0) - { - //overlap = object.y + object.height - y; - overlap = object.collisionMask.bottom - y; - - if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.DOWN) || collideUp == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.DOWN; - } - } - else if (object.collisionMask.deltaY < 0) - { - //overlap = object.y - height - y; - overlap = object.collisionMask.y - height - y; - - if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.UP) || collideDown == false) - { - overlap = 0; - } - else - { - object.touching |= Collision.UP; - } - } - } - } - - // TODO - with super low velocities you get lots of stuttering, set some kind of base minimum here - - // Then adjust their positions and velocities accordingly (if there was any overlap) - if (overlap != 0) - { - if (separate == true) - { - object.y = object.y - overlap; - object.velocity.y = -(object.velocity.y * object.elasticity); - } - - Collision.TILE_OVERLAP = true; - return true; - } - else - { - return false; - } - } - */ - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - (function (Physics) { - /// - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - Joint - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Advanced) { - var Joint = (function () { - function Joint(type, body1, body2, collideConnected) { - this.id = Phaser.Physics.Advanced.Manager.jointCounter++; - this.type = type; - this.body1 = body1; - this.body2 = body2; - this.collideConnected = collideConnected; - this.maxForce = 9999999999; - this.breakable = false; - } - Joint.prototype.getWorldAnchor1 = function () { - return this.body1.getWorldPoint(this.anchor1); - }; - Joint.prototype.getWorldAnchor2 = function () { - return this.body2.getWorldPoint(this.anchor2); - }; - Joint.prototype.setWorldAnchor1 = function (anchor1) { - this.anchor1 = this.body1.getLocalPoint(anchor1); - }; - Joint.prototype.setWorldAnchor2 = function (anchor2) { - this.anchor2 = this.body2.getLocalPoint(anchor2); - }; - return Joint; - })(); - Advanced.Joint = Joint; - })(Physics.Advanced || (Physics.Advanced = {})); - var Advanced = Physics.Advanced; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - (function (Physics) { - /// - /// - /// - /** - * Phaser - Advanced Physics Manager - * - * Your game only has one PhysicsManager instance and it's responsible for looking after, creating and colliding - * all of the physics objects in the world. - */ - (function (Advanced) { - var Manager = (function () { - function Manager(game) { - this.lastTime = Date.now(); - this.frameRateHz = 60; - this.timeDelta = 0; - //public paused: bool = false; - //public step: bool = false; // step through the simulation (i.e. per click) - this.paused = true; - this.step = 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; - Manager.SHAPE_NUM_TYPES = 3; - Manager.JOINT_TYPE_ANGLE = 0; - Manager.JOINT_TYPE_REVOLUTE = 1; - Manager.JOINT_TYPE_WELD = 2; - Manager.JOINT_TYPE_WHEEL = 3; - Manager.JOINT_TYPE_PRISMATIC = 4; - Manager.JOINT_TYPE_DISTANCE = 5; - Manager.JOINT_TYPE_ROPE = 6; - Manager.JOINT_TYPE_MOUSE = 7; - Manager.JOINT_LINEAR_SLOP = 0.0008; - Manager.JOINT_ANGULAR_SLOP = 2 * Phaser.GameMath.DEG_TO_RAD; - Manager.JOINT_MAX_LINEAR_CORRECTION = 0.5; - Manager.JOINT_MAX_ANGULAR_CORRECTION = 8 * Phaser.GameMath.DEG_TO_RAD; - Manager.JOINT_LIMIT_STATE_INACTIVE = 0; - Manager.JOINT_LIMIT_STATE_AT_LOWER = 1; - Manager.JOINT_LIMIT_STATE_AT_UPPER = 2; - Manager.JOINT_LIMIT_STATE_EQUAL_LIMITS = 3; - Manager.CONTACT_SOLVER_COLLISION_SLOP = 0.0008; - Manager.CONTACT_SOLVER_BAUMGARTE = 0.28; - Manager.CONTACT_SOLVER_MAX_LINEAR_CORRECTION = 1; - Manager.bodyCounter = 0; - Manager.jointCounter = 0; - Manager.shapeCounter = 0; - Manager.prototype.update = function () { - var time = Date.now(); - var frameTime = (time - this.lastTime) / 1000; - this.lastTime = time; - // if rAf - why? - frameTime = Math.floor(frameTime * 60 + 0.5) / 60; - //if (!mouseDown) - //{ - // var p = canvasToWorld(mousePosition); - // var body = space.findBodyByPoint(p); - // //domCanvas.style.cursor = body ? "pointer" : "default"; - //} - if(!this.paused || this.step) { - Manager.clear(); - var h = 1 / this.frameRateHz; - this.timeDelta += frameTime; - if(this.step) { - this.step = false; - this.timeDelta = h; - } - for(var maxSteps = 4; maxSteps > 0 && this.timeDelta >= h; maxSteps--) { - this.space.step(h, this.velocityIterations, this.positionIterations, this.warmStarting, this.allowSleep); - this.timeDelta -= h; - } - if(this.timeDelta > h) { - this.timeDelta = 0; - } - } - //frameCount++; - }; - Manager.prototype.pixelsToMeters = function (value) { - return value * 0.02; - }; - Manager.prototype.metersToPixels = function (value) { - return value * 50; - }; - Manager.pixelsToMeters = function pixelsToMeters(value) { - return value * 0.02; - }; - Manager.metersToPixels = function metersToPixels(value) { - return value * 50; - }; - Manager.p2m = function p2m(value) { - return value * 0.02; - }; - Manager.m2p = function m2p(value) { - return value * 50; - }; - Manager.areaForCircle = function areaForCircle(radius_outer, radius_inner) { - return Math.PI * (radius_outer * radius_outer - radius_inner * radius_inner); - }; - Manager.inertiaForCircle = function inertiaForCircle(mass, center, radius_outer, radius_inner) { - return mass * ((radius_outer * radius_outer + radius_inner * radius_inner) * 0.5 + center.lengthSq()); - }; - Manager.areaForSegment = function areaForSegment(a, b, radius) { - return radius * (Math.PI * radius + 2 * Phaser.Vec2Utils.distance(a, b)); - }; - Manager.centroidForSegment = function centroidForSegment(a, b) { - return Phaser.Vec2Utils.scale(Phaser.Vec2Utils.add(a, b), 0.5); - }; - Manager.inertiaForSegment = function inertiaForSegment(mass, a, b) { - var distsq = Phaser.Vec2Utils.distanceSq(b, a); - var offset = Phaser.Vec2Utils.scale(Phaser.Vec2Utils.add(a, b), 0.5); - return mass * (distsq / 12 + offset.lengthSq()); - }; - Manager.areaForPoly = function areaForPoly(verts) { - var area = 0; - for(var i = 0; i < verts.length; i++) { - area += Phaser.Vec2Utils.cross(verts[i], verts[(i + 1) % verts.length]); - } - return area / 2; - }; - Manager.centroidForPoly = function centroidForPoly(verts) { - var area = 0; - var vsum = new Phaser.Vec2(); - for(var i = 0; i < verts.length; i++) { - var v1 = verts[i]; - var v2 = verts[(i + 1) % verts.length]; - var cross = Phaser.Vec2Utils.cross(v1, v2); - area += cross; - // SO many vecs created here - unroll these bad boys - vsum.add(Phaser.Vec2Utils.scale(Phaser.Vec2Utils.add(v1, v2), cross)); - } - return Phaser.Vec2Utils.scale(vsum, 1 / (3 * area)); - }; - Manager.inertiaForPoly = function inertiaForPoly(mass, verts, offset) { - var sum1 = 0; - var sum2 = 0; - for(var i = 0; i < verts.length; i++) { - var v1 = Phaser.Vec2Utils.add(verts[i], offset); - var v2 = Phaser.Vec2Utils.add(verts[(i + 1) % verts.length], offset); - var a = Phaser.Vec2Utils.cross(v2, v1); - var b = Phaser.Vec2Utils.dot(v1, v1) + Phaser.Vec2Utils.dot(v1, v2) + Phaser.Vec2Utils.dot(v2, v2); - sum1 += a * b; - sum2 += a; - } - return (mass * sum1) / (6 * sum2); - }; - Manager.inertiaForBox = function inertiaForBox(mass, w, h) { - return mass * (w * w + h * h) / 12; - }; - Manager.createConvexHull = // Create the convex hull using the Gift wrapping algorithm (http://en.wikipedia.org/wiki/Gift_wrapping_algorithm) - function createConvexHull(points) { - // Find the right most point on the hull - var i0 = 0; - var x0 = points[0].x; - for(var i = 1; i < points.length; i++) { - var x = points[i].x; - if(x > x0 || (x == x0 && points[i].y < points[i0].y)) { - i0 = i; - x0 = x; - } - } - var n = points.length; - var hull = []; - var m = 0; - var ih = i0; - while(1) { - hull[m] = ih; - var ie = 0; - for(var j = 1; j < n; j++) { - if(ie == ih) { - ie = j; - continue; - } - var r = Phaser.Vec2Utils.subtract(points[ie], points[hull[m]]); - var v = Phaser.Vec2Utils.subtract(points[j], points[hull[m]]); - var c = Phaser.Vec2Utils.cross(r, v); - if(c < 0) { - ie = j; - } - // Collinearity check - if(c == 0 && v.lengthSq() > r.lengthSq()) { - ie = j; - } - } - m++; - ih = ie; - if(ie == i0) { - break; - } - } - // Copy vertices - var newPoints = []; - for(var i = 0; i < m; ++i) { - newPoints.push(points[hull[i]]); - } - return newPoints; - }; - return Manager; - })(); - Advanced.Manager = Manager; - })(Physics.Advanced || (Physics.Advanced = {})); - var Advanced = Physics.Advanced; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - (function (Physics) { - /// - /// - /// - /** - * Phaser - 2D AABB - * - * A 2D AABB object - */ - (function (Advanced) { - var Bounds = (function () { - /** - * Creates a new 2D AABB object. - * @class Bounds - * @constructor - * @return {Bounds} This object - **/ - function Bounds(mins, maxs) { - if (typeof mins === "undefined") { mins = null; } - if (typeof maxs === "undefined") { maxs = null; } - if(mins) { - this.mins = Phaser.Vec2Utils.clone(mins); - } else { - this.mins = new Phaser.Vec2(999999, 999999); - } - if(maxs) { - this.maxs = Phaser.Vec2Utils.clone(maxs); - } else { - this.maxs = new Phaser.Vec2(999999, 999999); - } - } - Bounds.prototype.toString = function () { - return [ - "mins:", - this.mins.toString(), - "maxs:", - this.maxs.toString() - ].join(" "); - }; - Bounds.prototype.setTo = function (mins, maxs) { - this.mins.setTo(mins.x, mins.y); - this.maxs.setTo(maxs.x, maxs.y); - }; - Bounds.prototype.copy = function (b) { - this.mins.copyFrom(b.mins); - this.maxs.copyFrom(b.maxs); - return this; - }; - Bounds.prototype.clear = function () { - this.mins.setTo(999999, 999999); - this.maxs.setTo(-999999, -999999); - return this; - }; - Object.defineProperty(Bounds.prototype, "x", { - get: function () { - return Phaser.Physics.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); - }; - Bounds.prototype.getPerimeter = /* - public getCenter() { - return vec2.scale(vec2.add(this.mins, this.maxs), 0.5); - } - - public getExtent() { - return vec2.scale(vec2.sub(this.maxs, this.mins), 0.5); - } - */ - function () { - return (this.maxs.x - this.mins.x + this.maxs.y - this.mins.y) * 2; - }; - Bounds.prototype.addPoint = function (p) { - if(this.mins.x > p.x) { - this.mins.x = p.x; - } - if(this.maxs.x < p.x) { - this.maxs.x = p.x; - } - if(this.mins.y > p.y) { - this.mins.y = p.y; - } - if(this.maxs.y < p.y) { - this.maxs.y = p.y; - } - return this; - }; - Bounds.prototype.addBounds = function (b) { - if(this.mins.x > b.mins.x) { - this.mins.x = b.mins.x; - } - if(this.maxs.x < b.maxs.x) { - this.maxs.x = b.maxs.x; - } - if(this.mins.y > b.mins.y) { - this.mins.y = b.mins.y; - } - if(this.maxs.y < b.maxs.y) { - this.maxs.y = b.maxs.y; - } - return this; - }; - Bounds.prototype.addBounds2 = function (mins, maxs) { - if(this.mins.x > mins.x) { - this.mins.x = mins.x; - } - if(this.maxs.x < maxs.x) { - this.maxs.x = maxs.x; - } - if(this.mins.y > mins.y) { - this.mins.y = mins.y; - } - if(this.maxs.y < maxs.y) { - this.maxs.y = maxs.y; - } - return this; - }; - Bounds.prototype.addExtents = function (center, extent_x, extent_y) { - if(this.mins.x > center.x - extent_x) { - this.mins.x = center.x - extent_x; - } - if(this.maxs.x < center.x + extent_x) { - this.maxs.x = center.x + extent_x; - } - if(this.mins.y > center.y - extent_y) { - this.mins.y = center.y - extent_y; - } - if(this.maxs.y < center.y + extent_y) { - this.maxs.y = center.y + extent_y; - } - return this; - }; - Bounds.prototype.expand = function (ax, ay) { - this.mins.x -= ax; - this.mins.y -= ay; - this.maxs.x += ax; - this.maxs.y += ay; - return this; - }; - Bounds.prototype.containPoint = function (p) { - if(p.x < this.mins.x || p.x > this.maxs.x || p.y < this.mins.y || p.y > this.maxs.y) { - return false; - } - return true; - }; - Bounds.prototype.intersectsBounds = function (b) { - if(this.mins.x > b.maxs.x || this.maxs.x < b.mins.x || this.mins.y > b.maxs.y || this.maxs.y < b.mins.y) { - return false; - } - return true; - }; - Bounds.expand = function expand(b, ax, ay) { - var b = new Bounds(b.mins, b.maxs); - b.expand(ax, ay); - return b; - }; - return Bounds; - })(); - Advanced.Bounds = Bounds; - })(Physics.Advanced || (Physics.Advanced = {})); - var Advanced = Physics.Advanced; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - (function (Physics) { - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - (function (Physics) { - /// - /// - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - Shape - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Advanced) { - var Shape = (function () { - function Shape(type) { - this.id = Phaser.Physics.Advanced.Manager.shapeCounter++; - this.type = type; - this.elasticity = 0.0; - this.friction = 1.0; - this.density = 1; - this.bounds = new Advanced.Bounds(); - } - Shape.prototype.findEdgeByPoint = // Over-ridden by ShapePoly - function (p, minDist) { - return -1; - }; - return Shape; - })(); - Advanced.Shape = Shape; - })(Physics.Advanced || (Physics.Advanced = {})); - var Advanced = Physics.Advanced; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - (function (Physics) { - /// - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - Contact - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Advanced) { - var Contact = (function () { - function Contact(p, n, d, hash) { - this.hash = hash; - this.point = p; - this.normal = n; - this.depth = d; - this.lambdaNormal = 0; - this.lambdaTangential = 0; - this.r1 = new Phaser.Vec2(); - this.r2 = new Phaser.Vec2(); - this.r1_local = new Phaser.Vec2(); - this.r2_local = new Phaser.Vec2(); - } - return Contact; - })(); - Advanced.Contact = Contact; - })(Physics.Advanced || (Physics.Advanced = {})); - var Advanced = Physics.Advanced; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - (function (Physics) { - /// - /// - /// - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - ContactSolver - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - //------------------------------------------------------------------------------------------------- - // Contact Constraint - // - // Non-penetration constraint: - // C = dot(p2 - p1, n) - // Cdot = dot(v2 - v1, n) - // J = [ -n, -cross(r1, n), n, cross(r2, n) ] - // - // impulse = JT * lambda = [ -n * lambda, -cross(r1, n) * lambda, n * lambda, cross(r1, n) * lambda ] - // - // Friction constraint: - // C = dot(p2 - p1, t) - // Cdot = dot(v2 - v1, t) - // J = [ -t, -cross(r1, t), t, cross(r2, t) ] - // - // impulse = JT * lambda = [ -t * lambda, -cross(r1, t) * lambda, t * lambda, cross(r1, t) * lambda ] - // - // NOTE: lambda is an impulse in constraint space. - //------------------------------------------------------------------------------------------------- - (function (Advanced) { - var ContactSolver = (function () { - function ContactSolver(shape1, shape2) { - this.shape1 = shape1; - this.shape2 = shape2; - this.contacts = []; - this.elasticity = 1; - this.friction = 1; - } - ContactSolver.prototype.update = function (newContactArr) { - for(var i = 0; i < newContactArr.length; i++) { - var newContact = newContactArr[i]; - var k = -1; - for(var j = 0; j < this.contacts.length; j++) { - if(newContact.hash == this.contacts[j].hash) { - k = j; - break; - } - } - if(k > -1) { - newContact.lambdaNormal = this.contacts[k].lambdaNormal; - newContact.lambdaTangential = this.contacts[k].lambdaTangential; - } - } - this.contacts = newContactArr; - }; - ContactSolver.prototype.initSolver = function (dt_inv) { - var body1 = this.shape1.body; - var body2 = this.shape2.body; - var sum_m_inv = body1.massInverted + body2.massInverted; - for(var i = 0; i < this.contacts.length; i++) { - var con = this.contacts[i]; - //console.log('initSolver con'); - //console.log(con); - // Transformed r1, r2 - Phaser.Vec2Utils.subtract(con.point, body1.position, con.r1); - Phaser.Vec2Utils.subtract(con.point, body2.position, con.r2); - //con.r1 = vec2.sub(con.point, body1.p); - //con.r2 = vec2.sub(con.point, body2.p); - // Local r1, r2 - Phaser.TransformUtils.unrotate(body1.transform, con.r1, con.r1_local); - Phaser.TransformUtils.unrotate(body2.transform, con.r2, con.r2_local); - //con.r1_local = body1.transform.unrotate(con.r1); - //con.r2_local = body2.transform.unrotate(con.r2); - var n = con.normal; - var t = Phaser.Vec2Utils.perp(con.normal); - // invEMn = J * invM * JT - // J = [ -n, -cross(r1, n), n, cross(r2, n) ] - var sn1 = Phaser.Vec2Utils.cross(con.r1, n); - var sn2 = Phaser.Vec2Utils.cross(con.r2, n); - var emn_inv = sum_m_inv + body1.inertiaInverted * sn1 * sn1 + body2.inertiaInverted * sn2 * sn2; - con.emn = emn_inv == 0 ? 0 : 1 / emn_inv; - // invEMt = J * invM * JT - // J = [ -t, -cross(r1, t), t, cross(r2, t) ] - var st1 = Phaser.Vec2Utils.cross(con.r1, t); - var st2 = Phaser.Vec2Utils.cross(con.r2, t); - var emt_inv = sum_m_inv + body1.inertiaInverted * st1 * st1 + body2.inertiaInverted * st2 * st2; - con.emt = emt_inv == 0 ? 0 : 1 / emt_inv; - // Linear velocities at contact point - // in 2D: cross(w, r) = perp(r) * w - var v1 = new Phaser.Vec2(); - var v2 = new Phaser.Vec2(); - Phaser.Vec2Utils.multiplyAdd(body1.velocity, Phaser.Vec2Utils.perp(con.r1), body1.angularVelocity, v1); - Phaser.Vec2Utils.multiplyAdd(body2.velocity, Phaser.Vec2Utils.perp(con.r2), body2.angularVelocity, v2); - //var v1 = vec2.mad(body1.v, vec2.perp(con.r1), body1.w); - //var v2 = vec2.mad(body2.v, vec2.perp(con.r2), body2.w); - // relative velocity at contact point - var rv = new Phaser.Vec2(); - Phaser.Vec2Utils.subtract(v2, v1, rv); - //var rv = vec2.sub(v2, v1); - // bounce velocity dot n - con.bounce = Phaser.Vec2Utils.dot(rv, con.normal) * this.elasticity; - } - }; - ContactSolver.prototype.warmStart = function () { - var body1 = this.shape1.body; - var body2 = this.shape2.body; - for(var i = 0; i < this.contacts.length; i++) { - var con = this.contacts[i]; - var n = con.normal; - var lambda_n = con.lambdaNormal; - var lambda_t = con.lambdaTangential; - // Apply accumulated impulses - //var impulse = vec2.rotate_vec(new vec2(lambda_n, lambda_t), n); - //var impulse = new vec2(lambda_n * n.x - lambda_t * n.y, lambda_t * n.x + lambda_n * n.y); - var impulse = new Phaser.Vec2(lambda_n * n.x - lambda_t * n.y, lambda_t * n.x + lambda_n * n.y); - //console.log('phaser warmStart impulse ' + i + ' = ' + impulse.toString()); - body1.velocity.multiplyAddByScalar(impulse, -body1.massInverted); - //body1.v.mad(impulse, -body1.m_inv); - body1.angularVelocity -= Phaser.Vec2Utils.cross(con.r1, impulse) * body1.inertiaInverted; - //body1.w -= vec2.cross(con.r1, impulse) * body1.i_inv; - body2.velocity.multiplyAddByScalar(impulse, body2.massInverted); - //body2.v.mad(impulse, body2.m_inv); - body2.angularVelocity += Phaser.Vec2Utils.cross(con.r2, impulse) * body2.inertiaInverted; - //body2.w += vec2.cross(con.r2, impulse) * body2.i_inv; - } - }; - ContactSolver.prototype.solveVelocityConstraints = function () { - var body1 = this.shape1.body; - var body2 = this.shape2.body; - 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); - var r1 = con.r1; - var r2 = con.r2; - // Linear velocities at contact point - // in 2D: cross(w, r) = perp(r) * w - var v1 = new Phaser.Vec2(); - var v2 = new Phaser.Vec2(); - Phaser.Vec2Utils.multiplyAdd(body1.velocity, Phaser.Vec2Utils.perp(r1), body1.angularVelocity, v1); - //var v1 = vec2.mad(body1.v, vec2.perp(r1), body1.w); - 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); - // Max friction constraint impulse (Coulomb's Law) - var lambda_t_max = con.lambdaNormal * this.friction; - // Accumulate and clamp - var lambda_t_old = con.lambdaTangential; - con.lambdaTangential = this.clamp(lambda_t_old + lambda_t, -lambda_t_max, lambda_t_max); - lambda_t = con.lambdaTangential - lambda_t_old; - // Apply the final impulses - //var impulse = vec2.rotate_vec(new vec2(lambda_n, lambda_t), n); - var impulse = new Phaser.Vec2(lambda_n * n.x - lambda_t * n.y, lambda_t * n.x + lambda_n * n.y); - 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); - 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; - var i2_inv = body2.inertiaInverted; - var sum_m_inv = m1_inv + m2_inv; - var max_penetration = 0; - for(var i = 0; i < this.contacts.length; i++) { - Advanced.Manager.write('------------- solvePositionConstraints ' + i); - var con = this.contacts[i]; - var n = con.normal; - var r1 = new Phaser.Vec2(); - var r2 = new Phaser.Vec2(); - // Transformed r1, r2 - Phaser.Vec2Utils.rotate(con.r1_local, body1.angle, r1); - //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(); - Phaser.Vec2Utils.add(body1.position, r1, p1); - //var p1 = vec2.add(body1.p, r1); - Phaser.Vec2Utils.add(body2.position, r2, p2); - //var p2 = vec2.add(body2.p, r2); - 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, dp); - //var dp = vec2.sub(p2, p1); - // Position constraint - var c = Phaser.Vec2Utils.dot(dp, n) + con.depth; - var correction = this.clamp(Advanced.Manager.CONTACT_SOLVER_BAUMGARTE * (c + Advanced.Manager.CONTACT_SOLVER_COLLISION_SLOP), -Advanced.Manager.CONTACT_SOLVER_MAX_LINEAR_CORRECTION, 0); - if(correction == 0) { - continue; - } - // We don't need max_penetration less than or equal slop - max_penetration = Math.max(max_penetration, -c); - // Compute lambda for position constraint - // Solve (J * invM * JT) * lambda = -C / dt - var sn1 = Phaser.Vec2Utils.cross(r1, n); - var sn2 = Phaser.Vec2Utils.cross(r2, n); - var em_inv = sum_m_inv + body1.inertiaInverted * sn1 * sn1 + body2.inertiaInverted * sn2 * sn2; - var lambda_dt = em_inv == 0 ? 0 : -correction / em_inv; - // Apply correction impulses - var impulse_dt = new Phaser.Vec2(); - Phaser.Vec2Utils.scale(n, lambda_dt, impulse_dt); - //var impulse_dt = vec2.scale(n, lambda_dt); - body1.position.multiplyAddByScalar(impulse_dt, -m1_inv); - //body1.p.mad(impulse_dt, -m1_inv); - body1.angle -= sn1 * lambda_dt * i1_inv; - body2.position.multiplyAddByScalar(impulse_dt, m2_inv); - //body2.p.mad(impulse_dt, m2_inv); - body2.angle += sn2 * lambda_dt * i2_inv; - 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) { - return v < min ? min : (v > max ? max : v); - }; - return ContactSolver; - })(); - Advanced.ContactSolver = ContactSolver; - })(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 - Shape - Circle - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Shapes) { - var Circle = (function (_super) { - __extends(Circle, _super); - function Circle(radius, x, y) { - if (typeof x === "undefined") { x = 0; } - if (typeof y === "undefined") { y = 0; } - _super.call(this, 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(); - this.finishVerts(); - } - Circle.prototype.finishVerts = function () { - this.radius = Math.abs(this.radius); - }; - Circle.prototype.duplicate = function () { - return new Circle(this.center.x, this.center.y, this.radius); - }; - Circle.prototype.recenter = function (c) { - this.center.subtract(c); - }; - Circle.prototype.transform = function (xf) { - Phaser.TransformUtils.transform(xf, this.center, this.center); - //this.center = xf.transform(this.center); - }; - Circle.prototype.untransform = function (xf) { - Phaser.TransformUtils.untransform(xf, this.center, this.center); - //this.center = xf.untransform(this.center); - }; - Circle.prototype.area = function () { - return Advanced.Manager.areaForCircle(this.radius, 0); - }; - Circle.prototype.centroid = function () { - return Phaser.Vec2Utils.clone(this.center); - }; - Circle.prototype.inertia = function (mass) { - return Advanced.Manager.inertiaForCircle(mass, this.center, this.radius, 0); - }; - Circle.prototype.cacheData = function (xf) { - Phaser.TransformUtils.transform(xf, this.center, this.tc); - //this.tc = xf.transform(this.center); - this.bounds.mins.setTo(this.tc.x - this.radius, this.tc.y - this.radius); - this.bounds.maxs.setTo(this.tc.x + this.radius, this.tc.y + this.radius); - }; - Circle.prototype.pointQuery = function (p) { - //return vec2.distsq(this.tc, p) < (this.r * this.r); - return Phaser.Vec2Utils.distanceSq(this.tc, p) < (this.radius * this.radius); - }; - Circle.prototype.findVertexByPoint = function (p, minDist) { - var dsq = minDist * minDist; - if(Phaser.Vec2Utils.distanceSq(this.tc, p) < dsq) { - return 0; - } - return -1; - }; - Circle.prototype.distanceOnPlane = function (n, d) { - Phaser.Vec2Utils.dot(n, this.tc) - this.radius - d; - }; - return Circle; - })(Phaser.Physics.Advanced.Shape); - Shapes.Circle = Circle; - })(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) { - /// - /// - /// - /// - /** - * 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) { - /// - /// - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - Shapes - Convex Polygon - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Shapes) { - var Poly = (function (_super) { - __extends(Poly, _super); - // Verts is an optional array of objects, the objects must have public x and y properties which will be used - // to seed this polygon (i.e. Vec2 objects, or just straight JS objects) and must wind COUNTER clockwise - function Poly(verts) { - _super.call(this, Advanced.Manager.SHAPE_TYPE_POLY); - this.verts = []; - this.planes = []; - this.tverts = []; - this.tplanes = []; - if(verts) { - for(var i = 0; i < verts.length; i++) { - this.verts[i] = new Phaser.Vec2(verts[i].x, verts[i].y); - this.tverts[i] = this.verts[i]; - //this.tverts[i] = new Phaser.Vec2(verts[i].x, verts[i].y); - this.tplanes[i] = new Phaser.Physics.Advanced.Plane(new Phaser.Vec2(), 0); - } - } - this.finishVerts(); - } - Poly.prototype.finishVerts = function () { - if(this.verts.length < 2) { - this.convexity = false; - this.planes = []; - return; - } - this.convexity = true; - this.tverts = []; - this.tplanes = []; - // Must be counter-clockwise verts - for(var i = 0; i < this.verts.length; i++) { - var a = this.verts[i]; - var b = this.verts[(i + 1) % this.verts.length]; - var n = Phaser.Vec2Utils.normalize(Phaser.Vec2Utils.perp(Phaser.Vec2Utils.subtract(a, b))); - this.planes[i] = new Phaser.Physics.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].normal; - //var d = this.planes[i].d; - if(Phaser.Vec2Utils.dot(this.planes[i].normal, this.verts[(i + 2) % this.verts.length]) - this.planes[i].d > 0) { - this.convexity = false; - } - } - }; - Poly.prototype.duplicate = function () { - return new Phaser.Physics.Advanced.Shapes.Poly(this.verts); - }; - Poly.prototype.recenter = function (c) { - for(var i = 0; i < this.verts.length; i++) { - this.verts[i].subtract(c); - } - }; - Poly.prototype.transform = function (xf) { - for(var i = 0; i < this.verts.length; i++) { - this.verts[i] = Phaser.TransformUtils.transform(xf, this.verts[i]); - //this.verts[i] = xf.transform(this.verts[i]); - } - }; - Poly.prototype.untransform = function (xf) { - for(var i = 0; i < this.verts.length; i++) { - this.verts[i] = Phaser.TransformUtils.untransform(xf, this.verts[i]); - //this.verts[i] = xf.untransform(this.verts[i]); - } - }; - Poly.prototype.area = function () { - return Advanced.Manager.areaForPoly(this.verts); - }; - Poly.prototype.centroid = function () { - return Advanced.Manager.centroidForPoly(this.verts); - }; - Poly.prototype.inertia = function (mass) { - return Advanced.Manager.inertiaForPoly(mass, this.verts, new Phaser.Vec2()); - }; - Poly.prototype.cacheData = function (xf) { - this.bounds.clear(); - var numVerts = this.verts.length; - Advanced.Manager.write('----------- Poly cacheData = ' + numVerts); - if(numVerts == 0) { - return; - } - for(var i = 0; i < numVerts; i++) { - this.tverts[i] = Phaser.TransformUtils.transform(xf, this.verts[i]); - //this.tverts[i] = xf.transform(this.verts[i]); - Advanced.Manager.write('tvert' + i + ' = ' + this.tverts[i].toString()); - } - if(numVerts < 2) { - this.bounds.addPoint(this.tverts[0]); - return; - } - for(var i = 0; i < numVerts; i++) { - var a = this.tverts[i]; - var b = this.tverts[(i + 1) % numVerts]; - var n = Phaser.Vec2Utils.normalize(Phaser.Vec2Utils.perp(Phaser.Vec2Utils.subtract(a, b))); - 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); - } - }; - Poly.prototype.pointQuery = function (p) { - if(!this.bounds.containPoint(p)) { - return false; - } - return this.containPoint(p); - }; - Poly.prototype.findVertexByPoint = function (p, minDist) { - var dsq = minDist * minDist; - for(var i = 0; i < this.tverts.length; i++) { - if(Phaser.Vec2Utils.distanceSq(this.tverts[i], p) < dsq) { - return i; - } - } - return -1; - }; - Poly.prototype.findEdgeByPoint = function (p, minDist) { - var dsq = minDist * minDist; - var numVerts = this.tverts.length; - for(var i = 0; i < this.tverts.length; i++) { - var v1 = this.tverts[i]; - var v2 = this.tverts[(i + 1) % numVerts]; - var n = this.tplanes[i].normal; - var dtv1 = Phaser.Vec2Utils.cross(v1, n); - var dtv2 = Phaser.Vec2Utils.cross(v2, n); - var dt = Phaser.Vec2Utils.cross(p, n); - if(dt > dtv1) { - if(Phaser.Vec2Utils.distanceSq(v1, p) < dsq) { - return i; - } - } else if(dt < dtv2) { - if(Phaser.Vec2Utils.distanceSq(v2, p) < dsq) { - return i; - } - } else { - var dist = Phaser.Vec2Utils.dot(n, p) - Phaser.Vec2Utils.dot(n, v1); - if(dist * dist < dsq) { - return i; - } - } - } - return -1; - }; - Poly.prototype.distanceOnPlane = function (n, d) { - var min = 999999; - for(var i = 0; i < this.verts.length; i++) { - min = Math.min(min, Phaser.Vec2Utils.dot(n, this.tverts[i])); - } - return min - d; - }; - Poly.prototype.containPoint = function (p) { - for(var i = 0; i < this.verts.length; i++) { - var plane = this.tplanes[i]; - if(Phaser.Vec2Utils.dot(plane.normal, p) - plane.d > 0) { - return false; - } - } - return true; - }; - Poly.prototype.containPointPartial = function (p, n) { - for(var i = 0; i < this.verts.length; i++) { - var plane = this.tplanes[i]; - if(Phaser.Vec2Utils.dot(plane.normal, n) < 0.0001) { - continue; - } - if(Phaser.Vec2Utils.dot(plane.normal, p) - plane.d > 0) { - return false; - } - } - return true; - }; - return Poly; - })(Phaser.Physics.Advanced.Shape); - Shapes.Poly = Poly; - })(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 - Segment - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Shapes) { - var Segment = (function (_super) { - __extends(Segment, _super); - function Segment(a, b, radius) { - _super.call(this, Advanced.Manager.SHAPE_TYPE_SEGMENT); - this.a = a.duplicate(); - this.b = b.duplicate(); - this.radius = radius; - this.normal = Phaser.Vec2Utils.perp(Phaser.Vec2Utils.subtract(b, a)); - this.normal.normalize(); - this.ta = new Phaser.Vec2(); - this.tb = new Phaser.Vec2(); - this.tn = new Phaser.Vec2(); - this.finishVerts(); - } - Segment.prototype.finishVerts = function () { - this.normal = Phaser.Vec2Utils.perp(Phaser.Vec2Utils.subtract(this.b, this.a)); - this.normal.normalize(); - this.radius = Math.abs(this.radius); - }; - Segment.prototype.duplicate = function () { - return new Phaser.Physics.Advanced.Shapes.Segment(this.a, this.b, this.radius); - }; - Segment.prototype.recenter = function (c) { - this.a.subtract(c); - this.b.subtract(c); - }; - Segment.prototype.transform = function (xf) { - Phaser.TransformUtils.transform(xf, this.a, this.a); - Phaser.TransformUtils.transform(xf, this.b, this.b); - //this.a = xf.transform(this.a); - //this.b = xf.transform(this.b); - }; - Segment.prototype.untransform = function (xf) { - Phaser.TransformUtils.untransform(xf, this.a, this.a); - Phaser.TransformUtils.untransform(xf, this.b, this.b); - //this.a = xf.untransform(this.a); - //this.b = xf.untransform(this.b); - }; - Segment.prototype.area = function () { - return Advanced.Manager.areaForSegment(this.a, this.b, this.radius); - }; - Segment.prototype.centroid = function () { - return Advanced.Manager.centroidForSegment(this.a, this.b); - }; - Segment.prototype.inertia = function (mass) { - return Advanced.Manager.inertiaForSegment(mass, this.a, this.b); - }; - Segment.prototype.cacheData = function (xf) { - Phaser.TransformUtils.transform(xf, this.a, this.ta); - Phaser.TransformUtils.transform(xf, this.b, this.tb); - //this.ta = xf.transform(this.a); - //this.tb = xf.transform(this.b); - this.tn = Phaser.Vec2Utils.perp(Phaser.Vec2Utils.subtract(this.tb, this.ta)).normalize(); - var l; - var r; - var t; - var b; - if(this.ta.x < this.tb.x) { - l = this.ta.x; - r = this.tb.x; - } else { - l = this.tb.x; - r = this.ta.x; - } - if(this.ta.y < this.tb.y) { - b = this.ta.y; - t = this.tb.y; - } else { - b = this.tb.y; - t = this.ta.y; - } - this.bounds.mins.setTo(l - this.radius, b - this.radius); - this.bounds.maxs.setTo(r + this.radius, t + this.radius); - }; - Segment.prototype.pointQuery = function (p) { - if(!this.bounds.containPoint(p)) { - return false; - } - var dn = Phaser.Vec2Utils.dot(this.tn, p) - Phaser.Vec2Utils.dot(this.ta, this.tn); - var dist = Math.abs(dn); - if(dist > this.radius) { - return false; - } - var dt = Phaser.Vec2Utils.cross(p, this.tn); - var dta = Phaser.Vec2Utils.cross(this.ta, this.tn); - var dtb = Phaser.Vec2Utils.cross(this.tb, this.tn); - if(dt <= dta) { - if(dt < dta - this.radius) { - return false; - } - return Phaser.Vec2Utils.distanceSq(this.ta, p) < (this.radius * this.radius); - } else if(dt > dtb) { - if(dt > dtb + this.radius) { - return false; - } - return Phaser.Vec2Utils.distanceSq(this.tb, p) < (this.radius * this.radius); - } - return true; - }; - Segment.prototype.findVertexByPoint = function (p, minDist) { - var dsq = minDist * minDist; - if(Phaser.Vec2Utils.distanceSq(this.ta, p) < dsq) { - return 0; - } - if(Phaser.Vec2Utils.distanceSq(this.tb, p) < dsq) { - return 1; - } - return -1; - }; - Segment.prototype.distanceOnPlane = function (n, d) { - var a = Phaser.Vec2Utils.dot(n, this.ta) - this.radius; - var b = Phaser.Vec2Utils.dot(n, this.tb) - this.radius; - return Math.min(a, b) - d; - }; - return Segment; - })(Phaser.Physics.Advanced.Shape); - Shapes.Segment = Segment; - })(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) { - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - Collision Handlers - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Advanced) { - var Collision = (function () { - function Collision() { - } - Collision.prototype.collide = function (a, b, contacts) { - // Circle (a is the circle) - if(a.type == Advanced.Manager.SHAPE_TYPE_CIRCLE) { - if(b.type == Advanced.Manager.SHAPE_TYPE_CIRCLE) { - return this.circle2Circle(a, b, contacts); - } else if(b.type == Advanced.Manager.SHAPE_TYPE_SEGMENT) { - return this.circle2Segment(a, b, contacts); - } else if(b.type == Advanced.Manager.SHAPE_TYPE_POLY) { - return this.circle2Poly(a, b, contacts); - } - } - // Segment (a is the segment) - if(a.type == Advanced.Manager.SHAPE_TYPE_SEGMENT) { - if(b.type == Advanced.Manager.SHAPE_TYPE_CIRCLE) { - return this.circle2Segment(b, a, contacts); - } else if(b.type == Advanced.Manager.SHAPE_TYPE_SEGMENT) { - return this.segment2Segment(a, b, contacts); - } else if(b.type == Advanced.Manager.SHAPE_TYPE_POLY) { - return this.segment2Poly(a, b, contacts); - } - } - // Poly (a is the poly) - if(a.type == Advanced.Manager.SHAPE_TYPE_POLY) { - if(b.type == Advanced.Manager.SHAPE_TYPE_CIRCLE) { - return this.circle2Poly(b, a, contacts); - } else if(b.type == Advanced.Manager.SHAPE_TYPE_SEGMENT) { - return this.segment2Poly(b, a, contacts); - } else if(b.type == Advanced.Manager.SHAPE_TYPE_POLY) { - return this.poly2Poly(a, b, contacts); - } - } - }; - Collision.prototype._circle2Circle = function (c1, r1, c2, r2, contactArr) { - var rmax = r1 + r2; - var t = new Phaser.Vec2(); - //var t = vec2.sub(c2, c1); - Phaser.Vec2Utils.subtract(c2, c1, t); - var distsq = t.lengthSq(); - if(distsq > rmax * rmax) { - return 0; - } - var dist = Math.sqrt(distsq); - var p = new Phaser.Vec2(); - Phaser.Vec2Utils.multiplyAdd(c1, t, 0.5 + (r1 - r2) * 0.5 / dist, p); - //var p = vec2.mad(c1, t, 0.5 + (r1 - r2) * 0.5 / dist); - var n = new Phaser.Vec2(); - //var n = (dist != 0) ? vec2.scale(t, 1 / dist) : vec2.zero; - if(dist != 0) { - Phaser.Vec2Utils.scale(t, 1 / dist, n); - } - var d = dist - rmax; - contactArr.push(new Advanced.Contact(p, n, d, 0)); - return 1; - }; - Collision.prototype.circle2Circle = function (circ1, circ2, contactArr) { - return this._circle2Circle(circ1.tc, circ1.radius, circ2.tc, circ2.radius, contactArr); - }; - Collision.prototype.circle2Segment = function (circ, seg, contactArr) { - var rsum = circ.radius + seg.radius; - // Normal distance from segment - var dn = Phaser.Vec2Utils.dot(circ.tc, seg.tn) - Phaser.Vec2Utils.dot(seg.ta, seg.tn); - var dist = (dn < 0 ? dn * -1 : dn) - rsum; - if(dist > 0) { - return 0; - } - // Tangential distance along segment - var dt = Phaser.Vec2Utils.cross(circ.tc, seg.tn); - var dtMin = Phaser.Vec2Utils.cross(seg.ta, seg.tn); - var dtMax = Phaser.Vec2Utils.cross(seg.tb, seg.tn); - if(dt < dtMin) { - if(dt < dtMin - rsum) { - return 0; - } - return this._circle2Circle(circ.tc, circ.radius, seg.ta, seg.radius, contactArr); - } else if(dt > dtMax) { - if(dt > dtMax + rsum) { - return 0; - } - return this._circle2Circle(circ.tc, circ.radius, seg.tb, seg.radius, contactArr); - } - var n = new Phaser.Vec2(); - if(dn > 0) { - n.copyFrom(seg.tn); - } else { - Phaser.Vec2Utils.negative(seg.tn, n); - } - //var n = (dn > 0) ? seg.tn : vec2.neg(seg.tn); - var c1 = new Phaser.Vec2(); - Phaser.Vec2Utils.multiplyAdd(circ.tc, n, -(circ.radius + dist * 0.5), c1); - var c2 = new Phaser.Vec2(); - Phaser.Vec2Utils.negative(n, c2); - contactArr.push(new Advanced.Contact(c1, c2, dist, 0)); - //contactArr.push(new Contact(vec2.mad(circ.tc, n, -(circ.r + dist * 0.5)), vec2.neg(n), dist, 0)); - return 1; - }; - Collision.prototype.circle2Poly = function (circ, poly, contactArr) { - var minDist = -999999; - var minIdx = -1; - for(var i = 0; i < poly.verts.length; i++) { - var plane = poly.tplanes[i]; - var dist = Phaser.Vec2Utils.dot(circ.tc, plane.normal) - plane.d - circ.radius; - if(dist > 0) { - return 0; - } else if(dist > minDist) { - minDist = dist; - minIdx = i; - } - } - var n = poly.tplanes[minIdx].normal; - var a = poly.tverts[minIdx]; - var b = poly.tverts[(minIdx + 1) % poly.verts.length]; - var dta = Phaser.Vec2Utils.cross(a, n); - var dtb = Phaser.Vec2Utils.cross(b, n); - var dt = Phaser.Vec2Utils.cross(circ.tc, n); - if(dt > dta) { - return this._circle2Circle(circ.tc, circ.radius, a, 0, contactArr); - } else if(dt < dtb) { - return this._circle2Circle(circ.tc, circ.radius, b, 0, contactArr); - } - var c1 = new Phaser.Vec2(); - Phaser.Vec2Utils.multiplyAdd(circ.tc, n, -(circ.radius + minDist * 0.5), c1); - var c2 = new Phaser.Vec2(); - Phaser.Vec2Utils.negative(n, c2); - contactArr.push(new Advanced.Contact(c1, c2, minDist, 0)); - //contactArr.push(new Contact(vec2.mad(circ.tc, n, -(circ.r + minDist * 0.5)), vec2.neg(n), minDist, 0)); - return 1; - }; - Collision.prototype.segmentPointDistanceSq = function (seg, p) { - var w = new Phaser.Vec2(); - var d = new Phaser.Vec2(); - Phaser.Vec2Utils.subtract(p, seg.ta, w); - Phaser.Vec2Utils.subtract(seg.tb, seg.ta, d); - //var w = vec2.sub(p, seg.ta); - //var d = vec2.sub(seg.tb, seg.ta); - var proj = w.dot(d); - if(proj <= 0) { - return w.dot(w); - } - var vsq = d.dot(d); - if(proj >= vsq) { - return w.dot(w) - 2 * proj + vsq; - } - return w.dot(w) - proj * proj / vsq; - }; - Collision.prototype.segment2Segment = // FIXME and optimise me lots!!! - function (seg1, seg2, contactArr) { - var d = []; - d[0] = this.segmentPointDistanceSq(seg1, seg2.ta); - d[1] = this.segmentPointDistanceSq(seg1, seg2.tb); - d[2] = this.segmentPointDistanceSq(seg2, seg1.ta); - d[3] = this.segmentPointDistanceSq(seg2, seg1.tb); - var idx1 = d[0] < d[1] ? 0 : 1; - var idx2 = d[2] < d[3] ? 2 : 3; - var idxm = d[idx1] < d[idx2] ? idx1 : idx2; - var s, t; - var u = Phaser.Vec2Utils.subtract(seg1.tb, seg1.ta); - var v = Phaser.Vec2Utils.subtract(seg2.tb, seg2.ta); - switch(idxm) { - case 0: - s = Phaser.Vec2Utils.dot(Phaser.Vec2Utils.subtract(seg2.ta, seg1.ta), u) / Phaser.Vec2Utils.dot(u, u); - s = s < 0 ? 0 : (s > 1 ? 1 : s); - t = 0; - break; - case 1: - s = Phaser.Vec2Utils.dot(Phaser.Vec2Utils.subtract(seg2.tb, seg1.ta), u) / Phaser.Vec2Utils.dot(u, u); - s = s < 0 ? 0 : (s > 1 ? 1 : s); - t = 1; - break; - case 2: - s = 0; - t = Phaser.Vec2Utils.dot(Phaser.Vec2Utils.subtract(seg1.ta, seg2.ta), v) / Phaser.Vec2Utils.dot(v, v); - t = t < 0 ? 0 : (t > 1 ? 1 : t); - break; - case 3: - s = 1; - t = Phaser.Vec2Utils.dot(Phaser.Vec2Utils.subtract(seg1.tb, seg2.ta), v) / Phaser.Vec2Utils.dot(v, v); - t = t < 0 ? 0 : (t > 1 ? 1 : t); - break; - } - var minp1 = Phaser.Vec2Utils.multiplyAdd(seg1.ta, u, s); - var minp2 = Phaser.Vec2Utils.multiplyAdd(seg2.ta, v, t); - return this._circle2Circle(minp1, seg1.radius, minp2, seg2.radius, contactArr); - }; - Collision.prototype.findPointsBehindSeg = // Identify vertexes that have penetrated the segment. - function (contactArr, seg, poly, dist, coef) { - var dta = Phaser.Vec2Utils.cross(seg.tn, seg.ta); - var dtb = Phaser.Vec2Utils.cross(seg.tn, seg.tb); - var n = new Phaser.Vec2(); - Phaser.Vec2Utils.scale(seg.tn, coef, n); - //var n = vec2.scale(seg.tn, coef); - for(var i = 0; i < poly.verts.length; i++) { - var v = poly.tverts[i]; - if(Phaser.Vec2Utils.dot(v, n) < Phaser.Vec2Utils.dot(seg.tn, seg.ta) * coef + seg.radius) { - var dt = Phaser.Vec2Utils.cross(seg.tn, v); - if(dta >= dt && dt >= dtb) { - contactArr.push(new Advanced.Contact(v, n, dist, (poly.id << 16) | i)); - } - } - } - }; - Collision.prototype.segment2Poly = function (seg, poly, contactArr) { - var seg_td = Phaser.Vec2Utils.dot(seg.tn, seg.ta); - var seg_d1 = poly.distanceOnPlane(seg.tn, seg_td) - seg.radius; - if(seg_d1 > 0) { - return 0; - } - var n = new Phaser.Vec2(); - Phaser.Vec2Utils.negative(seg.tn, n); - var seg_d2 = poly.distanceOnPlane(n, -seg_td) - seg.radius; - //var seg_d2 = poly.distanceOnPlane(vec2.neg(seg.tn), -seg_td) - seg.r; - if(seg_d2 > 0) { - return 0; - } - var poly_d = -999999; - var poly_i = -1; - for(var i = 0; i < poly.verts.length; i++) { - var plane = poly.tplanes[i]; - var dist = seg.distanceOnPlane(plane.normal, plane.d); - if(dist > 0) { - return 0; - } - if(dist > poly_d) { - poly_d = dist; - poly_i = i; - } - } - var poly_n = new Phaser.Vec2(); - Phaser.Vec2Utils.negative(poly.tplanes[poly_i].normal, poly_n); - //var poly_n = vec2.neg(poly.tplanes[poly_i].n); - var va = new Phaser.Vec2(); - Phaser.Vec2Utils.multiplyAdd(seg.ta, poly_n, seg.radius, va); - //var va = vec2.mad(seg.ta, poly_n, seg.r); - var vb = new Phaser.Vec2(); - Phaser.Vec2Utils.multiplyAdd(seg.tb, poly_n, seg.radius, vb); - //var vb = vec2.mad(seg.tb, poly_n, seg.r); - if(poly.containPoint(va)) { - contactArr.push(new Advanced.Contact(va, poly_n, poly_d, (seg.id << 16) | 0)); - } - if(poly.containPoint(vb)) { - contactArr.push(new Advanced.Contact(vb, poly_n, poly_d, (seg.id << 16) | 1)); - } - // Floating point precision problems here. - // This will have to do for now. - poly_d -= 0.1; - if(seg_d1 >= poly_d || seg_d2 >= poly_d) { - if(seg_d1 > seg_d2) { - this.findPointsBehindSeg(contactArr, seg, poly, seg_d1, 1); - } else { - this.findPointsBehindSeg(contactArr, seg, poly, seg_d2, -1); - } - } - // If no other collision points are found, try colliding endpoints. - if(contactArr.length == 0) { - var poly_a = poly.tverts[poly_i]; - var poly_b = poly.tverts[(poly_i + 1) % poly.verts.length]; - if(this._circle2Circle(seg.ta, seg.radius, poly_a, 0, contactArr)) { - return 1; - } - if(this._circle2Circle(seg.tb, seg.radius, poly_a, 0, contactArr)) { - return 1; - } - if(this._circle2Circle(seg.ta, seg.radius, poly_b, 0, contactArr)) { - return 1; - } - if(this._circle2Circle(seg.tb, seg.radius, poly_b, 0, contactArr)) { - return 1; - } - } - return contactArr.length; - }; - Collision.prototype.findMSA = // Find the minimum separating axis for the given poly and plane list. - function (poly, planes, num) { - var min_dist = -999999; - var min_index = -1; - for(var i = 0; i < num; i++) { - var dist = poly.distanceOnPlane(planes[i].normal, planes[i].d); - if(dist > 0) { - // no collision - return { - dist: 0, - index: -1 - }; - } else if(dist > min_dist) { - min_dist = dist; - min_index = i; - } - } - // new object - see what we can do here - return { - dist: min_dist, - index: min_index - }; - }; - Collision.prototype.findVertsFallback = function (contactArr, poly1, poly2, n, dist) { - var num = 0; - for(var i = 0; i < poly1.verts.length; i++) { - var v = poly1.tverts[i]; - if(poly2.containPointPartial(v, n)) { - contactArr.push(new Advanced.Contact(v, n, dist, (poly1.id << 16) | i)); - num++; - } - } - for(var i = 0; i < poly2.verts.length; i++) { - var v = poly2.tverts[i]; - if(poly1.containPointPartial(v, n)) { - contactArr.push(new Advanced.Contact(v, n, dist, (poly2.id << 16) | i)); - num++; - } - } - return num; - }; - Collision.prototype.findVerts = // Find the overlapped vertices. - function (contactArr, poly1, poly2, n, dist) { - var num = 0; - for(var i = 0; i < poly1.verts.length; i++) { - var v = poly1.tverts[i]; - if(poly2.containPoint(v)) { - contactArr.push(new Advanced.Contact(v, n, dist, (poly1.id << 16) | i)); - num++; - } - } - for(var i = 0; i < poly2.verts.length; i++) { - var v = poly2.tverts[i]; - if(poly1.containPoint(v)) { - contactArr.push(new Advanced.Contact(v, n, dist, (poly2.id << 16) | i)); - num++; - } - } - return num > 0 ? num : this.findVertsFallback(contactArr, poly1, poly2, n, dist); - }; - Collision.prototype.poly2Poly = function (poly1, poly2, contactArr) { - var msa1 = this.findMSA(poly2, poly1.tplanes, poly1.verts.length); - if(msa1.index == -1) { - console.log('poly2poly 0', msa1); - return 0; - } - var msa2 = this.findMSA(poly1, poly2.tplanes, poly2.verts.length); - if(msa2.index == -1) { - console.log('poly2poly 1', msa2); - return 0; - } - // Penetration normal direction should be from poly1 to poly2 - if(msa1.dist > msa2.dist) { - return this.findVerts(contactArr, poly1, poly2, poly1.tplanes[msa1.index].normal, msa1.dist); - } - return this.findVerts(contactArr, poly1, poly2, Phaser.Vec2Utils.negative(poly2.tplanes[msa2.index].normal), msa2.dist); - }; - return Collision; - })(); - Advanced.Collision = Collision; - })(Physics.Advanced || (Physics.Advanced = {})); - var Advanced = Physics.Advanced; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - (function (Physics) { - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -var Phaser; -(function (Phaser) { - (function (Physics) { - /// - /// - /// - /// - /// - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - Space - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Advanced) { - var Space = (function () { - function Space() { - this.stepCount = 0; - this.bodies = []; - this.bodyHash = { - }; - this.joints = []; - this.jointHash = { - }; - this.numContacts = 0; - this.contactSolvers = []; - //this.postSolve(arb) { }; - this.gravity = new Phaser.Vec2(0, 10); - this.damping = 0; - this._linTolSqr = Space.SLEEP_LINEAR_TOLERANCE * Space.SLEEP_LINEAR_TOLERANCE; - this._angTolSqr = Space.SLEEP_ANGULAR_TOLERANCE * Space.SLEEP_ANGULAR_TOLERANCE; - } - Space.TIME_TO_SLEEP = 0.5; - Space.SLEEP_LINEAR_TOLERANCE = 0.5; - Space.SLEEP_ANGULAR_TOLERANCE = 2 * Phaser.GameMath.DEG_TO_RAD; - Space.prototype.clear = function () { - Advanced.Manager.shapeCounter = 0; - Advanced.Manager.bodyCounter = 0; - Advanced.Manager.jointCounter = 0; - for(var i = 0; i < this.bodies.length; i++) { - if(this.bodies[i]) { - this.removeBody(this.bodies[i]); - } - } - this.bodies = []; - this.bodyHash = { - }; - this.joints = []; - this.jointHash = { - }; - this.contactSolvers = []; - this.stepCount = 0; - }; - Space.prototype.addBody = function (body) { - if(this.bodyHash[body.id] != undefined) { - return; - } - var index = this.bodies.push(body) - 1; - this.bodyHash[body.id] = index; - body.awake(true); - body.space = this; - body.cacheData('addBody'); - }; - Space.prototype.removeBody = function (body) { - if(this.bodyHash[body.id] == undefined) { - return; - } - // Remove linked joints - for(var i = 0; i < body.joints.length; i++) { - if(body.joints[i]) { - this.removeJoint(body.joints[i]); - } - } - body.space = null; - var index = this.bodyHash[body.id]; - delete this.bodyHash[body.id]; - delete this.bodies[index]; - }; - Space.prototype.addJoint = function (joint) { - if(this.jointHash[joint.id] != undefined) { - return; - } - joint.body1.awake(true); - joint.body2.awake(true); - var index = this.joints.push(joint) - 1; - this.jointHash[joint.id] = index; - var index = joint.body1.joints.push(joint) - 1; - joint.body1.jointHash[joint.id] = index; - var index = joint.body2.joints.push(joint) - 1; - joint.body2.jointHash[joint.id] = index; - }; - Space.prototype.removeJoint = function (joint) { - if(this.jointHash[joint.id] == undefined) { - return; - } - joint.body1.awake(true); - joint.body2.awake(true); - var index = joint.body1.jointHash[joint.id]; - delete joint.body1.jointHash[joint.id]; - delete joint.body1.joints[index]; - var index = joint.body2.jointHash[joint.id]; - delete joint.body2.jointHash[joint.id]; - delete joint.body2.joints[index]; - var index = this.jointHash[joint.id]; - delete this.jointHash[joint.id]; - delete this.joints[index]; - }; - Space.prototype.findShapeByPoint = function (p, refShape) { - var firstShape; - for(var i = 0; i < this.bodies.length; i++) { - var body = this.bodies[i]; - if(!body) { - continue; - } - for(var j = 0; j < body.shapes.length; j++) { - var shape = body.shapes[j]; - if(shape.pointQuery(p)) { - if(!refShape) { - return shape; - } - if(!firstShape) { - firstShape = shape; - } - if(shape == refShape) { - refShape = null; - } - } - } - } - return firstShape; - }; - Space.prototype.findBodyByPoint = function (p, refBody) { - var firstBody; - for(var i = 0; i < this.bodies.length; i++) { - var body = this.bodies[i]; - if(!body) { - continue; - } - for(var j = 0; j < body.shapes.length; j++) { - var shape = body.shapes[j]; - if(shape.pointQuery(p)) { - if(!refBody) { - return shape.body; - } - if(!firstBody) { - firstBody = shape.body; - } - if(shape.body == refBody) { - refBody = null; - } - break; - } - } - } - return firstBody; - }; - Space.prototype.shapeById = function (id) { - var shape; - for(var i = 0; i < this.bodies.length; i++) { - var body = this.bodies[i]; - if(!body) { - continue; - } - for(var j = 0; j < body.shapes.length; j++) { - if(body.shapes[j].id == id) { - return body.shapes[j]; - } - } - } - return null; - }; - Space.prototype.jointById = function (id) { - var index = this.jointHash[id]; - if(index != undefined) { - return this.joints[index]; - } - return null; - }; - Space.prototype.findVertexByPoint = function (p, minDist, refVertexId) { - var firstVertexId = -1; - refVertexId = refVertexId || -1; - for(var i = 0; i < this.bodies.length; i++) { - var body = this.bodies[i]; - if(!body) { - continue; - } - for(var j = 0; j < body.shapes.length; j++) { - var shape = body.shapes[j]; - var index = shape.findVertexByPoint(p, minDist); - if(index != -1) { - var vertex = (shape.id << 16) | index; - if(refVertexId == -1) { - return vertex; - } - if(firstVertexId == -1) { - firstVertexId = vertex; - } - if(vertex == refVertexId) { - refVertexId = -1; - } - } - } - } - return firstVertexId; - }; - Space.prototype.findEdgeByPoint = function (p, minDist, refEdgeId) { - var firstEdgeId = -1; - refEdgeId = refEdgeId || -1; - for(var i = 0; i < this.bodies.length; i++) { - var body = this.bodies[i]; - if(!body) { - continue; - } - for(var j = 0; j < body.shapes.length; j++) { - var shape = body.shapes[j]; - if(shape.type != Advanced.Manager.SHAPE_TYPE_POLY) { - continue; - } - var index = shape.findEdgeByPoint(p, minDist); - if(index != -1) { - var edge = (shape.id << 16) | index; - if(refEdgeId == -1) { - return edge; - } - if(firstEdgeId == -1) { - firstEdgeId = edge; - } - if(edge == refEdgeId) { - refEdgeId = -1; - } - } - } - } - return firstEdgeId; - }; - Space.prototype.findJointByPoint = function (p, minDist, refJointId) { - var firstJointId = -1; - var dsq = minDist * minDist; - refJointId = refJointId || -1; - for(var i = 0; i < this.joints.length; i++) { - var joint = this.joints[i]; - if(!joint) { - continue; - } - var jointId = -1; - if(Phaser.Vec2Utils.distanceSq(p, joint.getWorldAnchor1()) < dsq) { - jointId = (joint.id << 16 | 0); - } else if(Phaser.Vec2Utils.distanceSq(p, joint.getWorldAnchor2()) < dsq) { - jointId = (joint.id << 16 | 1); - } - if(jointId != -1) { - if(refJointId == -1) { - return jointId; - } - if(firstJointId == -1) { - firstJointId = jointId; - } - if(jointId == refJointId) { - refJointId = -1; - } - } - } - return firstJointId; - }; - Space.prototype.findContactSolver = function (shape1, shape2) { - Advanced.Manager.write('findContactSolver. Length: ' + this._cl); - for(var i = 0; i < this._cl; i++) { - var contactSolver = this.contactSolvers[i]; - if(shape1 == contactSolver.shape1 && shape2 == contactSolver.shape2) { - return contactSolver; - } - } - return null; - }; - Space.prototype.genTemporalContactSolvers = function () { - Advanced.Manager.write('genTemporalContactSolvers'); - this._cl = 0; - this.contactSolvers.length = 0; - this.numContacts = 0; - for(var body1Index = 0; body1Index < this._bl; body1Index++) { - if(!this.bodies[body1Index]) { - continue; - } - this.bodies[body1Index].stepCount = this.stepCount; - for(var body2Index = 0; body2Index < this._bl; body2Index++) { - if(this.bodies[body1Index].inContact(this.bodies[body2Index]) == false) { - continue; - } - Advanced.Manager.write('body1 and body2 intersect'); - for(var i = 0; i < this.bodies[body1Index].shapesLength; i++) { - for(var j = 0; j < this.bodies[body2Index].shapesLength; j++) { - this._shape1 = this.bodies[body1Index].shapes[i]; - this._shape2 = this.bodies[body2Index].shapes[j]; - var contactArr = []; - if(!Advanced.Manager.collision.collide(this._shape1, this._shape2, contactArr)) { - continue; - } - if(this._shape1.type > this._shape2.type) { - var temp = this._shape1; - this._shape1 = this._shape2; - this._shape2 = temp; - } - this.numContacts += contactArr.length; - // Result stored in this._contactSolver (see what we can do about generating some re-usable solvers) - var contactSolver = this.findContactSolver(this._shape1, this._shape2); - Advanced.Manager.write('findContactSolver result: ' + contactSolver); - if(contactSolver) { - contactSolver.update(contactArr); - this.contactSolvers.push(contactSolver); - } else { - Advanced.Manager.write('awake both bodies'); - this.bodies[body1Index].awake(true); - this.bodies[body2Index].awake(true); - var newContactSolver = new Advanced.ContactSolver(this._shape1, this._shape2); - newContactSolver.contacts = contactArr; - newContactSolver.elasticity = Math.max(this._shape1.elasticity, this._shape2.elasticity); - newContactSolver.friction = Math.sqrt(this._shape1.friction * this._shape2.friction); - this.contactSolvers.push(newContactSolver); - Advanced.Manager.write('new contact solver'); - } - } - } - } - } - this._cl = this.contactSolvers.length; - }; - Space.prototype.initSolver = function (warmStarting) { - Advanced.Manager.write('initSolver'); - Advanced.Manager.write('contactSolvers.length: ' + this._cl); - // Initialize contact solvers - for(var c = 0; c < this._cl; c++) { - this.contactSolvers[c].initSolver(this._deltaInv); - // Warm starting (apply cached impulse) - if(warmStarting) { - this.contactSolvers[c].warmStart(); - } - } - // Initialize joint solver - for(var j = 0; j < this.joints.length; j++) { - if(this.joints[j]) { - this.joints[j].initSolver(this._delta, warmStarting); - } - } - // Warm starting (apply cached impulse) - /* - if (warmStarting) - { - for (var c = 0; c < this._cl; c++) - { - this.contactSolvers[c].warmStart(); - } - } - */ - }; - Space.prototype.velocitySolver = function (iterations) { - Advanced.Manager.write('velocitySolver, iterations: ' + iterations + ' csa len: ' + this._cl); - for(var i = 0; i < iterations; i++) { - for(var j = 0; j < this._jl; j++) { - if(this.joints[j]) { - this.joints[j].solveVelocityConstraints(); - } - } - for(var c = 0; c < this._cl; c++) { - this.contactSolvers[c].solveVelocityConstraints(); - } - } - }; - Space.prototype.positionSolver = function (iterations) { - this._positionSolved = false; - for(var i = 0; i < iterations; i++) { - this._contactsOk = true; - this._jointsOk = true; - for(var c = 0; c < this._cl; c++) { - this._contactsOk = this.contactSolvers[c].solvePositionConstraints() && this._contactsOk; - } - for(var j = 0; j < this._jl; j++) { - if(this.joints[j]) { - this._jointsOk = this.joints[j].solvePositionConstraints() && this._jointsOk; - } - } - if(this._contactsOk && this._jointsOk) { - // exit early if the position errors are small - this._positionSolved = true; - break; - } - } - return this._positionSolved; - }; - Space.prototype.step = // Step through the physics simulation - function (dt, velocityIterations, positionIterations, warmStarting, allowSleep) { - Advanced.Manager.clear(); - Advanced.Manager.write('Space step ' + this.stepCount); - this._delta = dt; - this._deltaInv = 1 / dt; - this._bl = this.bodies.length; - this._jl = this.joints.length; - this.stepCount++; - // 1) Generate Contact Solvers (into the this.contactSolvers array) - this.genTemporalContactSolvers(); - Advanced.Manager.dump("Contact Solvers", this.bodies[1]); - // 2) Initialize the Contact Solvers - this.initSolver(warmStarting); - Advanced.Manager.dump("Init Solver", this.bodies[1]); - // 3) Intergrate velocity - for(var i = 0; i < this._bl; i++) { - if(this.bodies[i] && this.bodies[i].isDynamic && this.bodies[i].isAwake) { - this.bodies[i].updateVelocity(this.gravity, this._delta, this.damping); - } - } - Advanced.Manager.dump("Update Velocity", this.bodies[1]); - // 4) Awaken bodies via joints - for(var j = 0; i < this._jl; j++) { - if(!this.joints[j]) { - continue; - } - // combine - var awake1 = this.joints[j].body1.isAwake && !this.joints[j].body1.isStatic; - var awake2 = this.joints[j].body2.isAwake && !this.joints[j].body2.isStatic; - if(awake1 ^ awake2) { - if(!awake1) { - this.joints[j].body1.awake(true); - } - if(!awake2) { - this.joints[j].body2.awake(true); - } - } - } - // 5) Iterative velocity constraints solver - this.velocitySolver(velocityIterations); - Advanced.Manager.dump("Velocity Solvers", this.bodies[1]); - // 6) Intergrate position - for(var i = 0; i < this._bl; i++) { - if(this.bodies[i] && this.bodies[i].isDynamic && this.bodies[i].isAwake) { - this.bodies[i].updatePosition(this._delta); - } - } - Advanced.Manager.dump("Update Position", this.bodies[1]); - // 7) Process breakable joint - for(var i = 0; i < this._jl; i++) { - if(this.joints[i] && this.joints[i].breakable && (this.joints[i].getReactionForce(this._deltaInv).lengthSq() >= this.joints[i].maxForce * this.joints[i].maxForce)) { - this.removeJoint(this.joints[i]); - } - } - // 8) Iterative position constraints solver (result stored in this._positionSolved) - this.positionSolver(positionIterations); - Advanced.Manager.dump("Position Solver", this.bodies[1]); - // 9) Sync the Transforms - for(var i = 0; i < this._bl; i++) { - if(this.bodies[i]) { - this.bodies[i].syncTransform(); - } - } - Advanced.Manager.dump("Sync Transform", this.bodies[1]); - // 10) Post solve collision callback - if(this.postSolve) { - for(var i = 0; i < this._cl; i++) { - this.postSolve(this.contactSolvers[i]); - } - } - // 11) Cache Body Data - for(var i = 0; i < this._bl; i++) { - if(this.bodies[i] && this.bodies[i].isDynamic && this.bodies[i].isAwake) { - this.bodies[i].cacheData('post solve collision callback'); - } - } - Advanced.Manager.dump("Cache Data", this.bodies[1]); - Advanced.Manager.writeAll(); - // 12) Process sleeping - if(allowSleep) { - this._minSleepTime = 999999; - for(var i = 0; i < this._bl; i++) { - if(!this.bodies[i] || this.bodies[i].isDynamic == false) { - continue; - } - if(this.bodies[i].angularVelocity * this.bodies[i].angularVelocity > this._angTolSqr || this.bodies[i].velocity.dot(this.bodies[i].velocity) > this._linTolSqr) { - this.bodies[i].sleepTime = 0; - this._minSleepTime = 0; - } else { - this.bodies[i].sleepTime += this._delta; - this._minSleepTime = Math.min(this._minSleepTime, this.bodies[i].sleepTime); - } - } - if(this._positionSolved && this._minSleepTime >= Space.TIME_TO_SLEEP) { - for(var i = 0; i < this._bl; i++) { - if(this.bodies[i]) { - this.bodies[i].awake(false); - } - } - } - } - }; - return Space; - })(); - Advanced.Space = Space; - })(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(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 = 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, [ - { - 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) { - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /** - * Phaser - Advanced Physics - Body - * - * Based on the work Ju Hyung Lee started in JS PhyRus. - */ - (function (Advanced) { - var Body = (function () { - 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 - this.joints = []; - this.jointHash = { - }; - this.fixedRotation = false; - this.categoryBits = 0x0001; - this.maskBits = 0xFFFF; - this.stepCount = 0; - this.id = Phaser.Physics.Advanced.Manager.bodyCounter++; - this.name = 'body' + this.id; - this.type = type; - if(sprite) { - this.sprite = sprite; - this.game = sprite.game; - this.position = new Phaser.Vec2(Phaser.Physics.Advanced.Manager.pixelsToMeters(sprite.x), Phaser.Physics.Advanced.Manager.pixelsToMeters(sprite.y)); - this.angle = sprite.rotation; - } else { - 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); - this.centroid = new Phaser.Vec2(); - this.velocity = new Phaser.Vec2(); - this.force = new Phaser.Vec2(); - this.angularVelocity = 0; - this.torque = 0; - this.linearDamping = 0; - this.angularDamping = 0; - this.sleepTime = 0; - this.awaked = false; - this.shapes = []; - this.joints = []; - this.jointHash = { - }; - this.bounds = new Advanced.Bounds(); - this.fixedRotation = false; - this.categoryBits = 0x0001; - 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); - //for (var i = 0; i < this.shapes.length; i++) - //{ - // body.addShape(this.shapes[i].duplicate()); - //} - //body.resetMassData(); - //return body; - }; - Object.defineProperty(Body.prototype, "isDisabled", { - get: function () { - return this.type == Phaser.Types.BODY_DISABLED ? true : false; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Body.prototype, "isStatic", { - get: function () { - return this.type == Phaser.Types.BODY_STATIC ? true : false; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Body.prototype, "isKinetic", { - get: function () { - return this.type == Phaser.Types.BODY_KINETIC ? true : false; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Body.prototype, "isDynamic", { - get: function () { - return this.type == Phaser.Types.BODY_DYNAMIC ? true : false; - }, - enumerable: true, - configurable: true - }); - Body.prototype.setType = function (type) { - if(type == this.type) { - return; - } - this.force.setTo(0, 0); - this.velocity.setTo(0, 0); - this.torque = 0; - this.angularVelocity = 0; - this.type = type; - this.awake(true); - }; - Body.prototype.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; - this.shapes.push(shape); - this.shapesLength = this.shapes.length; - return shape; - }; - Body.prototype.removeShape = function (shape) { - var index = this.shapes.indexOf(shape); - if(index != -1) { - this.shapes.splice(index, 1); - shape.body = undefined; - } - this.shapesLength = this.shapes.length; - }; - Body.prototype.setMass = function (mass) { - this.mass = mass; - this.massInverted = mass > 0 ? 1 / mass : 0; - }; - Body.prototype.setInertia = function (inertia) { - this.inertia = inertia; - this.inertiaInverted = inertia > 0 ? 1 / inertia : 0; - }; - Body.prototype.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); - // 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 - return Phaser.TransformUtils.transform(this.transform, p); - }; - Body.prototype.getWorldVector = function (v) { - // OPTIMISE: Creating new vector - return Phaser.TransformUtils.rotate(this.transform, v); - }; - Body.prototype.getLocalPoint = function (p) { - // OPTIMISE: Creating new vector - return Phaser.TransformUtils.untransform(this.transform, p); - }; - Body.prototype.getLocalVector = function (v) { - // OPTIMISE: Creating new vector - return Phaser.TransformUtils.unrotate(this.transform, v); - }; - Body.prototype.setFixedRotation = function (flag) { - this.fixedRotation = flag; - this.resetMassData(); - }; - Body.prototype.resetMassData = function () { - this.centroid.setTo(0, 0); - this.mass = 0; - this.massInverted = 0; - this.inertia = 0; - this.inertiaInverted = 0; - if(this.isDynamic == false) { - Phaser.TransformUtils.transform(this.transform, this.centroid, this.position); - //this.position.copyFrom(this.transform.transform(this.centroid)); - return; - } - var totalMassCentroid = new Phaser.Vec2(0, 0); - var totalMass = 0; - var totalInertia = 0; - for(var i = 0; i < this.shapes.length; i++) { - var shape = this.shapes[i]; - var centroid = shape.centroid(); - var mass = shape.area() * shape.density; - var inertia = shape.inertia(mass); - //console.log('rmd', centroid, shape); - totalMassCentroid.multiplyAddByScalar(centroid, mass); - totalMass += mass; - totalInertia += inertia; - } - //this.centroid.copy(vec2.scale(totalMassCentroid, 1 / totalMass)); - Phaser.Vec2Utils.scale(totalMassCentroid, 1 / totalMass, this.centroid); - this.setMass(totalMass); - if(!this.fixedRotation) { - //this.setInertia(totalInertia - totalMass * vec2.dot(this.centroid, this.centroid)); - this.setInertia(totalInertia - totalMass * Phaser.Vec2Utils.dot(this.centroid, this.centroid)); - } - //console.log("mass = " + this.m + " inertia = " + this.i); - // Move center of mass - var oldPosition = Phaser.Vec2Utils.clone(this.position); - //this.position.copyFrom(this.transform.transform(this.centroid)); - Phaser.TransformUtils.transform(this.transform, this.centroid, this.position); - // Update center of mass velocity - //this.velocity.mad(vec2.perp(vec2.sub(this.position, old_p)), this.angularVelocity); - oldPosition.subtract(this.position); - this.velocity.multiplyAddByScalar(Phaser.Vec2Utils.perp(oldPosition, oldPosition), this.angularVelocity); - }; - Body.prototype.resetJointAnchors = function () { - for(var i = 0; i < this.joints.length; i++) { - var joint = this.joints[i]; - if(!joint) { - continue; - } - var anchor1 = joint.getWorldAnchor1(); - var anchor2 = joint.getWorldAnchor2(); - joint.setWorldAnchor1(anchor1); - joint.setWorldAnchor2(anchor2); - } - }; - Body.prototype.cacheData = function (source) { - if (typeof source === "undefined") { source = ''; } - 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); - Phaser.Vec2Utils.multiplyAdd(gravity, this.force, this.massInverted, this._tempVec2); - Phaser.Vec2Utils.multiplyAdd(this.velocity, this._tempVec2, dt, this.velocity); - this.angularVelocity = this.angularVelocity + this.torque * this.inertiaInverted * dt; - // Apply damping. - // ODE: dv/dt + c * v = 0 - // Solution: v(t) = v0 * exp(-c * t) - // Time step: v(t + dt) = v0 * exp(-c * (t + dt)) = v0 * exp(-c * t) * exp(-c * dt) = v * exp(-c * dt) - // v2 = exp(-c * dt) * v1 - // Taylor expansion: - // v2 = (1.0f - c * dt) * v1 - this.velocity.scale(this.clamp(1 - dt * (damping + this.linearDamping), 0, 1)); - this.angularVelocity *= this.clamp(1 - dt * (damping + this.angularDamping), 0, 1); - this.force.setTo(0, 0); - this.torque = 0; - }; - Body.prototype.inContact = function (body2) { - if(!body2 || this.stepCount == body2.stepCount) { - return false; - } - if(!(this.isAwake && this.isStatic == false) && !(body2.isAwake && body2.isStatic == false)) { - return false; - } - if(this.isCollidable(body2) == false) { - return false; - } - if(!this.bounds.intersectsBounds(body2.bounds)) { - return false; - } - return true; - }; - Body.prototype.clamp = function (v, min, max) { - return v < min ? min : (v > max ? max : v); - }; - Body.prototype.updatePosition = function (dt) { - //console.log('body update pos', this.position.y); - //console.log('pre add temp', this._tempVec2.y); - //this.position.addself(vec2.scale(this.velocity, dt)); - this.position.add(Phaser.Vec2Utils.scale(this.velocity, dt, this._tempVec2)); - //console.log('post add temp', this._tempVec2.y); - //console.log('post add', this.position.y); - this.angle += this.angularVelocity * dt; - }; - Body.prototype.resetForce = function () { - this.force.setTo(0, 0); - this.torque = 0; - }; - Body.prototype.applyForce = function (force, p) { - if(this.isDynamic == false) { - return; - } - if(this.isAwake == false) { - this.awake(true); - } - this.force.add(force); - // this.f.addself(force); - // this.torque += vec2.cross(vec2.sub(p, this.p), force); - Phaser.Vec2Utils.subtract(p, this.position, this._tempVec2); - this.torque += Phaser.Vec2Utils.cross(this._tempVec2, force); - }; - Body.prototype.applyForceToCenter = function (force) { - if(this.isDynamic == false) { - return; - } - if(this.isAwake == false) { - this.awake(true); - } - this.force.add(force); - }; - Body.prototype.applyTorque = function (torque) { - if(this.isDynamic == false) { - return; - } - if(this.isAwake == false) { - this.awake(true); - } - this.torque += torque; - }; - Body.prototype.applyLinearImpulse = function (impulse, p) { - if(this.isDynamic == false) { - return; - } - if(this.isAwake == false) { - this.awake(true); - } - this.velocity.multiplyAddByScalar(impulse, this.massInverted); - // 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; - }; - Body.prototype.applyAngularImpulse = function (impulse) { - if(this.isDynamic == false) { - return; - } - if(this.isAwake == false) { - this.awake(true); - } - this.angularVelocity += impulse * this.inertiaInverted; - }; - Body.prototype.kineticEnergy = function () { - var vsq = this.velocity.dot(this.velocity); - var wsq = this.angularVelocity * this.angularVelocity; - return 0.5 * (this.mass * vsq + this.inertia * wsq); - }; - Object.defineProperty(Body.prototype, "isAwake", { - get: function () { - return this.awaked; - }, - enumerable: true, - configurable: true - }); - Body.prototype.awake = function (flag) { - this.awaked = flag; - if(flag) { - this.sleepTime = 0; - } else { - this.velocity.setTo(0, 0); - this.angularVelocity = 0; - this.force.setTo(0, 0); - this.torque = 0; - } - }; - Body.prototype.isCollidable = function (other) { - if(this == other) { - return false; - } - if(this.isDynamic == false && other.isDynamic == false) { - return false; - } - if(!(this.maskBits & other.categoryBits) || !(other.maskBits & this.categoryBits)) { - return false; - } - for(var i = 0; i < this.joints.length; i++) { - var joint = this.joints[i]; - if(!this.joints[i] || (!this.joints[i].collideConnected && other.jointHash[this.joints[i].id] != undefined)) { - return false; - } - } - return true; - }; - return Body; - })(); - Advanced.Body = Body; - })(Physics.Advanced || (Physics.Advanced = {})); - var Advanced = Physics.Advanced; - })(Phaser.Physics || (Phaser.Physics = {})); - var Physics = Phaser.Physics; -})(Phaser || (Phaser = {})); -/// /// /// /// From c647792c129704c40dcd6d6ab8118913a1051119 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Wed, 26 Jun 2013 14:18:48 +0100 Subject: [PATCH 3/3] Physics updates --- GruntFile.js | 26 +- Phaser/components/Transform.ts | 11 +- Phaser/gameobjects/GameObjectFactory.ts | 5 +- Phaser/math/Vec2.ts | 2 + Phaser/math/Vec2Utils.ts | 4 +- Phaser/phaser.js | 16 - Phaser/physics/Body.ts | 16 +- Phaser/physics/Space.ts | 2 +- Phaser/physics/shapes/Box.ts | 6 + Phaser/physics/shapes/IShape.ts | 2 + Phaser/utils/DebugUtils.ts | 47 +- Tests/phaser-fx.js | 202 +------- Tests/phaser.js | 614 +++++++++++++----------- Tests/physics/simple test 1.js | 46 +- Tests/physics/simple test 1.ts | 15 +- build/phaser.d.ts | 414 ++++++++-------- build/phaser.js | 614 +++++++++++++----------- 17 files changed, 998 insertions(+), 1044 deletions(-) diff --git a/GruntFile.js b/GruntFile.js index d48f7e06..ae8e8ff8 100644 --- a/GruntFile.js +++ b/GruntFile.js @@ -51,15 +51,23 @@ module.exports = function (grunt) { comments: true } }, - fx: { - src: ['SpecialFX/**/*.ts'], - dest: 'build/phaser-fx.js', - options: { - target: 'ES5', - declaration: true, - comments: true - } - } + //tests: { + // src: ['Tests/**/*.ts'], + // options: { + // target: 'ES5', + // declaration: true, + // comments: true + // } + // } + //fx: { + // src: ['SpecialFX/**/*.ts'], + // dest: 'build/phaser-fx.js', + // options: { + // target: 'ES5', + // declaration: true, + // comments: true + // } + //} }, copy: { main: { diff --git a/Phaser/components/Transform.ts b/Phaser/components/Transform.ts index 47e51866..4d9cf796 100644 --- a/Phaser/components/Transform.ts +++ b/Phaser/components/Transform.ts @@ -1,5 +1,6 @@ /// /// +/// /** * Phaser - Components - Transform @@ -98,7 +99,7 @@ module Phaser.Components { this._halfSize.y = this.parent.height / 2; this._offset.x = this.origin.x * this.parent.width; this._offset.y = this.origin.y * this.parent.height; - this._angle = Math.atan2(this.halfHeight - this._offset.y, this.halfWidth - this._offset.x); + this._angle = Math.atan2(this.halfHeight - this._offset.x, this.halfWidth - this._offset.y); this._distance = Math.sqrt(((this._offset.x - this._halfSize.x) * (this._offset.x - this._halfSize.x)) + ((this._offset.y - this._halfSize.y) * (this._offset.y - this._halfSize.y))); this._size.x = this.parent.width; this._size.y = this.parent.height; @@ -240,22 +241,22 @@ module Phaser.Components { /** * Scale of the object. A scale of 1.0 is the original size. 0.5 half size. 2.0 double sized. */ - public scale: Phaser.Vec2; + public scale: Vec2; /** * Skew the object along the x and y axis. A skew value of 0 is no skew. */ - public skew: Phaser.Vec2; + public skew: Vec2; /** * The influence of camera movement upon the object, if supported. */ - public scrollFactor: Phaser.Vec2; + public scrollFactor: Vec2; /** * The origin is the point around which scale and rotation takes place and defaults to the top-left of the sprite. */ - public origin: Phaser.Vec2; + public origin: Vec2; /** * This value is added to the rotation of the object. diff --git a/Phaser/gameobjects/GameObjectFactory.ts b/Phaser/gameobjects/GameObjectFactory.ts index 47bc8f2b..dc9e071f 100644 --- a/Phaser/gameobjects/GameObjectFactory.ts +++ b/Phaser/gameobjects/GameObjectFactory.ts @@ -83,11 +83,12 @@ module Phaser { * @param y {number} Y position of the new sprite. * @param [key] {string} The image key as defined in the Game.Cache to use as the texture for this sprite * @param [frame] {string|number} If the sprite uses an image from a texture atlas or sprite sheet you can pass the frame here. Either a number for a frame ID or a string for a frame name. + * @param [bodyType] {number} The physics body type of the object (defaults to BODY_DYNAMIC) * @param [shapeType] The default body shape is either 0 for a Box or 1 for a Circle. See Sprite.body.addShape for custom shapes (polygons, etc) * @returns {Sprite} The newly created sprite object. */ - public physicsSprite(x: number, y: number, key?: string = '', frame? = null, shapeType?:number = 0): Sprite { - return this._world.group.add(new Sprite(this._game, x, y, key, frame, Phaser.Types.BODY_DYNAMIC, shapeType)); + public physicsSprite(x: number, y: number, key?: string = '', frame? = null, bodyType?: number = Phaser.Types.BODY_DYNAMIC, shapeType?:number = 0): Sprite { + return this._world.group.add(new Sprite(this._game, x, y, key, frame, bodyType, shapeType)); } /** diff --git a/Phaser/math/Vec2.ts b/Phaser/math/Vec2.ts index 14c451b3..d9bfab0f 100644 --- a/Phaser/math/Vec2.ts +++ b/Phaser/math/Vec2.ts @@ -23,6 +23,8 @@ module Phaser { this.x = x; this.y = y; + return this; + } /** diff --git a/Phaser/math/Vec2Utils.ts b/Phaser/math/Vec2Utils.ts index ec46d7b4..f78a26ff 100644 --- a/Phaser/math/Vec2Utils.ts +++ b/Phaser/math/Vec2Utils.ts @@ -68,7 +68,7 @@ module Phaser { * @param {Vec2} out The output Vec2 that is the result of the operation. * @return {Vec2} A Vec2 that is the scaled vector. */ - static scale(a: Vec2, s: number, out?: Vec2 = new Vec2): Vec2 { + static scale(a: Phaser.Vec2, s: number, out?: Phaser.Vec2 = new Phaser.Vec2): Phaser.Vec2 { return out.setTo(a.x * s, a.y * s); } @@ -212,7 +212,7 @@ module Phaser { * @param {Vec2} out The output Vec2 that is the result of the operation. * @return {Vec2} A Vec2. */ - static normalRightHand(a: Vec2, out?: Vec2 = this): Vec2 { + static normalRightHand(a: Vec2, out?: Vec2 = new Vec2): Vec2 { return out.setTo(a.y * -1, a.x); } diff --git a/Phaser/phaser.js b/Phaser/phaser.js index 7b20a194..ec56656e 100644 --- a/Phaser/phaser.js +++ b/Phaser/phaser.js @@ -1,19 +1,3 @@ -/** -* Phaser -* -* v1.0.0 - June XX 2013 -* -* A small and feature-packed 2D canvas game framework born from the firey pits of Flixel and Kiwi. -* -* Richard Davey (@photonstorm) -* -* Many thanks to Adam Saltsman (@ADAMATOMIC) for releasing Flixel, from both which Phaser -* and my love of game development took a lot of inspiration. -* -* "If you want your children to be intelligent, read them fairy tales." -* "If you want them to be more intelligent, read them more fairy tales." -* -- Albert Einstein -*/ var Phaser; (function (Phaser) { Phaser.VERSION = 'Phaser version 1.0.0'; diff --git a/Phaser/physics/Body.ts b/Phaser/physics/Body.ts index aa9c82d1..0e65ebab 100644 --- a/Phaser/physics/Body.ts +++ b/Phaser/physics/Body.ts @@ -91,7 +91,7 @@ module Phaser.Physics { /** * Reference to Phaser.Game */ - public game: Game; + public game: Phaser.Game; /** * Reference to the parent Sprite @@ -461,7 +461,7 @@ module Phaser.Physics { this.bounds.clear(); - for (var i = 0; i < this.shapes.length; i++) + for (var i = 0; i < this.shapesLength; i++) { var shape: IShape = this.shapes[i]; shape.cacheData(this.transform); @@ -534,13 +534,13 @@ module Phaser.Physics { this.angle += this.angularVelocity * dt; - if (this.sprite) - { - this.sprite.x = this.position.x * 50; - this.sprite.y = this.position.y * 50; + if (this.sprite) + { + this.sprite.x = this.position.x * 50; + this.sprite.y = this.position.y * 50; // Obey fixed rotation? - this.sprite.rotation = this.game.math.radiansToDegrees(this.angle); - } + this.sprite.rotation = this.game.math.radiansToDegrees(this.angle); + } } diff --git a/Phaser/physics/Space.ts b/Phaser/physics/Space.ts index f8e8d9bb..c9b3b809 100644 --- a/Phaser/physics/Space.ts +++ b/Phaser/physics/Space.ts @@ -723,7 +723,7 @@ module Phaser.Physics { Manager.dump("Velocity Solvers", this.bodies[1]); - // 6) Intergrate position + // 6) Integrate position for (var i = 0; i < this._bl; i++) { if (this.bodies[i] && this.bodies[i].isDynamic && this.bodies[i].isAwake) diff --git a/Phaser/physics/shapes/Box.ts b/Phaser/physics/shapes/Box.ts index 461faf86..3650e803 100644 --- a/Phaser/physics/shapes/Box.ts +++ b/Phaser/physics/shapes/Box.ts @@ -17,14 +17,20 @@ module Phaser.Physics.Shapes { // Give in pixels constructor(x, y, width, height) { + console.log('Box px', x, y, width, height); + x = Manager.pixelsToMeters(x); y = Manager.pixelsToMeters(y); width = Manager.pixelsToMeters(width); height = Manager.pixelsToMeters(height); + console.log('Box m', x, y, width, height); + var hw = width * 0.5; var hh = height * 0.5; + console.log('Box hh', hw, hh); + super([ { x: -hw + x, y: +hh + y }, { x: -hw + x, y: -hh + y }, diff --git a/Phaser/physics/shapes/IShape.ts b/Phaser/physics/shapes/IShape.ts index 1e49f5a9..c1f0ddb4 100644 --- a/Phaser/physics/shapes/IShape.ts +++ b/Phaser/physics/shapes/IShape.ts @@ -33,8 +33,10 @@ module Phaser.Physics { findEdgeByPoint(p: Phaser.Vec2, minDist: number): number; findVertexByPoint(p: Phaser.Vec2, minDist: number): number; + // The verts of the shape (in local coordinate space) verts: Phaser.Vec2[]; planes: Phaser.Physics.Plane[]; + // The translated verts (in world space) tverts: Phaser.Vec2[]; tplanes: Phaser.Physics.Plane[]; convexity: bool; diff --git a/Phaser/utils/DebugUtils.ts b/Phaser/utils/DebugUtils.ts index c593f7ed..a4ae9613 100644 --- a/Phaser/utils/DebugUtils.ts +++ b/Phaser/utils/DebugUtils.ts @@ -42,6 +42,40 @@ module Phaser { } + /** + * Render debug infos. (including name, bounds info, position and some other properties) + * @param x {number} X position of the debug info to be rendered. + * @param y {number} Y position of the debug info to be rendered. + * @param [color] {number} color of the debug info to be rendered. (format is css color string) + */ + static renderPhysicsBodyInfo(body: Phaser.Physics.Body, x: number, y: number, color?: string = 'rgb(255,255,255)') { + + DebugUtils.context.fillStyle = color; + DebugUtils.context.fillText('Body ID: ' + body.name, x, y); + DebugUtils.context.fillText('Position x: ' + body.position.x.toFixed(1) + ' y: ' + body.position.y.toFixed(1) + ' rotation: ' + body.angle.toFixed(1), x, y + 14); + DebugUtils.context.fillText('World x: ' + (body.position.x * 50).toFixed(1) + ' y: ' + (body.position.y * 50).toFixed(1), x, y + 28); + DebugUtils.context.fillText('Velocity x: ' + body.velocity.x.toFixed(1) + ' y: ' + body.velocity.y.toFixed(1), x, y + 42); + + if (body.shapes[0].verts.length > 0) + { + + DebugUtils.context.fillText('Vert 1 x: ' + (body.shapes[0].verts[0].x * 50) + ' y: ' + (body.shapes[0].verts[0].y * 50), x, y + 56); + DebugUtils.context.fillText('Vert 2 x: ' + (body.shapes[0].verts[1].x * 50) + ' y: ' + (body.shapes[0].verts[1].y * 50), x, y + 70); + DebugUtils.context.fillText('Vert 3 x: ' + (body.shapes[0].tverts[2].x * 50) + ' y: ' + (body.shapes[0].tverts[2].y * 50), x, y + 84); + DebugUtils.context.fillText('Vert 4 x: ' + (body.shapes[0].tverts[3].x * 50) + ' y: ' + (body.shapes[0].tverts[3].y * 50), x, y + 98); + + +/* + DebugUtils.context.fillText('Vert 1 x: ' + body.shapes[0].verts[0].x.toFixed(1) + ' y: ' + body.shapes[0].verts[0].y.toFixed(1), x, y + 56); + DebugUtils.context.fillText('Vert 2 x: ' + body.shapes[0].verts[1].x.toFixed(1) + ' y: ' + body.shapes[0].verts[1].y.toFixed(1), x, y + 70); + DebugUtils.context.fillText('Vert 3 x: ' + body.shapes[0].verts[2].x.toFixed(1) + ' y: ' + body.shapes[0].verts[2].y.toFixed(1), x, y + 84); + DebugUtils.context.fillText('Vert 4 x: ' + body.shapes[0].verts[3].x.toFixed(1) + ' y: ' + body.shapes[0].verts[3].y.toFixed(1), x, y + 98); +*/ + + } + + } + static renderSpriteBounds(sprite: Sprite, camera?: Camera = null, color?: string = 'rgba(0,255,0,0.2)') { if (camera == null) @@ -59,7 +93,7 @@ module Phaser { static renderPhysicsBody(body: Phaser.Physics.Body, lineWidth: number = 1, fillStyle: string = 'rgba(0,255,0,0.2)', sleepStyle: string = 'rgba(100,100,100,0.2)') { - for (var s = 0; s < body.shapes.length; s++) + for (var s = 0; s < body.shapesLength; s++) { DebugUtils.context.beginPath(); @@ -67,13 +101,16 @@ module Phaser { { var verts = body.shapes[s].tverts; - DebugUtils.context.moveTo((body.position.x + verts[0].x) * 50, (body.position.y + verts[0].y) * 50); +// DebugUtils.context.moveTo(body.position.x * 50 + verts[0].x, body.position.y * 50 + verts[0].y); + DebugUtils.context.moveTo(verts[0].x * 50, verts[0].y * 50); - for (var i = 0; i < verts.length; i++) { - DebugUtils.context.lineTo((body.position.x + verts[i].x) * 50, (body.position.y + verts[i].y) * 50); + for (var i = 1; i < verts.length; i++) { +// DebugUtils.context.lineTo(body.position.x * 50 + verts[i].x, body.position.y * 50 + verts[i].y); + DebugUtils.context.lineTo(verts[i].x * 50, verts[i].y * 50); } - DebugUtils.context.lineTo((body.position.x + verts[verts.length - 1].x) * 50, (body.position.y + verts[verts.length - 1].y) * 50); +// DebugUtils.context.lineTo(body.position.x * 50 + verts[0].x, body.position.y * 50 + verts[0].y); + DebugUtils.context.lineTo(verts[0].x * 50, verts[0].y * 50); } else if (body.shapes[s].type == Phaser.Physics.Manager.SHAPE_TYPE_CIRCLE) { diff --git a/Tests/phaser-fx.js b/Tests/phaser-fx.js index 6499d8da..dc65ef51 100644 --- a/Tests/phaser-fx.js +++ b/Tests/phaser-fx.js @@ -1,12 +1,6 @@ var Phaser; (function (Phaser) { (function (FX) { - /// - /** - * Phaser - FX - Camera - Flash - * - * The camera is filled with the given color and returns to normal at the given duration. - */ (function (Camera) { var Flash = (function () { function Flash(game) { @@ -15,21 +9,12 @@ var Phaser; this._fxFlashAlpha = 0; this._game = game; } - Flash.prototype.start = /** - * The camera is filled with this color and returns to normal at the given duration. - * - * @param Color The color you want to use in 0xRRGGBB format, i.e. 0xffffff for white. - * @param Duration How long it takes for the flash to fade. - * @param OnComplete An optional function you want to run when the flash finishes. Set to null for no callback. - * @param Force Force an already running flash effect to reset. - */ - function (color, duration, onComplete, force) { + Flash.prototype.start = function (color, duration, onComplete, force) { if (typeof color === "undefined") { color = 0xffffff; } if (typeof duration === "undefined") { duration = 1; } if (typeof onComplete === "undefined") { onComplete = null; } if (typeof force === "undefined") { force = false; } if(force === false && this._fxFlashAlpha > 0) { - // You can't flash again unless you force it return; } if(duration <= 0) { @@ -44,7 +29,6 @@ var Phaser; this._fxFlashComplete = onComplete; }; Flash.prototype.postUpdate = function () { - // Update the Flash effect if(this._fxFlashAlpha > 0) { this._fxFlashAlpha -= this._game.time.elapsed / this._fxFlashDuration; if(this._game.math.roundTo(this._fxFlashAlpha, -2) <= 0) { @@ -72,38 +56,17 @@ var Phaser; var Phaser; (function (Phaser) { (function (FX) { - /// - /** - * Phaser - FX - Camera - Border - * - * Creates a border around a camera. - */ (function (Camera) { var Border = (function () { function Border(game, parent) { - /** - * Whether render border of this camera or not. (default is false) - * @type {boolean} - */ this.showBorder = false; - /** - * Color of border of this camera. (in css color string) - * @type {string} - */ this.borderColor = 'rgb(255,255,255)'; this._game = game; this._parent = parent; } - Border.prototype.start = /** - * You can name the function that starts the effect whatever you like, but we used 'start' in our effects. - */ - function () { + Border.prototype.start = function () { }; - Border.prototype.postRender = /** - * Post-render is called during the objects render cycle, after the children/image data has been rendered. - * It happens directly BEFORE a canvas context.restore has happened if added to a Camera. - */ - function (camera, cameraX, cameraY, cameraWidth, cameraHeight) { + Border.prototype.postRender = function (camera, cameraX, cameraY, cameraWidth, cameraHeight) { if(this.showBorder == true) { this._game.stage.context.strokeStyle = this.borderColor; this._game.stage.context.lineWidth = 1; @@ -122,50 +85,23 @@ var Phaser; var Phaser; (function (Phaser) { (function (FX) { - /// - /** - * Phaser - FX - Camera - Template - * - * A Template FX file you can use to create your own Camera FX. - * If you don't use any of the methods below (i.e. preUpdate, render, etc) then DELETE THEM to avoid un-necessary calls by the FXManager. - */ (function (Camera) { var Template = (function () { function Template(game, parent) { this._game = game; this._parent = parent; } - Template.prototype.start = /** - * You can name the function that starts the effect whatever you like, but we used 'start' in our effects. - */ - function () { + Template.prototype.start = function () { }; - Template.prototype.preUpdate = /** - * Pre-update is called at the start of the objects update cycle, before any other updates have taken place. - */ - function () { + Template.prototype.preUpdate = function () { }; - Template.prototype.postUpdate = /** - * Post-update is called at the end of the objects update cycle, after other update logic has taken place. - */ - function () { + Template.prototype.postUpdate = function () { }; - Template.prototype.preRender = /** - * Pre-render is called at the start of the object render cycle, before any transforms have taken place. - * It happens directly AFTER a canvas context.save has happened if added to a Camera. - */ - function (camera, cameraX, cameraY, cameraWidth, cameraHeight) { + Template.prototype.preRender = function (camera, cameraX, cameraY, cameraWidth, cameraHeight) { }; - Template.prototype.render = /** - * render is called during the objects render cycle, right after all transforms have finished, but before any children/image data is rendered. - */ - function (camera, cameraX, cameraY, cameraWidth, cameraHeight) { + Template.prototype.render = function (camera, cameraX, cameraY, cameraWidth, cameraHeight) { }; - Template.prototype.postRender = /** - * Post-render is called during the objects render cycle, after the children/image data has been rendered. - * It happens directly BEFORE a canvas context.restore has happened if added to a Camera. - */ - function (camera, cameraX, cameraY, cameraWidth, cameraHeight) { + Template.prototype.postRender = function (camera, cameraX, cameraY, cameraWidth, cameraHeight) { }; return Template; })(); @@ -178,13 +114,6 @@ var Phaser; var Phaser; (function (Phaser) { (function (FX) { - /// - /** - * Phaser - FX - Camera - Mirror - * - * Creates a mirror effect for a camera. - * Can mirror the camera image horizontally, vertically or both with an optional fill color overlay. - */ (function (Camera) { var Mirror = (function () { function Mirror(game, parent) { @@ -199,11 +128,7 @@ var Phaser; this._canvas.height = parent.height; this._context = this._canvas.getContext('2d'); } - Mirror.prototype.start = /** - * This is the rectangular region to grab from the Camera used in the Mirror effect - * It is rendered to the Stage at Mirror.x/y (note the use of Stage coordinates, not World coordinates) - */ - function (x, y, region, fillColor) { + Mirror.prototype.start = function (x, y, region, fillColor) { if (typeof fillColor === "undefined") { fillColor = 'rgba(0, 0, 100, 0.5)'; } this.x = x; this.y = y; @@ -216,15 +141,7 @@ var Phaser; this._context.fillStyle = this._mirrorColor; } }; - Mirror.prototype.postRender = /** - * Post-render is called during the objects render cycle, after the children/image data has been rendered. - * It happens directly BEFORE a canvas context.restore has happened if added to a Camera. - */ - function (camera, cameraX, cameraY, cameraWidth, cameraHeight) { - //if (this.cls) - //{ - // this._context.clearRect(0, 0, this._mirrorWidth, this._mirrorHeight); - //} + Mirror.prototype.postRender = function (camera, cameraX, cameraY, cameraWidth, cameraHeight) { this._sx = cameraX + this._mirrorX; this._sy = cameraY + this._mirrorY; if(this.flipX == true && this.flipY == false) { @@ -232,16 +149,7 @@ var Phaser; } else if(this.flipY == true && this.flipX == false) { this._sy = 0; } - this._context.drawImage(this._game.stage.canvas, // Source Image - this._sx, // Source X (location within the source image) - this._sy, // Source Y - this._mirrorWidth, // Source Width - this._mirrorHeight, // Source Height - 0, // Destination X (where on the canvas it'll be drawn) - 0, // Destination Y - this._mirrorWidth, // Destination Width (always same as Source Width unless scaled) - this._mirrorHeight); - // Destination Height (always same as Source Height unless scaled) + this._context.drawImage(this._game.stage.canvas, this._sx, this._sy, this._mirrorWidth, this._mirrorHeight, 0, 0, this._mirrorWidth, this._mirrorHeight); if(this._mirrorColor) { this._context.fillRect(0, 0, this._mirrorWidth, this._mirrorHeight); } @@ -267,49 +175,19 @@ var Phaser; var Phaser; (function (Phaser) { (function (FX) { - /// - /** - * Phaser - FX - Camera - Shadow - * - * Creates a drop-shadow effect on the camera window. - */ (function (Camera) { var Shadow = (function () { function Shadow(game, parent) { - /** - * Render camera shadow or not. (default is false) - * @type {boolean} - */ this.showShadow = false; - /** - * Color of shadow, in css color string. - * @type {string} - */ this.shadowColor = 'rgb(0,0,0)'; - /** - * Blur factor of shadow. - * @type {number} - */ this.shadowBlur = 10; - /** - * Offset of the shadow from camera's position. - * @type {Point} - */ this.shadowOffset = new Phaser.Point(4, 4); this._game = game; this._parent = parent; } - Shadow.prototype.start = /** - * You can name the function that starts the effect whatever you like, but we used 'start' in our effects. - */ - function () { + Shadow.prototype.start = function () { }; - Shadow.prototype.preRender = /** - * Pre-render is called at the start of the object render cycle, before any transforms have taken place. - * It happens directly AFTER a canvas context.save has happened if added to a Camera. - */ - function (camera, cameraX, cameraY, cameraWidth, cameraHeight) { - // Shadow + Shadow.prototype.preRender = function (camera, cameraX, cameraY, cameraWidth, cameraHeight) { if(this.showShadow == true) { this._game.stage.context.shadowColor = this.shadowColor; this._game.stage.context.shadowBlur = this.shadowBlur; @@ -317,11 +195,7 @@ var Phaser; this._game.stage.context.shadowOffsetY = this.shadowOffset.y; } }; - Shadow.prototype.render = /** - * render is called during the objects render cycle, right after all transforms have finished, but before any children/image data is rendered. - */ - function (camera, cameraX, cameraY, cameraWidth, cameraHeight) { - // Shadow off + Shadow.prototype.render = function (camera, cameraX, cameraY, cameraWidth, cameraHeight) { if(this.showShadow == true) { this._game.stage.context.shadowBlur = 0; this._game.stage.context.shadowOffsetX = 0; @@ -339,12 +213,6 @@ var Phaser; var Phaser; (function (Phaser) { (function (FX) { - /// - /** - * Phaser - FX - Camera - Scanlines - * - * Give your game that classic retro feel! - */ (function (Camera) { var Scanlines = (function () { function Scanlines(game, parent) { @@ -370,12 +238,6 @@ var Phaser; var Phaser; (function (Phaser) { (function (FX) { - /// - /** - * Phaser - FX - Camera - Shake - * - * A simple camera shake effect. - */ (function (Camera) { var Shake = (function () { function Shake(game, camera) { @@ -392,16 +254,7 @@ var Phaser; Shake.SHAKE_BOTH_AXES = 0; Shake.SHAKE_HORIZONTAL_ONLY = 1; Shake.SHAKE_VERTICAL_ONLY = 2; - Shake.prototype.start = /** - * A simple camera shake effect. - * - * @param Intensity Percentage of screen size representing the maximum distance that the screen can move while shaking. - * @param Duration The length in seconds that the shaking effect should last. - * @param OnComplete A function you want to run when the shake effect finishes. - * @param Force Force the effect to reset (default = true, unlike flash() and fade()!). - * @param Direction Whether to shake on both axes, just up and down, or just side to side (use class constants SHAKE_BOTH_AXES, SHAKE_VERTICAL_ONLY, or SHAKE_HORIZONTAL_ONLY). - */ - function (intensity, duration, onComplete, force, direction) { + Shake.prototype.start = function (intensity, duration, onComplete, force, direction) { if (typeof intensity === "undefined") { intensity = 0.05; } if (typeof duration === "undefined") { duration = 0.5; } if (typeof onComplete === "undefined") { onComplete = null; } @@ -410,7 +263,6 @@ var Phaser; if(!force && ((this._fxShakeOffset.x != 0) || (this._fxShakeOffset.y != 0))) { return; } - // If a shake is not already running we need to store the offsets here if(this._fxShakeOffset.x == 0 && this._fxShakeOffset.y == 0) { this._fxShakePrevX = this._parent.x; this._fxShakePrevY = this._parent.y; @@ -422,7 +274,6 @@ var Phaser; this._fxShakeOffset.setTo(0, 0); }; Shake.prototype.postUpdate = function () { - // Update the "shake" special effect if(this._fxShakeDuration > 0) { this._fxShakeDuration -= this._game.time.elapsed; if(this._game.math.roundTo(this._fxShakeDuration, -2) <= 0) { @@ -435,11 +286,9 @@ var Phaser; } } else { if((this._fxShakeDirection == Shake.SHAKE_BOTH_AXES) || (this._fxShakeDirection == Shake.SHAKE_HORIZONTAL_ONLY)) { - //this._fxShakeOffset.x = ((this._game.math.random() * this._fxShakeIntensity * this.worldView.width * 2 - this._fxShakeIntensity * this.worldView.width) * this._zoom; this._fxShakeOffset.x = (this._game.math.random() * this._fxShakeIntensity * this._parent.worldView.width * 2 - this._fxShakeIntensity * this._parent.worldView.width); } if((this._fxShakeDirection == Shake.SHAKE_BOTH_AXES) || (this._fxShakeDirection == Shake.SHAKE_VERTICAL_ONLY)) { - //this._fxShakeOffset.y = (this._game.math.random() * this._fxShakeIntensity * this.worldView.height * 2 - this._fxShakeIntensity * this.worldView.height) * this._zoom; this._fxShakeOffset.y = (this._game.math.random() * this._fxShakeIntensity * this._parent.worldView.height * 2 - this._fxShakeIntensity * this._parent.worldView.height); } } @@ -462,12 +311,6 @@ var Phaser; var Phaser; (function (Phaser) { (function (FX) { - /// - /** - * Phaser - FX - Camera - Fade - * - * The camera is filled with the given color and returns to normal at the given duration. - */ (function (Camera) { var Fade = (function () { function Fade(game) { @@ -476,21 +319,12 @@ var Phaser; this._fxFadeAlpha = 0; this._game = game; } - Fade.prototype.start = /** - * The camera is gradually filled with this color. - * - * @param Color The color you want to use in 0xRRGGBB format, i.e. 0xffffff for white. - * @param Duration How long it takes for the flash to fade. - * @param OnComplete An optional function you want to run when the flash finishes. Set to null for no callback. - * @param Force Force an already running flash effect to reset. - */ - function (color, duration, onComplete, force) { + Fade.prototype.start = function (color, duration, onComplete, force) { if (typeof color === "undefined") { color = 0x000000; } if (typeof duration === "undefined") { duration = 1; } if (typeof onComplete === "undefined") { onComplete = null; } if (typeof force === "undefined") { force = false; } if(force === false && this._fxFadeAlpha > 0) { - // You can't fade again unless you force it return; } if(duration <= 0) { @@ -505,7 +339,6 @@ var Phaser; this._fxFadeComplete = onComplete; }; Fade.prototype.postUpdate = function () { - // Update the Fade effect if(this._fxFadeAlpha > 0) { this._fxFadeAlpha += this._game.time.elapsed / this._fxFadeDuration; if(this._game.math.roundTo(this._fxFadeAlpha, -2) >= 1) { @@ -517,7 +350,6 @@ var Phaser; } }; Fade.prototype.postRender = function (camera, cameraX, cameraY, cameraWidth, cameraHeight) { - // "Fade" FX if(this._fxFadeAlpha > 0) { this._game.stage.context.fillStyle = this._fxFadeColor + this._fxFadeAlpha + ')'; this._game.stage.context.fillRect(cameraX, cameraY, cameraWidth, cameraHeight); diff --git a/Tests/phaser.js b/Tests/phaser.js index 661e4d30..0df38b19 100644 --- a/Tests/phaser.js +++ b/Tests/phaser.js @@ -760,6 +760,7 @@ var Phaser; if (typeof y === "undefined") { y = 0; } this.x = x; this.y = y; + return this; } Vec2.prototype.copyFrom = /** * Copies the x and y properties from any given object to this Vec2. @@ -3086,6 +3087,7 @@ var Phaser; (function (Phaser) { /// /// + /// /** * Phaser - Components - Transform */ @@ -3138,7 +3140,7 @@ var Phaser; this._halfSize.y = this.parent.height / 2; this._offset.x = this.origin.x * this.parent.width; this._offset.y = this.origin.y * this.parent.height; - this._angle = Math.atan2(this.halfHeight - this._offset.y, this.halfWidth - this._offset.x); + this._angle = Math.atan2(this.halfHeight - this._offset.x, this.halfWidth - this._offset.y); this._distance = Math.sqrt(((this._offset.x - this._halfSize.x) * (this._offset.x - this._halfSize.x)) + ((this._offset.y - this._halfSize.y) * (this._offset.y - this._halfSize.y))); this._size.x = this.parent.width; this._size.y = this.parent.height; @@ -4123,7 +4125,7 @@ var Phaser; * @return {Vec2} A Vec2. */ function normalRightHand(a, out) { - if (typeof out === "undefined") { out = this; } + if (typeof out === "undefined") { out = new Phaser.Vec2(); } return out.setTo(a.y * -1, a.x); }; Vec2Utils.normalize = /** @@ -6466,7 +6468,7 @@ var Phaser; // 5) Iterative velocity constraints solver this.velocitySolver(velocityIterations); Physics.Manager.dump("Velocity Solvers", this.bodies[1]); - // 6) Intergrate position + // 6) Integrate position for(var i = 0; i < this._bl; i++) { if(this.bodies[i] && this.bodies[i].isDynamic && this.bodies[i].isAwake) { this.bodies[i].updatePosition(this._delta); @@ -6597,12 +6599,15 @@ var Phaser; __extends(Box, _super); // Give in pixels function Box(x, y, width, height) { + console.log('Box px', x, y, width, height); x = Physics.Manager.pixelsToMeters(x); y = Physics.Manager.pixelsToMeters(y); width = Physics.Manager.pixelsToMeters(width); height = Physics.Manager.pixelsToMeters(height); + console.log('Box m', x, y, width, height); var hw = width * 0.5; var hh = height * 0.5; + console.log('Box hh', hw, hh); _super.call(this, [ { x: -hw + x, @@ -6932,7 +6937,7 @@ var Phaser; Physics.Manager.write('p: ' + this.position.toString()); Physics.Manager.write('xf: ' + this.transform.toString()); this.bounds.clear(); - for(var i = 0; i < this.shapes.length; i++) { + for(var i = 0; i < this.shapesLength; i++) { var shape = this.shapes[i]; shape.cacheData(this.transform); this.bounds.addBounds(shape.bounds); @@ -13573,14 +13578,16 @@ var Phaser; * @param y {number} Y position of the new sprite. * @param [key] {string} The image key as defined in the Game.Cache to use as the texture for this sprite * @param [frame] {string|number} If the sprite uses an image from a texture atlas or sprite sheet you can pass the frame here. Either a number for a frame ID or a string for a frame name. + * @param [bodyType] {number} The physics body type of the object (defaults to BODY_DYNAMIC) * @param [shapeType] The default body shape is either 0 for a Box or 1 for a Circle. See Sprite.body.addShape for custom shapes (polygons, etc) * @returns {Sprite} The newly created sprite object. */ - function (x, y, key, frame, shapeType) { + function (x, y, key, frame, bodyType, shapeType) { if (typeof key === "undefined") { key = ''; } if (typeof frame === "undefined") { frame = null; } + if (typeof bodyType === "undefined") { bodyType = Phaser.Types.BODY_DYNAMIC; } if (typeof shapeType === "undefined") { shapeType = 0; } - return this._world.group.add(new Phaser.Sprite(this._game, x, y, key, frame, Phaser.Types.BODY_DYNAMIC, shapeType)); + return this._world.group.add(new Phaser.Sprite(this._game, x, y, key, frame, bodyType, shapeType)); }; GameObjectFactory.prototype.dynamicTexture = /** * Create a new DynamicTexture with specific size. @@ -18582,6 +18589,32 @@ var Phaser; DebugUtils.context.fillText('cx: ' + sprite.cameraView.x + ' cy: ' + sprite.cameraView.y + ' cw: ' + sprite.cameraView.width + ' ch: ' + sprite.cameraView.height + ' cb: ' + sprite.cameraView.bottom + ' cr: ' + sprite.cameraView.right, x, y + 70); DebugUtils.context.fillText('inCamera: ' + DebugUtils.game.renderer.inCamera(DebugUtils.game.camera, sprite), x, y + 84); }; + DebugUtils.renderPhysicsBodyInfo = /** + * Render debug infos. (including name, bounds info, position and some other properties) + * @param x {number} X position of the debug info to be rendered. + * @param y {number} Y position of the debug info to be rendered. + * @param [color] {number} color of the debug info to be rendered. (format is css color string) + */ + function renderPhysicsBodyInfo(body, x, y, color) { + if (typeof color === "undefined") { color = 'rgb(255,255,255)'; } + DebugUtils.context.fillStyle = color; + DebugUtils.context.fillText('Body ID: ' + body.name, x, y); + DebugUtils.context.fillText('Position x: ' + body.position.x.toFixed(1) + ' y: ' + body.position.y.toFixed(1) + ' rotation: ' + body.angle.toFixed(1), x, y + 14); + DebugUtils.context.fillText('World x: ' + (body.position.x * 50).toFixed(1) + ' y: ' + (body.position.y * 50).toFixed(1), x, y + 28); + DebugUtils.context.fillText('Velocity x: ' + body.velocity.x.toFixed(1) + ' y: ' + body.velocity.y.toFixed(1), x, y + 42); + if(body.shapes[0].verts.length > 0) { + DebugUtils.context.fillText('Vert 1 x: ' + (body.shapes[0].verts[0].x * 50) + ' y: ' + (body.shapes[0].verts[0].y * 50), x, y + 56); + DebugUtils.context.fillText('Vert 2 x: ' + (body.shapes[0].verts[1].x * 50) + ' y: ' + (body.shapes[0].verts[1].y * 50), x, y + 70); + DebugUtils.context.fillText('Vert 3 x: ' + (body.shapes[0].tverts[2].x * 50) + ' y: ' + (body.shapes[0].tverts[2].y * 50), x, y + 84); + DebugUtils.context.fillText('Vert 4 x: ' + (body.shapes[0].tverts[3].x * 50) + ' y: ' + (body.shapes[0].tverts[3].y * 50), x, y + 98); + /* + DebugUtils.context.fillText('Vert 1 x: ' + body.shapes[0].verts[0].x.toFixed(1) + ' y: ' + body.shapes[0].verts[0].y.toFixed(1), x, y + 56); + DebugUtils.context.fillText('Vert 2 x: ' + body.shapes[0].verts[1].x.toFixed(1) + ' y: ' + body.shapes[0].verts[1].y.toFixed(1), x, y + 70); + DebugUtils.context.fillText('Vert 3 x: ' + body.shapes[0].verts[2].x.toFixed(1) + ' y: ' + body.shapes[0].verts[2].y.toFixed(1), x, y + 84); + DebugUtils.context.fillText('Vert 4 x: ' + body.shapes[0].verts[3].x.toFixed(1) + ' y: ' + body.shapes[0].verts[3].y.toFixed(1), x, y + 98); + */ + } + }; DebugUtils.renderSpriteBounds = function renderSpriteBounds(sprite, camera, color) { if (typeof camera === "undefined") { camera = null; } if (typeof color === "undefined") { color = 'rgba(0,255,0,0.2)'; } @@ -18597,15 +18630,18 @@ var Phaser; if (typeof lineWidth === "undefined") { lineWidth = 1; } if (typeof fillStyle === "undefined") { fillStyle = 'rgba(0,255,0,0.2)'; } if (typeof sleepStyle === "undefined") { sleepStyle = 'rgba(100,100,100,0.2)'; } - for(var s = 0; s < body.shapes.length; s++) { + for(var s = 0; s < body.shapesLength; s++) { DebugUtils.context.beginPath(); if(body.shapes[s].type == Phaser.Physics.Manager.SHAPE_TYPE_POLY) { var verts = body.shapes[s].tverts; - DebugUtils.context.moveTo((body.position.x + verts[0].x) * 50, (body.position.y + verts[0].y) * 50); - for(var i = 0; i < verts.length; i++) { - DebugUtils.context.lineTo((body.position.x + verts[i].x) * 50, (body.position.y + verts[i].y) * 50); + // DebugUtils.context.moveTo(body.position.x * 50 + verts[0].x, body.position.y * 50 + verts[0].y); + DebugUtils.context.moveTo(verts[0].x * 50, verts[0].y * 50); + for(var i = 1; i < verts.length; i++) { + // DebugUtils.context.lineTo(body.position.x * 50 + verts[i].x, body.position.y * 50 + verts[i].y); + DebugUtils.context.lineTo(verts[i].x * 50, verts[i].y * 50); } - DebugUtils.context.lineTo((body.position.x + verts[verts.length - 1].x) * 50, (body.position.y + verts[verts.length - 1].y) * 50); + // DebugUtils.context.lineTo(body.position.x * 50 + verts[0].x, body.position.y * 50 + verts[0].y); + DebugUtils.context.lineTo(verts[0].x * 50, verts[0].y * 50); } else if(body.shapes[s].type == Phaser.Physics.Manager.SHAPE_TYPE_CIRCLE) { var circle = body.shapes[s]; DebugUtils.context.arc(circle.tc.x * 50, circle.tc.y * 50, circle.radius * 50, 0, Math.PI * 2, false); @@ -19058,6 +19094,84 @@ var Phaser; })(); Phaser.Game = Game; })(Phaser || (Phaser = {})); +/// +/** +* Phaser - State +* +* This is a base State class which can be extended if you are creating your game using TypeScript. +*/ +var Phaser; +(function (Phaser) { + var State = (function () { + /** + * State constructor + * Create a new State. + */ + function State(game) { + this.game = game; + this.add = game.add; + this.camera = game.camera; + this.cache = game.cache; + this.input = game.input; + this.load = game.load; + this.math = game.math; + this.motion = game.motion; + this.sound = game.sound; + this.stage = game.stage; + this.time = game.time; + this.tweens = game.tweens; + this.world = game.world; + } + State.prototype.init = // Override these in your own States + /** + * Override this method to add some load operations. + * If you need to use the loader, you may need to use them here. + */ + function () { + }; + State.prototype.create = /** + * This method is called after the game engine successfully switches states. + * Feel free to add any setup code here.(Do not load anything here, override init() instead) + */ + function () { + }; + State.prototype.update = /** + * Put update logic here. + */ + function () { + }; + State.prototype.render = /** + * Put render operations here. + */ + function () { + }; + State.prototype.paused = /** + * This method will be called when game paused. + */ + function () { + }; + State.prototype.destroy = /** + * This method will be called when the state is destroyed + */ + function () { + }; + return State; + })(); + Phaser.State = State; + /** + * Checks for overlaps between two objects using the world QuadTree. Can be GameObject vs. GameObject, GameObject vs. Group or Group vs. Group. + * Note: Does not take the objects scrollFactor into account. All overlaps are check in world space. + * @param object1 The first GameObject or Group to check. If null the world.group is used. + * @param object2 The second GameObject or Group to check. + * @param notifyCallback A callback function that is called if the objects overlap. The two objects will be passed to this function in the same order in which you passed them to Collision.overlap. + * @param processCallback A callback function that lets you perform additional checks against the two objects if they overlap. If this is set then notifyCallback will only be called if processCallback returns true. + * @param context The context in which the callbacks will be called + * @returns {boolean} true if the objects overlap, otherwise false. + */ + //public collide(objectOrGroup1 = null, objectOrGroup2 = null, notifyCallback = null, context? = this.game.callbackContext): bool { + // return this.collision.overlap(objectOrGroup1, objectOrGroup2, notifyCallback, Collision.separate, context); + //} + })(Phaser || (Phaser = {})); var Phaser; (function (Phaser) { /** @@ -19400,6 +19514,206 @@ var Phaser; Phaser.Line = Line; })(Phaser || (Phaser = {})); /// +/** +* Phaser - IntersectResult +* +* A light-weight result object to hold the results of an intersection. For when you need more than just true/false. +*/ +var Phaser; +(function (Phaser) { + var IntersectResult = (function () { + function IntersectResult() { + /** + * Did they intersect or not? + * @property result + * @type {Boolean} + */ + this.result = false; + } + IntersectResult.prototype.setTo = /** + * + * @method setTo + * @param {Number} x1 + * @param {Number} y1 + * @param {Number} [x2] + * @param {Number} [y2] + * @param {Number} [width] + * @param {Number} [height] + */ + function (x1, y1, x2, y2, width, height) { + if (typeof x2 === "undefined") { x2 = 0; } + if (typeof y2 === "undefined") { y2 = 0; } + if (typeof width === "undefined") { width = 0; } + if (typeof height === "undefined") { height = 0; } + this.x = x1; + this.y = y1; + this.x1 = x1; + this.y1 = y1; + this.x2 = x2; + this.y2 = y2; + this.width = width; + this.height = height; + }; + return IntersectResult; + })(); + Phaser.IntersectResult = IntersectResult; +})(Phaser || (Phaser = {})); +/// +/// +/// +/** +* Phaser - Mat3Utils +* +* A collection of methods useful for manipulating and performing operations on Mat3 objects. +* +*/ +var Phaser; +(function (Phaser) { + var Mat3Utils = (function () { + function Mat3Utils() { } + Mat3Utils.transpose = /** + * Transpose the values of a Mat3 + **/ + function transpose(source, dest) { + if (typeof dest === "undefined") { dest = null; } + if(dest === null) { + // Transpose ourselves + var a01 = source.data[1]; + var a02 = source.data[2]; + var a12 = source.data[5]; + source.data[1] = source.data[3]; + source.data[2] = source.data[6]; + source.data[3] = a01; + source.data[5] = source.data[7]; + source.data[6] = a02; + source.data[7] = a12; + } else { + source.data[0] = dest.data[0]; + source.data[1] = dest.data[3]; + source.data[2] = dest.data[6]; + source.data[3] = dest.data[1]; + source.data[4] = dest.data[4]; + source.data[5] = dest.data[7]; + source.data[6] = dest.data[2]; + source.data[7] = dest.data[5]; + source.data[8] = dest.data[8]; + } + return source; + }; + Mat3Utils.invert = /** + * Inverts a Mat3 + **/ + function invert(source) { + var a00 = source.data[0]; + var a01 = source.data[1]; + var a02 = source.data[2]; + var a10 = source.data[3]; + var a11 = source.data[4]; + var a12 = source.data[5]; + var a20 = source.data[6]; + var a21 = source.data[7]; + var a22 = source.data[8]; + var b01 = a22 * a11 - a12 * a21; + var b11 = -a22 * a10 + a12 * a20; + var b21 = a21 * a10 - a11 * a20; + // Determinant + var det = a00 * b01 + a01 * b11 + a02 * b21; + if(!det) { + return null; + } + det = 1.0 / det; + source.data[0] = b01 * det; + source.data[1] = (-a22 * a01 + a02 * a21) * det; + source.data[2] = (a12 * a01 - a02 * a11) * det; + source.data[3] = b11 * det; + source.data[4] = (a22 * a00 - a02 * a20) * det; + source.data[5] = (-a12 * a00 + a02 * a10) * det; + source.data[6] = b21 * det; + source.data[7] = (-a21 * a00 + a01 * a20) * det; + source.data[8] = (a11 * a00 - a01 * a10) * det; + return source; + }; + Mat3Utils.adjoint = /** + * Calculates the adjugate of a Mat3 + **/ + function adjoint(source) { + var a00 = source.data[0]; + var a01 = source.data[1]; + var a02 = source.data[2]; + var a10 = source.data[3]; + var a11 = source.data[4]; + var a12 = source.data[5]; + var a20 = source.data[6]; + var a21 = source.data[7]; + var a22 = source.data[8]; + source.data[0] = (a11 * a22 - a12 * a21); + source.data[1] = (a02 * a21 - a01 * a22); + source.data[2] = (a01 * a12 - a02 * a11); + source.data[3] = (a12 * a20 - a10 * a22); + source.data[4] = (a00 * a22 - a02 * a20); + source.data[5] = (a02 * a10 - a00 * a12); + source.data[6] = (a10 * a21 - a11 * a20); + source.data[7] = (a01 * a20 - a00 * a21); + source.data[8] = (a00 * a11 - a01 * a10); + return source; + }; + Mat3Utils.determinant = /** + * Calculates the adjugate of a Mat3 + **/ + function determinant(source) { + var a00 = source.data[0]; + var a01 = source.data[1]; + var a02 = source.data[2]; + var a10 = source.data[3]; + var a11 = source.data[4]; + var a12 = source.data[5]; + var a20 = source.data[6]; + var a21 = source.data[7]; + var a22 = source.data[8]; + return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20); + }; + Mat3Utils.multiply = /** + * Multiplies two Mat3s + **/ + function multiply(source, b) { + var a00 = source.data[0]; + var a01 = source.data[1]; + var a02 = source.data[2]; + var a10 = source.data[3]; + var a11 = source.data[4]; + var a12 = source.data[5]; + var a20 = source.data[6]; + var a21 = source.data[7]; + var a22 = source.data[8]; + var b00 = b.data[0]; + var b01 = b.data[1]; + var b02 = b.data[2]; + var b10 = b.data[3]; + var b11 = b.data[4]; + var b12 = b.data[5]; + var b20 = b.data[6]; + var b21 = b.data[7]; + var b22 = b.data[8]; + source.data[0] = b00 * a00 + b01 * a10 + b02 * a20; + source.data[1] = b00 * a01 + b01 * a11 + b02 * a21; + source.data[2] = b00 * a02 + b01 * a12 + b02 * a22; + source.data[3] = b10 * a00 + b11 * a10 + b12 * a20; + source.data[4] = b10 * a01 + b11 * a11 + b12 * a21; + source.data[5] = b10 * a02 + b11 * a12 + b12 * a22; + source.data[6] = b20 * a00 + b21 * a10 + b22 * a20; + source.data[7] = b20 * a01 + b21 * a11 + b22 * a21; + source.data[8] = b20 * a02 + b21 * a12 + b22 * a22; + return source; + }; + Mat3Utils.fromQuaternion = function fromQuaternion() { + }; + Mat3Utils.normalFromMat4 = function normalFromMat4() { + }; + return Mat3Utils; + })(); + Phaser.Mat3Utils = Mat3Utils; +})(Phaser || (Phaser = {})); +/// /// /// /// @@ -19563,161 +19877,6 @@ var Phaser; Phaser.CircleUtils = CircleUtils; })(Phaser || (Phaser = {})); /// -/// -/// -/** -* Phaser - Mat3Utils -* -* A collection of methods useful for manipulating and performing operations on Mat3 objects. -* -*/ -var Phaser; -(function (Phaser) { - var Mat3Utils = (function () { - function Mat3Utils() { } - Mat3Utils.transpose = /** - * Transpose the values of a Mat3 - **/ - function transpose(source, dest) { - if (typeof dest === "undefined") { dest = null; } - if(dest === null) { - // Transpose ourselves - var a01 = source.data[1]; - var a02 = source.data[2]; - var a12 = source.data[5]; - source.data[1] = source.data[3]; - source.data[2] = source.data[6]; - source.data[3] = a01; - source.data[5] = source.data[7]; - source.data[6] = a02; - source.data[7] = a12; - } else { - source.data[0] = dest.data[0]; - source.data[1] = dest.data[3]; - source.data[2] = dest.data[6]; - source.data[3] = dest.data[1]; - source.data[4] = dest.data[4]; - source.data[5] = dest.data[7]; - source.data[6] = dest.data[2]; - source.data[7] = dest.data[5]; - source.data[8] = dest.data[8]; - } - return source; - }; - Mat3Utils.invert = /** - * Inverts a Mat3 - **/ - function invert(source) { - var a00 = source.data[0]; - var a01 = source.data[1]; - var a02 = source.data[2]; - var a10 = source.data[3]; - var a11 = source.data[4]; - var a12 = source.data[5]; - var a20 = source.data[6]; - var a21 = source.data[7]; - var a22 = source.data[8]; - var b01 = a22 * a11 - a12 * a21; - var b11 = -a22 * a10 + a12 * a20; - var b21 = a21 * a10 - a11 * a20; - // Determinant - var det = a00 * b01 + a01 * b11 + a02 * b21; - if(!det) { - return null; - } - det = 1.0 / det; - source.data[0] = b01 * det; - source.data[1] = (-a22 * a01 + a02 * a21) * det; - source.data[2] = (a12 * a01 - a02 * a11) * det; - source.data[3] = b11 * det; - source.data[4] = (a22 * a00 - a02 * a20) * det; - source.data[5] = (-a12 * a00 + a02 * a10) * det; - source.data[6] = b21 * det; - source.data[7] = (-a21 * a00 + a01 * a20) * det; - source.data[8] = (a11 * a00 - a01 * a10) * det; - return source; - }; - Mat3Utils.adjoint = /** - * Calculates the adjugate of a Mat3 - **/ - function adjoint(source) { - var a00 = source.data[0]; - var a01 = source.data[1]; - var a02 = source.data[2]; - var a10 = source.data[3]; - var a11 = source.data[4]; - var a12 = source.data[5]; - var a20 = source.data[6]; - var a21 = source.data[7]; - var a22 = source.data[8]; - source.data[0] = (a11 * a22 - a12 * a21); - source.data[1] = (a02 * a21 - a01 * a22); - source.data[2] = (a01 * a12 - a02 * a11); - source.data[3] = (a12 * a20 - a10 * a22); - source.data[4] = (a00 * a22 - a02 * a20); - source.data[5] = (a02 * a10 - a00 * a12); - source.data[6] = (a10 * a21 - a11 * a20); - source.data[7] = (a01 * a20 - a00 * a21); - source.data[8] = (a00 * a11 - a01 * a10); - return source; - }; - Mat3Utils.determinant = /** - * Calculates the adjugate of a Mat3 - **/ - function determinant(source) { - var a00 = source.data[0]; - var a01 = source.data[1]; - var a02 = source.data[2]; - var a10 = source.data[3]; - var a11 = source.data[4]; - var a12 = source.data[5]; - var a20 = source.data[6]; - var a21 = source.data[7]; - var a22 = source.data[8]; - return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20); - }; - Mat3Utils.multiply = /** - * Multiplies two Mat3s - **/ - function multiply(source, b) { - var a00 = source.data[0]; - var a01 = source.data[1]; - var a02 = source.data[2]; - var a10 = source.data[3]; - var a11 = source.data[4]; - var a12 = source.data[5]; - var a20 = source.data[6]; - var a21 = source.data[7]; - var a22 = source.data[8]; - var b00 = b.data[0]; - var b01 = b.data[1]; - var b02 = b.data[2]; - var b10 = b.data[3]; - var b11 = b.data[4]; - var b12 = b.data[5]; - var b20 = b.data[6]; - var b21 = b.data[7]; - var b22 = b.data[8]; - source.data[0] = b00 * a00 + b01 * a10 + b02 * a20; - source.data[1] = b00 * a01 + b01 * a11 + b02 * a21; - source.data[2] = b00 * a02 + b01 * a12 + b02 * a22; - source.data[3] = b10 * a00 + b11 * a10 + b12 * a20; - source.data[4] = b10 * a01 + b11 * a11 + b12 * a21; - source.data[5] = b10 * a02 + b11 * a12 + b12 * a22; - source.data[6] = b20 * a00 + b21 * a10 + b22 * a20; - source.data[7] = b20 * a01 + b21 * a11 + b22 * a21; - source.data[8] = b20 * a02 + b21 * a12 + b22 * a22; - return source; - }; - Mat3Utils.fromQuaternion = function fromQuaternion() { - }; - Mat3Utils.normalFromMat4 = function normalFromMat4() { - }; - return Mat3Utils; - })(); - Phaser.Mat3Utils = Mat3Utils; -})(Phaser || (Phaser = {})); -/// /// /// /// @@ -19745,126 +19904,3 @@ var Phaser; })(); Phaser.PixelUtils = PixelUtils; })(Phaser || (Phaser = {})); -/// -/** -* Phaser - IntersectResult -* -* A light-weight result object to hold the results of an intersection. For when you need more than just true/false. -*/ -var Phaser; -(function (Phaser) { - var IntersectResult = (function () { - function IntersectResult() { - /** - * Did they intersect or not? - * @property result - * @type {Boolean} - */ - this.result = false; - } - IntersectResult.prototype.setTo = /** - * - * @method setTo - * @param {Number} x1 - * @param {Number} y1 - * @param {Number} [x2] - * @param {Number} [y2] - * @param {Number} [width] - * @param {Number} [height] - */ - function (x1, y1, x2, y2, width, height) { - if (typeof x2 === "undefined") { x2 = 0; } - if (typeof y2 === "undefined") { y2 = 0; } - if (typeof width === "undefined") { width = 0; } - if (typeof height === "undefined") { height = 0; } - this.x = x1; - this.y = y1; - this.x1 = x1; - this.y1 = y1; - this.x2 = x2; - this.y2 = y2; - this.width = width; - this.height = height; - }; - return IntersectResult; - })(); - Phaser.IntersectResult = IntersectResult; -})(Phaser || (Phaser = {})); -/// -/** -* Phaser - State -* -* This is a base State class which can be extended if you are creating your game using TypeScript. -*/ -var Phaser; -(function (Phaser) { - var State = (function () { - /** - * State constructor - * Create a new State. - */ - function State(game) { - this.game = game; - this.add = game.add; - this.camera = game.camera; - this.cache = game.cache; - this.input = game.input; - this.load = game.load; - this.math = game.math; - this.motion = game.motion; - this.sound = game.sound; - this.stage = game.stage; - this.time = game.time; - this.tweens = game.tweens; - this.world = game.world; - } - State.prototype.init = // Override these in your own States - /** - * Override this method to add some load operations. - * If you need to use the loader, you may need to use them here. - */ - function () { - }; - State.prototype.create = /** - * This method is called after the game engine successfully switches states. - * Feel free to add any setup code here.(Do not load anything here, override init() instead) - */ - function () { - }; - State.prototype.update = /** - * Put update logic here. - */ - function () { - }; - State.prototype.render = /** - * Put render operations here. - */ - function () { - }; - State.prototype.paused = /** - * This method will be called when game paused. - */ - function () { - }; - State.prototype.destroy = /** - * This method will be called when the state is destroyed - */ - function () { - }; - return State; - })(); - Phaser.State = State; - /** - * Checks for overlaps between two objects using the world QuadTree. Can be GameObject vs. GameObject, GameObject vs. Group or Group vs. Group. - * Note: Does not take the objects scrollFactor into account. All overlaps are check in world space. - * @param object1 The first GameObject or Group to check. If null the world.group is used. - * @param object2 The second GameObject or Group to check. - * @param notifyCallback A callback function that is called if the objects overlap. The two objects will be passed to this function in the same order in which you passed them to Collision.overlap. - * @param processCallback A callback function that lets you perform additional checks against the two objects if they overlap. If this is set then notifyCallback will only be called if processCallback returns true. - * @param context The context in which the callbacks will be called - * @returns {boolean} true if the objects overlap, otherwise false. - */ - //public collide(objectOrGroup1 = null, objectOrGroup2 = null, notifyCallback = null, context? = this.game.callbackContext): bool { - // return this.collision.overlap(objectOrGroup1, objectOrGroup2, notifyCallback, Collision.separate, context); - //} - })(Phaser || (Phaser = {})); diff --git a/Tests/physics/simple test 1.js b/Tests/physics/simple test 1.js index 7ecb0802..44a660aa 100644 --- a/Tests/physics/simple test 1.js +++ b/Tests/physics/simple test 1.js @@ -1,25 +1,21 @@ -/// -(function () { - var game = new Phaser.Game(this, 'game', 800, 600, init, create, null, render); - function init() { - // Using Phasers asset loader we load up a PNG from the assets folder - game.load.image('atari', 'assets/sprites/atari130xe.png'); - game.load.image('ball', 'assets/sprites/shinyball.png'); - game.load.start(); - } - var atari; - var ball; - function create() { - // Add some gravity to the world, otherwise nothing will actually happen - game.physics.gravity.setTo(0, 10); - //atari = game.add.physicsSprite(220/2, 450, 'atari'); - atari = game.add.physicsSprite(320, 450, 'atari'); - // We'll make the atari sprite a static body, so it won't be influenced by gravity or other forces - atari.body.type = Phaser.Types.BODY_STATIC; - ball = game.add.physicsSprite(330, 0, 'ball', null, 0); - } - function render() { - Phaser.DebugUtils.renderPhysicsBody(atari.body); - Phaser.DebugUtils.renderPhysicsBody(ball.body); - } -})(); +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, null, render); + function init() { + game.load.image('atari', 'assets/sprites/atari130xe.png'); + game.load.image('ball', 'assets/sprites/shinyball.png'); + game.load.start(); + } + var atari; + var ball; + function create() { + game.physics.gravity.setTo(0, 5); + atari = game.add.physicsSprite(300, 450, 'atari', null, Phaser.Types.BODY_STATIC); + ball = game.add.physicsSprite(300 - 20, 0, 'ball'); + } + function render() { + Phaser.DebugUtils.renderPhysicsBodyInfo(atari.body, 32, 32); + Phaser.DebugUtils.renderPhysicsBodyInfo(ball.body, 320, 32); + Phaser.DebugUtils.renderPhysicsBody(atari.body); + Phaser.DebugUtils.renderPhysicsBody(ball.body); + } +})(); diff --git a/Tests/physics/simple test 1.ts b/Tests/physics/simple test 1.ts index c35cc3c1..aef0b341 100644 --- a/Tests/physics/simple test 1.ts +++ b/Tests/physics/simple test 1.ts @@ -19,19 +19,24 @@ function create() { // Add some gravity to the world, otherwise nothing will actually happen - game.physics.gravity.setTo(0, 10); + game.physics.gravity.setTo(0, 5); - //atari = game.add.physicsSprite(220/2, 450, 'atari'); - atari = game.add.physicsSprite(320, 450, 'atari'); // We'll make the atari sprite a static body, so it won't be influenced by gravity or other forces - atari.body.type = Phaser.Types.BODY_STATIC; + atari = game.add.physicsSprite(300, 450, 'atari', null, Phaser.Types.BODY_STATIC); - ball = game.add.physicsSprite(330, 0, 'ball', null, 0); + // atari = 220px width (110 = center x) + // ball = 32px width (16 = center x) + + // Ball will be a dynamic body and fall based on gravity + ball = game.add.physicsSprite(300-20, 0, 'ball'); } function render() { + Phaser.DebugUtils.renderPhysicsBodyInfo(atari.body, 32, 32); + Phaser.DebugUtils.renderPhysicsBodyInfo(ball.body, 320, 32); + Phaser.DebugUtils.renderPhysicsBody(atari.body); Phaser.DebugUtils.renderPhysicsBody(ball.body); diff --git a/build/phaser.d.ts b/build/phaser.d.ts index d09681a8..ca875925 100644 --- a/build/phaser.d.ts +++ b/build/phaser.d.ts @@ -6666,10 +6666,11 @@ module Phaser { * @param y {number} Y position of the new sprite. * @param [key] {string} The image key as defined in the Game.Cache to use as the texture for this sprite * @param [frame] {string|number} If the sprite uses an image from a texture atlas or sprite sheet you can pass the frame here. Either a number for a frame ID or a string for a frame name. + * @param [bodyType] {number} The physics body type of the object (defaults to BODY_DYNAMIC) * @param [shapeType] The default body shape is either 0 for a Box or 1 for a Circle. See Sprite.body.addShape for custom shapes (polygons, etc) * @returns {Sprite} The newly created sprite object. */ - public physicsSprite(x: number, y: number, key?: string, frame?, shapeType?: number): Sprite; + public physicsSprite(x: number, y: number, key?: string, frame?, bodyType?: number, shapeType?: number): Sprite; /** * Create a new DynamicTexture with specific size. * @@ -9300,6 +9301,13 @@ module Phaser { * @param [color] {number} color of the debug info to be rendered. (format is css color string) */ static renderSpriteInfo(sprite: Sprite, x: number, y: number, color?: string): void; + /** + * Render debug infos. (including name, bounds info, position and some other properties) + * @param x {number} X position of the debug info to be rendered. + * @param y {number} Y position of the debug info to be rendered. + * @param [color] {number} color of the debug info to be rendered. (format is css color string) + */ + static renderPhysicsBodyInfo(body: Physics.Body, x: number, y: number, color?: string): void; static renderSpriteBounds(sprite: Sprite, camera?: Camera, color?: string): void; static renderPhysicsBody(body: Physics.Body, lineWidth?: number, fillStyle?: string, sleepStyle?: string): void; } @@ -9543,6 +9551,110 @@ module Phaser { } } /** +* Phaser - State +* +* This is a base State class which can be extended if you are creating your game using TypeScript. +*/ +module Phaser { + class State { + /** + * State constructor + * Create a new State. + */ + constructor(game: Game); + /** + * Reference to Game. + */ + public game: Game; + /** + * Currently used camera. + * @type {Camera} + */ + public camera: Camera; + /** + * Reference to the assets cache. + * @type {Cache} + */ + public cache: Cache; + /** + * Reference to the GameObject Factory. + * @type {GameObjectFactory} + */ + public add: GameObjectFactory; + /** + * Reference to the input manager + * @type {Input} + */ + public input: Input; + /** + * Reference to the assets loader. + * @type {Loader} + */ + public load: Loader; + /** + * Reference to the math helper. + * @type {GameMath} + */ + public math: GameMath; + /** + * Reference to the motion helper. + * @type {Motion} + */ + public motion: Motion; + /** + * Reference to the sound manager. + * @type {SoundManager} + */ + public sound: SoundManager; + /** + * Reference to the stage. + * @type {Stage} + */ + public stage: Stage; + /** + * Reference to game clock. + * @type {Time} + */ + public time: Time; + /** + * Reference to the tween manager. + * @type {TweenManager} + */ + public tweens: TweenManager; + /** + * Reference to the world. + * @type {World} + */ + public world: World; + /** + * Override this method to add some load operations. + * If you need to use the loader, you may need to use them here. + */ + public init(): void; + /** + * This method is called after the game engine successfully switches states. + * Feel free to add any setup code here.(Do not load anything here, override init() instead) + */ + public create(): void; + /** + * Put update logic here. + */ + public update(): void; + /** + * Put render operations here. + */ + public render(): void; + /** + * This method will be called when game paused. + */ + public paused(): void; + /** + * This method will be called when the state is destroyed + */ + public destroy(): void; + } +} +/** * Phaser - Components - Debug * * @@ -9723,6 +9835,104 @@ module Phaser { } } /** +* Phaser - IntersectResult +* +* A light-weight result object to hold the results of an intersection. For when you need more than just true/false. +*/ +module Phaser { + class IntersectResult { + /** + * Did they intersect or not? + * @property result + * @type {Boolean} + */ + public result: bool; + /** + * @property x + * @type {Number} + */ + public x: number; + /** + * @property y + * @type {Number} + */ + public y: number; + /** + * @property x1 + * @type {Number} + */ + public x1: number; + /** + * @property y1 + * @type {Number} + */ + public y1: number; + /** + * @property x2 + * @type {Number} + */ + public x2: number; + /** + * @property y2 + * @type {Number} + */ + public y2: number; + /** + * @property width + * @type {Number} + */ + public width: number; + /** + * @property height + * @type {Number} + */ + public height: number; + /** + * + * @method setTo + * @param {Number} x1 + * @param {Number} y1 + * @param {Number} [x2] + * @param {Number} [y2] + * @param {Number} [width] + * @param {Number} [height] + */ + public setTo(x1: number, y1: number, x2?: number, y2?: number, width?: number, height?: number): void; + } +} +/** +* Phaser - Mat3Utils +* +* A collection of methods useful for manipulating and performing operations on Mat3 objects. +* +*/ +module Phaser { + class Mat3Utils { + /** + * Transpose the values of a Mat3 + **/ + static transpose(source: Mat3, dest?: Mat3): Mat3; + /** + * Inverts a Mat3 + **/ + static invert(source: Mat3): Mat3; + /** + * Calculates the adjugate of a Mat3 + **/ + static adjoint(source: Mat3): Mat3; + /** + * Calculates the adjugate of a Mat3 + **/ + static determinant(source: Mat3): number; + /** + * Multiplies two Mat3s + **/ + static multiply(source: Mat3, b: Mat3): Mat3; + static fromQuaternion(): void; + static normalFromMat4(): void; + } +} +/** * Phaser - CircleUtils * * A collection of methods useful for manipulating and comparing Circle objects. @@ -9806,38 +10016,6 @@ module Phaser { } } /** -* Phaser - Mat3Utils -* -* A collection of methods useful for manipulating and performing operations on Mat3 objects. -* -*/ -module Phaser { - class Mat3Utils { - /** - * Transpose the values of a Mat3 - **/ - static transpose(source: Mat3, dest?: Mat3): Mat3; - /** - * Inverts a Mat3 - **/ - static invert(source: Mat3): Mat3; - /** - * Calculates the adjugate of a Mat3 - **/ - static adjoint(source: Mat3): Mat3; - /** - * Calculates the adjugate of a Mat3 - **/ - static determinant(source: Mat3): number; - /** - * Multiplies two Mat3s - **/ - static multiply(source: Mat3, b: Mat3): Mat3; - static fromQuaternion(): void; - static normalFromMat4(): void; - } -} -/** * Phaser - PixelUtils * * A collection of methods useful for manipulating pixels. @@ -9858,173 +10036,3 @@ module Phaser { static getPixel(key: string, x: number, y: number): number; } } -/** -* Phaser - IntersectResult -* -* A light-weight result object to hold the results of an intersection. For when you need more than just true/false. -*/ -module Phaser { - class IntersectResult { - /** - * Did they intersect or not? - * @property result - * @type {Boolean} - */ - public result: bool; - /** - * @property x - * @type {Number} - */ - public x: number; - /** - * @property y - * @type {Number} - */ - public y: number; - /** - * @property x1 - * @type {Number} - */ - public x1: number; - /** - * @property y1 - * @type {Number} - */ - public y1: number; - /** - * @property x2 - * @type {Number} - */ - public x2: number; - /** - * @property y2 - * @type {Number} - */ - public y2: number; - /** - * @property width - * @type {Number} - */ - public width: number; - /** - * @property height - * @type {Number} - */ - public height: number; - /** - * - * @method setTo - * @param {Number} x1 - * @param {Number} y1 - * @param {Number} [x2] - * @param {Number} [y2] - * @param {Number} [width] - * @param {Number} [height] - */ - public setTo(x1: number, y1: number, x2?: number, y2?: number, width?: number, height?: number): void; - } -} -/** -* Phaser - State -* -* This is a base State class which can be extended if you are creating your game using TypeScript. -*/ -module Phaser { - class State { - /** - * State constructor - * Create a new State. - */ - constructor(game: Game); - /** - * Reference to Game. - */ - public game: Game; - /** - * Currently used camera. - * @type {Camera} - */ - public camera: Camera; - /** - * Reference to the assets cache. - * @type {Cache} - */ - public cache: Cache; - /** - * Reference to the GameObject Factory. - * @type {GameObjectFactory} - */ - public add: GameObjectFactory; - /** - * Reference to the input manager - * @type {Input} - */ - public input: Input; - /** - * Reference to the assets loader. - * @type {Loader} - */ - public load: Loader; - /** - * Reference to the math helper. - * @type {GameMath} - */ - public math: GameMath; - /** - * Reference to the motion helper. - * @type {Motion} - */ - public motion: Motion; - /** - * Reference to the sound manager. - * @type {SoundManager} - */ - public sound: SoundManager; - /** - * Reference to the stage. - * @type {Stage} - */ - public stage: Stage; - /** - * Reference to game clock. - * @type {Time} - */ - public time: Time; - /** - * Reference to the tween manager. - * @type {TweenManager} - */ - public tweens: TweenManager; - /** - * Reference to the world. - * @type {World} - */ - public world: World; - /** - * Override this method to add some load operations. - * If you need to use the loader, you may need to use them here. - */ - public init(): void; - /** - * This method is called after the game engine successfully switches states. - * Feel free to add any setup code here.(Do not load anything here, override init() instead) - */ - public create(): void; - /** - * Put update logic here. - */ - public update(): void; - /** - * Put render operations here. - */ - public render(): void; - /** - * This method will be called when game paused. - */ - public paused(): void; - /** - * This method will be called when the state is destroyed - */ - public destroy(): void; - } -} diff --git a/build/phaser.js b/build/phaser.js index 661e4d30..0df38b19 100644 --- a/build/phaser.js +++ b/build/phaser.js @@ -760,6 +760,7 @@ var Phaser; if (typeof y === "undefined") { y = 0; } this.x = x; this.y = y; + return this; } Vec2.prototype.copyFrom = /** * Copies the x and y properties from any given object to this Vec2. @@ -3086,6 +3087,7 @@ var Phaser; (function (Phaser) { /// /// + /// /** * Phaser - Components - Transform */ @@ -3138,7 +3140,7 @@ var Phaser; this._halfSize.y = this.parent.height / 2; this._offset.x = this.origin.x * this.parent.width; this._offset.y = this.origin.y * this.parent.height; - this._angle = Math.atan2(this.halfHeight - this._offset.y, this.halfWidth - this._offset.x); + this._angle = Math.atan2(this.halfHeight - this._offset.x, this.halfWidth - this._offset.y); this._distance = Math.sqrt(((this._offset.x - this._halfSize.x) * (this._offset.x - this._halfSize.x)) + ((this._offset.y - this._halfSize.y) * (this._offset.y - this._halfSize.y))); this._size.x = this.parent.width; this._size.y = this.parent.height; @@ -4123,7 +4125,7 @@ var Phaser; * @return {Vec2} A Vec2. */ function normalRightHand(a, out) { - if (typeof out === "undefined") { out = this; } + if (typeof out === "undefined") { out = new Phaser.Vec2(); } return out.setTo(a.y * -1, a.x); }; Vec2Utils.normalize = /** @@ -6466,7 +6468,7 @@ var Phaser; // 5) Iterative velocity constraints solver this.velocitySolver(velocityIterations); Physics.Manager.dump("Velocity Solvers", this.bodies[1]); - // 6) Intergrate position + // 6) Integrate position for(var i = 0; i < this._bl; i++) { if(this.bodies[i] && this.bodies[i].isDynamic && this.bodies[i].isAwake) { this.bodies[i].updatePosition(this._delta); @@ -6597,12 +6599,15 @@ var Phaser; __extends(Box, _super); // Give in pixels function Box(x, y, width, height) { + console.log('Box px', x, y, width, height); x = Physics.Manager.pixelsToMeters(x); y = Physics.Manager.pixelsToMeters(y); width = Physics.Manager.pixelsToMeters(width); height = Physics.Manager.pixelsToMeters(height); + console.log('Box m', x, y, width, height); var hw = width * 0.5; var hh = height * 0.5; + console.log('Box hh', hw, hh); _super.call(this, [ { x: -hw + x, @@ -6932,7 +6937,7 @@ var Phaser; Physics.Manager.write('p: ' + this.position.toString()); Physics.Manager.write('xf: ' + this.transform.toString()); this.bounds.clear(); - for(var i = 0; i < this.shapes.length; i++) { + for(var i = 0; i < this.shapesLength; i++) { var shape = this.shapes[i]; shape.cacheData(this.transform); this.bounds.addBounds(shape.bounds); @@ -13573,14 +13578,16 @@ var Phaser; * @param y {number} Y position of the new sprite. * @param [key] {string} The image key as defined in the Game.Cache to use as the texture for this sprite * @param [frame] {string|number} If the sprite uses an image from a texture atlas or sprite sheet you can pass the frame here. Either a number for a frame ID or a string for a frame name. + * @param [bodyType] {number} The physics body type of the object (defaults to BODY_DYNAMIC) * @param [shapeType] The default body shape is either 0 for a Box or 1 for a Circle. See Sprite.body.addShape for custom shapes (polygons, etc) * @returns {Sprite} The newly created sprite object. */ - function (x, y, key, frame, shapeType) { + function (x, y, key, frame, bodyType, shapeType) { if (typeof key === "undefined") { key = ''; } if (typeof frame === "undefined") { frame = null; } + if (typeof bodyType === "undefined") { bodyType = Phaser.Types.BODY_DYNAMIC; } if (typeof shapeType === "undefined") { shapeType = 0; } - return this._world.group.add(new Phaser.Sprite(this._game, x, y, key, frame, Phaser.Types.BODY_DYNAMIC, shapeType)); + return this._world.group.add(new Phaser.Sprite(this._game, x, y, key, frame, bodyType, shapeType)); }; GameObjectFactory.prototype.dynamicTexture = /** * Create a new DynamicTexture with specific size. @@ -18582,6 +18589,32 @@ var Phaser; DebugUtils.context.fillText('cx: ' + sprite.cameraView.x + ' cy: ' + sprite.cameraView.y + ' cw: ' + sprite.cameraView.width + ' ch: ' + sprite.cameraView.height + ' cb: ' + sprite.cameraView.bottom + ' cr: ' + sprite.cameraView.right, x, y + 70); DebugUtils.context.fillText('inCamera: ' + DebugUtils.game.renderer.inCamera(DebugUtils.game.camera, sprite), x, y + 84); }; + DebugUtils.renderPhysicsBodyInfo = /** + * Render debug infos. (including name, bounds info, position and some other properties) + * @param x {number} X position of the debug info to be rendered. + * @param y {number} Y position of the debug info to be rendered. + * @param [color] {number} color of the debug info to be rendered. (format is css color string) + */ + function renderPhysicsBodyInfo(body, x, y, color) { + if (typeof color === "undefined") { color = 'rgb(255,255,255)'; } + DebugUtils.context.fillStyle = color; + DebugUtils.context.fillText('Body ID: ' + body.name, x, y); + DebugUtils.context.fillText('Position x: ' + body.position.x.toFixed(1) + ' y: ' + body.position.y.toFixed(1) + ' rotation: ' + body.angle.toFixed(1), x, y + 14); + DebugUtils.context.fillText('World x: ' + (body.position.x * 50).toFixed(1) + ' y: ' + (body.position.y * 50).toFixed(1), x, y + 28); + DebugUtils.context.fillText('Velocity x: ' + body.velocity.x.toFixed(1) + ' y: ' + body.velocity.y.toFixed(1), x, y + 42); + if(body.shapes[0].verts.length > 0) { + DebugUtils.context.fillText('Vert 1 x: ' + (body.shapes[0].verts[0].x * 50) + ' y: ' + (body.shapes[0].verts[0].y * 50), x, y + 56); + DebugUtils.context.fillText('Vert 2 x: ' + (body.shapes[0].verts[1].x * 50) + ' y: ' + (body.shapes[0].verts[1].y * 50), x, y + 70); + DebugUtils.context.fillText('Vert 3 x: ' + (body.shapes[0].tverts[2].x * 50) + ' y: ' + (body.shapes[0].tverts[2].y * 50), x, y + 84); + DebugUtils.context.fillText('Vert 4 x: ' + (body.shapes[0].tverts[3].x * 50) + ' y: ' + (body.shapes[0].tverts[3].y * 50), x, y + 98); + /* + DebugUtils.context.fillText('Vert 1 x: ' + body.shapes[0].verts[0].x.toFixed(1) + ' y: ' + body.shapes[0].verts[0].y.toFixed(1), x, y + 56); + DebugUtils.context.fillText('Vert 2 x: ' + body.shapes[0].verts[1].x.toFixed(1) + ' y: ' + body.shapes[0].verts[1].y.toFixed(1), x, y + 70); + DebugUtils.context.fillText('Vert 3 x: ' + body.shapes[0].verts[2].x.toFixed(1) + ' y: ' + body.shapes[0].verts[2].y.toFixed(1), x, y + 84); + DebugUtils.context.fillText('Vert 4 x: ' + body.shapes[0].verts[3].x.toFixed(1) + ' y: ' + body.shapes[0].verts[3].y.toFixed(1), x, y + 98); + */ + } + }; DebugUtils.renderSpriteBounds = function renderSpriteBounds(sprite, camera, color) { if (typeof camera === "undefined") { camera = null; } if (typeof color === "undefined") { color = 'rgba(0,255,0,0.2)'; } @@ -18597,15 +18630,18 @@ var Phaser; if (typeof lineWidth === "undefined") { lineWidth = 1; } if (typeof fillStyle === "undefined") { fillStyle = 'rgba(0,255,0,0.2)'; } if (typeof sleepStyle === "undefined") { sleepStyle = 'rgba(100,100,100,0.2)'; } - for(var s = 0; s < body.shapes.length; s++) { + for(var s = 0; s < body.shapesLength; s++) { DebugUtils.context.beginPath(); if(body.shapes[s].type == Phaser.Physics.Manager.SHAPE_TYPE_POLY) { var verts = body.shapes[s].tverts; - DebugUtils.context.moveTo((body.position.x + verts[0].x) * 50, (body.position.y + verts[0].y) * 50); - for(var i = 0; i < verts.length; i++) { - DebugUtils.context.lineTo((body.position.x + verts[i].x) * 50, (body.position.y + verts[i].y) * 50); + // DebugUtils.context.moveTo(body.position.x * 50 + verts[0].x, body.position.y * 50 + verts[0].y); + DebugUtils.context.moveTo(verts[0].x * 50, verts[0].y * 50); + for(var i = 1; i < verts.length; i++) { + // DebugUtils.context.lineTo(body.position.x * 50 + verts[i].x, body.position.y * 50 + verts[i].y); + DebugUtils.context.lineTo(verts[i].x * 50, verts[i].y * 50); } - DebugUtils.context.lineTo((body.position.x + verts[verts.length - 1].x) * 50, (body.position.y + verts[verts.length - 1].y) * 50); + // DebugUtils.context.lineTo(body.position.x * 50 + verts[0].x, body.position.y * 50 + verts[0].y); + DebugUtils.context.lineTo(verts[0].x * 50, verts[0].y * 50); } else if(body.shapes[s].type == Phaser.Physics.Manager.SHAPE_TYPE_CIRCLE) { var circle = body.shapes[s]; DebugUtils.context.arc(circle.tc.x * 50, circle.tc.y * 50, circle.radius * 50, 0, Math.PI * 2, false); @@ -19058,6 +19094,84 @@ var Phaser; })(); Phaser.Game = Game; })(Phaser || (Phaser = {})); +/// +/** +* Phaser - State +* +* This is a base State class which can be extended if you are creating your game using TypeScript. +*/ +var Phaser; +(function (Phaser) { + var State = (function () { + /** + * State constructor + * Create a new State. + */ + function State(game) { + this.game = game; + this.add = game.add; + this.camera = game.camera; + this.cache = game.cache; + this.input = game.input; + this.load = game.load; + this.math = game.math; + this.motion = game.motion; + this.sound = game.sound; + this.stage = game.stage; + this.time = game.time; + this.tweens = game.tweens; + this.world = game.world; + } + State.prototype.init = // Override these in your own States + /** + * Override this method to add some load operations. + * If you need to use the loader, you may need to use them here. + */ + function () { + }; + State.prototype.create = /** + * This method is called after the game engine successfully switches states. + * Feel free to add any setup code here.(Do not load anything here, override init() instead) + */ + function () { + }; + State.prototype.update = /** + * Put update logic here. + */ + function () { + }; + State.prototype.render = /** + * Put render operations here. + */ + function () { + }; + State.prototype.paused = /** + * This method will be called when game paused. + */ + function () { + }; + State.prototype.destroy = /** + * This method will be called when the state is destroyed + */ + function () { + }; + return State; + })(); + Phaser.State = State; + /** + * Checks for overlaps between two objects using the world QuadTree. Can be GameObject vs. GameObject, GameObject vs. Group or Group vs. Group. + * Note: Does not take the objects scrollFactor into account. All overlaps are check in world space. + * @param object1 The first GameObject or Group to check. If null the world.group is used. + * @param object2 The second GameObject or Group to check. + * @param notifyCallback A callback function that is called if the objects overlap. The two objects will be passed to this function in the same order in which you passed them to Collision.overlap. + * @param processCallback A callback function that lets you perform additional checks against the two objects if they overlap. If this is set then notifyCallback will only be called if processCallback returns true. + * @param context The context in which the callbacks will be called + * @returns {boolean} true if the objects overlap, otherwise false. + */ + //public collide(objectOrGroup1 = null, objectOrGroup2 = null, notifyCallback = null, context? = this.game.callbackContext): bool { + // return this.collision.overlap(objectOrGroup1, objectOrGroup2, notifyCallback, Collision.separate, context); + //} + })(Phaser || (Phaser = {})); var Phaser; (function (Phaser) { /** @@ -19400,6 +19514,206 @@ var Phaser; Phaser.Line = Line; })(Phaser || (Phaser = {})); /// +/** +* Phaser - IntersectResult +* +* A light-weight result object to hold the results of an intersection. For when you need more than just true/false. +*/ +var Phaser; +(function (Phaser) { + var IntersectResult = (function () { + function IntersectResult() { + /** + * Did they intersect or not? + * @property result + * @type {Boolean} + */ + this.result = false; + } + IntersectResult.prototype.setTo = /** + * + * @method setTo + * @param {Number} x1 + * @param {Number} y1 + * @param {Number} [x2] + * @param {Number} [y2] + * @param {Number} [width] + * @param {Number} [height] + */ + function (x1, y1, x2, y2, width, height) { + if (typeof x2 === "undefined") { x2 = 0; } + if (typeof y2 === "undefined") { y2 = 0; } + if (typeof width === "undefined") { width = 0; } + if (typeof height === "undefined") { height = 0; } + this.x = x1; + this.y = y1; + this.x1 = x1; + this.y1 = y1; + this.x2 = x2; + this.y2 = y2; + this.width = width; + this.height = height; + }; + return IntersectResult; + })(); + Phaser.IntersectResult = IntersectResult; +})(Phaser || (Phaser = {})); +/// +/// +/// +/** +* Phaser - Mat3Utils +* +* A collection of methods useful for manipulating and performing operations on Mat3 objects. +* +*/ +var Phaser; +(function (Phaser) { + var Mat3Utils = (function () { + function Mat3Utils() { } + Mat3Utils.transpose = /** + * Transpose the values of a Mat3 + **/ + function transpose(source, dest) { + if (typeof dest === "undefined") { dest = null; } + if(dest === null) { + // Transpose ourselves + var a01 = source.data[1]; + var a02 = source.data[2]; + var a12 = source.data[5]; + source.data[1] = source.data[3]; + source.data[2] = source.data[6]; + source.data[3] = a01; + source.data[5] = source.data[7]; + source.data[6] = a02; + source.data[7] = a12; + } else { + source.data[0] = dest.data[0]; + source.data[1] = dest.data[3]; + source.data[2] = dest.data[6]; + source.data[3] = dest.data[1]; + source.data[4] = dest.data[4]; + source.data[5] = dest.data[7]; + source.data[6] = dest.data[2]; + source.data[7] = dest.data[5]; + source.data[8] = dest.data[8]; + } + return source; + }; + Mat3Utils.invert = /** + * Inverts a Mat3 + **/ + function invert(source) { + var a00 = source.data[0]; + var a01 = source.data[1]; + var a02 = source.data[2]; + var a10 = source.data[3]; + var a11 = source.data[4]; + var a12 = source.data[5]; + var a20 = source.data[6]; + var a21 = source.data[7]; + var a22 = source.data[8]; + var b01 = a22 * a11 - a12 * a21; + var b11 = -a22 * a10 + a12 * a20; + var b21 = a21 * a10 - a11 * a20; + // Determinant + var det = a00 * b01 + a01 * b11 + a02 * b21; + if(!det) { + return null; + } + det = 1.0 / det; + source.data[0] = b01 * det; + source.data[1] = (-a22 * a01 + a02 * a21) * det; + source.data[2] = (a12 * a01 - a02 * a11) * det; + source.data[3] = b11 * det; + source.data[4] = (a22 * a00 - a02 * a20) * det; + source.data[5] = (-a12 * a00 + a02 * a10) * det; + source.data[6] = b21 * det; + source.data[7] = (-a21 * a00 + a01 * a20) * det; + source.data[8] = (a11 * a00 - a01 * a10) * det; + return source; + }; + Mat3Utils.adjoint = /** + * Calculates the adjugate of a Mat3 + **/ + function adjoint(source) { + var a00 = source.data[0]; + var a01 = source.data[1]; + var a02 = source.data[2]; + var a10 = source.data[3]; + var a11 = source.data[4]; + var a12 = source.data[5]; + var a20 = source.data[6]; + var a21 = source.data[7]; + var a22 = source.data[8]; + source.data[0] = (a11 * a22 - a12 * a21); + source.data[1] = (a02 * a21 - a01 * a22); + source.data[2] = (a01 * a12 - a02 * a11); + source.data[3] = (a12 * a20 - a10 * a22); + source.data[4] = (a00 * a22 - a02 * a20); + source.data[5] = (a02 * a10 - a00 * a12); + source.data[6] = (a10 * a21 - a11 * a20); + source.data[7] = (a01 * a20 - a00 * a21); + source.data[8] = (a00 * a11 - a01 * a10); + return source; + }; + Mat3Utils.determinant = /** + * Calculates the adjugate of a Mat3 + **/ + function determinant(source) { + var a00 = source.data[0]; + var a01 = source.data[1]; + var a02 = source.data[2]; + var a10 = source.data[3]; + var a11 = source.data[4]; + var a12 = source.data[5]; + var a20 = source.data[6]; + var a21 = source.data[7]; + var a22 = source.data[8]; + return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20); + }; + Mat3Utils.multiply = /** + * Multiplies two Mat3s + **/ + function multiply(source, b) { + var a00 = source.data[0]; + var a01 = source.data[1]; + var a02 = source.data[2]; + var a10 = source.data[3]; + var a11 = source.data[4]; + var a12 = source.data[5]; + var a20 = source.data[6]; + var a21 = source.data[7]; + var a22 = source.data[8]; + var b00 = b.data[0]; + var b01 = b.data[1]; + var b02 = b.data[2]; + var b10 = b.data[3]; + var b11 = b.data[4]; + var b12 = b.data[5]; + var b20 = b.data[6]; + var b21 = b.data[7]; + var b22 = b.data[8]; + source.data[0] = b00 * a00 + b01 * a10 + b02 * a20; + source.data[1] = b00 * a01 + b01 * a11 + b02 * a21; + source.data[2] = b00 * a02 + b01 * a12 + b02 * a22; + source.data[3] = b10 * a00 + b11 * a10 + b12 * a20; + source.data[4] = b10 * a01 + b11 * a11 + b12 * a21; + source.data[5] = b10 * a02 + b11 * a12 + b12 * a22; + source.data[6] = b20 * a00 + b21 * a10 + b22 * a20; + source.data[7] = b20 * a01 + b21 * a11 + b22 * a21; + source.data[8] = b20 * a02 + b21 * a12 + b22 * a22; + return source; + }; + Mat3Utils.fromQuaternion = function fromQuaternion() { + }; + Mat3Utils.normalFromMat4 = function normalFromMat4() { + }; + return Mat3Utils; + })(); + Phaser.Mat3Utils = Mat3Utils; +})(Phaser || (Phaser = {})); +/// /// /// /// @@ -19563,161 +19877,6 @@ var Phaser; Phaser.CircleUtils = CircleUtils; })(Phaser || (Phaser = {})); /// -/// -/// -/** -* Phaser - Mat3Utils -* -* A collection of methods useful for manipulating and performing operations on Mat3 objects. -* -*/ -var Phaser; -(function (Phaser) { - var Mat3Utils = (function () { - function Mat3Utils() { } - Mat3Utils.transpose = /** - * Transpose the values of a Mat3 - **/ - function transpose(source, dest) { - if (typeof dest === "undefined") { dest = null; } - if(dest === null) { - // Transpose ourselves - var a01 = source.data[1]; - var a02 = source.data[2]; - var a12 = source.data[5]; - source.data[1] = source.data[3]; - source.data[2] = source.data[6]; - source.data[3] = a01; - source.data[5] = source.data[7]; - source.data[6] = a02; - source.data[7] = a12; - } else { - source.data[0] = dest.data[0]; - source.data[1] = dest.data[3]; - source.data[2] = dest.data[6]; - source.data[3] = dest.data[1]; - source.data[4] = dest.data[4]; - source.data[5] = dest.data[7]; - source.data[6] = dest.data[2]; - source.data[7] = dest.data[5]; - source.data[8] = dest.data[8]; - } - return source; - }; - Mat3Utils.invert = /** - * Inverts a Mat3 - **/ - function invert(source) { - var a00 = source.data[0]; - var a01 = source.data[1]; - var a02 = source.data[2]; - var a10 = source.data[3]; - var a11 = source.data[4]; - var a12 = source.data[5]; - var a20 = source.data[6]; - var a21 = source.data[7]; - var a22 = source.data[8]; - var b01 = a22 * a11 - a12 * a21; - var b11 = -a22 * a10 + a12 * a20; - var b21 = a21 * a10 - a11 * a20; - // Determinant - var det = a00 * b01 + a01 * b11 + a02 * b21; - if(!det) { - return null; - } - det = 1.0 / det; - source.data[0] = b01 * det; - source.data[1] = (-a22 * a01 + a02 * a21) * det; - source.data[2] = (a12 * a01 - a02 * a11) * det; - source.data[3] = b11 * det; - source.data[4] = (a22 * a00 - a02 * a20) * det; - source.data[5] = (-a12 * a00 + a02 * a10) * det; - source.data[6] = b21 * det; - source.data[7] = (-a21 * a00 + a01 * a20) * det; - source.data[8] = (a11 * a00 - a01 * a10) * det; - return source; - }; - Mat3Utils.adjoint = /** - * Calculates the adjugate of a Mat3 - **/ - function adjoint(source) { - var a00 = source.data[0]; - var a01 = source.data[1]; - var a02 = source.data[2]; - var a10 = source.data[3]; - var a11 = source.data[4]; - var a12 = source.data[5]; - var a20 = source.data[6]; - var a21 = source.data[7]; - var a22 = source.data[8]; - source.data[0] = (a11 * a22 - a12 * a21); - source.data[1] = (a02 * a21 - a01 * a22); - source.data[2] = (a01 * a12 - a02 * a11); - source.data[3] = (a12 * a20 - a10 * a22); - source.data[4] = (a00 * a22 - a02 * a20); - source.data[5] = (a02 * a10 - a00 * a12); - source.data[6] = (a10 * a21 - a11 * a20); - source.data[7] = (a01 * a20 - a00 * a21); - source.data[8] = (a00 * a11 - a01 * a10); - return source; - }; - Mat3Utils.determinant = /** - * Calculates the adjugate of a Mat3 - **/ - function determinant(source) { - var a00 = source.data[0]; - var a01 = source.data[1]; - var a02 = source.data[2]; - var a10 = source.data[3]; - var a11 = source.data[4]; - var a12 = source.data[5]; - var a20 = source.data[6]; - var a21 = source.data[7]; - var a22 = source.data[8]; - return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20); - }; - Mat3Utils.multiply = /** - * Multiplies two Mat3s - **/ - function multiply(source, b) { - var a00 = source.data[0]; - var a01 = source.data[1]; - var a02 = source.data[2]; - var a10 = source.data[3]; - var a11 = source.data[4]; - var a12 = source.data[5]; - var a20 = source.data[6]; - var a21 = source.data[7]; - var a22 = source.data[8]; - var b00 = b.data[0]; - var b01 = b.data[1]; - var b02 = b.data[2]; - var b10 = b.data[3]; - var b11 = b.data[4]; - var b12 = b.data[5]; - var b20 = b.data[6]; - var b21 = b.data[7]; - var b22 = b.data[8]; - source.data[0] = b00 * a00 + b01 * a10 + b02 * a20; - source.data[1] = b00 * a01 + b01 * a11 + b02 * a21; - source.data[2] = b00 * a02 + b01 * a12 + b02 * a22; - source.data[3] = b10 * a00 + b11 * a10 + b12 * a20; - source.data[4] = b10 * a01 + b11 * a11 + b12 * a21; - source.data[5] = b10 * a02 + b11 * a12 + b12 * a22; - source.data[6] = b20 * a00 + b21 * a10 + b22 * a20; - source.data[7] = b20 * a01 + b21 * a11 + b22 * a21; - source.data[8] = b20 * a02 + b21 * a12 + b22 * a22; - return source; - }; - Mat3Utils.fromQuaternion = function fromQuaternion() { - }; - Mat3Utils.normalFromMat4 = function normalFromMat4() { - }; - return Mat3Utils; - })(); - Phaser.Mat3Utils = Mat3Utils; -})(Phaser || (Phaser = {})); -/// /// /// /// @@ -19745,126 +19904,3 @@ var Phaser; })(); Phaser.PixelUtils = PixelUtils; })(Phaser || (Phaser = {})); -/// -/** -* Phaser - IntersectResult -* -* A light-weight result object to hold the results of an intersection. For when you need more than just true/false. -*/ -var Phaser; -(function (Phaser) { - var IntersectResult = (function () { - function IntersectResult() { - /** - * Did they intersect or not? - * @property result - * @type {Boolean} - */ - this.result = false; - } - IntersectResult.prototype.setTo = /** - * - * @method setTo - * @param {Number} x1 - * @param {Number} y1 - * @param {Number} [x2] - * @param {Number} [y2] - * @param {Number} [width] - * @param {Number} [height] - */ - function (x1, y1, x2, y2, width, height) { - if (typeof x2 === "undefined") { x2 = 0; } - if (typeof y2 === "undefined") { y2 = 0; } - if (typeof width === "undefined") { width = 0; } - if (typeof height === "undefined") { height = 0; } - this.x = x1; - this.y = y1; - this.x1 = x1; - this.y1 = y1; - this.x2 = x2; - this.y2 = y2; - this.width = width; - this.height = height; - }; - return IntersectResult; - })(); - Phaser.IntersectResult = IntersectResult; -})(Phaser || (Phaser = {})); -/// -/** -* Phaser - State -* -* This is a base State class which can be extended if you are creating your game using TypeScript. -*/ -var Phaser; -(function (Phaser) { - var State = (function () { - /** - * State constructor - * Create a new State. - */ - function State(game) { - this.game = game; - this.add = game.add; - this.camera = game.camera; - this.cache = game.cache; - this.input = game.input; - this.load = game.load; - this.math = game.math; - this.motion = game.motion; - this.sound = game.sound; - this.stage = game.stage; - this.time = game.time; - this.tweens = game.tweens; - this.world = game.world; - } - State.prototype.init = // Override these in your own States - /** - * Override this method to add some load operations. - * If you need to use the loader, you may need to use them here. - */ - function () { - }; - State.prototype.create = /** - * This method is called after the game engine successfully switches states. - * Feel free to add any setup code here.(Do not load anything here, override init() instead) - */ - function () { - }; - State.prototype.update = /** - * Put update logic here. - */ - function () { - }; - State.prototype.render = /** - * Put render operations here. - */ - function () { - }; - State.prototype.paused = /** - * This method will be called when game paused. - */ - function () { - }; - State.prototype.destroy = /** - * This method will be called when the state is destroyed - */ - function () { - }; - return State; - })(); - Phaser.State = State; - /** - * Checks for overlaps between two objects using the world QuadTree. Can be GameObject vs. GameObject, GameObject vs. Group or Group vs. Group. - * Note: Does not take the objects scrollFactor into account. All overlaps are check in world space. - * @param object1 The first GameObject or Group to check. If null the world.group is used. - * @param object2 The second GameObject or Group to check. - * @param notifyCallback A callback function that is called if the objects overlap. The two objects will be passed to this function in the same order in which you passed them to Collision.overlap. - * @param processCallback A callback function that lets you perform additional checks against the two objects if they overlap. If this is set then notifyCallback will only be called if processCallback returns true. - * @param context The context in which the callbacks will be called - * @returns {boolean} true if the objects overlap, otherwise false. - */ - //public collide(objectOrGroup1 = null, objectOrGroup2 = null, notifyCallback = null, context? = this.game.callbackContext): bool { - // return this.collision.overlap(objectOrGroup1, objectOrGroup2, notifyCallback, Collision.separate, context); - //} - })(Phaser || (Phaser = {}));