diff --git a/Phaser/core/Vec2.ts b/Phaser/core/Vec2.ts index ec290914..e3118c35 100644 --- a/Phaser/core/Vec2.ts +++ b/Phaser/core/Vec2.ts @@ -203,6 +203,20 @@ module Phaser { } + /** + * Multiply this vector by the given scalar. + * + * @param {number} scalar + * @return {Vec2} This for chaining. + */ + public multiplyByScalar(scalar: number): Vec2 { + + this.x *= scalar; + this.y *= scalar; + return this; + + } + /** * Divide this vector by the given scalar. * diff --git a/Phaser/physics/PhysicsManager.ts b/Phaser/physics/PhysicsManager.ts index 0c176853..a9e476f2 100644 --- a/Phaser/physics/PhysicsManager.ts +++ b/Phaser/physics/PhysicsManager.ts @@ -23,6 +23,9 @@ module Phaser.Physics { this.bounds = new Rectangle(0, 0, width, height); + this._distance = new Vec2; + this._tangent = new Vec2; + this._objects = []; } @@ -39,6 +42,8 @@ module Phaser.Physics { private _delta: number; private _velocityDelta: number; private _length: number = 0; + private _distance: Vec2; + private _tangent: Vec2; public bounds: Rectangle; @@ -158,126 +163,215 @@ module Phaser.Physics { } - private collideWorld(obj:IPhysicsShape) { + private collideWorld(shape:IPhysicsShape) { // Collide on the x-axis - var dx: number = obj.world.bounds.x - (obj.position.x - obj.bounds.halfWidth); + this._distance.x = shape.world.bounds.x - (shape.position.x - shape.bounds.halfWidth); - if (0 < dx) + if (0 < this._distance.x) { // Hit Left - obj.oH = 1; - obj.position.x += dx; - - if (obj.sprite.physics.bounce.x > 0) - { - obj.sprite.physics.velocity.x *= -(obj.sprite.physics.bounce.x); - } - else - { - obj.sprite.physics.velocity.x = 0; - } + this._tangent.setTo(1, 0); + this.separateX(shape, this._distance, this._tangent); } else { - dx = (obj.position.x + obj.bounds.halfWidth) - obj.world.bounds.right; + this._distance.x = (shape.position.x + shape.bounds.halfWidth) - shape.world.bounds.right; - if (0 < dx) + if (0 < this._distance.x) { // Hit Right - obj.oH = -1; - obj.position.x -= dx; - - if (obj.sprite.physics.bounce.x > 0) - { - obj.sprite.physics.velocity.x *= -(obj.sprite.physics.bounce.x); - } - else - { - obj.sprite.physics.velocity.x = 0; - } + this._tangent.setTo(-1, 0); + this._distance.reverse(); + this.separateX(shape, this._distance, this._tangent); } } // Collide on the y-axis - var dy: number = obj.world.bounds.y - (obj.position.y - obj.bounds.halfHeight); + this._distance.y = shape.world.bounds.y - (shape.position.y - shape.bounds.halfHeight); - if (0 < dy) + if (0 < this._distance.y) { // Hit Top - obj.oV = 1; - obj.position.y += dy; - - if (obj.sprite.physics.bounce.y > 0) - { - obj.sprite.physics.velocity.y *= -(obj.sprite.physics.bounce.y); - } - else - { - obj.sprite.physics.velocity.y = 0; - } + this._tangent.setTo(0, 1); + this.separateY(shape, this._distance, this._tangent); } else { - dy = (obj.position.y + obj.bounds.halfHeight) - obj.world.bounds.bottom; + this._distance.y = (shape.position.y + shape.bounds.halfHeight) - shape.world.bounds.bottom; - if (0 < dy) + if (0 < this._distance.y) { // Hit Bottom - obj.oV = -1; - obj.position.y -= dy; - - if (obj.sprite.physics.bounce.y > 0) - { - obj.sprite.physics.velocity.y *= -(obj.sprite.physics.bounce.y); - } - else - { - obj.sprite.physics.velocity.y = 0; - } + this._tangent.setTo(0, -1); + this._distance.reverse(); + this.separateY(shape, this._distance, this._tangent); } } } /* - private processWorld(px, py, dx, dy, tile) { + private OLDButWorkingcollideWorld(obj:IPhysicsShape) { - // Velocity - //this.sprite.physics.velocity.x = this.position.x - this.oldPosition.x; - //this.sprite.physics.velocity.y = this.position.y - this.oldPosition.y; + this._distance.setTo(0, 0); - // Optimise!!! - var dp: number = (this.sprite.physics.velocity.x * dx + this.sprite.physics.velocity.y * dy); - var nx: number = dp * dx; - var ny: number = dp * dy; - var tx: number = this.sprite.physics.velocity.x - nx; - var ty: number = this.sprite.physics.velocity.y - ny; - - var bx, by, fx, fy; - - if (dp < 0) + // Collide on the x-axis + this._distance.x = obj.world.bounds.x - (obj.position.x - obj.bounds.halfWidth); + + if (0 < this._distance.x) { - fx = tx * this.sprite.physics.friction.x; - fy = ty * this.sprite.physics.friction.y; - bx = (nx * (1 + this.sprite.physics.bounce.x)); - by = (ny * (1 + this.sprite.physics.bounce.y)); - //this.sprite.physics.velocity.x = bx; - //this.sprite.physics.velocity.y = by; + // Hit Left + // Parameter order: px, py (distance), dx, dy (tangent) + this._tangent.setTo(1, 0); + this.separate(obj, this._distance, this._tangent); } else { - bx = by = fx = fy = 0; + this._distance.x = (obj.position.x + obj.bounds.halfWidth) - obj.world.bounds.right; + + if (0 < this._distance.x) + { + // Hit Right + // Parameter order: px, py (distance), dx, dy (tangent) + this._tangent.setTo(-1, 0); + this._distance.x = -this._distance.x; + this.separate(obj, this._distance, this._tangent); + } } - this.position.x += px; - this.position.y += py; + // Collide on the y-axis + this._distance.x = 0; + this._distance.y = obj.world.bounds.y - (obj.position.y - obj.bounds.halfHeight); - this.oldPosition.x += px + bx + fx; - this.oldPosition.y += py + by + fy; + if (0 < this._distance.y) + { + // Hit Top + this._tangent.setTo(0, 1); + this.separate(obj, this._distance, this._tangent); + } + else + { + this._distance.y = (obj.position.y + obj.bounds.halfHeight) - obj.world.bounds.bottom; + + if (0 < this._distance.y) + { + // Hit Bottom + this._tangent.setTo(0, -1); + this._distance.y = -this._distance.y; + this.separate(obj, this._distance, this._tangent); + } + } + + } + */ + + private separateX(shape: IPhysicsShape, distance: Vec2, tangent: Vec2) { + + // collision edges + shape.oH = tangent.x; + + // only apply collision response forces if the object is travelling into, and not out of, the collision + if (Vec2Utils.dot(shape.physics.velocity, tangent) < 0) + { + // Apply horizontal bounce + if (shape.physics.bounce.x > 0) + { + shape.physics.velocity.x *= -(shape.physics.bounce.x); + } + else + { + shape.physics.velocity.x = 0; + } + } + + shape.position.x += distance.x; + + } + + private separateY(shape: IPhysicsShape, distance: Vec2, tangent: Vec2) { + + // collision edges + shape.oV = tangent.y; + + // only apply collision response forces if the object is travelling into, and not out of, the collision + if (Vec2Utils.dot(shape.physics.velocity, tangent) < 0) + { + // Apply horizontal bounce + if (shape.physics.bounce.y > 0) + { + shape.physics.velocity.y *= -(shape.physics.bounce.y); + } + else + { + shape.physics.velocity.y = 0; + } + } + + shape.position.y += distance.y; + + } + + private separate(shape:IPhysicsShape, distance: Vec2, tangent: Vec2) { + + // collision edges + shape.oH = tangent.x; + shape.oV = tangent.y; + + // Velocity (move to temp vars) + + // was vx/vy + var velocity: Vec2 = Vec2Utils.subtract(shape.position, shape.oldPosition); + + // was dp + var dot: number = Vec2Utils.dot(shape.physics.velocity, tangent); + + // project velocity onto the collision normal + // was nx/ny + tangent.multiplyByScalar(dot); + + // was tx/ty (tangent velocity?) + var tangentVelocity: Vec2 = Vec2Utils.subtract(velocity, tangent); + + // only apply collision response forces if the object is travelling into, and not out of, the collision + if (dot < 0) + { + // Apply horizontal bounce + if (distance.x != 0) + { + if (shape.physics.bounce.x > 0) + { + shape.physics.velocity.x *= -(shape.physics.bounce.x); + } + else + { + shape.physics.velocity.x = 0; + } + } + + // Apply vertical bounce + if (distance.y != 0) + { + if (shape.physics.bounce.y > 0) + { + shape.physics.velocity.y *= -(shape.physics.bounce.y); + } + else + { + shape.physics.velocity.y = 0; + } + } + } + else + { + // moving out of collision + } + + // project object out of collision + //console.log('proj out', distance.x, distance.y,'dot',dot); + shape.position.add(distance); } - */ } diff --git a/Tests/phaser.js b/Tests/phaser.js index a8a836c1..365aa70d 100644 --- a/Tests/phaser.js +++ b/Tests/phaser.js @@ -5874,6 +5874,8 @@ var Phaser; this.bounce = new Phaser.Vec2(); this.friction = new Phaser.Vec2(); this.bounds = new Phaser.Rectangle(0, 0, width, height); + this._distance = new Phaser.Vec2(); + this._tangent = new Phaser.Vec2(); this._objects = []; } PhysicsManager.prototype.add = // Add some sanity checks here + remove method, etc @@ -5955,96 +5957,161 @@ var Phaser; }; PhysicsManager.prototype.collideWorld = function (obj) { // Collide on the x-axis - var dx = obj.world.bounds.x - (obj.position.x - obj.bounds.halfWidth); - if(0 < dx) { + this._distance.x = obj.world.bounds.x - (obj.position.x - obj.bounds.halfWidth); + if(0 < this._distance.x) { // Hit Left - obj.oH = 1; - obj.position.x += dx; - if(obj.sprite.physics.bounce.x > 0) { - obj.sprite.physics.velocity.x *= -(obj.sprite.physics.bounce.x); - } else { - obj.sprite.physics.velocity.x = 0; - } + this._tangent.setTo(1, 0); + this.separateX(obj, this._distance, this._tangent); } else { - dx = (obj.position.x + obj.bounds.halfWidth) - obj.world.bounds.right; - if(0 < dx) { + this._distance.x = (obj.position.x + obj.bounds.halfWidth) - obj.world.bounds.right; + if(0 < this._distance.x) { // Hit Right - obj.oH = -1; - obj.position.x -= dx; - if(obj.sprite.physics.bounce.x > 0) { - obj.sprite.physics.velocity.x *= -(obj.sprite.physics.bounce.x); - } else { - obj.sprite.physics.velocity.x = 0; - } + this._tangent.setTo(-1, 0); + this._distance.reverse(); + this.separateX(obj, this._distance, this._tangent); } } // Collide on the y-axis - var dy = obj.world.bounds.y - (obj.position.y - obj.bounds.halfHeight); - if(0 < dy) { + this._distance.y = obj.world.bounds.y - (obj.position.y - obj.bounds.halfHeight); + if(0 < this._distance.y) { // Hit Top - obj.oV = 1; - obj.position.y += dy; - if(obj.sprite.physics.bounce.y > 0) { - obj.sprite.physics.velocity.y *= -(obj.sprite.physics.bounce.y); - } else { - obj.sprite.physics.velocity.y = 0; - } + this._tangent.setTo(0, 1); + this.separateY(obj, this._distance, this._tangent); } else { - dy = (obj.position.y + obj.bounds.halfHeight) - obj.world.bounds.bottom; - if(0 < dy) { + this._distance.y = (obj.position.y + obj.bounds.halfHeight) - obj.world.bounds.bottom; + if(0 < this._distance.y) { // Hit Bottom - obj.oV = -1; - obj.position.y -= dy; - if(obj.sprite.physics.bounce.y > 0) { - obj.sprite.physics.velocity.y *= -(obj.sprite.physics.bounce.y); - } else { - obj.sprite.physics.velocity.y = 0; - } + this._tangent.setTo(0, -1); + this._distance.reverse(); + this.separateY(obj, this._distance, this._tangent); } } }; + PhysicsManager.prototype.separateX = /* + private OLDButWorkingcollideWorld(obj:IPhysicsShape) { + + this._distance.setTo(0, 0); + + // Collide on the x-axis + this._distance.x = obj.world.bounds.x - (obj.position.x - obj.bounds.halfWidth); + + if (0 < this._distance.x) + { + // Hit Left + // Parameter order: px, py (distance), dx, dy (tangent) + this._tangent.setTo(1, 0); + this.separate(obj, this._distance, this._tangent); + } + else + { + this._distance.x = (obj.position.x + obj.bounds.halfWidth) - obj.world.bounds.right; + + if (0 < this._distance.x) + { + // Hit Right + // Parameter order: px, py (distance), dx, dy (tangent) + this._tangent.setTo(-1, 0); + this._distance.x = -this._distance.x; + this.separate(obj, this._distance, this._tangent); + } + } + + // Collide on the y-axis + this._distance.x = 0; + this._distance.y = obj.world.bounds.y - (obj.position.y - obj.bounds.halfHeight); + + if (0 < this._distance.y) + { + // Hit Top + this._tangent.setTo(0, 1); + this.separate(obj, this._distance, this._tangent); + } + else + { + this._distance.y = (obj.position.y + obj.bounds.halfHeight) - obj.world.bounds.bottom; + + if (0 < this._distance.y) + { + // Hit Bottom + this._tangent.setTo(0, -1); + this._distance.y = -this._distance.y; + this.separate(obj, this._distance, this._tangent); + } + } + + } + */ + function (shape, distance, tangent) { + // collision edges + shape.oH = tangent.x; + // only apply collision response forces if the object is travelling into, and not out of, the collision + if(Phaser.Vec2Utils.dot(shape.physics.velocity, tangent) < 0) { + // Apply horizontal bounce + if(shape.physics.bounce.x > 0) { + shape.physics.velocity.x *= -(shape.physics.bounce.x); + } else { + shape.physics.velocity.x = 0; + } + } + shape.position.x += distance.x; + }; + PhysicsManager.prototype.separateY = function (shape, distance, tangent) { + // collision edges + shape.oV = tangent.y; + // only apply collision response forces if the object is travelling into, and not out of, the collision + if(Phaser.Vec2Utils.dot(shape.physics.velocity, tangent) < 0) { + // Apply horizontal bounce + if(shape.physics.bounce.y > 0) { + shape.physics.velocity.y *= -(shape.physics.bounce.y); + } else { + shape.physics.velocity.y = 0; + } + } + shape.position.y += distance.y; + }; + PhysicsManager.prototype.separate = function (shape, distance, tangent) { + // collision edges + shape.oH = tangent.x; + shape.oV = tangent.y; + // Velocity (move to temp vars) + // was vx/vy + var velocity = Phaser.Vec2Utils.subtract(shape.position, shape.oldPosition); + // was dp + var dot = Phaser.Vec2Utils.dot(shape.physics.velocity, tangent); + // project velocity onto the collision normal + // was nx/ny + tangent.multiplyByScalar(dot); + // was tx/ty (tangent velocity?) + var tangentVelocity = Phaser.Vec2Utils.subtract(velocity, tangent); + // only apply collision response forces if the object is travelling into, and not out of, the collision + if(dot < 0) { + // Apply horizontal bounce + if(distance.x != 0) { + if(shape.physics.bounce.x > 0) { + shape.physics.velocity.x *= -(shape.physics.bounce.x); + } else { + shape.physics.velocity.x = 0; + } + } + // Apply vertical bounce + if(distance.y != 0) { + if(shape.physics.bounce.y > 0) { + shape.physics.velocity.y *= -(shape.physics.bounce.y); + } else { + shape.physics.velocity.y = 0; + } + } + } else { + // moving out of collision + } + // project object out of collision + //console.log('proj out', distance.x, distance.y,'dot',dot); + shape.position.add(distance); + }; return PhysicsManager; })(); Physics.PhysicsManager = PhysicsManager; - /* - private processWorld(px, py, dx, dy, tile) { - - // Velocity - //this.sprite.physics.velocity.x = this.position.x - this.oldPosition.x; - //this.sprite.physics.velocity.y = this.position.y - this.oldPosition.y; - - // Optimise!!! - var dp: number = (this.sprite.physics.velocity.x * dx + this.sprite.physics.velocity.y * dy); - var nx: number = dp * dx; - var ny: number = dp * dy; - var tx: number = this.sprite.physics.velocity.x - nx; - var ty: number = this.sprite.physics.velocity.y - ny; - - var bx, by, fx, fy; - - if (dp < 0) - { - fx = tx * this.sprite.physics.friction.x; - fy = ty * this.sprite.physics.friction.y; - bx = (nx * (1 + this.sprite.physics.bounce.x)); - by = (ny * (1 + this.sprite.physics.bounce.y)); - //this.sprite.physics.velocity.x = bx; - //this.sprite.physics.velocity.y = by; - } - else - { - bx = by = fx = fy = 0; - } - - this.position.x += px; - this.position.y += py; - - this.oldPosition.x += px + bx + fx; - this.oldPosition.y += py + by + fy; - - } - */ - })(Phaser.Physics || (Phaser.Physics = {})); + })(Phaser.Physics || (Phaser.Physics = {})); var Physics = Phaser.Physics; })(Phaser || (Phaser = {})); var Phaser; @@ -11167,7 +11234,6 @@ var Phaser; * Used to create texture when texture image is small than size of the zone. */ function (regionWidth, regionHeight) { - console.log('create repeat'); // Work out how many we'll need of the source image to make it tile properly var tileWidth = Math.ceil(this.width / regionWidth) * regionWidth; var tileHeight = Math.ceil(this.height / regionHeight) * regionHeight; @@ -12013,6 +12079,17 @@ var Phaser; this.y *= y || x; return this; }; + Vec2.prototype.multiplyByScalar = /** + * Multiply this vector by the given scalar. + * + * @param {number} scalar + * @return {Vec2} This for chaining. + */ + function (scalar) { + this.x *= scalar; + this.y *= scalar; + return this; + }; Vec2.prototype.divideByScalar = /** * Divide this vector by the given scalar. * diff --git a/Tests/physics/aabb 1.js b/Tests/physics/aabb 1.js index bd9375c5..1c79427d 100644 --- a/Tests/physics/aabb 1.js +++ b/Tests/physics/aabb 1.js @@ -11,8 +11,8 @@ atari = game.add.sprite(200, 300, 'atari'); atari.texture.alpha = 0.5; //atari.scale.setTo(1.5, 1.5); - atari.physics.shape.setSize(150, 50); - atari.physics.shape.offset.setTo(50, 25); + //atari.physics.shape.setSize(150, 50); + //atari.physics.shape.offset.setTo(50, 25); //atari.physics.gravity.setTo(0, 2); atari.physics.bounce.setTo(0.7, 0.7); atari.physics.drag.setTo(10, 10); diff --git a/Tests/physics/aabb 1.ts b/Tests/physics/aabb 1.ts index ac8392cd..cd906c54 100644 --- a/Tests/physics/aabb 1.ts +++ b/Tests/physics/aabb 1.ts @@ -20,8 +20,8 @@ atari.texture.alpha = 0.5; //atari.scale.setTo(1.5, 1.5); - atari.physics.shape.setSize(150, 50); - atari.physics.shape.offset.setTo(50, 25); + //atari.physics.shape.setSize(150, 50); + //atari.physics.shape.offset.setTo(50, 25); //atari.physics.gravity.setTo(0, 2); atari.physics.bounce.setTo(0.7, 0.7); diff --git a/Tests/scrollzones/skewed scroller.js b/Tests/scrollzones/skewed scroller.js index 87d12c89..84c6e6a2 100644 --- a/Tests/scrollzones/skewed scroller.js +++ b/Tests/scrollzones/skewed scroller.js @@ -11,17 +11,12 @@ var topFace; function create() { topFace = game.add.scrollZone('balls', 200, 0, 204, 204).setSpeed(0, 2.2); - topFace.skew.setTo(0, Math.tan(game.math.radiansToDegrees(-30)))// 0,-30 + scale(1,1.16) - ; + topFace.skew.setTo(0, Math.tan(game.math.radiansToDegrees(-30))); topFace.scale.setTo(1, 1.3); leftFace = game.add.scrollZone('balls', 110, 264, 204, 204).setSpeed(0, 2.1); - leftFace.skew.setTo(0, Math.tan(game.math.radiansToDegrees(30)))// 0,30deg - ; + leftFace.skew.setTo(0, Math.tan(game.math.radiansToDegrees(30))); rightFace = game.add.scrollZone('balls', 200, 466, 204, 204).setSpeed(0, 2); - rightFace.skew.setTo(0, Math.tan(game.math.radiansToDegrees(-30)))// 0,-30 + scale(1,1.16) - ; + rightFace.skew.setTo(0, Math.tan(game.math.radiansToDegrees(-30))); rightFace.scale.setTo(1, 0.8); - //var a = Math.tan(game.math.radiansToDegrees(-180)) - //game.add.tween(rightFace.skew).to({ x: 2, y: 4 }, 4000, Phaser.Easing.Linear.None, true, 0, true); - } + } })(); diff --git a/build/phaser.d.ts b/build/phaser.d.ts index 6efbe513..e583854f 100644 --- a/build/phaser.d.ts +++ b/build/phaser.d.ts @@ -3242,6 +3242,8 @@ module Phaser.Physics { private _delta; private _velocityDelta; private _length; + private _distance; + private _tangent; public bounds: Rectangle; public gravity: Vec2; public drag: Vec2; @@ -3263,6 +3265,9 @@ module Phaser.Physics { */ public computeVelocity(velocity: number, gravity?: number, acceleration?: number, drag?: number, max?: number): number; private collideWorld(obj); + private separateX(shape, distance, tangent); + private separateY(shape, distance, tangent); + private separate(shape, distance, tangent); } } /** @@ -6566,6 +6571,13 @@ module Phaser { */ public scale(x: number, y?: number): Vec2; /** + * Multiply this vector by the given scalar. + * + * @param {number} scalar + * @return {Vec2} This for chaining. + */ + public multiplyByScalar(scalar: number): Vec2; + /** * Divide this vector by the given scalar. * * @param {number} scalar diff --git a/build/phaser.js b/build/phaser.js index a8a836c1..365aa70d 100644 --- a/build/phaser.js +++ b/build/phaser.js @@ -5874,6 +5874,8 @@ var Phaser; this.bounce = new Phaser.Vec2(); this.friction = new Phaser.Vec2(); this.bounds = new Phaser.Rectangle(0, 0, width, height); + this._distance = new Phaser.Vec2(); + this._tangent = new Phaser.Vec2(); this._objects = []; } PhysicsManager.prototype.add = // Add some sanity checks here + remove method, etc @@ -5955,96 +5957,161 @@ var Phaser; }; PhysicsManager.prototype.collideWorld = function (obj) { // Collide on the x-axis - var dx = obj.world.bounds.x - (obj.position.x - obj.bounds.halfWidth); - if(0 < dx) { + this._distance.x = obj.world.bounds.x - (obj.position.x - obj.bounds.halfWidth); + if(0 < this._distance.x) { // Hit Left - obj.oH = 1; - obj.position.x += dx; - if(obj.sprite.physics.bounce.x > 0) { - obj.sprite.physics.velocity.x *= -(obj.sprite.physics.bounce.x); - } else { - obj.sprite.physics.velocity.x = 0; - } + this._tangent.setTo(1, 0); + this.separateX(obj, this._distance, this._tangent); } else { - dx = (obj.position.x + obj.bounds.halfWidth) - obj.world.bounds.right; - if(0 < dx) { + this._distance.x = (obj.position.x + obj.bounds.halfWidth) - obj.world.bounds.right; + if(0 < this._distance.x) { // Hit Right - obj.oH = -1; - obj.position.x -= dx; - if(obj.sprite.physics.bounce.x > 0) { - obj.sprite.physics.velocity.x *= -(obj.sprite.physics.bounce.x); - } else { - obj.sprite.physics.velocity.x = 0; - } + this._tangent.setTo(-1, 0); + this._distance.reverse(); + this.separateX(obj, this._distance, this._tangent); } } // Collide on the y-axis - var dy = obj.world.bounds.y - (obj.position.y - obj.bounds.halfHeight); - if(0 < dy) { + this._distance.y = obj.world.bounds.y - (obj.position.y - obj.bounds.halfHeight); + if(0 < this._distance.y) { // Hit Top - obj.oV = 1; - obj.position.y += dy; - if(obj.sprite.physics.bounce.y > 0) { - obj.sprite.physics.velocity.y *= -(obj.sprite.physics.bounce.y); - } else { - obj.sprite.physics.velocity.y = 0; - } + this._tangent.setTo(0, 1); + this.separateY(obj, this._distance, this._tangent); } else { - dy = (obj.position.y + obj.bounds.halfHeight) - obj.world.bounds.bottom; - if(0 < dy) { + this._distance.y = (obj.position.y + obj.bounds.halfHeight) - obj.world.bounds.bottom; + if(0 < this._distance.y) { // Hit Bottom - obj.oV = -1; - obj.position.y -= dy; - if(obj.sprite.physics.bounce.y > 0) { - obj.sprite.physics.velocity.y *= -(obj.sprite.physics.bounce.y); - } else { - obj.sprite.physics.velocity.y = 0; - } + this._tangent.setTo(0, -1); + this._distance.reverse(); + this.separateY(obj, this._distance, this._tangent); } } }; + PhysicsManager.prototype.separateX = /* + private OLDButWorkingcollideWorld(obj:IPhysicsShape) { + + this._distance.setTo(0, 0); + + // Collide on the x-axis + this._distance.x = obj.world.bounds.x - (obj.position.x - obj.bounds.halfWidth); + + if (0 < this._distance.x) + { + // Hit Left + // Parameter order: px, py (distance), dx, dy (tangent) + this._tangent.setTo(1, 0); + this.separate(obj, this._distance, this._tangent); + } + else + { + this._distance.x = (obj.position.x + obj.bounds.halfWidth) - obj.world.bounds.right; + + if (0 < this._distance.x) + { + // Hit Right + // Parameter order: px, py (distance), dx, dy (tangent) + this._tangent.setTo(-1, 0); + this._distance.x = -this._distance.x; + this.separate(obj, this._distance, this._tangent); + } + } + + // Collide on the y-axis + this._distance.x = 0; + this._distance.y = obj.world.bounds.y - (obj.position.y - obj.bounds.halfHeight); + + if (0 < this._distance.y) + { + // Hit Top + this._tangent.setTo(0, 1); + this.separate(obj, this._distance, this._tangent); + } + else + { + this._distance.y = (obj.position.y + obj.bounds.halfHeight) - obj.world.bounds.bottom; + + if (0 < this._distance.y) + { + // Hit Bottom + this._tangent.setTo(0, -1); + this._distance.y = -this._distance.y; + this.separate(obj, this._distance, this._tangent); + } + } + + } + */ + function (shape, distance, tangent) { + // collision edges + shape.oH = tangent.x; + // only apply collision response forces if the object is travelling into, and not out of, the collision + if(Phaser.Vec2Utils.dot(shape.physics.velocity, tangent) < 0) { + // Apply horizontal bounce + if(shape.physics.bounce.x > 0) { + shape.physics.velocity.x *= -(shape.physics.bounce.x); + } else { + shape.physics.velocity.x = 0; + } + } + shape.position.x += distance.x; + }; + PhysicsManager.prototype.separateY = function (shape, distance, tangent) { + // collision edges + shape.oV = tangent.y; + // only apply collision response forces if the object is travelling into, and not out of, the collision + if(Phaser.Vec2Utils.dot(shape.physics.velocity, tangent) < 0) { + // Apply horizontal bounce + if(shape.physics.bounce.y > 0) { + shape.physics.velocity.y *= -(shape.physics.bounce.y); + } else { + shape.physics.velocity.y = 0; + } + } + shape.position.y += distance.y; + }; + PhysicsManager.prototype.separate = function (shape, distance, tangent) { + // collision edges + shape.oH = tangent.x; + shape.oV = tangent.y; + // Velocity (move to temp vars) + // was vx/vy + var velocity = Phaser.Vec2Utils.subtract(shape.position, shape.oldPosition); + // was dp + var dot = Phaser.Vec2Utils.dot(shape.physics.velocity, tangent); + // project velocity onto the collision normal + // was nx/ny + tangent.multiplyByScalar(dot); + // was tx/ty (tangent velocity?) + var tangentVelocity = Phaser.Vec2Utils.subtract(velocity, tangent); + // only apply collision response forces if the object is travelling into, and not out of, the collision + if(dot < 0) { + // Apply horizontal bounce + if(distance.x != 0) { + if(shape.physics.bounce.x > 0) { + shape.physics.velocity.x *= -(shape.physics.bounce.x); + } else { + shape.physics.velocity.x = 0; + } + } + // Apply vertical bounce + if(distance.y != 0) { + if(shape.physics.bounce.y > 0) { + shape.physics.velocity.y *= -(shape.physics.bounce.y); + } else { + shape.physics.velocity.y = 0; + } + } + } else { + // moving out of collision + } + // project object out of collision + //console.log('proj out', distance.x, distance.y,'dot',dot); + shape.position.add(distance); + }; return PhysicsManager; })(); Physics.PhysicsManager = PhysicsManager; - /* - private processWorld(px, py, dx, dy, tile) { - - // Velocity - //this.sprite.physics.velocity.x = this.position.x - this.oldPosition.x; - //this.sprite.physics.velocity.y = this.position.y - this.oldPosition.y; - - // Optimise!!! - var dp: number = (this.sprite.physics.velocity.x * dx + this.sprite.physics.velocity.y * dy); - var nx: number = dp * dx; - var ny: number = dp * dy; - var tx: number = this.sprite.physics.velocity.x - nx; - var ty: number = this.sprite.physics.velocity.y - ny; - - var bx, by, fx, fy; - - if (dp < 0) - { - fx = tx * this.sprite.physics.friction.x; - fy = ty * this.sprite.physics.friction.y; - bx = (nx * (1 + this.sprite.physics.bounce.x)); - by = (ny * (1 + this.sprite.physics.bounce.y)); - //this.sprite.physics.velocity.x = bx; - //this.sprite.physics.velocity.y = by; - } - else - { - bx = by = fx = fy = 0; - } - - this.position.x += px; - this.position.y += py; - - this.oldPosition.x += px + bx + fx; - this.oldPosition.y += py + by + fy; - - } - */ - })(Phaser.Physics || (Phaser.Physics = {})); + })(Phaser.Physics || (Phaser.Physics = {})); var Physics = Phaser.Physics; })(Phaser || (Phaser = {})); var Phaser; @@ -11167,7 +11234,6 @@ var Phaser; * Used to create texture when texture image is small than size of the zone. */ function (regionWidth, regionHeight) { - console.log('create repeat'); // Work out how many we'll need of the source image to make it tile properly var tileWidth = Math.ceil(this.width / regionWidth) * regionWidth; var tileHeight = Math.ceil(this.height / regionHeight) * regionHeight; @@ -12013,6 +12079,17 @@ var Phaser; this.y *= y || x; return this; }; + Vec2.prototype.multiplyByScalar = /** + * Multiply this vector by the given scalar. + * + * @param {number} scalar + * @return {Vec2} This for chaining. + */ + function (scalar) { + this.x *= scalar; + this.y *= scalar; + return this; + }; Vec2.prototype.divideByScalar = /** * Divide this vector by the given scalar. *