diff --git a/examples/collision/sprite vs sprite.js b/examples/collision/sprite vs sprite.js index 6a8edbd8..82e4a0b7 100644 --- a/examples/collision/sprite vs sprite.js +++ b/examples/collision/sprite vs sprite.js @@ -43,9 +43,7 @@ function collisionHandler (obj1, obj2) { function render() { - // game.debug.renderBodyInfo(sprite1, 16, 16); - - game.debug.renderPolygon(sprite1.body.polygons); - game.debug.renderPolygon(sprite2.body.polygons); + game.debug.renderPhysicsBody(sprite1.body); + game.debug.renderPhysicsBody(sprite2.body); } \ No newline at end of file diff --git a/examples/wip/platform.js b/examples/wip/platform.js index b8a411ec..6b446394 100644 --- a/examples/wip/platform.js +++ b/examples/wip/platform.js @@ -28,7 +28,7 @@ function create() { layer = map.createLayer('Tile Layer 1'); - // layer.debug = true; + layer.debug = true; game.physics.gravity.y = 150; @@ -48,7 +48,7 @@ function create() { balls.setAll('body.minBounceVelocity', 0.9); balls.setAll('body.friction', 0.5); - sprite2 = game.add.sprite(300, 250, 'gameboy', 2); + sprite2 = game.add.sprite(340, 250, 'gameboy', 2); sprite2.name = 'green'; sprite2.body.collideWorldBounds = true; // sprite2.body.bounce.setTo(0.5, 0.5); @@ -67,8 +67,11 @@ function create() { function launch() { - sprite.body.velocity.x = -200; - sprite.body.velocity.y = -200; + // sprite.body.velocity.x = -200; + // sprite.body.velocity.y = -200; + + sprite2.body.velocity.x = -200; + sprite2.body.velocity.y = -200; } @@ -91,7 +94,14 @@ function update() { function render() { - game.debug.renderText(game.time.fps + ' (min: ' + game.time.fpsMin + ' max: ' + game.time.fpsMax + ') ' + game.time.physicsElapsed, 32, 32); + game.debug.renderBodyInfo(sprite2, 32, 32); + // game.debug.renderPhysicsBody(sprite2.body); + + + // game.debug.renderText(sprite2.body.left, 32, 30); + // game.debug.renderText(sprite2.body.right, 32, 50); + // game.debug.renderText(sprite2.body.top, 32, 70); + // game.debug.renderText(sprite2.body.bottom, 32, 90); // if (sprite) // { diff --git a/src/geom/Rectangle.js b/src/geom/Rectangle.js index 35104b8d..6b6b3dcb 100644 --- a/src/geom/Rectangle.js +++ b/src/geom/Rectangle.js @@ -653,13 +653,6 @@ Phaser.Rectangle.intersects = function (a, b) { return !(a.right < b.x || a.bottom < b.y || a.x > b.right || a.y > b.bottom); - // return (a.x < b.right && b.x < a.right && a.y < b.bottom && b.y < a.bottom); - - // return (a.x <= b.right && b.x <= a.right && a.y <= b.bottom && b.y <= a.bottom); - - // return (a.left <= b.right && b.left <= a.right && a.top <= b.bottom && b.top <= a.bottom); - // return !(a.x > b.right + tolerance || a.right < b.x - tolerance || a.y > b.bottom + tolerance || a.bottom < b.y - tolerance); - }; /** diff --git a/src/physics/arcade/ArcadePhysics.js b/src/physics/arcade/ArcadePhysics.js index 57e3dc86..99e1edb2 100644 --- a/src/physics/arcade/ArcadePhysics.js +++ b/src/physics/arcade/ArcadePhysics.js @@ -706,7 +706,7 @@ Phaser.Physics.Arcade.prototype = { */ collideSpriteVsTilemapLayer: function (sprite, tilemapLayer, collideCallback, processCallback, callbackContext) { - this._mapData = tilemapLayer.getTiles(sprite.body.x, sprite.body.y, sprite.body.width, sprite.body.height, true); + this._mapData = tilemapLayer.getTiles(sprite.body.left, sprite.body.top, sprite.body.width, sprite.body.height, true); if (this._mapData.length === 0) { @@ -715,7 +715,6 @@ Phaser.Physics.Arcade.prototype = { if (this._mapData.length > 1) { - // console.log(' multi sep ---------------------------------------------------------------------------------------------'); this.separateTiles(sprite.body, this._mapData); } else @@ -792,8 +791,7 @@ Phaser.Physics.Arcade.prototype = { */ separate: function (body1, body2, processCallback, callbackContext, overlapOnly) { - // if (body1 === body2 || Phaser.Rectangle.intersects(body1, body2) === false) - if (body1 === body2) + if (body1 === body2 || this.intersects(body1, body2) === false) { return false; } @@ -822,6 +820,25 @@ Phaser.Physics.Arcade.prototype = { }, + /** + * Performs a rect intersection test against the two objects. + * Objects must expose properties: width, height, left, right, top, bottom. + * @method Phaser.Physics.Arcade#intersects + * @param {object} a - The first object to test. + * @param {object} b - The second object to test. + * @returns {boolean} Returns true if the objects intersect, otherwise false. + */ + intersects: function (a, b) { + + if (a.width <= 0 || a.height <= 0 || b.width <= 0 || b.height <= 0) + { + return false; + } + + return !(a.right < b.left || a.bottom < b.top || a.left > b.right || a.top > b.bottom); + + }, + /** * The core separation function to separate a physics body and an array of tiles. * @method Phaser.Physics.Arcade#separateTiles @@ -848,7 +865,7 @@ Phaser.Physics.Arcade.prototype = { { tile = tiles[i]; - if (Phaser.Rectangle.intersects(body, tile)) + if (this.intersects(body, tile)) { // They overlap. Any custom callbacks? if (tile.tile.callback || tile.layer.callbacks[tile.tile.index]) @@ -869,7 +886,7 @@ Phaser.Physics.Arcade.prototype = { if (body.deltaX() < 0 && body.checkCollision.left && tile.tile.faceRight) { // LEFT - localOverlapX = body.x - tile.right; + localOverlapX = body.left - tile.right; if (localOverlapX >= body.deltaX()) { @@ -895,7 +912,7 @@ Phaser.Physics.Arcade.prototype = { if (body.deltaY() < 0 && body.checkCollision.up && tile.tile.faceBottom) { // UP - localOverlapY = body.y - tile.bottom; + localOverlapY = body.top - tile.bottom; // Distance check if (localOverlapY >= body.deltaY()) @@ -944,7 +961,7 @@ Phaser.Physics.Arcade.prototype = { separateTile: function (body, tile) { // Can't separate two immovable objects (tiles are always immovable) - if (body.immovable || Phaser.Rectangle.intersects(body, tile) === false) + if (body.immovable || this.intersects(body, tile) === false) { return false; } @@ -973,7 +990,7 @@ Phaser.Physics.Arcade.prototype = { if (body.deltaX() < 0 && body.checkCollision.left && tile.tile.faceRight) { // LEFT - body.overlapX = body.x - tile.right; + body.overlapX = body.left - tile.right; if (body.overlapX >= body.deltaX()) { @@ -1000,7 +1017,7 @@ Phaser.Physics.Arcade.prototype = { if (body.deltaY() < 0 && body.checkCollision.up && tile.tile.faceBottom) { // UP - body.overlapY = body.y - tile.bottom; + body.overlapY = body.top - tile.bottom; // Distance check if (body.overlapY >= body.deltaY()) @@ -1037,42 +1054,17 @@ Phaser.Physics.Arcade.prototype = { */ processTileSeparation: function (body) { + // Swap for a hit tile? if (body.touching.none) { return false; } - if (body.touching.left || body.touching.right) - { - body.x -= body.overlapX; - body.preX -= body.overlapX; + body.x += body.overlapX; + body.y += body.overlapY; - if (body.bounce.x === 0) - { - body.velocity.x = 0; - } - else - { - body.velocity.x = -body.velocity.x * body.bounce.x; - body.reboundCheck(true, false); - } - } - - if (body.touching.up || body.touching.down) - { - body.y -= body.overlapY; - body.preY -= body.overlapY; - - if (body.bounce.y === 0) - { - body.velocity.y = 0; - } - else - { - body.velocity.y = -body.velocity.y * body.bounce.y; - body.reboundCheck(false, true); - } - } + body.setBlockFlag(body.blocked.left, body.blocked.right, body.blocked.up, body.blocked.down, body.overlapX, body.overlapY); + body.reboundCheck(true, true, true); return true; diff --git a/src/physics/arcade/Body.js b/src/physics/arcade/Body.js index f79f3a92..ca2384c7 100644 --- a/src/physics/arcade/Body.js +++ b/src/physics/arcade/Body.js @@ -30,18 +30,6 @@ Phaser.Physics.Arcade.Body = function (sprite) { */ this.offset = new Phaser.Point(); - /** - * @property {number} x - The x position of the physics body. - * @readonly - */ - // this.x = sprite.x; - - /** - * @property {number} y - The y position of the physics body. - * @readonly - */ - // this.y = sprite.y; - /** * @property {number} preX - The previous x position of the physics body. * @readonly @@ -60,43 +48,6 @@ Phaser.Physics.Arcade.Body = function (sprite) { */ this.preRotation = sprite.angle; - /** - * @property {number} sourceWidth - The un-scaled original size. - * @readonly - */ - // this.sourceWidth = sprite.currentFrame.sourceSizeW; - - /** - * @property {number} sourceHeight - The un-scaled original size. - * @readonly - */ - // this.sourceHeight = sprite.currentFrame.sourceSizeH; - - /** - * @property {number} width - The calculated width of the physics body. - */ - // this.width = sprite.currentFrame.sourceSizeW; - - /** - * @property .numInternal ID cache - */ - // this.height = sprite.currentFrame.sourceSizeH; - - /** - * @property {number} halfWidth - The calculated width / 2 of the physics body. - */ - // this.halfWidth = Math.floor(sprite.currentFrame.sourceSizeW / 2); - - /** - * @property {number} halfHeight - The calculated height / 2 of the physics body. - */ - // this.halfHeight = Math.floor(sprite.currentFrame.sourceSizeH / 2); - - /** - * @property {Phaser.Point} center - The center coordinate of the Physics Body. - */ - // this.center = new Phaser.Point(this.x + this.halfWidth, this.y + this.halfHeight); - /** * @property {Phaser.Point} velocity - The velocity of the Body. */ @@ -113,7 +64,7 @@ Phaser.Physics.Arcade.Body = function (sprite) { this.speed = 0; /** - * @property {number} angle - The angle of the Body in radians. + * @property {number} angle - The angle of the Body based on its velocity in radians. */ this.angle = 0; @@ -283,6 +234,42 @@ Phaser.Physics.Arcade.Body = function (sprite) { */ this.polygon = null; + /** + * @property {number} left - The left-most point of this Body. + * @readonly + */ + this.left = 0; + + /** + * @property {number} right - The right-most point of this Body. + * @readonly + */ + this.right = 0; + + /** + * @property {number} top - The top-most point of this Body. + * @readonly + */ + this.top = 0; + + /** + * @property {number} bottom - The bottom-most point of this Body. + * @readonly + */ + this.bottom = 0; + + /** + * @property {number} width - The current width of the Body, taking into account the point rotation. + * @readonly + */ + this.width = 0; + + /** + * @property {number} height - The current height of the Body, taking into account the point rotation. + * @readonly + */ + this.height = 0; + /** * @property {Phaser.Point} _temp - Internal cache var. * @private @@ -319,6 +306,11 @@ Phaser.Physics.Arcade.Body = function (sprite) { */ this._distances = [0, 0, 0, 0]; + this.blockFlags = [0, 0, 0, 0]; + + this.overlapX = 0; + this.overlapY = 0; + // Set-up the default shape this.setRectangle(sprite.width, sprite.height, -sprite._cache.halfWidth, -sprite._cache.halfHeight); @@ -447,10 +439,28 @@ Phaser.Physics.Arcade.Body.prototype = { } } - this.blocked.up = false; - this.blocked.down = false; - this.blocked.left = false; - this.blocked.right = false; + this.updateBounds(); + + if (this.blocked.left && this.blockFlags[0] !== this.left) + { + this.blocked.left = false; + } + + if (this.blocked.right && this.blockFlags[1] !== this.right) + { + this.blocked.right = false; + } + + if (this.blocked.up && this.blockFlags[2] !== this.top) + { + this.blocked.up = false; + } + + if (this.blocked.down && this.blockFlags[3] !== this.bottom) + { + console.log('reset down block flag', this.blockFlags[3], this.bottom); + this.blocked.down = false; + } this.touching.none = true; this.touching.up = false; @@ -470,6 +480,100 @@ Phaser.Physics.Arcade.Body.prototype = { }, + setBlockFlag: function (left, right, up, down, x, y) { + + if (left) + { + this.blockFlags[0] = this.left + x; + console.log('left flag set to', this.blockFlags[0]); + } + else if (right) + { + this.blockFlags[1] = this.right + y; + console.log('right flag set to', this.blockFlags[1]); + } + + if (up) + { + this.blockFlags[2] = this.top + y; + // this.blockFlags[2] = this.top; + console.log('up flag set to', this.blockFlags[2]); + } + else if (down) + { + this.blockFlags[3] = this.bottom + y; + // this.blockFlags[3] = this.bottom; + console.log('down flag set to', this.blockFlags[3]); + } + + }, + + /** + * Internal method that updates the left, right, top, bottom, width and height properties. + * + * @method Phaser.Physics.Arcade#updateBounds + * @protected + */ + updateBounds: function () { + + if (this.type === Phaser.Physics.Arcade.CIRCLE) + { + this.left = this.shape.pos.x - this.shape.r; + this.right = this.shape.pos.x + this.shape.r; + this.top = this.shape.pos.y - this.shape.r; + this.bottom = this.shape.pos.y + this.shape.r; + } + else + { + this.left = this.polygon.pos.x - this.polygon.points[0].x; + this.right = this.polygon.pos.x + this.polygon.points[0].x; + this.top = this.polygon.pos.y - this.polygon.points[0].y; + this.bottom = this.polygon.pos.y + this.polygon.points[0].y; + + var temp; + + for (var i = 1, len = this.polygon.points.length; i < len; i++) + { + // Left + temp = this.polygon.pos.x - this.polygon.points[i].x; + + if (temp < this.left) + { + this.left = temp; + } + + // Right + temp = this.polygon.pos.x + this.polygon.points[i].x; + + if (temp > this.right) + { + this.right = temp; + } + + // Top + temp = this.polygon.pos.y - this.polygon.points[i].y; + + if (temp < this.top) + { + this.top = temp; + } + + // Bottom + temp = this.polygon.pos.y + this.polygon.points[i].y; + + if (temp > this.bottom) + { + this.bottom = temp; + } + } + + this.width = this.right - this.left; + this.height = this.bottom - this.top; + + } + + }, + /** * Internal method. * @@ -523,7 +627,7 @@ Phaser.Physics.Arcade.Body.prototype = { if (y) { - if (rebound && (this.blocked.up || this.blocked.down)) + if (rebound && this.bounce.y && (this.blocked.up || this.blocked.down)) { this.velocity.y *= -this.bounce.y; } @@ -776,6 +880,8 @@ Phaser.Physics.Arcade.Body.prototype = { return this.customSeparateCallback.call(this.customSeparateContext, this, response); } + console.log(this.sprite.name, 'collided with', body.sprite.name, response); + this._distances[0] = body.right - this.x; // Distance of B to face on left side of A this._distances[1] = this.right - body.x; // Distance of B to face on right side of A this._distances[2] = body.bottom - this.y; // Distance of B to face on bottom side of A @@ -810,20 +916,8 @@ Phaser.Physics.Arcade.Body.prototype = { } } - if (this.collideWorldBounds) - { - // this.checkWorldBounds(); - this.adjustWorldBounds(); - } - - if (body.collideWorldBounds) - { - // body.checkWorldBounds(); - body.adjustWorldBounds(); - } - - this.syncPosition(); - body.syncPosition(); + this.game.physics.checkBounds(this); + this.game.physics.checkBounds(body); return true; @@ -1024,26 +1118,7 @@ Phaser.Physics.Arcade.Body.prototype = { }, /** - * Internal method that syncs the Body coordinates with the SAT shape and polygon positions. - * - * @method Phaser.Physics.Arcade#syncPosition - * @protected - */ - syncPosition: function () { - - this.shape.pos.x = this.x; - this.shape.pos.y = this.y; - - if (this.polygon) - { - this.polygon.pos.x = this.x; - this.polygon.pos.y = this.y; - } - - }, - - /** - * Internal method. + * Internal method. Integrates velocity, global gravity and the delta timer. * * @method Phaser.Physics.Arcade#integrateVelocity * @protected @@ -1067,6 +1142,7 @@ Phaser.Physics.Arcade.Body.prototype = { { this.y += this._dy; this.velocity.y += this._temp.y; + // console.log('y added', this._dy); } if (this.velocity.x > this.maxVelocity.x) @@ -1137,43 +1213,8 @@ Phaser.Physics.Arcade.Body.prototype = { }, /** - * You can modify the size of the physics Body to be any dimension you need. - * So it could be smaller or larger than the parent Sprite. You can also control the x and y offset, which - * is the position of the Body relative to the top-left of the Sprite. - * - * @method Phaser.Physics.Arcade#setSize - * @param {number} width - The width of the Body. - * @param {number} height - The height of the Body. - * @param {number} [offsetX=0] - The X offset of the Body from the Sprite position. - * @param {number} [offsetY=0] - The Y offset of the Body from the Sprite position. - setSize: function (width, height, offsetX, offsetY) { - - if (typeof offsetX === 'undefined') { offsetX = 0; } - if (typeof offsetY === 'undefined') { offsetY = 0; } - - this.sourceWidth = width; - this.sourceHeight = height; - this.width = this.sourceWidth * this._sx; - this.height = this.sourceHeight * this._sy; - this.halfWidth = Math.floor(this.width / 2); - this.halfHeight = Math.floor(this.height / 2); - this.offset.setTo(offsetX, offsetY); - this.center.setTo(this.x + this.halfWidth, this.y + this.halfHeight); - - if (this.type === Phaser.Physics.Arcade.RECT) - { - this.setBox(); - } - else - { - this.setCircle(); - } - - }, - */ - - /** - * Resets all Body values (velocity, acceleration, rotation, etc) + * Resets the Body motion values: velocity, acceleration, angularVelocity and angularAcceleration. + * Also resets the forces to defaults: gravity, bounce, minVelocity,maxVelocity, angularDrag, maxAngular, mass, friction and checkCollision. * * @method Phaser.Physics.Arcade#reset */ @@ -1181,27 +1222,17 @@ Phaser.Physics.Arcade.Body.prototype = { this.velocity.setTo(0, 0); this.acceleration.setTo(0, 0); - this.angularVelocity = 0; this.angularAcceleration = 0; - this.preX = (this.sprite.world.x - (this.sprite.anchor.x * this.width)) + this.offset.x; - this.preY = (this.sprite.world.y - (this.sprite.anchor.y * this.height)) + this.offset.y; - this.preRotation = this.sprite.angle; - - this.x = this.preX; - this.y = this.preY; - this.rotation = this.preRotation; - - this.shape.pos.x = this.x; - this.shape.pos.y = this.y; - - if (this.polygon) - { - this.polygon.pos.x = this.x; - this.polygon.pos.y = this.y; - } - - this.center.setTo(this.x + this.halfWidth, this.y + this.halfHeight); + this.gravity.setTo(0, 0); + this.bounce.setTo(0, 0); + this.minVelocity.setTo(5, 5); + this.maxVelocity.setTo(1000, 1000); + this.angularDrag = 0; + this.maxAngular = 1000; + this.mass = 1; + this.friction = 0.1; + this.checkCollision = { none: false, any: true, up: true, down: true, left: true, right: true }; }, @@ -1239,79 +1270,6 @@ Phaser.Physics.Arcade.Body.prototype = { Phaser.Physics.Arcade.Body.prototype.constructor = Phaser.Physics.Arcade.Body; -/** -* @name Phaser.Physics.Arcade.Body#bottom -* @property {number} bottom - The bottom value of this Body (same as Body.y + Body.height) -*/ -Object.defineProperty(Phaser.Physics.Arcade.Body.prototype, "bottom", { - - /** - * The sum of the y and height properties. Changing the bottom property of a Rectangle object has no effect on the x, y and width properties, but does change the height property. - * @method bottom - * @return {number} - */ - get: function () { - return this.y + this.height; - }, - - /** - * The sum of the y and height properties. Changing the bottom property of a Rectangle object has no effect on the x, y and width properties, but does change the height property. - * @method bottom - * @param {number} value - */ - set: function (value) { - - if (value <= this.y) - { - this.height = 0; - } - else - { - this.height = (this.y - value); - } - - } - -}); - -/** -* @name Phaser.Physics.Arcade.Body#right -* @property {number} right - The right value of this Body (same as Body.x + Body.width) -*/ -Object.defineProperty(Phaser.Physics.Arcade.Body.prototype, "right", { - - /** - * The sum of the x and width properties. Changing the right property of a Rectangle object has no effect on the x, y and height properties. - * However it does affect the width property. - * @method right - * @return {number} - */ - get: function () { - return this.x + this.width; - }, - - /** - * The sum of the x and width properties. Changing the right property of a Rectangle object has no effect on the x, y and height properties. - * However it does affect the width property. - * @method right - * @param {number} value - */ - set: function (value) { - - if (value <= this.x) - { - this.width = 0; - } - else - { - this.width = this.x + value; - } - - } - -}); - - /** * @name Phaser.Physics.Arcade.Body#x * @property {number} x @@ -1395,3 +1353,18 @@ Object.defineProperty(Phaser.Physics.Arcade.Body.prototype, "y", { } }); + +/** +* @name Phaser.Physics.Arcade.Body#movingLeft +* @property {number} movingLeft +*/ +Object.defineProperty(Phaser.Physics.Arcade.Body.prototype, "movingLeft", { + + /** + * @method movingLeft + * @return {boolean} + */ + get: function () { + } + +}); diff --git a/src/tilemap/Tile.js b/src/tilemap/Tile.js index 546bdcf0..fef0eeba 100644 --- a/src/tilemap/Tile.js +++ b/src/tilemap/Tile.js @@ -236,14 +236,14 @@ Object.defineProperty(Phaser.Tile.prototype, "canCollide", { }); /** -* @name Phaser.Tile#bottom -* @property {number} bottom - The sum of the y and height properties. +* @name Phaser.Tile#left +* @property {number} left - The x value. * @readonly */ -Object.defineProperty(Phaser.Tile.prototype, "bottom", { +Object.defineProperty(Phaser.Tile.prototype, "left", { get: function () { - return this.y + this.height; + return this.x; } }); @@ -260,3 +260,29 @@ Object.defineProperty(Phaser.Tile.prototype, "right", { } }); + +/** +* @name Phaser.Tile#top +* @property {number} top - The y value. +* @readonly +*/ +Object.defineProperty(Phaser.Tile.prototype, "top", { + + get: function () { + return this.y; + } + +}); + +/** +* @name Phaser.Tile#bottom +* @property {number} bottom - The sum of the y and height properties. +* @readonly +*/ +Object.defineProperty(Phaser.Tile.prototype, "bottom", { + + get: function () { + return this.y + this.height; + } + +});