From 39e7b84cd93013f6e24e76a276da536addfafc4c Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Fri, 31 May 2013 04:20:49 +0100 Subject: [PATCH] Flixel level separation merged with the new Physics shapes. --- Phaser/Phaser.csproj | 4 + Phaser/components/sprite/Physics.ts | 6 + Phaser/core/Polygon.ts | 54 +++ Phaser/physics/AABB.ts | 85 ++++- Phaser/physics/Circle.ts | 88 ++++- Phaser/physics/IPhysicsShape.ts | 13 +- Phaser/physics/PhysicsManager.ts | 371 +++++++++++++++++-- Phaser/utils/SpriteUtils.ts | 22 ++ Tests/Tests.csproj | 4 + Tests/phaser.js | 553 ++++++++++++++++++++++++---- Tests/physics/aabb vs aabb 1.js | 10 +- Tests/physics/aabb vs aabb 1.ts | 10 +- Tests/physics/circle 1.js | 13 +- Tests/physics/circle 1.ts | 16 +- Tests/physics/test 1.js | 42 +++ Tests/physics/test 1.ts | 70 ++++ build/phaser.d.ts | 76 +++- build/phaser.js | 553 ++++++++++++++++++++++++---- 18 files changed, 1782 insertions(+), 208 deletions(-) create mode 100644 Phaser/core/Polygon.ts create mode 100644 Tests/physics/test 1.js create mode 100644 Tests/physics/test 1.ts diff --git a/Phaser/Phaser.csproj b/Phaser/Phaser.csproj index e3c83e30..0196f2ed 100644 --- a/Phaser/Phaser.csproj +++ b/Phaser/Phaser.csproj @@ -76,6 +76,10 @@ Point.ts + + + Polygon.ts + Rectangle.ts diff --git a/Phaser/components/sprite/Physics.ts b/Phaser/components/sprite/Physics.ts index cce6c279..cf52fa05 100644 --- a/Phaser/components/sprite/Physics.ts +++ b/Phaser/components/sprite/Physics.ts @@ -25,7 +25,10 @@ module Phaser.Components { this.velocity = new Vec2; this.acceleration = new Vec2; + this.touching = Phaser.Types.NONE; + this.wasTouching = Phaser.Types.NONE; + this.allowCollisions = Phaser.Types.ANY; this.shape = this.game.world.physics.add(new Phaser.Physics.AABB(this.game, this._sprite, this._sprite.x, this._sprite.y, this._sprite.width, this._sprite.height)); @@ -47,6 +50,7 @@ module Phaser.Components { * @type {boolean} */ public moves: bool = true; + public mass: number = 1; public gravity: Vec2; public drag: Vec2; @@ -56,6 +60,8 @@ module Phaser.Components { public acceleration: Vec2; public touching: number; + public allowCollisions: number; + public wasTouching: number; public setCircle(diameter: number) { diff --git a/Phaser/core/Polygon.ts b/Phaser/core/Polygon.ts new file mode 100644 index 00000000..d1e851c4 --- /dev/null +++ b/Phaser/core/Polygon.ts @@ -0,0 +1,54 @@ +/// + +/** +* Phaser - Polygon +* +* +*/ + +module Phaser { + + export class Polygon { + + /** + * + **/ + constructor(game: Game, points: Point[]) { + + this.game = game; + this.context = game.stage.context; + + this.points = []; + + for (var i = 0; i < points.length; i++) + { + this.points.push(new Point().copyFrom(points[i])); + } + + } + + public points: Point[]; + public game: Game; + public context: CanvasRenderingContext2D; + + public render() { + + this.context.beginPath(); + this.context.strokeStyle = 'rgb(255,255,0)'; + this.context.moveTo(this.points[0].x, this.points[0].y); + + for (var i = 1; i < this.points.length; i++) + { + this.context.lineTo(this.points[i].x, this.points[i].y); + } + + this.context.lineTo(this.points[0].x, this.points[0].y); + + this.context.stroke(); + this.context.closePath(); + + } + + } + +} \ No newline at end of file diff --git a/Phaser/physics/AABB.ts b/Phaser/physics/AABB.ts index a508cbd8..e7a7dadd 100644 --- a/Phaser/physics/AABB.ts +++ b/Phaser/physics/AABB.ts @@ -47,9 +47,6 @@ module Phaser.Physics { public scale: Vec2; public bounds: Rectangle; - public oH: number; - public oV: number; - public preUpdate() { this.oldPosition.copyFrom(this.position); @@ -88,12 +85,6 @@ module Phaser.Physics { public render(context:CanvasRenderingContext2D) { - //context.beginPath(); - //context.strokeStyle = 'rgb(255,255,0)'; - //context.strokeRect(this.bounds.x, this.bounds.y, this.bounds.width, this.bounds.height); - //context.stroke(); - //context.closePath(); - 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); @@ -104,7 +95,7 @@ module Phaser.Physics { context.fillStyle = 'rgb(0,255,0)'; context.fillRect(this.position.x, this.position.y, 2, 2); - if (this.physics.touching == Phaser.Types.LEFT) + if (this.physics.touching & Phaser.Types.LEFT) { context.beginPath(); context.strokeStyle = 'rgb(255,0,0)'; @@ -113,7 +104,7 @@ module Phaser.Physics { context.stroke(); context.closePath(); } - else if (this.physics.touching == Phaser.Types.RIGHT) + if (this.physics.touching & Phaser.Types.RIGHT) { context.beginPath(); context.strokeStyle = 'rgb(255,0,0)'; @@ -123,7 +114,7 @@ module Phaser.Physics { context.closePath(); } - if (this.physics.touching == Phaser.Types.UP) + if (this.physics.touching & Phaser.Types.UP) { context.beginPath(); context.strokeStyle = 'rgb(255,0,0)'; @@ -132,7 +123,7 @@ module Phaser.Physics { context.stroke(); context.closePath(); } - else if (this.physics.touching == Phaser.Types.DOWN) + if (this.physics.touching & Phaser.Types.DOWN) { context.beginPath(); context.strokeStyle = 'rgb(255,0,0)'; @@ -144,6 +135,74 @@ module Phaser.Physics { } + public get hullWidth(): number { + + if (this.deltaX > 0) + { + return this.bounds.width + this.deltaX; + } + else + { + return this.bounds.width - this.deltaX; + } + + } + + public get hullHeight(): number { + + if (this.deltaY > 0) + { + return this.bounds.height + this.deltaY; + } + else + { + return this.bounds.height - this.deltaY; + } + + } + + public get hullX(): number { + + if (this.position.x < this.oldPosition.x) + { + return this.position.x; + } + else + { + return this.oldPosition.x; + } + + } + + public get hullY(): number { + + if (this.position.y < this.oldPosition.y) + { + return this.position.y; + } + else + { + return this.oldPosition.y; + } + + } + + public get deltaXAbs(): number { + return (this.deltaX > 0 ? this.deltaX : -this.deltaX); + } + + public get deltaYAbs(): number { + return (this.deltaY > 0 ? this.deltaY : -this.deltaY); + } + + public get deltaX(): number { + return this.position.x - this.oldPosition.x; + } + + public get deltaY(): number { + return this.position.y - this.oldPosition.y; + } + } } \ No newline at end of file diff --git a/Phaser/physics/Circle.ts b/Phaser/physics/Circle.ts index 11fc6f44..52fd0c99 100644 --- a/Phaser/physics/Circle.ts +++ b/Phaser/physics/Circle.ts @@ -49,13 +49,14 @@ module Phaser.Physics { public bounds: Rectangle; public radius: number; - public oH: number; - public oV: number; public preUpdate() { this.oldPosition.copyFrom(this.position); + this.bounds.x = this.position.x - this.bounds.halfWidth; + this.bounds.y = this.position.y - this.bounds.halfHeight; + if (this.sprite) { this.position.setTo((this.sprite.x + this.bounds.halfWidth) + this.offset.x, (this.sprite.y + this.bounds.halfHeight) + this.offset.y); @@ -74,8 +75,8 @@ module Phaser.Physics { public update() { - this.bounds.x = this.position.x; - this.bounds.y = this.position.y; + //this.bounds.x = this.position.x; + //this.bounds.y = this.position.y; } @@ -89,15 +90,20 @@ module Phaser.Physics { public render(context:CanvasRenderingContext2D) { context.beginPath(); - context.strokeStyle = 'rgb(0,255,0)'; + //context.strokeStyle = 'rgb(255,255,0)'; + //context.strokeRect(this.position.x - this.bounds.halfWidth, this.position.y - this.bounds.halfHeight, this.bounds.width, this.bounds.height); + //context.fillStyle = 'rgba(0,0,255,0.8)'; + context.strokeStyle = 'rgba(0,0,255,0.5)'; context.arc(this.position.x, this.position.y, this.radius, 0, Math.PI * 2); + //context.fill(); context.stroke(); context.closePath(); // center point - context.fillStyle = 'rgb(0,255,0)'; + context.fillStyle = 'rgb(255,255,0)'; context.fillRect(this.position.x, this.position.y, 2, 2); + /* if (this.oH == 1) { context.beginPath(); @@ -135,9 +141,79 @@ module Phaser.Physics { context.stroke(); context.closePath(); } + */ } + public get hullWidth(): number { + + if (this.deltaX > 0) + { + return this.bounds.width + this.deltaX; + } + else + { + return this.bounds.width - this.deltaX; + } + + } + + public get hullHeight(): number { + + if (this.deltaY > 0) + { + return this.bounds.height + this.deltaY; + } + else + { + return this.bounds.height - this.deltaY; + } + + } + + public get hullX(): number { + + if (this.position.x < this.oldPosition.x) + { + return this.position.x; + } + else + { + return this.oldPosition.x; + } + + } + + public get hullY(): number { + + if (this.position.y < this.oldPosition.y) + { + return this.position.y; + } + else + { + return this.oldPosition.y; + } + + } + + public get deltaXAbs(): number { + return (this.deltaX > 0 ? this.deltaX : -this.deltaX); + } + + public get deltaYAbs(): number { + return (this.deltaY > 0 ? this.deltaY : -this.deltaY); + } + + public get deltaX(): number { + return this.position.x - this.oldPosition.x; + } + + public get deltaY(): number { + return this.position.y - this.oldPosition.y; + } + + } } \ No newline at end of file diff --git a/Phaser/physics/IPhysicsShape.ts b/Phaser/physics/IPhysicsShape.ts index bc172da1..15cb2a75 100644 --- a/Phaser/physics/IPhysicsShape.ts +++ b/Phaser/physics/IPhysicsShape.ts @@ -20,14 +20,23 @@ module Phaser.Physics { offset: Vec2; bounds: Rectangle; - oH: number; - oV: number; + //oH: number; + //oV: number; setSize(width: number, height: number); preUpdate(); update(); render(context:CanvasRenderingContext2D); + hullX; + hullY; + hullWidth; + hullHeight; + deltaX; + deltaY; + deltaXAbs; + deltaYAbs; + } } diff --git a/Phaser/physics/PhysicsManager.ts b/Phaser/physics/PhysicsManager.ts index 10c010e9..49d0dcbd 100644 --- a/Phaser/physics/PhysicsManager.ts +++ b/Phaser/physics/PhysicsManager.ts @@ -87,14 +87,13 @@ module Phaser.Physics { this.updateMotion(this._objects[i]); this.collideWorld(this._objects[i]); - if (this._objects[i].physics.immovable == false) + for (var x = 0; x < this._length; x++) { - for (var x = 0; x < this._length; x++) + if (this._objects[x] && this._objects[x] !== this._objects[i]) { - if (this._objects[x] !== this._objects[i]) - { - this.collideShapes(this._objects[i], this._objects[x]); - } + //this.collideShapes(this._objects[i], this._objects[x]); + var r = this.NEWseparate(this._objects[i], this._objects[x]); + //console.log('sep', r); } } @@ -203,63 +202,379 @@ module Phaser.Physics { return; } + this._distance.setTo(0, 0); + this._tangent.setTo(0, 0); + // Simple bounds check first if (RectangleUtils.intersects(shapeA.bounds, shapeB.bounds)) { // Collide on the x-axis - if (shapeA.bounds.right >= shapeB.bounds.x && shapeA.bounds.right <= shapeB.bounds.right) + if (shapeA.physics.velocity.x > 0 && shapeA.bounds.right > shapeB.bounds.x && shapeA.bounds.right <= shapeB.bounds.right) { // The right side of ShapeA hit the left side of ShapeB this._distance.x = shapeB.bounds.x - shapeA.bounds.right; if (this._distance.x != 0) { - this._tangent.setTo(-1, 0); - this.separateX(shapeA, shapeB, this._distance, this._tangent); + this._tangent.x = -1; } } - else if (shapeA.bounds.x <= shapeB.bounds.right && shapeA.bounds.x >= shapeB.bounds.x) + else if (shapeA.physics.velocity.x < 0 && shapeA.bounds.x < shapeB.bounds.right && shapeA.bounds.x >= shapeB.bounds.x) { // The left side of ShapeA hit the right side of ShapeB this._distance.x = shapeB.bounds.right - shapeA.bounds.x; if (this._distance.x != 0) { - this._tangent.setTo(1, 0); - this.separateX(shapeA, shapeB, this._distance, this._tangent); + this._tangent.x = 1; } } // Collide on the y-axis - if (shapeA.bounds.y <= shapeB.bounds.bottom && shapeA.bounds.y >= shapeB.bounds.y) + if (shapeA.physics.velocity.y < 0 && shapeA.bounds.y < shapeB.bounds.bottom && shapeA.bounds.y > shapeB.bounds.y) { - console.log(shapeA.bounds.y, shapeB.bounds.bottom, shapeB.bounds.y); + console.log('top A -> bot B'); // The top of ShapeA hit the bottom of ShapeB this._distance.y = shapeB.bounds.bottom - shapeA.bounds.y; + console.log(shapeA.bounds, shapeB.bounds, this._distance.y); if (this._distance.y != 0) { - this._tangent.setTo(0, 1); - this.separateY(shapeA, shapeB, this._distance, this._tangent); + this._tangent.y = 1; } } - else if (shapeA.bounds.bottom >= shapeB.bounds.y && shapeA.bounds.bottom <= shapeB.bounds.bottom) + else if (shapeA.physics.velocity.y > 0 && shapeA.bounds.bottom > shapeB.bounds.y && shapeA.bounds.bottom < shapeB.bounds.bottom) { - console.log(shapeA.bounds.bottom, shapeB.bounds.y, shapeB.bounds.bottom); // The bottom of ShapeA hit the top of ShapeB this._distance.y = shapeB.bounds.y - shapeA.bounds.bottom; if (this._distance.y != 0) { - this._tangent.setTo(0, -1); - this.separateY(shapeA, shapeB, this._distance, this._tangent); + this._tangent.y = -1; } } - + + // Separate + if (this._distance.equals(0) == false) + { + //this.separate(shapeA, shapeB, this._distance, this._tangent); + } } } + /** + * The core Collision separation function used by Collision.overlap. + * @param object1 The first GameObject to separate + * @param object2 The second GameObject to separate + * @returns {boolean} Returns true if the objects were separated, otherwise false. + */ + public NEWseparate(object1, object2): bool { + + var separatedX: bool = this.separateSpriteToSpriteX(object1, object2); + var separatedY: bool = this.separateSpriteToSpriteY(object1, object2); + + return separatedX || separatedY; + + } + + private checkHullIntersection(shape1:IPhysicsShape, shape2:IPhysicsShape): bool { + + //if ((shape1.hullX + shape1.hullWidth > shape2.hullX) && (shape1.hullX < shape2.hullX + shape2.bounds.width) && (shape1.hullY + shape1.hullHeight > shape2.hullY) && (shape1.hullY < shape2.hullY + shape2.hullHeight)) + // maybe not bounds.width? + if ((shape1.hullX + shape1.hullWidth > shape2.hullX) && (shape1.hullX < shape2.hullX + shape2.hullWidth) && (shape1.hullY + shape1.hullHeight > shape2.hullY) && (shape1.hullY < shape2.hullY + shape2.hullHeight)) + { + return true; + } + else + { + return false; + } + + } + + /** + * 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 separateSpriteToSpriteX(object1:Sprite, object2:Sprite): bool { + + // Can't separate two immovable objects + if (object1.physics.immovable && object2.physics.immovable) + { + return false; + } + + // First, get the two object deltas + var overlap: number = 0; + + if (object1.physics.shape.deltaX != object2.physics.shape.deltaX) + { + if (RectangleUtils.intersects(object1.physics.shape.bounds, object2.physics.shape.bounds)) + { + //var maxOverlap: number = object1.physics.shape.deltaXAbs + object2.physics.shape.deltaXAbs + Collision.OVERLAP_BIAS; + var maxOverlap: number = object1.physics.shape.deltaXAbs + object2.physics.shape.deltaXAbs + 4; + + // If they did overlap (and can), figure out by how much and flip the corresponding flags + if (object1.physics.shape.deltaX > object2.physics.shape.deltaX) + { + overlap = object1.physics.shape.bounds.right - object2.physics.shape.bounds.x; + + if ((overlap > maxOverlap) || !(object1.physics.allowCollisions & Phaser.Types.RIGHT) || !(object2.physics.allowCollisions & Phaser.Types.LEFT)) + { + overlap = 0; + } + else + { + object1.physics.touching |= Phaser.Types.RIGHT; + object2.physics.touching |= Phaser.Types.LEFT; + } + } + else if (object1.physics.shape.deltaX < object2.physics.shape.deltaX) + { + overlap = object1.physics.shape.bounds.x - object2.physics.shape.bounds.width - object2.physics.shape.bounds.x; + + if ((-overlap > maxOverlap) || !(object1.physics.allowCollisions & Phaser.Types.LEFT) || !(object2.physics.allowCollisions & Phaser.Types.RIGHT)) + { + overlap = 0; + } + else + { + object1.physics.touching |= Phaser.Types.LEFT; + object2.physics.touching |= Phaser.Types.RIGHT; + } + } + } + } + + // Then adjust their positions and velocities accordingly (if there was any overlap) + if (overlap != 0) + { + var obj1Velocity: number = object1.physics.velocity.x; + var obj2Velocity: number = object2.physics.velocity.x; + + if (!object1.physics.immovable && !object2.physics.immovable) + { + overlap *= 0.5; + object1.physics.shape.position.x = object1.physics.shape.position.x - overlap; + object2.physics.shape.position.x += overlap; + + var obj1NewVelocity: number = Math.sqrt((obj2Velocity * obj2Velocity * object2.physics.mass) / object1.physics.mass) * ((obj2Velocity > 0) ? 1 : -1); + var obj2NewVelocity: number = Math.sqrt((obj1Velocity * obj1Velocity * object1.physics.mass) / object2.physics.mass) * ((obj1Velocity > 0) ? 1 : -1); + var average: number = (obj1NewVelocity + obj2NewVelocity) * 0.5; + obj1NewVelocity -= average; + obj2NewVelocity -= average; + object1.physics.velocity.x = average + obj1NewVelocity * object1.physics.bounce.x; + object2.physics.velocity.x = average + obj2NewVelocity * object2.physics.bounce.x; + } + else if (!object1.physics.immovable) + { + overlap *= 2; + object1.physics.shape.position.x -= overlap; + object1.physics.velocity.x = obj2Velocity - obj1Velocity * object1.physics.bounce.x; + } + else if (!object2.physics.immovable) + { + overlap *= 2; + object2.physics.shape.position.x += overlap; + object2.physics.velocity.x = obj1Velocity - obj2Velocity * object2.physics.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 separateSpriteToSpriteY(object1:Sprite, object2:Sprite): bool { + + // Can't separate two immovable objects + if (object1.physics.immovable && object2.physics.immovable) { + return false; + } + + // First, get the two object deltas + var overlap: number = 0; + + if (object1.physics.shape.deltaY != object2.physics.shape.deltaY) + { + if (RectangleUtils.intersects(object1.physics.shape.bounds, object2.physics.shape.bounds)) + { + // This is the only place to use the DeltaAbs values + //var maxOverlap: number = object1.physics.shape.deltaYAbs + object2.physics.shape.deltaYAbs + Phaser.Types.OVERLAP_BIAS; + var maxOverlap: number = object1.physics.shape.deltaYAbs + object2.physics.shape.deltaYAbs + 4; + + // If they did overlap (and can), figure out by how much and flip the corresponding flags + if (object1.physics.shape.deltaY > object2.physics.shape.deltaY) + { + overlap = object1.physics.shape.bounds.bottom - object2.physics.shape.bounds.y; + + if ((overlap > maxOverlap) || !(object1.physics.allowCollisions & Phaser.Types.DOWN) || !(object2.physics.allowCollisions & Phaser.Types.UP)) + { + overlap = 0; + } + else + { + object1.physics.touching |= Phaser.Types.DOWN; + object2.physics.touching |= Phaser.Types.UP; + } + } + else if (object1.physics.shape.deltaY < object2.physics.shape.deltaY) + { + overlap = object1.physics.shape.bounds.y - object2.physics.shape.bounds.height - object2.physics.shape.bounds.y; + + if ((-overlap > maxOverlap) || !(object1.physics.allowCollisions & Phaser.Types.UP) || !(object2.physics.allowCollisions & Phaser.Types.DOWN)) + { + overlap = 0; + } + else + { + object1.physics.touching |= Phaser.Types.UP; + object2.physics.touching |= Phaser.Types.DOWN; + } + } + } + } + + // Then adjust their positions and velocities accordingly (if there was any overlap) + if (overlap != 0) + { + var obj1Velocity: number = object1.physics.velocity.y; + var obj2Velocity: number = object2.physics.velocity.y; + + if (!object1.physics.immovable && !object2.physics.immovable) + { + overlap *= 0.5; + object1.physics.shape.position.y = object1.physics.shape.position.y - overlap; + object2.physics.shape.position.y += overlap; + + var obj1NewVelocity: number = Math.sqrt((obj2Velocity * obj2Velocity * object2.physics.mass) / object1.physics.mass) * ((obj2Velocity > 0) ? 1 : -1); + var obj2NewVelocity: number = Math.sqrt((obj1Velocity * obj1Velocity * object1.physics.mass) / object2.physics.mass) * ((obj1Velocity > 0) ? 1 : -1); + var average: number = (obj1NewVelocity + obj2NewVelocity) * 0.5; + obj1NewVelocity -= average; + obj2NewVelocity -= average; + object1.physics.velocity.y = average + obj1NewVelocity * object1.physics.bounce.y; + object2.physics.velocity.y = average + obj2NewVelocity * object2.physics.bounce.y; + } + else if (!object1.physics.immovable) + { + overlap *= 2; + object1.physics.shape.position.y -= overlap; + object1.physics.velocity.y = obj2Velocity - obj1Velocity * object1.physics.bounce.y; + // This is special case code that handles things like horizontal moving platforms you can ride + if (object2.active && object2.physics.moves && (object1.physics.shape.deltaY > object2.physics.shape.deltaY)) + { + object1.physics.shape.position.x += object2.physics.shape.position.x - object2.physics.shape.oldPosition.x; + } + } + else if (!object2.physics.immovable) + { + overlap *= 2; + object2.physics.shape.position.y += overlap; + object2.physics.velocity.y = obj1Velocity - obj2Velocity * object2.physics.bounce.y; + // This is special case code that handles things like horizontal moving platforms you can ride + if (object1.active && object1.physics.moves && (object1.physics.shape.deltaY < object2.physics.shape.deltaY)) + { + object2.physics.shape.position.x += object1.physics.shape.position.x - object1.physics.shape.oldPosition.x; + } + } + + return true; + } + else + { + return false; + } + } + + + + + + + + + private separate(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 @@ -324,7 +639,7 @@ module Phaser.Physics { } // collision edges - shapeA.oH = tangent.x; + //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) @@ -361,7 +676,7 @@ module Phaser.Physics { } // collision edges - shapeA.oV = tangent.y; + //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) @@ -396,7 +711,7 @@ module Phaser.Physics { } // collision edges - shapeA.oH = tangent.x; + //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) @@ -430,7 +745,7 @@ module Phaser.Physics { } // collision edges - shapeA.oV = tangent.y; + //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) @@ -450,11 +765,11 @@ module Phaser.Physics { } - private separate(shape:IPhysicsShape, distance: Vec2, tangent: Vec2) { + private OLDseparate(shape:IPhysicsShape, distance: Vec2, tangent: Vec2) { // collision edges - shape.oH = tangent.x; - shape.oV = tangent.y; + //shape.oH = tangent.x; + //shape.oV = tangent.y; // Velocity (move to temp vars) diff --git a/Phaser/utils/SpriteUtils.ts b/Phaser/utils/SpriteUtils.ts index 4511e6a5..c92f38f7 100644 --- a/Phaser/utils/SpriteUtils.ts +++ b/Phaser/utils/SpriteUtils.ts @@ -70,6 +70,28 @@ module Phaser { */ static ALIGN_BOTTOM_RIGHT: number = 8; + + + static getAsPoints(sprite: Sprite): Phaser.Point[] { + + var out: Phaser.Point[] = []; + + // top left + out.push(new Point(sprite.x, sprite.y)); + + // top right + out.push(new Point(sprite.x + sprite.width, sprite.y)); + + // bottom right + out.push(new Point(sprite.x + sprite.width, sprite.y + sprite.height)); + + // bottom left + out.push(new Point(sprite.x, sprite.y + sprite.height)); + + return out; + + } + /** * Checks to see if some GameObject overlaps this GameObject or Group. * If the group has a LOT of things in it, it might be faster to use Collision.overlaps(). diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index ed58efb4..26839bf2 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -82,6 +82,10 @@ circle 1.ts + + + test 1.ts + ballscroller.ts diff --git a/Tests/phaser.js b/Tests/phaser.js index a414e491..b01a4f9c 100644 --- a/Tests/phaser.js +++ b/Tests/phaser.js @@ -3541,6 +3541,18 @@ var Phaser; SpriteUtils.ALIGN_BOTTOM_LEFT = 6; SpriteUtils.ALIGN_BOTTOM_CENTER = 7; SpriteUtils.ALIGN_BOTTOM_RIGHT = 8; + SpriteUtils.getAsPoints = function getAsPoints(sprite) { + var out = []; + // top left + out.push(new Phaser.Point(sprite.x, sprite.y)); + // top right + out.push(new Phaser.Point(sprite.x + sprite.width, sprite.y)); + // bottom right + out.push(new Phaser.Point(sprite.x + sprite.width, sprite.y + sprite.height)); + // bottom left + out.push(new Phaser.Point(sprite.x, sprite.y + sprite.height)); + return out; + }; SpriteUtils.setBounds = /** * Checks to see if some GameObject overlaps this GameObject or Group. * If the group has a LOT of things in it, it might be faster to use Collision.overlaps(). @@ -5891,12 +5903,12 @@ var Phaser; this._objects[i].preUpdate(); this.updateMotion(this._objects[i]); this.collideWorld(this._objects[i]); - if(this._objects[i].physics.immovable == false) { - for(var x = 0; x < this._length; x++) { - if(this._objects[x] !== this._objects[i]) { - this.collideShapes(this._objects[i], this._objects[x]); - } - } + 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); + } } } } @@ -5971,43 +5983,250 @@ var Phaser; if(shapeA.physics.immovable && shapeB.physics.immovable) { return; } + this._distance.setTo(0, 0); + this._tangent.setTo(0, 0); // Simple bounds check first if(Phaser.RectangleUtils.intersects(shapeA.bounds, shapeB.bounds)) { // Collide on the x-axis - if(shapeA.bounds.right >= shapeB.bounds.x && shapeA.bounds.right <= shapeB.bounds.right) { + if(shapeA.physics.velocity.x > 0 && shapeA.bounds.right > shapeB.bounds.x && shapeA.bounds.right <= shapeB.bounds.right) { // The right side of ShapeA hit the left side of ShapeB this._distance.x = shapeB.bounds.x - shapeA.bounds.right; if(this._distance.x != 0) { - this._tangent.setTo(-1, 0); - this.separateX(shapeA, shapeB, this._distance, this._tangent); + this._tangent.x = -1; } - } else if(shapeA.bounds.x <= shapeB.bounds.right && shapeA.bounds.x >= shapeB.bounds.x) { + } else if(shapeA.physics.velocity.x < 0 && shapeA.bounds.x < shapeB.bounds.right && shapeA.bounds.x >= shapeB.bounds.x) { // The left side of ShapeA hit the right side of ShapeB this._distance.x = shapeB.bounds.right - shapeA.bounds.x; if(this._distance.x != 0) { - this._tangent.setTo(1, 0); - this.separateX(shapeA, shapeB, this._distance, this._tangent); + this._tangent.x = 1; } } // Collide on the y-axis - if(shapeA.bounds.y <= shapeB.bounds.bottom && shapeA.bounds.y >= shapeB.bounds.y) { - console.log(shapeA.bounds.y, shapeB.bounds.bottom, shapeB.bounds.y); + if(shapeA.physics.velocity.y < 0 && shapeA.bounds.y < shapeB.bounds.bottom && shapeA.bounds.y > shapeB.bounds.y) { + console.log('top A -> bot B'); // The top of ShapeA hit the bottom of ShapeB this._distance.y = shapeB.bounds.bottom - shapeA.bounds.y; + console.log(shapeA.bounds, shapeB.bounds, this._distance.y); if(this._distance.y != 0) { - this._tangent.setTo(0, 1); - this.separateY(shapeA, shapeB, this._distance, this._tangent); + this._tangent.y = 1; } - } else if(shapeA.bounds.bottom >= shapeB.bounds.y && shapeA.bounds.bottom <= shapeB.bounds.bottom) { - console.log(shapeA.bounds.bottom, shapeB.bounds.y, shapeB.bounds.bottom); + } else if(shapeA.physics.velocity.y > 0 && shapeA.bounds.bottom > shapeB.bounds.y && shapeA.bounds.bottom < shapeB.bounds.bottom) { // The bottom of ShapeA hit the top of ShapeB this._distance.y = shapeB.bounds.y - shapeA.bounds.bottom; if(this._distance.y != 0) { - this._tangent.setTo(0, -1); - this.separateY(shapeA, shapeB, this._distance, this._tangent); + this._tangent.y = -1; + } + } + // Separate + if(this._distance.equals(0) == false) { + //this.separate(shapeA, shapeB, this._distance, this._tangent); + } + } + }; + PhysicsManager.prototype.NEWseparate = /** + * The core Collision separation function used by Collision.overlap. + * @param object1 The first GameObject to separate + * @param object2 The second GameObject to separate + * @returns {boolean} Returns true if the objects were separated, otherwise false. + */ + function (object1, object2) { + var separatedX = this.separateSpriteToSpriteX(object1, object2); + var separatedY = this.separateSpriteToSpriteY(object1, object2); + return separatedX || separatedY; + }; + PhysicsManager.prototype.checkHullIntersection = function (shape1, shape2) { + //if ((shape1.hullX + shape1.hullWidth > shape2.hullX) && (shape1.hullX < shape2.hullX + shape2.bounds.width) && (shape1.hullY + shape1.hullHeight > shape2.hullY) && (shape1.hullY < shape2.hullY + shape2.hullHeight)) + // maybe not bounds.width? + if((shape1.hullX + shape1.hullWidth > shape2.hullX) && (shape1.hullX < shape2.hullX + shape2.hullWidth) && (shape1.hullY + shape1.hullHeight > shape2.hullY) && (shape1.hullY < shape2.hullY + shape2.hullHeight)) { + return true; + } else { + return false; + } + }; + PhysicsManager.prototype.separateSpriteToSpriteX = /** + * 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 (object1, object2) { + // Can't separate two immovable objects + if(object1.physics.immovable && object2.physics.immovable) { + return false; + } + // First, get the two object deltas + var overlap = 0; + if(object1.physics.shape.deltaX != object2.physics.shape.deltaX) { + if(Phaser.RectangleUtils.intersects(object1.physics.shape.bounds, object2.physics.shape.bounds)) { + //var maxOverlap: number = object1.physics.shape.deltaXAbs + object2.physics.shape.deltaXAbs + Collision.OVERLAP_BIAS; + var maxOverlap = object1.physics.shape.deltaXAbs + object2.physics.shape.deltaXAbs + 4; + // If they did overlap (and can), figure out by how much and flip the corresponding flags + if(object1.physics.shape.deltaX > object2.physics.shape.deltaX) { + overlap = object1.physics.shape.bounds.right - object2.physics.shape.bounds.x; + if((overlap > maxOverlap) || !(object1.physics.allowCollisions & Phaser.Types.RIGHT) || !(object2.physics.allowCollisions & Phaser.Types.LEFT)) { + overlap = 0; + } else { + object1.physics.touching |= Phaser.Types.RIGHT; + object2.physics.touching |= Phaser.Types.LEFT; + } + } else if(object1.physics.shape.deltaX < object2.physics.shape.deltaX) { + overlap = object1.physics.shape.bounds.x - object2.physics.shape.bounds.width - object2.physics.shape.bounds.x; + if((-overlap > maxOverlap) || !(object1.physics.allowCollisions & Phaser.Types.LEFT) || !(object2.physics.allowCollisions & Phaser.Types.RIGHT)) { + overlap = 0; + } else { + object1.physics.touching |= Phaser.Types.LEFT; + object2.physics.touching |= Phaser.Types.RIGHT; + } } } } + // Then adjust their positions and velocities accordingly (if there was any overlap) + if(overlap != 0) { + var obj1Velocity = object1.physics.velocity.x; + var obj2Velocity = object2.physics.velocity.x; + if(!object1.physics.immovable && !object2.physics.immovable) { + overlap *= 0.5; + object1.physics.shape.position.x = object1.physics.shape.position.x - overlap; + object2.physics.shape.position.x += overlap; + var obj1NewVelocity = Math.sqrt((obj2Velocity * obj2Velocity * object2.physics.mass) / object1.physics.mass) * ((obj2Velocity > 0) ? 1 : -1); + var obj2NewVelocity = Math.sqrt((obj1Velocity * obj1Velocity * object1.physics.mass) / object2.physics.mass) * ((obj1Velocity > 0) ? 1 : -1); + var average = (obj1NewVelocity + obj2NewVelocity) * 0.5; + obj1NewVelocity -= average; + obj2NewVelocity -= average; + object1.physics.velocity.x = average + obj1NewVelocity * object1.physics.bounce.x; + object2.physics.velocity.x = average + obj2NewVelocity * object2.physics.bounce.x; + } else if(!object1.physics.immovable) { + overlap *= 2; + object1.physics.shape.position.x -= overlap; + object1.physics.velocity.x = obj2Velocity - obj1Velocity * object1.physics.bounce.x; + } else if(!object2.physics.immovable) { + overlap *= 2; + object2.physics.shape.position.x += overlap; + object2.physics.velocity.x = obj1Velocity - obj2Velocity * object2.physics.bounce.x; + } + return true; + } else { + return false; + } + }; + PhysicsManager.prototype.separateSpriteToSpriteY = /** + * 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 (object1, object2) { + // Can't separate two immovable objects + if(object1.physics.immovable && object2.physics.immovable) { + return false; + } + // First, get the two object deltas + var overlap = 0; + if(object1.physics.shape.deltaY != object2.physics.shape.deltaY) { + if(Phaser.RectangleUtils.intersects(object1.physics.shape.bounds, object2.physics.shape.bounds)) { + // This is the only place to use the DeltaAbs values + //var maxOverlap: number = object1.physics.shape.deltaYAbs + object2.physics.shape.deltaYAbs + Phaser.Types.OVERLAP_BIAS; + var maxOverlap = object1.physics.shape.deltaYAbs + object2.physics.shape.deltaYAbs + 4; + // If they did overlap (and can), figure out by how much and flip the corresponding flags + if(object1.physics.shape.deltaY > object2.physics.shape.deltaY) { + overlap = object1.physics.shape.bounds.bottom - object2.physics.shape.bounds.y; + if((overlap > maxOverlap) || !(object1.physics.allowCollisions & Phaser.Types.DOWN) || !(object2.physics.allowCollisions & Phaser.Types.UP)) { + overlap = 0; + } else { + object1.physics.touching |= Phaser.Types.DOWN; + object2.physics.touching |= Phaser.Types.UP; + } + } else if(object1.physics.shape.deltaY < object2.physics.shape.deltaY) { + overlap = object1.physics.shape.bounds.y - object2.physics.shape.bounds.height - object2.physics.shape.bounds.y; + if((-overlap > maxOverlap) || !(object1.physics.allowCollisions & Phaser.Types.UP) || !(object2.physics.allowCollisions & Phaser.Types.DOWN)) { + overlap = 0; + } else { + object1.physics.touching |= Phaser.Types.UP; + object2.physics.touching |= Phaser.Types.DOWN; + } + } + } + } + // Then adjust their positions and velocities accordingly (if there was any overlap) + if(overlap != 0) { + var obj1Velocity = object1.physics.velocity.y; + var obj2Velocity = object2.physics.velocity.y; + if(!object1.physics.immovable && !object2.physics.immovable) { + overlap *= 0.5; + object1.physics.shape.position.y = object1.physics.shape.position.y - overlap; + object2.physics.shape.position.y += overlap; + var obj1NewVelocity = Math.sqrt((obj2Velocity * obj2Velocity * object2.physics.mass) / object1.physics.mass) * ((obj2Velocity > 0) ? 1 : -1); + var obj2NewVelocity = Math.sqrt((obj1Velocity * obj1Velocity * object1.physics.mass) / object2.physics.mass) * ((obj1Velocity > 0) ? 1 : -1); + var average = (obj1NewVelocity + obj2NewVelocity) * 0.5; + obj1NewVelocity -= average; + obj2NewVelocity -= average; + object1.physics.velocity.y = average + obj1NewVelocity * object1.physics.bounce.y; + object2.physics.velocity.y = average + obj2NewVelocity * object2.physics.bounce.y; + } else if(!object1.physics.immovable) { + overlap *= 2; + object1.physics.shape.position.y -= overlap; + object1.physics.velocity.y = obj2Velocity - obj1Velocity * object1.physics.bounce.y; + // This is special case code that handles things like horizontal moving platforms you can ride + if(object2.active && object2.physics.moves && (object1.physics.shape.deltaY > object2.physics.shape.deltaY)) { + object1.physics.shape.position.x += object2.physics.shape.position.x - object2.physics.shape.oldPosition.x; + } + } else if(!object2.physics.immovable) { + overlap *= 2; + object2.physics.shape.position.y += overlap; + object2.physics.velocity.y = obj1Velocity - obj2Velocity * object2.physics.bounce.y; + // This is special case code that handles things like horizontal moving platforms you can ride + if(object1.active && object1.physics.moves && (object1.physics.shape.deltaY < object2.physics.shape.deltaY)) { + object2.physics.shape.position.x += object1.physics.shape.position.x - object1.physics.shape.oldPosition.x; + } + } + return true; + } else { + return false; + } + }; + PhysicsManager.prototype.separate = function (shapeA, shapeB, distance, tangent) { + 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 = Phaser.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('------------------------------------------------'); }; PhysicsManager.prototype.collideWorld = function (shape) { // Collide on the x-axis @@ -6052,7 +6271,7 @@ var Phaser; shapeB.physics.touching |= Phaser.Types.LEFT; } // collision edges - shapeA.oH = tangent.x; + //shapeA.oH = tangent.x; // only apply collision response forces if the object is travelling into, and not out of, the collision if(Phaser.Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) { // Apply horizontal bounce @@ -6076,7 +6295,7 @@ var Phaser; shapeB.physics.touching |= Phaser.Types.UP; } // collision edges - shapeA.oV = tangent.y; + //shapeA.oV = tangent.y; // only apply collision response forces if the object is travelling into, and not out of, the collision if(Phaser.Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) { // Apply horizontal bounce @@ -6098,7 +6317,7 @@ var Phaser; shapeA.physics.touching |= Phaser.Types.RIGHT; } // collision edges - shapeA.oH = tangent.x; + //shapeA.oH = tangent.x; // only apply collision response forces if the object is travelling into, and not out of, the collision if(Phaser.Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) { // Apply horizontal bounce @@ -6119,7 +6338,7 @@ var Phaser; shapeA.physics.touching |= Phaser.Types.DOWN; } // collision edges - shapeA.oV = tangent.y; + //shapeA.oV = tangent.y; // only apply collision response forces if the object is travelling into, and not out of, the collision if(Phaser.Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) { // Apply horizontal bounce @@ -6131,10 +6350,10 @@ var Phaser; } shapeA.position.y += distance.y; }; - PhysicsManager.prototype.separate = function (shape, distance, tangent) { + PhysicsManager.prototype.OLDseparate = function (shape, distance, tangent) { // collision edges - shape.oH = tangent.x; - shape.oV = tangent.y; + //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); @@ -6266,11 +6485,6 @@ var Phaser; this.bounds.height = height; }; AABB.prototype.render = function (context) { - //context.beginPath(); - //context.strokeStyle = 'rgb(255,255,0)'; - //context.strokeRect(this.bounds.x, this.bounds.y, this.bounds.width, this.bounds.height); - //context.stroke(); - //context.closePath(); 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); @@ -6279,14 +6493,15 @@ var Phaser; // center point context.fillStyle = 'rgb(0,255,0)'; context.fillRect(this.position.x, this.position.y, 2, 2); - if(this.physics.touching == Phaser.Types.LEFT) { + if(this.physics.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(); - } else if(this.physics.touching == Phaser.Types.RIGHT) { + } + if(this.physics.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); @@ -6294,14 +6509,15 @@ var Phaser; context.stroke(); context.closePath(); } - if(this.physics.touching == Phaser.Types.UP) { + if(this.physics.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(); - } else if(this.physics.touching == Phaser.Types.DOWN) { + } + if(this.physics.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); @@ -6310,6 +6526,78 @@ var Phaser; context.closePath(); } }; + Object.defineProperty(AABB.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(AABB.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(AABB.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(AABB.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(AABB.prototype, "deltaXAbs", { + get: function () { + return (this.deltaX > 0 ? this.deltaX : -this.deltaX); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(AABB.prototype, "deltaYAbs", { + get: function () { + return (this.deltaY > 0 ? this.deltaY : -this.deltaY); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(AABB.prototype, "deltaX", { + get: function () { + return this.position.x - this.oldPosition.x; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(AABB.prototype, "deltaY", { + get: function () { + return this.position.y - this.oldPosition.y; + }, + enumerable: true, + configurable: true + }); return AABB; })(); Physics.AABB = AABB; @@ -12279,6 +12567,8 @@ var Phaser; } Circle.prototype.preUpdate = function () { this.oldPosition.copyFrom(this.position); + this.bounds.x = this.position.x - this.bounds.halfWidth; + this.bounds.y = this.position.y - this.bounds.halfHeight; if(this.sprite) { this.position.setTo((this.sprite.x + this.bounds.halfWidth) + this.offset.x, (this.sprite.y + this.bounds.halfHeight) + this.offset.y); // Update scale / dimensions @@ -12291,53 +12581,138 @@ var Phaser; } }; Circle.prototype.update = function () { - this.bounds.x = this.position.x; - this.bounds.y = this.position.y; - }; + //this.bounds.x = this.position.x; + //this.bounds.y = this.position.y; + }; Circle.prototype.setSize = function (width, height) { this.bounds.width = width; this.bounds.height = height; }; Circle.prototype.render = function (context) { context.beginPath(); - context.strokeStyle = 'rgb(0,255,0)'; + //context.strokeStyle = 'rgb(255,255,0)'; + //context.strokeRect(this.position.x - this.bounds.halfWidth, this.position.y - this.bounds.halfHeight, this.bounds.width, this.bounds.height); + //context.fillStyle = 'rgba(0,0,255,0.8)'; + context.strokeStyle = 'rgba(0,0,255,0.5)'; context.arc(this.position.x, this.position.y, this.radius, 0, Math.PI * 2); + //context.fill(); context.stroke(); context.closePath(); // center point - context.fillStyle = 'rgb(0,255,0)'; + context.fillStyle = 'rgb(255,255,0)'; context.fillRect(this.position.x, this.position.y, 2, 2); - if(this.oH == 1) { - 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(); - } else if(this.oH == -1) { - 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.oH == 1) + { + 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.oV == 1) { - 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(); - } else if(this.oV == -1) { - 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(); + else if (this.oH == -1) + { + 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.oV == 1) + { + 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(); + } + else if (this.oV == -1) + { + 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(); + } + */ + }; + Object.defineProperty(Circle.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(Circle.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(Circle.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(Circle.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(Circle.prototype, "deltaXAbs", { + get: function () { + return (this.deltaX > 0 ? this.deltaX : -this.deltaX); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Circle.prototype, "deltaYAbs", { + get: function () { + return (this.deltaY > 0 ? this.deltaY : -this.deltaY); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Circle.prototype, "deltaX", { + get: function () { + return this.position.x - this.oldPosition.x; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Circle.prototype, "deltaY", { + get: function () { + return this.position.y - this.oldPosition.y; + }, + enumerable: true, + configurable: true + }); return Circle; })(); Physics.Circle = Circle; @@ -12368,6 +12743,7 @@ var Phaser; * @type {boolean} */ this.moves = true; + this.mass = 1; this.game = parent.game; this._sprite = parent; this.gravity = Phaser.Vec2Utils.clone(this.game.world.physics.gravity); @@ -12377,6 +12753,8 @@ var Phaser; this.velocity = new Phaser.Vec2(); this.acceleration = new Phaser.Vec2(); this.touching = Phaser.Types.NONE; + this.wasTouching = Phaser.Types.NONE; + this.allowCollisions = Phaser.Types.ANY; this.shape = this.game.world.physics.add(new Phaser.Physics.AABB(this.game, this._sprite, this._sprite.x, this._sprite.y, this._sprite.width, this._sprite.height)); } Physics.prototype.setCircle = function (diameter) { @@ -12415,6 +12793,41 @@ var Phaser; var Components = Phaser.Components; })(Phaser || (Phaser = {})); /// +/** +* Phaser - Polygon +* +* +*/ +var Phaser; +(function (Phaser) { + var Polygon = (function () { + /** + * + **/ + function Polygon(game, points) { + this.game = game; + this.context = game.stage.context; + this.points = []; + for(var i = 0; i < points.length; i++) { + this.points.push(new Phaser.Point().copyFrom(points[i])); + } + } + Polygon.prototype.render = function () { + this.context.beginPath(); + this.context.strokeStyle = 'rgb(255,255,0)'; + this.context.moveTo(this.points[0].x, this.points[0].y); + for(var i = 1; i < this.points.length; i++) { + this.context.lineTo(this.points[i].x, this.points[i].y); + } + this.context.lineTo(this.points[0].x, this.points[0].y); + this.context.stroke(); + this.context.closePath(); + }; + return Polygon; + })(); + Phaser.Polygon = Polygon; +})(Phaser || (Phaser = {})); +/// /// /// /// diff --git a/Tests/physics/aabb vs aabb 1.js b/Tests/physics/aabb vs aabb 1.js index 10a698ff..0fa3b93a 100644 --- a/Tests/physics/aabb vs aabb 1.js +++ b/Tests/physics/aabb vs aabb 1.js @@ -14,15 +14,15 @@ //atari = game.add.sprite(350, 500, 'atari'); atari = game.add.sprite(0, 310, 'atari'); card = game.add.sprite(400, 300, 'card'); - card.physics.immovable = true; + //card.physics.immovable = true; //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.bounce.setTo(1, 1); //atari.physics.drag.setTo(10, 10); - //card.physics.bounce.setTo(0.7, 0.7); + card.physics.bounce.setTo(0.7, 0.7); //card.physics.velocity.x = -50; } function update() { diff --git a/Tests/physics/aabb vs aabb 1.ts b/Tests/physics/aabb vs aabb 1.ts index 68cf8e3e..9bd68ab0 100644 --- a/Tests/physics/aabb vs aabb 1.ts +++ b/Tests/physics/aabb vs aabb 1.ts @@ -23,19 +23,19 @@ atari = game.add.sprite(0, 310, 'atari'); card = game.add.sprite(400, 300, 'card'); - card.physics.immovable = true; + //card.physics.immovable = true; //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.bounce.setTo(1, 1); //atari.physics.drag.setTo(10, 10); - //card.physics.bounce.setTo(0.7, 0.7); + card.physics.bounce.setTo(0.7, 0.7); //card.physics.velocity.x = -50; } diff --git a/Tests/physics/circle 1.js b/Tests/physics/circle 1.js index 0d0bc7fd..2a31a112 100644 --- a/Tests/physics/circle 1.js +++ b/Tests/physics/circle 1.js @@ -4,12 +4,15 @@ function init() { // Using Phasers asset loader we load up a PNG from the assets folder game.loader.addImageFile('atari', 'assets/sprites/mushroom2.png'); + game.loader.addImageFile('card', 'assets/sprites/mana_card.png'); game.loader.load(); } var atari; + var card; function create() { atari = game.add.sprite(200, 300, 'atari'); - atari.texture.alpha = 0.5; + card = game.add.sprite(400, 300, 'card'); + //atari.texture.alpha = 0.5; //atari.scale.setTo(1.5, 1.5); atari.physics.setCircle(50); //atari.physics.shape.setSize(150, 50); @@ -17,6 +20,7 @@ //atari.physics.gravity.setTo(0, 2); atari.physics.bounce.setTo(0.7, 0.7); atari.physics.drag.setTo(10, 10); + card.physics.bounce.setTo(0.7, 0.7); } function update() { atari.physics.acceleration.x = 0; @@ -34,5 +38,12 @@ } function render() { atari.physics.renderDebugInfo(16, 16); + game.stage.context.save(); + game.stage.context.beginPath(); + game.stage.context.strokeStyle = 'rgba(255,0,255,0.5)'; + game.stage.context.arc(200, 200, 50, 0, Math.PI * 2); + game.stage.context.stroke(); + game.stage.context.closePath(); + game.stage.context.restore(); } })(); diff --git a/Tests/physics/circle 1.ts b/Tests/physics/circle 1.ts index 556dc117..123c9a86 100644 --- a/Tests/physics/circle 1.ts +++ b/Tests/physics/circle 1.ts @@ -8,16 +8,19 @@ // Using Phasers asset loader we load up a PNG from the assets folder game.loader.addImageFile('atari', 'assets/sprites/mushroom2.png'); + game.loader.addImageFile('card', 'assets/sprites/mana_card.png'); game.loader.load(); } var atari: Phaser.Sprite; + var card: Phaser.Sprite; function create() { atari = game.add.sprite(200, 300, 'atari'); - atari.texture.alpha = 0.5; + card = game.add.sprite(400, 300, 'card'); + //atari.texture.alpha = 0.5; //atari.scale.setTo(1.5, 1.5); atari.physics.setCircle(50); @@ -29,6 +32,8 @@ atari.physics.bounce.setTo(0.7, 0.7); atari.physics.drag.setTo(10, 10); + card.physics.bounce.setTo(0.7, 0.7); + } function update() { @@ -60,6 +65,15 @@ atari.physics.renderDebugInfo(16, 16); + game.stage.context.save(); + game.stage.context.beginPath(); + game.stage.context.strokeStyle = 'rgba(255,0,255,0.5)'; + game.stage.context.arc(200, 200, 50, 0, Math.PI * 2); + game.stage.context.stroke(); + game.stage.context.closePath(); + game.stage.context.restore(); + + } })(); diff --git a/Tests/physics/test 1.js b/Tests/physics/test 1.js new file mode 100644 index 00000000..814eabd8 --- /dev/null +++ b/Tests/physics/test 1.js @@ -0,0 +1,42 @@ +/// +/// +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update, render); + function init() { + // Using Phasers asset loader we load up a PNG from the assets folder + game.loader.addImageFile('atari', 'assets/sprites/atari800xl.png'); + game.loader.load(); + } + var atari; + var p; + var atari2; + var p2; + function create() { + atari = game.add.sprite(200, 300, 'atari'); + atari.texture.alpha = 0.2; + atari2 = game.add.sprite(500, 300, 'atari'); + atari2.texture.alpha = 0.2; + p = new Phaser.Polygon(game, Phaser.SpriteUtils.getAsPoints(atari)); + p2 = new Phaser.Polygon(game, Phaser.SpriteUtils.getAsPoints(atari2)); + } + function update() { + atari.physics.acceleration.x = 0; + atari.physics.acceleration.y = 0; + if(game.input.keyboard.isDown(Phaser.Keyboard.LEFT)) { + atari.physics.acceleration.x = -150; + } else if(game.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) { + atari.physics.acceleration.x = 150; + } + if(game.input.keyboard.isDown(Phaser.Keyboard.UP)) { + atari.physics.acceleration.y = -150; + } else if(game.input.keyboard.isDown(Phaser.Keyboard.DOWN)) { + atari.physics.acceleration.y = 150; + } + } + function render() { + atari.physics.renderDebugInfo(16, 16); + p.render(); + p2.render(); + } +})(); diff --git a/Tests/physics/test 1.ts b/Tests/physics/test 1.ts new file mode 100644 index 00000000..19744ede --- /dev/null +++ b/Tests/physics/test 1.ts @@ -0,0 +1,70 @@ +/// +/// +/// + +(function () { + + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update, render); + + function init() { + + // Using Phasers asset loader we load up a PNG from the assets folder + game.loader.addImageFile('atari', 'assets/sprites/atari800xl.png'); + game.loader.load(); + + } + + var atari: Phaser.Sprite; + var p: Phaser.Polygon; + + var atari2: Phaser.Sprite; + var p2: Phaser.Polygon; + + function create() { + + atari = game.add.sprite(200, 300, 'atari'); + atari.texture.alpha = 0.2; + + atari2 = game.add.sprite(500, 300, 'atari'); + atari2.texture.alpha = 0.2; + + p = new Phaser.Polygon(game, Phaser.SpriteUtils.getAsPoints(atari)); + p2 = new Phaser.Polygon(game, Phaser.SpriteUtils.getAsPoints(atari2)); + + } + + function update() { + + atari.physics.acceleration.x = 0; + atari.physics.acceleration.y = 0; + + if (game.input.keyboard.isDown(Phaser.Keyboard.LEFT)) + { + atari.physics.acceleration.x = -150; + } + else if (game.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) + { + atari.physics.acceleration.x = 150; + } + + if (game.input.keyboard.isDown(Phaser.Keyboard.UP)) + { + atari.physics.acceleration.y = -150; + } + else if (game.input.keyboard.isDown(Phaser.Keyboard.DOWN)) + { + atari.physics.acceleration.y = 150; + } + + } + + function render() { + + atari.physics.renderDebugInfo(16, 16); + + p.render(); + p2.render(); + + } + +})(); diff --git a/build/phaser.d.ts b/build/phaser.d.ts index 19ffd41c..904a266f 100644 --- a/build/phaser.d.ts +++ b/build/phaser.d.ts @@ -2137,6 +2137,7 @@ module Phaser { * @type {number} */ static ALIGN_BOTTOM_RIGHT: number; + static getAsPoints(sprite: Sprite): Point[]; /** * Set the world bounds that this GameObject can exist within. By default a GameObject can exist anywhere * in the world. But by setting the bounds (which are given in world dimensions, not screen dimensions) @@ -3216,12 +3217,18 @@ module Phaser.Physics { oldPosition: Vec2; offset: Vec2; bounds: Rectangle; - oH: number; - oV: number; setSize(width: number, height: number); preUpdate(); update(); render(context: CanvasRenderingContext2D); + hullX; + hullY; + hullWidth; + hullHeight; + deltaX; + deltaY; + deltaXAbs; + deltaYAbs; } } /** @@ -3266,12 +3273,35 @@ module Phaser.Physics { */ public computeVelocity(velocity: number, gravity?: number, acceleration?: number, drag?: number, max?: number): number; private collideShapes(shapeA, shapeB); + /** + * The core Collision separation function used by Collision.overlap. + * @param object1 The first GameObject to separate + * @param object2 The second GameObject to separate + * @returns {boolean} Returns true if the objects were separated, otherwise false. + */ + public NEWseparate(object1, object2): bool; + private checkHullIntersection(shape1, shape2); + /** + * 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 separateSpriteToSpriteX(object1: Sprite, object2: Sprite): 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 separateSpriteToSpriteY(object1: Sprite, object2: Sprite): bool; + private separate(shapeA, shapeB, distance, tangent); private collideWorld(shape); private separateX(shapeA, shapeB, distance, tangent); private separateY(shapeA, shapeB, distance, tangent); private separateXWall(shapeA, distance, tangent); private separateYWall(shapeA, distance, tangent); - private separate(shape, distance, tangent); + private OLDseparate(shape, distance, tangent); } } /** @@ -3289,12 +3319,18 @@ module Phaser.Physics { public offset: Vec2; public scale: Vec2; public bounds: Rectangle; - public oH: number; - public oV: number; public preUpdate(): void; public update(): void; public setSize(width: number, height: number): void; public render(context: CanvasRenderingContext2D): 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; } } /** @@ -6669,12 +6705,18 @@ module Phaser.Physics { public scale: Vec2; public bounds: Rectangle; public radius: number; - public oH: number; - public oV: number; public preUpdate(): void; public update(): void; public setSize(width: number, height: number): void; public render(context: CanvasRenderingContext2D): 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; } } /** @@ -6696,6 +6738,7 @@ module Phaser.Components { * @type {boolean} */ public moves: bool; + public mass: number; public gravity: Vec2; public drag: Vec2; public bounce: Vec2; @@ -6703,6 +6746,8 @@ module Phaser.Components { public velocity: Vec2; public acceleration: Vec2; public touching: number; + public allowCollisions: number; + public wasTouching: number; public setCircle(diameter: number): void; /** * Internal function for updating the position and speed of this object. @@ -6718,6 +6763,23 @@ module Phaser.Components { } } /** +* Phaser - Polygon +* +* +*/ +module Phaser { + class Polygon { + /** + * + **/ + constructor(game: Game, points: Point[]); + public points: Point[]; + public game: Game; + public context: CanvasRenderingContext2D; + public render(): void; + } +} +/** * Phaser - CircleUtils * * A collection of methods useful for manipulating and comparing Circle objects. diff --git a/build/phaser.js b/build/phaser.js index a414e491..b01a4f9c 100644 --- a/build/phaser.js +++ b/build/phaser.js @@ -3541,6 +3541,18 @@ var Phaser; SpriteUtils.ALIGN_BOTTOM_LEFT = 6; SpriteUtils.ALIGN_BOTTOM_CENTER = 7; SpriteUtils.ALIGN_BOTTOM_RIGHT = 8; + SpriteUtils.getAsPoints = function getAsPoints(sprite) { + var out = []; + // top left + out.push(new Phaser.Point(sprite.x, sprite.y)); + // top right + out.push(new Phaser.Point(sprite.x + sprite.width, sprite.y)); + // bottom right + out.push(new Phaser.Point(sprite.x + sprite.width, sprite.y + sprite.height)); + // bottom left + out.push(new Phaser.Point(sprite.x, sprite.y + sprite.height)); + return out; + }; SpriteUtils.setBounds = /** * Checks to see if some GameObject overlaps this GameObject or Group. * If the group has a LOT of things in it, it might be faster to use Collision.overlaps(). @@ -5891,12 +5903,12 @@ var Phaser; this._objects[i].preUpdate(); this.updateMotion(this._objects[i]); this.collideWorld(this._objects[i]); - if(this._objects[i].physics.immovable == false) { - for(var x = 0; x < this._length; x++) { - if(this._objects[x] !== this._objects[i]) { - this.collideShapes(this._objects[i], this._objects[x]); - } - } + 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); + } } } } @@ -5971,43 +5983,250 @@ var Phaser; if(shapeA.physics.immovable && shapeB.physics.immovable) { return; } + this._distance.setTo(0, 0); + this._tangent.setTo(0, 0); // Simple bounds check first if(Phaser.RectangleUtils.intersects(shapeA.bounds, shapeB.bounds)) { // Collide on the x-axis - if(shapeA.bounds.right >= shapeB.bounds.x && shapeA.bounds.right <= shapeB.bounds.right) { + if(shapeA.physics.velocity.x > 0 && shapeA.bounds.right > shapeB.bounds.x && shapeA.bounds.right <= shapeB.bounds.right) { // The right side of ShapeA hit the left side of ShapeB this._distance.x = shapeB.bounds.x - shapeA.bounds.right; if(this._distance.x != 0) { - this._tangent.setTo(-1, 0); - this.separateX(shapeA, shapeB, this._distance, this._tangent); + this._tangent.x = -1; } - } else if(shapeA.bounds.x <= shapeB.bounds.right && shapeA.bounds.x >= shapeB.bounds.x) { + } else if(shapeA.physics.velocity.x < 0 && shapeA.bounds.x < shapeB.bounds.right && shapeA.bounds.x >= shapeB.bounds.x) { // The left side of ShapeA hit the right side of ShapeB this._distance.x = shapeB.bounds.right - shapeA.bounds.x; if(this._distance.x != 0) { - this._tangent.setTo(1, 0); - this.separateX(shapeA, shapeB, this._distance, this._tangent); + this._tangent.x = 1; } } // Collide on the y-axis - if(shapeA.bounds.y <= shapeB.bounds.bottom && shapeA.bounds.y >= shapeB.bounds.y) { - console.log(shapeA.bounds.y, shapeB.bounds.bottom, shapeB.bounds.y); + if(shapeA.physics.velocity.y < 0 && shapeA.bounds.y < shapeB.bounds.bottom && shapeA.bounds.y > shapeB.bounds.y) { + console.log('top A -> bot B'); // The top of ShapeA hit the bottom of ShapeB this._distance.y = shapeB.bounds.bottom - shapeA.bounds.y; + console.log(shapeA.bounds, shapeB.bounds, this._distance.y); if(this._distance.y != 0) { - this._tangent.setTo(0, 1); - this.separateY(shapeA, shapeB, this._distance, this._tangent); + this._tangent.y = 1; } - } else if(shapeA.bounds.bottom >= shapeB.bounds.y && shapeA.bounds.bottom <= shapeB.bounds.bottom) { - console.log(shapeA.bounds.bottom, shapeB.bounds.y, shapeB.bounds.bottom); + } else if(shapeA.physics.velocity.y > 0 && shapeA.bounds.bottom > shapeB.bounds.y && shapeA.bounds.bottom < shapeB.bounds.bottom) { // The bottom of ShapeA hit the top of ShapeB this._distance.y = shapeB.bounds.y - shapeA.bounds.bottom; if(this._distance.y != 0) { - this._tangent.setTo(0, -1); - this.separateY(shapeA, shapeB, this._distance, this._tangent); + this._tangent.y = -1; + } + } + // Separate + if(this._distance.equals(0) == false) { + //this.separate(shapeA, shapeB, this._distance, this._tangent); + } + } + }; + PhysicsManager.prototype.NEWseparate = /** + * The core Collision separation function used by Collision.overlap. + * @param object1 The first GameObject to separate + * @param object2 The second GameObject to separate + * @returns {boolean} Returns true if the objects were separated, otherwise false. + */ + function (object1, object2) { + var separatedX = this.separateSpriteToSpriteX(object1, object2); + var separatedY = this.separateSpriteToSpriteY(object1, object2); + return separatedX || separatedY; + }; + PhysicsManager.prototype.checkHullIntersection = function (shape1, shape2) { + //if ((shape1.hullX + shape1.hullWidth > shape2.hullX) && (shape1.hullX < shape2.hullX + shape2.bounds.width) && (shape1.hullY + shape1.hullHeight > shape2.hullY) && (shape1.hullY < shape2.hullY + shape2.hullHeight)) + // maybe not bounds.width? + if((shape1.hullX + shape1.hullWidth > shape2.hullX) && (shape1.hullX < shape2.hullX + shape2.hullWidth) && (shape1.hullY + shape1.hullHeight > shape2.hullY) && (shape1.hullY < shape2.hullY + shape2.hullHeight)) { + return true; + } else { + return false; + } + }; + PhysicsManager.prototype.separateSpriteToSpriteX = /** + * 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 (object1, object2) { + // Can't separate two immovable objects + if(object1.physics.immovable && object2.physics.immovable) { + return false; + } + // First, get the two object deltas + var overlap = 0; + if(object1.physics.shape.deltaX != object2.physics.shape.deltaX) { + if(Phaser.RectangleUtils.intersects(object1.physics.shape.bounds, object2.physics.shape.bounds)) { + //var maxOverlap: number = object1.physics.shape.deltaXAbs + object2.physics.shape.deltaXAbs + Collision.OVERLAP_BIAS; + var maxOverlap = object1.physics.shape.deltaXAbs + object2.physics.shape.deltaXAbs + 4; + // If they did overlap (and can), figure out by how much and flip the corresponding flags + if(object1.physics.shape.deltaX > object2.physics.shape.deltaX) { + overlap = object1.physics.shape.bounds.right - object2.physics.shape.bounds.x; + if((overlap > maxOverlap) || !(object1.physics.allowCollisions & Phaser.Types.RIGHT) || !(object2.physics.allowCollisions & Phaser.Types.LEFT)) { + overlap = 0; + } else { + object1.physics.touching |= Phaser.Types.RIGHT; + object2.physics.touching |= Phaser.Types.LEFT; + } + } else if(object1.physics.shape.deltaX < object2.physics.shape.deltaX) { + overlap = object1.physics.shape.bounds.x - object2.physics.shape.bounds.width - object2.physics.shape.bounds.x; + if((-overlap > maxOverlap) || !(object1.physics.allowCollisions & Phaser.Types.LEFT) || !(object2.physics.allowCollisions & Phaser.Types.RIGHT)) { + overlap = 0; + } else { + object1.physics.touching |= Phaser.Types.LEFT; + object2.physics.touching |= Phaser.Types.RIGHT; + } } } } + // Then adjust their positions and velocities accordingly (if there was any overlap) + if(overlap != 0) { + var obj1Velocity = object1.physics.velocity.x; + var obj2Velocity = object2.physics.velocity.x; + if(!object1.physics.immovable && !object2.physics.immovable) { + overlap *= 0.5; + object1.physics.shape.position.x = object1.physics.shape.position.x - overlap; + object2.physics.shape.position.x += overlap; + var obj1NewVelocity = Math.sqrt((obj2Velocity * obj2Velocity * object2.physics.mass) / object1.physics.mass) * ((obj2Velocity > 0) ? 1 : -1); + var obj2NewVelocity = Math.sqrt((obj1Velocity * obj1Velocity * object1.physics.mass) / object2.physics.mass) * ((obj1Velocity > 0) ? 1 : -1); + var average = (obj1NewVelocity + obj2NewVelocity) * 0.5; + obj1NewVelocity -= average; + obj2NewVelocity -= average; + object1.physics.velocity.x = average + obj1NewVelocity * object1.physics.bounce.x; + object2.physics.velocity.x = average + obj2NewVelocity * object2.physics.bounce.x; + } else if(!object1.physics.immovable) { + overlap *= 2; + object1.physics.shape.position.x -= overlap; + object1.physics.velocity.x = obj2Velocity - obj1Velocity * object1.physics.bounce.x; + } else if(!object2.physics.immovable) { + overlap *= 2; + object2.physics.shape.position.x += overlap; + object2.physics.velocity.x = obj1Velocity - obj2Velocity * object2.physics.bounce.x; + } + return true; + } else { + return false; + } + }; + PhysicsManager.prototype.separateSpriteToSpriteY = /** + * 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 (object1, object2) { + // Can't separate two immovable objects + if(object1.physics.immovable && object2.physics.immovable) { + return false; + } + // First, get the two object deltas + var overlap = 0; + if(object1.physics.shape.deltaY != object2.physics.shape.deltaY) { + if(Phaser.RectangleUtils.intersects(object1.physics.shape.bounds, object2.physics.shape.bounds)) { + // This is the only place to use the DeltaAbs values + //var maxOverlap: number = object1.physics.shape.deltaYAbs + object2.physics.shape.deltaYAbs + Phaser.Types.OVERLAP_BIAS; + var maxOverlap = object1.physics.shape.deltaYAbs + object2.physics.shape.deltaYAbs + 4; + // If they did overlap (and can), figure out by how much and flip the corresponding flags + if(object1.physics.shape.deltaY > object2.physics.shape.deltaY) { + overlap = object1.physics.shape.bounds.bottom - object2.physics.shape.bounds.y; + if((overlap > maxOverlap) || !(object1.physics.allowCollisions & Phaser.Types.DOWN) || !(object2.physics.allowCollisions & Phaser.Types.UP)) { + overlap = 0; + } else { + object1.physics.touching |= Phaser.Types.DOWN; + object2.physics.touching |= Phaser.Types.UP; + } + } else if(object1.physics.shape.deltaY < object2.physics.shape.deltaY) { + overlap = object1.physics.shape.bounds.y - object2.physics.shape.bounds.height - object2.physics.shape.bounds.y; + if((-overlap > maxOverlap) || !(object1.physics.allowCollisions & Phaser.Types.UP) || !(object2.physics.allowCollisions & Phaser.Types.DOWN)) { + overlap = 0; + } else { + object1.physics.touching |= Phaser.Types.UP; + object2.physics.touching |= Phaser.Types.DOWN; + } + } + } + } + // Then adjust their positions and velocities accordingly (if there was any overlap) + if(overlap != 0) { + var obj1Velocity = object1.physics.velocity.y; + var obj2Velocity = object2.physics.velocity.y; + if(!object1.physics.immovable && !object2.physics.immovable) { + overlap *= 0.5; + object1.physics.shape.position.y = object1.physics.shape.position.y - overlap; + object2.physics.shape.position.y += overlap; + var obj1NewVelocity = Math.sqrt((obj2Velocity * obj2Velocity * object2.physics.mass) / object1.physics.mass) * ((obj2Velocity > 0) ? 1 : -1); + var obj2NewVelocity = Math.sqrt((obj1Velocity * obj1Velocity * object1.physics.mass) / object2.physics.mass) * ((obj1Velocity > 0) ? 1 : -1); + var average = (obj1NewVelocity + obj2NewVelocity) * 0.5; + obj1NewVelocity -= average; + obj2NewVelocity -= average; + object1.physics.velocity.y = average + obj1NewVelocity * object1.physics.bounce.y; + object2.physics.velocity.y = average + obj2NewVelocity * object2.physics.bounce.y; + } else if(!object1.physics.immovable) { + overlap *= 2; + object1.physics.shape.position.y -= overlap; + object1.physics.velocity.y = obj2Velocity - obj1Velocity * object1.physics.bounce.y; + // This is special case code that handles things like horizontal moving platforms you can ride + if(object2.active && object2.physics.moves && (object1.physics.shape.deltaY > object2.physics.shape.deltaY)) { + object1.physics.shape.position.x += object2.physics.shape.position.x - object2.physics.shape.oldPosition.x; + } + } else if(!object2.physics.immovable) { + overlap *= 2; + object2.physics.shape.position.y += overlap; + object2.physics.velocity.y = obj1Velocity - obj2Velocity * object2.physics.bounce.y; + // This is special case code that handles things like horizontal moving platforms you can ride + if(object1.active && object1.physics.moves && (object1.physics.shape.deltaY < object2.physics.shape.deltaY)) { + object2.physics.shape.position.x += object1.physics.shape.position.x - object1.physics.shape.oldPosition.x; + } + } + return true; + } else { + return false; + } + }; + PhysicsManager.prototype.separate = function (shapeA, shapeB, distance, tangent) { + 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 = Phaser.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('------------------------------------------------'); }; PhysicsManager.prototype.collideWorld = function (shape) { // Collide on the x-axis @@ -6052,7 +6271,7 @@ var Phaser; shapeB.physics.touching |= Phaser.Types.LEFT; } // collision edges - shapeA.oH = tangent.x; + //shapeA.oH = tangent.x; // only apply collision response forces if the object is travelling into, and not out of, the collision if(Phaser.Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) { // Apply horizontal bounce @@ -6076,7 +6295,7 @@ var Phaser; shapeB.physics.touching |= Phaser.Types.UP; } // collision edges - shapeA.oV = tangent.y; + //shapeA.oV = tangent.y; // only apply collision response forces if the object is travelling into, and not out of, the collision if(Phaser.Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) { // Apply horizontal bounce @@ -6098,7 +6317,7 @@ var Phaser; shapeA.physics.touching |= Phaser.Types.RIGHT; } // collision edges - shapeA.oH = tangent.x; + //shapeA.oH = tangent.x; // only apply collision response forces if the object is travelling into, and not out of, the collision if(Phaser.Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) { // Apply horizontal bounce @@ -6119,7 +6338,7 @@ var Phaser; shapeA.physics.touching |= Phaser.Types.DOWN; } // collision edges - shapeA.oV = tangent.y; + //shapeA.oV = tangent.y; // only apply collision response forces if the object is travelling into, and not out of, the collision if(Phaser.Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) { // Apply horizontal bounce @@ -6131,10 +6350,10 @@ var Phaser; } shapeA.position.y += distance.y; }; - PhysicsManager.prototype.separate = function (shape, distance, tangent) { + PhysicsManager.prototype.OLDseparate = function (shape, distance, tangent) { // collision edges - shape.oH = tangent.x; - shape.oV = tangent.y; + //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); @@ -6266,11 +6485,6 @@ var Phaser; this.bounds.height = height; }; AABB.prototype.render = function (context) { - //context.beginPath(); - //context.strokeStyle = 'rgb(255,255,0)'; - //context.strokeRect(this.bounds.x, this.bounds.y, this.bounds.width, this.bounds.height); - //context.stroke(); - //context.closePath(); 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); @@ -6279,14 +6493,15 @@ var Phaser; // center point context.fillStyle = 'rgb(0,255,0)'; context.fillRect(this.position.x, this.position.y, 2, 2); - if(this.physics.touching == Phaser.Types.LEFT) { + if(this.physics.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(); - } else if(this.physics.touching == Phaser.Types.RIGHT) { + } + if(this.physics.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); @@ -6294,14 +6509,15 @@ var Phaser; context.stroke(); context.closePath(); } - if(this.physics.touching == Phaser.Types.UP) { + if(this.physics.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(); - } else if(this.physics.touching == Phaser.Types.DOWN) { + } + if(this.physics.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); @@ -6310,6 +6526,78 @@ var Phaser; context.closePath(); } }; + Object.defineProperty(AABB.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(AABB.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(AABB.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(AABB.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(AABB.prototype, "deltaXAbs", { + get: function () { + return (this.deltaX > 0 ? this.deltaX : -this.deltaX); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(AABB.prototype, "deltaYAbs", { + get: function () { + return (this.deltaY > 0 ? this.deltaY : -this.deltaY); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(AABB.prototype, "deltaX", { + get: function () { + return this.position.x - this.oldPosition.x; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(AABB.prototype, "deltaY", { + get: function () { + return this.position.y - this.oldPosition.y; + }, + enumerable: true, + configurable: true + }); return AABB; })(); Physics.AABB = AABB; @@ -12279,6 +12567,8 @@ var Phaser; } Circle.prototype.preUpdate = function () { this.oldPosition.copyFrom(this.position); + this.bounds.x = this.position.x - this.bounds.halfWidth; + this.bounds.y = this.position.y - this.bounds.halfHeight; if(this.sprite) { this.position.setTo((this.sprite.x + this.bounds.halfWidth) + this.offset.x, (this.sprite.y + this.bounds.halfHeight) + this.offset.y); // Update scale / dimensions @@ -12291,53 +12581,138 @@ var Phaser; } }; Circle.prototype.update = function () { - this.bounds.x = this.position.x; - this.bounds.y = this.position.y; - }; + //this.bounds.x = this.position.x; + //this.bounds.y = this.position.y; + }; Circle.prototype.setSize = function (width, height) { this.bounds.width = width; this.bounds.height = height; }; Circle.prototype.render = function (context) { context.beginPath(); - context.strokeStyle = 'rgb(0,255,0)'; + //context.strokeStyle = 'rgb(255,255,0)'; + //context.strokeRect(this.position.x - this.bounds.halfWidth, this.position.y - this.bounds.halfHeight, this.bounds.width, this.bounds.height); + //context.fillStyle = 'rgba(0,0,255,0.8)'; + context.strokeStyle = 'rgba(0,0,255,0.5)'; context.arc(this.position.x, this.position.y, this.radius, 0, Math.PI * 2); + //context.fill(); context.stroke(); context.closePath(); // center point - context.fillStyle = 'rgb(0,255,0)'; + context.fillStyle = 'rgb(255,255,0)'; context.fillRect(this.position.x, this.position.y, 2, 2); - if(this.oH == 1) { - 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(); - } else if(this.oH == -1) { - 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.oH == 1) + { + 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.oV == 1) { - 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(); - } else if(this.oV == -1) { - 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(); + else if (this.oH == -1) + { + 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.oV == 1) + { + 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(); + } + else if (this.oV == -1) + { + 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(); + } + */ + }; + Object.defineProperty(Circle.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(Circle.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(Circle.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(Circle.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(Circle.prototype, "deltaXAbs", { + get: function () { + return (this.deltaX > 0 ? this.deltaX : -this.deltaX); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Circle.prototype, "deltaYAbs", { + get: function () { + return (this.deltaY > 0 ? this.deltaY : -this.deltaY); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Circle.prototype, "deltaX", { + get: function () { + return this.position.x - this.oldPosition.x; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Circle.prototype, "deltaY", { + get: function () { + return this.position.y - this.oldPosition.y; + }, + enumerable: true, + configurable: true + }); return Circle; })(); Physics.Circle = Circle; @@ -12368,6 +12743,7 @@ var Phaser; * @type {boolean} */ this.moves = true; + this.mass = 1; this.game = parent.game; this._sprite = parent; this.gravity = Phaser.Vec2Utils.clone(this.game.world.physics.gravity); @@ -12377,6 +12753,8 @@ var Phaser; this.velocity = new Phaser.Vec2(); this.acceleration = new Phaser.Vec2(); this.touching = Phaser.Types.NONE; + this.wasTouching = Phaser.Types.NONE; + this.allowCollisions = Phaser.Types.ANY; this.shape = this.game.world.physics.add(new Phaser.Physics.AABB(this.game, this._sprite, this._sprite.x, this._sprite.y, this._sprite.width, this._sprite.height)); } Physics.prototype.setCircle = function (diameter) { @@ -12415,6 +12793,41 @@ var Phaser; var Components = Phaser.Components; })(Phaser || (Phaser = {})); /// +/** +* Phaser - Polygon +* +* +*/ +var Phaser; +(function (Phaser) { + var Polygon = (function () { + /** + * + **/ + function Polygon(game, points) { + this.game = game; + this.context = game.stage.context; + this.points = []; + for(var i = 0; i < points.length; i++) { + this.points.push(new Phaser.Point().copyFrom(points[i])); + } + } + Polygon.prototype.render = function () { + this.context.beginPath(); + this.context.strokeStyle = 'rgb(255,255,0)'; + this.context.moveTo(this.points[0].x, this.points[0].y); + for(var i = 1; i < this.points.length; i++) { + this.context.lineTo(this.points[i].x, this.points[i].y); + } + this.context.lineTo(this.points[0].x, this.points[0].y); + this.context.stroke(); + this.context.closePath(); + }; + return Polygon; + })(); + Phaser.Polygon = Polygon; +})(Phaser || (Phaser = {})); +/// /// /// ///