From a5343b4bc09ba13d1e1c12b838f490966931829e Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Fri, 19 Jul 2013 16:53:47 +0100 Subject: [PATCH] Quick commit before I merge the new tests --- build/phaser.d.ts | 1 + todo/phaser clean up/ArcadePhysics.ts | 1121 +++++++++++++++++++++++++ 2 files changed, 1122 insertions(+) create mode 100644 todo/phaser clean up/ArcadePhysics.ts diff --git a/build/phaser.d.ts b/build/phaser.d.ts index 33f5318a..c143276a 100644 --- a/build/phaser.d.ts +++ b/build/phaser.d.ts @@ -1326,6 +1326,7 @@ module Phaser { private _dh; /** * Controls the CSS3 Filters applied to the textures canvas object. + * Only really useful if you attach this canvas to the DOM. * @type {Phaser.Components.CSS3Filters} */ public css3: Components.CSS3Filters; diff --git a/todo/phaser clean up/ArcadePhysics.ts b/todo/phaser clean up/ArcadePhysics.ts new file mode 100644 index 00000000..00ae9b18 --- /dev/null +++ b/todo/phaser clean up/ArcadePhysics.ts @@ -0,0 +1,1121 @@ +/// +/// +/// +/// +/// + +/** +* Phaser - PhysicsManager +* +* Your game only has one PhysicsManager instance and it's responsible for looking after, creating and colliding +* all of the physics objects in the world. +*/ + + +module Phaser.Physics { + + export class ArcadePhysics { + + constructor(game: Game, width: number, height: number) { + + this.game = game; + + this.gravity = new Vec2; + this.drag = new Vec2; + this.bounce = new Vec2; + this.angularDrag = 0; + + this.bounds = new Rectangle(0, 0, width, height); + + this._distance = new Vec2; + this._tangent = new Vec2; + + this.members = new Group(game); + + } + + /** + * Local private reference to Game. + */ + public game: Game; + + /** + * Physics object pool + */ + public members: Group; + + // Temp calculation vars + private _drag: number; + private _delta: number; + private _velocityDelta: number; + private _length: number = 0; + private _distance: Vec2; + private _tangent: Vec2; + private _separatedX: bool; + private _separatedY: bool; + private _overlap: number; + private _maxOverlap: number; + private _obj1Velocity: number; + private _obj2Velocity: number; + private _obj1NewVelocity: number; + private _obj2NewVelocity: number; + private _average: number; + private _quadTree: QuadTree; + private _quadTreeResult: bool; + + public bounds: Rectangle; + + public gravity: Vec2; + public drag: Vec2; + public bounce: Vec2; + public angularDrag: number; + + /** + * The overlap bias is used when calculating hull overlap before separation - change it if you have especially small or large GameObjects + * @type {number} + */ + static OVERLAP_BIAS: number = 4; + + /** + * The overlap bias is used when calculating hull overlap before separation - change it if you have especially small or large GameObjects + * @type {number} + */ + static TILE_OVERLAP: bool = false; + + /** + * @type {number} + */ + public worldDivisions: number = 6; + + + /* + public update() { + + this._length = this._objects.length; + + for (var i = 0; i < this._length; i++) + { + if (this._objects[i]) + { + this._objects[i].preUpdate(); + this.updateMotion(this._objects[i]); + this.collideWorld(this._objects[i]); + + for (var x = 0; x < this._length; x++) + { + if (this._objects[x] && this._objects[x] !== this._objects[i]) + { + //this.collideShapes(this._objects[i], this._objects[x]); + var r = this.NEWseparate(this._objects[i], this._objects[x]); + //console.log('sep', r); + } + } + + } + } + + } + + public render() { + + // iterate through the objects here, updating and colliding + for (var i = 0; i < this._length; i++) + { + if (this._objects[i]) + { + this._objects[i].render(this.game.stage.context); + } + } + + } +*/ + + public updateMotion(body: Phaser.Physics.Body) { + + if (body.type == Types.BODY_DISABLED) + { + return; + } + + this._velocityDelta = (this.computeVelocity(body.angularVelocity, body.gravity.x, body.angularAcceleration, body.angularDrag, body.maxAngular) - body.angularVelocity) / 2; + body.angularVelocity += this._velocityDelta; + body.sprite.transform.rotation += body.angularVelocity * this.game.time.elapsed; + body.angularVelocity += this._velocityDelta; + + this._velocityDelta = (this.computeVelocity(body.velocity.x, body.gravity.x, body.acceleration.x, body.drag.x) - body.velocity.x) / 2; + body.velocity.x += this._velocityDelta; + this._delta = body.velocity.x * this.game.time.elapsed; + body.velocity.x += this._velocityDelta; + //body.position.x += this._delta; + body.sprite.x += this._delta; + + this._velocityDelta = (this.computeVelocity(body.velocity.y, body.gravity.y, body.acceleration.y, body.drag.y) - body.velocity.y) / 2; + body.velocity.y += this._velocityDelta; + this._delta = body.velocity.y * this.game.time.elapsed; + body.velocity.y += this._velocityDelta; + //body.position.y += this._delta; + body.sprite.y += this._delta; + + } + + /** + * A tween-like function that takes a starting velocity and some other factors and returns an altered velocity. + * + * @param {number} Velocity Any component of velocity (e.g. 20). + * @param {number} Acceleration Rate at which the velocity is changing. + * @param {number} Drag Really kind of a deceleration, this is how much the velocity changes if Acceleration is not set. + * @param {number} Max An absolute value cap for the velocity. + * + * @return {number} The altered Velocity value. + */ + public computeVelocity(velocity: number, gravity: number = 0, acceleration: number = 0, drag: number = 0, max: number = 10000): number { + + if (acceleration !== 0) + { + velocity += (acceleration + gravity) * this.game.time.elapsed; + } + else if (drag !== 0) + { + this._drag = drag * this.game.time.elapsed; + + if (velocity - this._drag > 0) + { + velocity = velocity - this._drag; + } + else if (velocity + this._drag < 0) + { + velocity += this._drag; + } + else + { + velocity = 0; + } + + velocity += gravity; + } + + if ((velocity != 0) && (max != 10000)) + { + if (velocity > max) + { + velocity = max; + } + else if (velocity < -max) + { + velocity = -max; + } + } + + return velocity; + + } + + /** + * The core Collision separation method. + * @param body1 The first Physics.Body to separate + * @param body2 The second Physics.Body to separate + * @returns {boolean} Returns true if the bodies were separated, otherwise false. + */ + public separate(body1: Body, body2: Body): bool { + + this._separatedX = this.separateBodyX(body1, body2); + this._separatedY = this.separateBodyY(body1, body2); + + return this._separatedX || this._separatedY; + + } + + public checkHullIntersection(body1: Body, body2:Body): bool { + return ((body1.hullX + body1.hullWidth > body2.hullX) && (body1.hullX < body2.hullX + body2.hullWidth) && (body1.hullY + body1.hullHeight > body2.hullY) && (body1.hullY < body2.hullY + body2.hullHeight)); + } + + /** + * Separates the two objects on their x axis + * @param object1 The first GameObject to separate + * @param object2 The second GameObject to separate + * @returns {boolean} Whether the objects in fact touched and were separated along the X axis. + */ + public separateBodyX(body1: Body, body2: Body): bool { + + // Can't separate two disabled or static objects + if ((body1.type == Types.BODY_DISABLED || body1.type == Types.BODY_STATIC) && (body2.type == Types.BODY_DISABLED || body2.type == Types.BODY_STATIC)) + { + return false; + } + + // First, get the two object deltas + this._overlap = 0; + + if (body1.deltaX != body2.deltaX) + { + if (RectangleUtils.intersects(body1.bounds, body2.bounds)) + { + this._maxOverlap = body1.deltaXAbs + body2.deltaXAbs + PhysicsManager.OVERLAP_BIAS; + + // If they did overlap (and can), figure out by how much and flip the corresponding flags + if (body1.deltaX > body2.deltaX) + { + this._overlap = body1.bounds.right - body2.bounds.x; + + if ((this._overlap > this._maxOverlap) || !(body1.allowCollisions & Types.RIGHT) || !(body2.allowCollisions & Types.LEFT)) + { + this._overlap = 0; + } + else + { + body1.touching |= Types.RIGHT; + body2.touching |= Types.LEFT; + } + } + else if (body1.deltaX < body2.deltaX) + { + this._overlap = body1.bounds.x - body2.bounds.width - body2.bounds.x; + + if ((-this._overlap > this._maxOverlap) || !(body1.allowCollisions & Types.LEFT) || !(body2.allowCollisions & Types.RIGHT)) + { + this._overlap = 0; + } + else + { + body1.touching |= Types.LEFT; + body2.touching |= Types.RIGHT; + } + } + } + } + + // Then adjust their positions and velocities accordingly (if there was any overlap) + if (this._overlap != 0) + { + this._obj1Velocity = body1.velocity.x; + this._obj2Velocity = body2.velocity.x; + + /** + * Dynamic = gives and receives impacts + * Static = gives but doesn't receive impacts, cannot be moved by physics + * Kinematic = gives impacts, but never receives, can be moved by physics + */ + + // 2 dynamic bodies will exchange velocities + if (body1.type == Types.BODY_DYNAMIC && body2.type == Types.BODY_DYNAMIC) + { + this._overlap *= 0.5; + body1.position.x = body1.position.x - this._overlap; + body2.position.x += this._overlap; + + this._obj1NewVelocity = Math.sqrt((this._obj2Velocity * this._obj2Velocity * body2.mass) / body1.mass) * ((this._obj2Velocity > 0) ? 1 : -1); + this._obj2NewVelocity = Math.sqrt((this._obj1Velocity * this._obj1Velocity * body1.mass) / body2.mass) * ((this._obj1Velocity > 0) ? 1 : -1); + this._average = (this._obj1NewVelocity + this._obj2NewVelocity) * 0.5; + this._obj1NewVelocity -= this._average; + this._obj2NewVelocity -= this._average; + body1.velocity.x = this._average + this._obj1NewVelocity * body1.bounce.x; + body2.velocity.x = this._average + this._obj2NewVelocity * body2.bounce.x; + } + else if (body2.type != Types.BODY_DYNAMIC) + { + // Body 2 is Static or Kinematic + this._overlap *= 2; + body1.position.x -= this._overlap; + body1.velocity.x = this._obj2Velocity - this._obj1Velocity * body1.bounce.x; + } + else if (body1.type != Types.BODY_DYNAMIC) + { + // Body 1 is Static or Kinematic + this._overlap *= 2; + body2.position.x += this._overlap; + body2.velocity.x = this._obj1Velocity - this._obj2Velocity * body2.bounce.x; + } + + return true; + } + else + { + return false; + } + + } + + /** + * Separates the two objects on their y axis + * @param object1 The first GameObject to separate + * @param object2 The second GameObject to separate + * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis. + */ + public separateBodyY(body1: Body, body2: Body): bool { + + // Can't separate two immovable objects + if ((body1.type == Types.BODY_DISABLED || body1.type == Types.BODY_STATIC) && (body2.type == Types.BODY_DISABLED || body2.type == Types.BODY_STATIC)) + { + return false; + } + + // First, get the two object deltas + this._overlap = 0; + + if (body1.deltaY != body2.deltaY) + { + if (RectangleUtils.intersects(body1.bounds, body2.bounds)) + { + // This is the only place to use the DeltaAbs values + this._maxOverlap = body1.deltaYAbs + body2.deltaYAbs + PhysicsManager.OVERLAP_BIAS; + + // If they did overlap (and can), figure out by how much and flip the corresponding flags + if (body1.deltaY > body2.deltaY) + { + this._overlap = body1.bounds.bottom - body2.bounds.y; + + if ((this._overlap > this._maxOverlap) || !(body1.allowCollisions & Types.DOWN) || !(body2.allowCollisions & Types.UP)) + { + this._overlap = 0; + } + else + { + body1.touching |= Types.DOWN; + body2.touching |= Types.UP; + } + } + else if (body1.deltaY < body2.deltaY) + { + this._overlap = body1.bounds.y - body2.bounds.height - body2.bounds.y; + + if ((-this._overlap > this._maxOverlap) || !(body1.allowCollisions & Types.UP) || !(body2.allowCollisions & Types.DOWN)) + { + this._overlap = 0; + } + else + { + body1.touching |= Types.UP; + body2.touching |= Types.DOWN; + } + } + } + } + + // Then adjust their positions and velocities accordingly (if there was any overlap) + if (this._overlap != 0) + { + this._obj1Velocity = body1.velocity.y; + this._obj2Velocity = body2.velocity.y; + + /** + * Dynamic = gives and receives impacts + * Static = gives but doesn't receive impacts, cannot be moved by physics + * Kinematic = gives impacts, but never receives, can be moved by physics + */ + + if (body1.type == Types.BODY_DYNAMIC && body2.type == Types.BODY_DYNAMIC) + { + this._overlap *= 0.5; + body1.position.y = body1.position.y - this._overlap; + body2.position.y += this._overlap; + + this._obj1NewVelocity = Math.sqrt((this._obj2Velocity * this._obj2Velocity * body2.mass) / body1.mass) * ((this._obj2Velocity > 0) ? 1 : -1); + this._obj2NewVelocity = Math.sqrt((this._obj1Velocity * this._obj1Velocity * body1.mass) / body2.mass) * ((this._obj1Velocity > 0) ? 1 : -1); + var average: number = (this._obj1NewVelocity + this._obj2NewVelocity) * 0.5; + this._obj1NewVelocity -= average; + this._obj2NewVelocity -= average; + body1.velocity.y = average + this._obj1NewVelocity * body1.bounce.y; + body2.velocity.y = average + this._obj2NewVelocity * body2.bounce.y; + } + else if (body2.type != Types.BODY_DYNAMIC) + { + this._overlap *= 2; + body1.position.y -= this._overlap; + body1.velocity.y = this._obj2Velocity - this._obj1Velocity * body1.bounce.y; + // This is special case code that handles things like horizontal moving platforms you can ride + //if (body2.parent.active && body2.moves && (body1.deltaY > body2.deltaY)) + if (body2.sprite.active && (body1.deltaY > body2.deltaY)) + { + body1.position.x += body2.position.x - body2.oldPosition.x; + } + } + else if (body1.type != Types.BODY_DYNAMIC) + { + this._overlap *= 2; + body2.position.y += this._overlap; + body2.velocity.y = this._obj1Velocity - this._obj2Velocity * body2.bounce.y; + // This is special case code that handles things like horizontal moving platforms you can ride + //if (object1.active && body1.moves && (body1.deltaY < body2.deltaY)) + if (body1.sprite.active && (body1.deltaY < body2.deltaY)) + { + body2.position.x += body1.position.x - body1.oldPosition.x; + } + } + + return true; + } + else + { + return false; + } + } + + + + + + + + /* + private TILEseparate(shapeA: IPhysicsShape, shapeB: IPhysicsShape, distance: Vec2, tangent: Vec2) { + + if (tangent.x == 1) + { + console.log('1 The left side of ShapeA hit the right side of ShapeB', Math.floor(distance.x)); + shapeA.physics.touching |= Phaser.Types.LEFT; + shapeB.physics.touching |= Phaser.Types.RIGHT; + } + else if (tangent.x == -1) + { + console.log('2 The right side of ShapeA hit the left side of ShapeB', Math.floor(distance.x)); + shapeA.physics.touching |= Phaser.Types.RIGHT; + shapeB.physics.touching |= Phaser.Types.LEFT; + } + + if (tangent.y == 1) + { + console.log('3 The top of ShapeA hit the bottom of ShapeB', Math.floor(distance.y)); + shapeA.physics.touching |= Phaser.Types.UP; + shapeB.physics.touching |= Phaser.Types.DOWN; + } + else if (tangent.y == -1) + { + console.log('4 The bottom of ShapeA hit the top of ShapeB', Math.floor(distance.y)); + shapeA.physics.touching |= Phaser.Types.DOWN; + shapeB.physics.touching |= Phaser.Types.UP; + } + + + // only apply collision response forces if the object is travelling into, and not out of, the collision + var dot = Vec2Utils.dot(shapeA.physics.velocity, tangent); + + if (dot < 0) + { + console.log('in to', dot); + + // Apply horizontal bounce + if (shapeA.physics.bounce.x > 0) + { + shapeA.physics.velocity.x *= -(shapeA.physics.bounce.x); + } + else + { + shapeA.physics.velocity.x = 0; + } + // Apply horizontal bounce + if (shapeA.physics.bounce.y > 0) + { + shapeA.physics.velocity.y *= -(shapeA.physics.bounce.y); + } + else + { + shapeA.physics.velocity.y = 0; + } + } + else + { + console.log('out of', dot); + } + + shapeA.position.x += Math.floor(distance.x); + //shapeA.bounds.x += Math.floor(distance.x); + + shapeA.position.y += Math.floor(distance.y); + //shapeA.bounds.y += distance.y; + + console.log('------------------------------------------------'); + + } + + private collideWorld(shape:IPhysicsShape) { + + // Collide on the x-axis + this._distance.x = shape.world.bounds.x - (shape.position.x - shape.bounds.halfWidth); + + if (0 < this._distance.x) + { + // Hit Left + this._tangent.setTo(1, 0); + this.separateXWall(shape, this._distance, this._tangent); + } + else + { + this._distance.x = (shape.position.x + shape.bounds.halfWidth) - shape.world.bounds.right; + + if (0 < this._distance.x) + { + // Hit Right + this._tangent.setTo(-1, 0); + this._distance.reverse(); + this.separateXWall(shape, this._distance, this._tangent); + } + } + + // Collide on the y-axis + this._distance.y = shape.world.bounds.y - (shape.position.y - shape.bounds.halfHeight); + + if (0 < this._distance.y) + { + // Hit Top + this._tangent.setTo(0, 1); + this.separateYWall(shape, this._distance, this._tangent); + } + else + { + this._distance.y = (shape.position.y + shape.bounds.halfHeight) - shape.world.bounds.bottom; + + if (0 < this._distance.y) + { + // Hit Bottom + this._tangent.setTo(0, -1); + this._distance.reverse(); + this.separateYWall(shape, this._distance, this._tangent); + } + } + + } + + private separateX(shapeA: IPhysicsShape, shapeB: IPhysicsShape, distance: Vec2, tangent: Vec2) { + + if (tangent.x == 1) + { + console.log('The left side of ShapeA hit the right side of ShapeB', distance.x); + shapeA.physics.touching |= Phaser.Types.LEFT; + shapeB.physics.touching |= Phaser.Types.RIGHT; + } + else + { + console.log('The right side of ShapeA hit the left side of ShapeB', distance.x); + shapeA.physics.touching |= Phaser.Types.RIGHT; + shapeB.physics.touching |= Phaser.Types.LEFT; + } + + // collision edges + //shapeA.oH = tangent.x; + + // only apply collision response forces if the object is travelling into, and not out of, the collision + if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) + { + // Apply horizontal bounce + if (shapeA.physics.bounce.x > 0) + { + shapeA.physics.velocity.x *= -(shapeA.physics.bounce.x); + } + else + { + shapeA.physics.velocity.x = 0; + } + } + + shapeA.position.x += distance.x; + shapeA.bounds.x += distance.x; + + } + + private separateY(shapeA: IPhysicsShape, shapeB: IPhysicsShape, distance: Vec2, tangent: Vec2) { + + if (tangent.y == 1) + { + console.log('The top of ShapeA hit the bottom of ShapeB', distance.y); + shapeA.physics.touching |= Phaser.Types.UP; + shapeB.physics.touching |= Phaser.Types.DOWN; + } + else + { + console.log('The bottom of ShapeA hit the top of ShapeB', distance.y); + shapeA.physics.touching |= Phaser.Types.DOWN; + shapeB.physics.touching |= Phaser.Types.UP; + } + + // collision edges + //shapeA.oV = tangent.y; + + // only apply collision response forces if the object is travelling into, and not out of, the collision + if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) + { + // Apply horizontal bounce + if (shapeA.physics.bounce.y > 0) + { + shapeA.physics.velocity.y *= -(shapeA.physics.bounce.y); + } + else + { + shapeA.physics.velocity.y = 0; + } + } + + shapeA.position.y += distance.y; + shapeA.bounds.y += distance.y; + + } + + private separateXWall(shapeA: IPhysicsShape, distance: Vec2, tangent: Vec2) { + + if (tangent.x == 1) + { + console.log('The left side of ShapeA hit the right side of ShapeB', distance.x); + shapeA.physics.touching |= Phaser.Types.LEFT; + } + else + { + console.log('The right side of ShapeA hit the left side of ShapeB', distance.x); + shapeA.physics.touching |= Phaser.Types.RIGHT; + } + + // collision edges + //shapeA.oH = tangent.x; + + // only apply collision response forces if the object is travelling into, and not out of, the collision + if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) + { + // Apply horizontal bounce + if (shapeA.physics.bounce.x > 0) + { + shapeA.physics.velocity.x *= -(shapeA.physics.bounce.x); + } + else + { + shapeA.physics.velocity.x = 0; + } + } + + shapeA.position.x += distance.x; + + } + + private separateYWall(shapeA: IPhysicsShape, distance: Vec2, tangent: Vec2) { + + if (tangent.y == 1) + { + console.log('The top of ShapeA hit the bottom of ShapeB', distance.y); + shapeA.physics.touching |= Phaser.Types.UP; + } + else + { + console.log('The bottom of ShapeA hit the top of ShapeB', distance.y); + shapeA.physics.touching |= Phaser.Types.DOWN; + } + + // collision edges + //shapeA.oV = tangent.y; + + // only apply collision response forces if the object is travelling into, and not out of, the collision + if (Vec2Utils.dot(shapeA.physics.velocity, tangent) < 0) + { + // Apply horizontal bounce + if (shapeA.physics.bounce.y > 0) + { + shapeA.physics.velocity.y *= -(shapeA.physics.bounce.y); + } + else + { + shapeA.physics.velocity.y = 0; + } + } + + shapeA.position.y += distance.y; + + } + */ + + /** + * Checks for overlaps between two objects using the world QuadTree. Can be Sprite vs. Sprite, Sprite vs. Group or Group vs. Group. + * Note: Does not take the objects scrollFactor into account. All overlaps are check in world space. + * @param object1 The first Sprite or Group to check. If null the world.group is used. + * @param object2 The second Sprite or Group to check. + * @param notifyCallback A callback function that is called if the objects overlap. The two objects will be passed to this function in the same order in which you passed them to Collision.overlap. + * @param processCallback A callback function that lets you perform additional checks against the two objects if they overlap. If this is set then notifyCallback will only be called if processCallback returns true. + * @param context The context in which the callbacks will be called + * @returns {boolean} true if the objects overlap, otherwise false. + */ + public overlap(object1 = null, object2 = null, notifyCallback = null, processCallback = null, context = null): bool { + + /* + if (object1 == null) + { + object1 = this.game.world.group; + } + + if (object2 == object1) + { + object2 = null; + } + + QuadTree.divisions = this.worldDivisions; + + this._quadTree = new Phaser.QuadTree(this, this.bounds.x, this.bounds.y, this.bounds.width, this.bounds.height); + + this._quadTree.load(object1, object2, notifyCallback, processCallback, context); + + this._quadTreeResult = this._quadTree.execute(); + + console.log('over', this._quadTreeResult); + + this._quadTree.destroy(); + + this._quadTree = null; + + return this._quadTreeResult; + */ + + return false; + + } + + + + + + + /** + * Collision resolution specifically for GameObjects vs. Tiles. + * @param object The GameObject to separate + * @param tile The Tile to separate + * @returns {boolean} Whether the objects in fact touched and were separated + */ + public separateTile(object:Sprite, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool, collideUp: bool, collideDown: bool, separateX: bool, separateY: bool): bool { + + //var separatedX: bool = this.separateTileX(object, x, y, width, height, mass, collideLeft, collideRight, separateX); + //var separatedY: bool = this.separateTileY(object, x, y, width, height, mass, collideUp, collideDown, separateY); + + //return separatedX || separatedY; + + return false; + + } + + /** + * Separates the two objects on their x axis + * @param object The GameObject to separate + * @param tile The Tile to separate + * @returns {boolean} Whether the objects in fact touched and were separated along the X axis. + */ + /* + public separateTileX(object:Sprite, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool, separate: bool): bool { + + // Can't separate two immovable objects (tiles are always immovable) + if (object.immovable) + { + return false; + } + + // First, get the object delta + var overlap: number = 0; + var objDelta: number = object.x - object.last.x; + //var objDelta: number = object.collisionMask.deltaX; + + if (objDelta != 0) + { + // Check if the X hulls actually overlap + var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; + //var objDeltaAbs: number = object.collisionMask.deltaXAbs; + var objBounds: Rectangle = new Rectangle(object.x - ((objDelta > 0) ? objDelta : 0), object.last.y, object.width + ((objDelta > 0) ? objDelta : -objDelta), object.height); + + if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) + { + var maxOverlap: number = objDeltaAbs + Collision.OVERLAP_BIAS; + + // If they did overlap (and can), figure out by how much and flip the corresponding flags + if (objDelta > 0) + { + overlap = object.x + object.width - x; + + if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.RIGHT) || collideLeft == false) + { + overlap = 0; + } + else + { + object.touching |= Collision.RIGHT; + } + } + else if (objDelta < 0) + { + overlap = object.x - width - x; + + if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.LEFT) || collideRight == false) + { + overlap = 0; + } + else + { + object.touching |= Collision.LEFT; + } + + } + + } + } + + // Then adjust their positions and velocities accordingly (if there was any overlap) + if (overlap != 0) + { + if (separate == true) + { + //console.log(' + object.x = object.x - overlap; + object.velocity.x = -(object.velocity.x * object.elasticity); + } + + Collision.TILE_OVERLAP = true; + return true; + } + else + { + return false; + } + + } + */ + + /** + * Separates the two objects on their y axis + * @param object The first GameObject to separate + * @param tile The second GameObject to separate + * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis. + */ + /* + public separateTileY(object: Sprite, x: number, y: number, width: number, height: number, mass: number, collideUp: bool, collideDown: bool, separate: bool): bool { + + // Can't separate two immovable objects (tiles are always immovable) + if (object.immovable) + { + return false; + } + + // First, get the two object deltas + var overlap: number = 0; + var objDelta: number = object.y - object.last.y; + + if (objDelta != 0) + { + // Check if the Y hulls actually overlap + var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; + var objBounds: Rectangle = new Rectangle(object.x, object.y - ((objDelta > 0) ? objDelta : 0), object.width, object.height + objDeltaAbs); + + if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) + { + var maxOverlap: number = objDeltaAbs + Collision.OVERLAP_BIAS; + + // If they did overlap (and can), figure out by how much and flip the corresponding flags + if (objDelta > 0) + { + overlap = object.y + object.height - y; + + if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.DOWN) || collideUp == false) + { + overlap = 0; + } + else + { + object.touching |= Collision.DOWN; + } + } + else if (objDelta < 0) + { + overlap = object.y - height - y; + + if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.UP) || collideDown == false) + { + overlap = 0; + } + else + { + object.touching |= Collision.UP; + } + } + } + } + + // TODO - with super low velocities you get lots of stuttering, set some kind of base minimum here + + // Then adjust their positions and velocities accordingly (if there was any overlap) + if (overlap != 0) + { + if (separate == true) + { + object.y = object.y - overlap; + object.velocity.y = -(object.velocity.y * object.elasticity); + } + + Collision.TILE_OVERLAP = true; + return true; + } + else + { + return false; + } + } + */ + + + /** + * Separates the two objects on their x axis + * @param object The GameObject to separate + * @param tile The Tile to separate + * @returns {boolean} Whether the objects in fact touched and were separated along the X axis. + */ + /* + public static NEWseparateTileX(object:Sprite, x: number, y: number, width: number, height: number, mass: number, collideLeft: bool, collideRight: bool, separate: bool): bool { + + // Can't separate two immovable objects (tiles are always immovable) + if (object.immovable) + { + return false; + } + + // First, get the object delta + var overlap: number = 0; + + if (object.collisionMask.deltaX != 0) + { + // Check if the X hulls actually overlap + //var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; + //var objBounds: Rectangle = new Rectangle(object.x - ((objDelta > 0) ? objDelta : 0), object.last.y, object.width + ((objDelta > 0) ? objDelta : -objDelta), object.height); + + //if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) + if (object.collisionMask.intersectsRaw(x, x + width, y, y + height)) + { + var maxOverlap: number = object.collisionMask.deltaXAbs + Collision.OVERLAP_BIAS; + + // If they did overlap (and can), figure out by how much and flip the corresponding flags + if (object.collisionMask.deltaX > 0) + { + //overlap = object.x + object.width - x; + overlap = object.collisionMask.right - x; + + if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.RIGHT) || collideLeft == false) + { + overlap = 0; + } + else + { + object.touching |= Collision.RIGHT; + } + } + else if (object.collisionMask.deltaX < 0) + { + //overlap = object.x - width - x; + overlap = object.collisionMask.x - width - x; + + if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.LEFT) || collideRight == false) + { + overlap = 0; + } + else + { + object.touching |= Collision.LEFT; + } + + } + + } + } + + // Then adjust their positions and velocities accordingly (if there was any overlap) + if (overlap != 0) + { + if (separate == true) + { + object.x = object.x - overlap; + object.velocity.x = -(object.velocity.x * object.elasticity); + } + + Collision.TILE_OVERLAP = true; + return true; + } + else + { + return false; + } + + } + */ + + /** + * Separates the two objects on their y axis + * @param object The first GameObject to separate + * @param tile The second GameObject to separate + * @returns {boolean} Whether the objects in fact touched and were separated along the Y axis. + */ + /* + public NEWseparateTileY(object: Sprite, x: number, y: number, width: number, height: number, mass: number, collideUp: bool, collideDown: bool, separate: bool): bool { + + // Can't separate two immovable objects (tiles are always immovable) + if (object.immovable) + { + return false; + } + + // First, get the two object deltas + var overlap: number = 0; + //var objDelta: number = object.y - object.last.y; + + if (object.collisionMask.deltaY != 0) + { + // Check if the Y hulls actually overlap + //var objDeltaAbs: number = (objDelta > 0) ? objDelta : -objDelta; + //var objBounds: Rectangle = new Rectangle(object.x, object.y - ((objDelta > 0) ? objDelta : 0), object.width, object.height + objDeltaAbs); + + //if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) + if (object.collisionMask.intersectsRaw(x, x + width, y, y + height)) + { + //var maxOverlap: number = objDeltaAbs + Collision.OVERLAP_BIAS; + var maxOverlap: number = object.collisionMask.deltaYAbs + Collision.OVERLAP_BIAS; + + // If they did overlap (and can), figure out by how much and flip the corresponding flags + if (object.collisionMask.deltaY > 0) + { + //overlap = object.y + object.height - y; + overlap = object.collisionMask.bottom - y; + + if ((overlap > maxOverlap) || !(object.allowCollisions & Collision.DOWN) || collideUp == false) + { + overlap = 0; + } + else + { + object.touching |= Collision.DOWN; + } + } + else if (object.collisionMask.deltaY < 0) + { + //overlap = object.y - height - y; + overlap = object.collisionMask.y - height - y; + + if ((-overlap > maxOverlap) || !(object.allowCollisions & Collision.UP) || collideDown == false) + { + overlap = 0; + } + else + { + object.touching |= Collision.UP; + } + } + } + } + + // TODO - with super low velocities you get lots of stuttering, set some kind of base minimum here + + // Then adjust their positions and velocities accordingly (if there was any overlap) + if (overlap != 0) + { + if (separate == true) + { + object.y = object.y - overlap; + object.velocity.y = -(object.velocity.y * object.elasticity); + } + + Collision.TILE_OVERLAP = true; + return true; + } + else + { + return false; + } + } + */ + + } + +} \ No newline at end of file