From 9deb5514a21dc79d12c6e6ed13cbeec229806ea2 Mon Sep 17 00:00:00 2001 From: photonstorm Date: Tue, 28 Jan 2014 05:01:17 +0000 Subject: [PATCH] ArcadePhysics.setBoundsToWorld implemented. Body.setCircle, setRectangle and setPolygon all working. Tidying up Body class. Need to add tile collision special case handler next. --- README.md | 1 + examples/wip/tween-relative.js | 50 +++- src/gameobjects/Sprite.js | 2 +- src/physics/arcade/ArcadePhysics.js | 166 ++++++++++++- src/physics/arcade/Body.js | 350 ++++++++++++++++------------ src/utils/Debug.js | 59 +++++ 6 files changed, 464 insertions(+), 164 deletions(-) diff --git a/README.md b/README.md index 0e56f6ac..645089d1 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,7 @@ Significant API changes: * Body.rebound is a boolean that controls if a body will exchange velocity on collision. Set to false to allow it to be 'pushed' (see new examples). * Removed Body.deltaAbsX and deltaAbsY as they are no longer used internally. * Body.screenX and screenY moved to getters, no longer calculated every frame. +* ArcadePhysics now has setBounds and setBoundsToWorld, and you can specify which walls are created or not (left, right, up, down) New features: diff --git a/examples/wip/tween-relative.js b/examples/wip/tween-relative.js index 759f3067..7d0b8f2b 100644 --- a/examples/wip/tween-relative.js +++ b/examples/wip/tween-relative.js @@ -16,20 +16,56 @@ function create() { game.stage.backgroundColor = '#2384e7'; - arrowStart = game.add.sprite(100, 100, 'arrows', 0); + // game.physics.setBoundsToWorld(true, true, false, false); - arrowEnd = game.add.sprite(400, 100, 'arrows', 1); + // arrowStart = game.add.sprite(100, 100, 'arrows', 0); + // arrowEnd = game.add.sprite(400, 100, 'arrows', 1); - sprite = game.add.sprite(100, 164, 'phaser'); + // sprite = game.add.sprite(100, 164, 'phaser'); + sprite = game.add.sprite(300, 364, 'phaser'); + sprite.anchor.setTo(0.5, 0.5); sprite.inputEnabled = true; + sprite.body.collideWorldBounds = true; + sprite.body.bounce.setTo(1, 1); + + // sprite.body.allowRotation = true; + // sprite.body.polygon.translate(100, 0); + + + sprite.body.setPolygon([new SAT.Vector(0,0), new SAT.Vector(60, 0), new SAT.Vector(100, 40), new SAT.Vector(60, 80), new SAT.Vector(0, 80)], -50, -40); + + + // sprite.body.setCircle(50); + // sprite.body.offset.setTo(50, 50); + + // console.log(sprite.body.x, sprite.body.y, sprite.body.shape.radius); sprite.events.onInputDown.add(move, this); + // sprite.body.polygons.rotate(0.4); + // sprite.rotation = 0.4; + + // console.log(sprite.body.polygons); + } function move() { - console.log('moving'); + console.log('move'); + + sprite.body.velocity.x = 200; + sprite.body.velocity.y = -200; + // sprite.body.angularVelocity = 2; + + // sprite.rotation = 0.4; + + // console.log(sprite.body.polygon.points); + + // to: function (properties, duration, ease, autoStart, delay, repeat, yoyo) { + + game.add.tween(sprite).to( { angle: 359 }, 4000, Phaser.Easing.Linear.None, true, 0, 1000, false); + + // sprite.scale.setTo(2, 2); if (sprite.x === 100) { @@ -53,13 +89,13 @@ function render() { // game.debug.renderText('Click sprite to tween', 32, 32); } - game.debug.renderText('x: ' + arrowStart.x, arrowStart.x, arrowStart.y - 4); - game.debug.renderText('x: ' + arrowEnd.x, arrowEnd.x, arrowEnd.y - 4); + // game.debug.renderText('x: ' + arrowStart.x, arrowStart.x, arrowStart.y - 4); + // game.debug.renderText('x: ' + arrowEnd.x, arrowEnd.x, arrowEnd.y - 4); game.debug.renderText('sprite.x: ' + sprite.x + ' deltaX: ' + sprite.deltaX, 32, 32); game.debug.renderText('sprite.y: ' + sprite.y + ' deltaY: ' + sprite.deltaY, 32, 48); - game.debug.renderPolygon(sprite.body.polygons); + game.debug.renderPhysicsBody(sprite.body); game.debug.renderPoint(sprite.center); diff --git a/src/gameobjects/Sprite.js b/src/gameobjects/Sprite.js index cf17ea54..d092fd3d 100644 --- a/src/gameobjects/Sprite.js +++ b/src/gameobjects/Sprite.js @@ -604,7 +604,7 @@ Phaser.Sprite.prototype.updateBounds = function() { // Update our physics bounds if (this.body) { - this.body.updateBounds(this.center.x, this.center.y, this._cache.scaleX, this._cache.scaleY); + this.body.updateScale(this._cache.scaleX, this._cache.scaleY); } }; diff --git a/src/physics/arcade/ArcadePhysics.js b/src/physics/arcade/ArcadePhysics.js index 570d4739..57e3dc86 100644 --- a/src/physics/arcade/ArcadePhysics.js +++ b/src/physics/arcade/ArcadePhysics.js @@ -29,6 +29,31 @@ Phaser.Physics.Arcade = function (game) { */ this.gravity = new Phaser.Point(); + /** + * @property {SAT.Box} worldLeft - The left hand side of the physics bounds. + */ + this.worldLeft = null; + + /** + * @property {SAT.Box} worldRight - The right hand side of the physics bounds. + */ + this.worldRight = null; + + /** + * @property {SAT.Box} worldTop - The top side of the physics bounds. + */ + this.worldTop = null; + + /** + * @property {SAT.Box} worldBottom - The bottom of the physics bounds. + */ + this.worldBottom = null; + + /** + * @property {array} worldPolys - An array of the polygon data from the physics bounds. + */ + this.worldPolys = [ null, null, null, null ]; + /** * @property {Phaser.QuadTree} quadTree - The world QuadTree. */ @@ -110,6 +135,9 @@ Phaser.Physics.Arcade = function (game) { */ this._response = new SAT.Response(); + // Set the bounds to the world as default + this.setBoundsToWorld(true, true, true, true); + }; /** @@ -132,6 +160,141 @@ Phaser.Physics.Arcade.POLYGON = 2; Phaser.Physics.Arcade.prototype = { + /** + * Checks the given Physics.Body against the Physics Bounds, if any are set and separates them, setting the blocked flags on the Body as it does so. + * + * @method Phaser.Physics.Arcade#checkBounds + * @param {Phaser.Physics.Arcade.Body} The Body object to be checked. + */ + checkBounds: function (body) { + + if (!body.collideWorldBounds || (!this.worldLeft && !this.worldRight && !this.worldTop && !this.worldBottom)) + { + return; + } + + this._response.clear(); + + var test = SAT.testPolygonPolygon; + var part = body.polygon; + + if (body.type === Phaser.Physics.Arcade.CIRCLE) + { + test = SAT.testPolygonCircle; + part = body.shape; + } + + if (this.worldLeft && test(this.worldPolys[0], part, this._response)) + { + body.blocked.left = true; + part.pos.add(this._response.overlapV); + } + else if (this.worldRight && test(this.worldPolys[1], part, this._response)) + { + body.blocked.right = true; + part.pos.add(this._response.overlapV); + } + + this._response.clear(); + + if (this.worldTop && test(this.worldPolys[2], part, this._response)) + { + body.blocked.up = true; + part.pos.add(this._response.overlapV); + } + else if (this.worldBottom && test(this.worldPolys[3], part, this._response)) + { + body.blocked.down = true; + part.pos.add(this._response.overlapV); + } + + }, + + /** + * Sets the bounds of the Physics world to match the Game.World. + * You can optionally set which 'walls' to create: left, right, top or bottom. + * + * @method Phaser.Physics.Arcade#setBoundsToWorld + * @param {boolean} [left=true] - If true will create the left bounds wall. + * @param {boolean} [right=true] - If true will create the right bounds wall. + * @param {boolean} [top=true] - If true will create the top bounds wall. + * @param {boolean} [bottom=true] - If true will create the bottom bounds wall. + */ + setBoundsToWorld: function (left, right, top, bottom) { + + this.setBounds(this.game.world.bounds.x, this.game.world.bounds.y, this.game.world.bounds.width, this.game.world.bounds.height, left, right, top, bottom); + + }, + + /** + * Sets the bounds of the Physics world to match the given world pixel dimensions. + * You can optionally set which 'walls' to create: left, right, top or bottom. + * + * @method Phaser.Physics.Arcade#setBounds + * @param {number} x - The x coordinate of the top-left corner of the bounds. + * @param {number} y - The y coordinate of the top-left corner of the bounds. + * @param {number} width - The width of the bounds. + * @param {number} height - The height of the bounds. + * @param {boolean} [left=true] - If true will create the left bounds wall. + * @param {boolean} [right=true] - If true will create the right bounds wall. + * @param {boolean} [top=true] - If true will create the top bounds wall. + * @param {boolean} [bottom=true] - If true will create the bottom bounds wall. + */ + setBounds: function (x, y, width, height, left, right, top, bottom) { + + if (typeof left === 'undefined') { left = true; } + if (typeof right === 'undefined') { right = true; } + if (typeof top === 'undefined') { top = true; } + if (typeof bottom === 'undefined') { bottom = true; } + + var thickness = 100; + + if (left) + { + this.worldLeft = new SAT.Box(new SAT.Vector(x - thickness, y), thickness, height); + this.worldPolys[0] = this.worldLeft.toPolygon(); + } + else + { + this.worldLeft = null; + this.worldPolys[0] = null; + } + + if (right) + { + this.worldRight = new SAT.Box(new SAT.Vector(x + width, y), thickness, height); + this.worldPolys[1] = this.worldRight.toPolygon(); + } + else + { + this.worldRight = null; + this.worldPolys[1] = null; + } + + if (top) + { + this.worldTop = new SAT.Box(new SAT.Vector(x, y - thickness), width, thickness); + this.worldPolys[2] = this.worldTop.toPolygon(); + } + else + { + this.worldTop = null; + this.worldPolys[2] = null; + } + + if (bottom) + { + this.worldBottom = new SAT.Box(new SAT.Vector(x, y + height), width, thickness); + this.worldPolys[3] = this.worldBottom.toPolygon(); + } + else + { + this.worldBottom = null; + this.worldPolys[3] = null; + } + + }, + /** * Called automatically by a Physics body, it updates all motion related values on the Body. * @@ -629,7 +792,8 @@ Phaser.Physics.Arcade.prototype = { */ separate: function (body1, body2, processCallback, callbackContext, overlapOnly) { - if (body1 === body2 || Phaser.Rectangle.intersects(body1, body2) === false) + // if (body1 === body2 || Phaser.Rectangle.intersects(body1, body2) === false) + if (body1 === body2) { return false; } diff --git a/src/physics/arcade/Body.js b/src/physics/arcade/Body.js index eda52526..f79f3a92 100644 --- a/src/physics/arcade/Body.js +++ b/src/physics/arcade/Body.js @@ -34,13 +34,13 @@ Phaser.Physics.Arcade.Body = function (sprite) { * @property {number} x - The x position of the physics body. * @readonly */ - this.x = sprite.x; + // this.x = sprite.x; /** * @property {number} y - The y position of the physics body. * @readonly */ - this.y = sprite.y; + // this.y = sprite.y; /** * @property {number} preX - The previous x position of the physics body. @@ -64,38 +64,38 @@ Phaser.Physics.Arcade.Body = function (sprite) { * @property {number} sourceWidth - The un-scaled original size. * @readonly */ - this.sourceWidth = sprite.currentFrame.sourceSizeW; + // this.sourceWidth = sprite.currentFrame.sourceSizeW; /** * @property {number} sourceHeight - The un-scaled original size. * @readonly */ - this.sourceHeight = sprite.currentFrame.sourceSizeH; + // this.sourceHeight = sprite.currentFrame.sourceSizeH; /** * @property {number} width - The calculated width of the physics body. */ - this.width = sprite.currentFrame.sourceSizeW; + // this.width = sprite.currentFrame.sourceSizeW; /** * @property .numInternal ID cache */ - this.height = sprite.currentFrame.sourceSizeH; + // this.height = sprite.currentFrame.sourceSizeH; /** * @property {number} halfWidth - The calculated width / 2 of the physics body. */ - this.halfWidth = Math.floor(sprite.currentFrame.sourceSizeW / 2); + // 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); + // 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); + // this.center = new Phaser.Point(this.x + this.halfWidth, this.y + this.halfHeight); /** * @property {Phaser.Point} velocity - The velocity of the Body. @@ -169,6 +169,12 @@ Phaser.Physics.Arcade.Body = function (sprite) { */ this.mass = 1; + /** + * @property {number} friction - The amount of friction this body experiences during motion. + * @default + */ + this.friction = 0.1; + /** * Set the checkCollision properties to control which directions collision is processed for this Body. * For example checkCollision.up = false means it won't collide when the collision happened while moving up. @@ -202,25 +208,25 @@ Phaser.Physics.Arcade.Body = function (sprite) { this.immovable = false; /** - * @property {boolean} moves - Set to true to allow the Physics system to move this Body, or false to move it manually. + * @property {boolean} moves - Set to true to allow the Physics system (such as velocity) to move this Body, or false to move it manually. * @default */ this.moves = true; /** - * @property {number} rotation - The amount the parent Sprite is rotated. Note: You cannot rotate an AABB. + * @property {number} rotation - The amount the parent Sprite is rotated. * @default */ this.rotation = 0; /** - * @property {boolean} allowRotation - Allow angular rotation? This will cause the Sprite to be rotated via angularVelocity, etc. Note that the AABB remains un-rotated. + * @property {boolean} allowRotation - Allow angular rotation? This will cause the Sprite to be rotated via angularVelocity, etc. * @default */ this.allowRotation = true; /** - * @property {boolean} allowGravity - Allow this Body to be influenced by the global Gravity value? Note: It will always be influenced by the local gravity value. + * @property {boolean} allowGravity - Allow this Body to be influenced by the global Gravity value? Note: It will always be influenced by the local gravity if set. * @default */ this.allowGravity = true; @@ -249,12 +255,6 @@ Phaser.Physics.Arcade.Body = function (sprite) { */ this.collideCallbackContext = null; - /** - * @property {number} friction - The amount of friction this body experiences during motion. - * @default - */ - this.friction = 0.1; - /** * A Body can be set to collide against the World bounds automatically and rebound back into the World if this is set to true. Otherwise it will leave the World. * @property {boolean} collideWorldBounds - Should the Body collide with the World bounds? @@ -276,13 +276,12 @@ Phaser.Physics.Arcade.Body = function (sprite) { /** * @property {SAT.Box|SAT.Circle|SAT.Polygon} shape - The SAT Collision shape. */ - this.shape = new SAT.Box(new SAT.Vector(this.x, this.y), this.width, this.height); + this.shape = null; /** - * @property {SAT.Polygon} polygons - The SAT Polygons, as derived from the Shape. - * @private + * @property {SAT.Polygon} polygon - The SAT Polygons, as derived from the Shape. */ - this.polygons = this.shape.toPolygon(); + this.polygon = null; /** * @property {Phaser.Point} _temp - Internal cache var. @@ -320,49 +319,105 @@ Phaser.Physics.Arcade.Body = function (sprite) { */ this._distances = [0, 0, 0, 0]; + // Set-up the default shape + this.setRectangle(sprite.width, sprite.height, -sprite._cache.halfWidth, -sprite._cache.halfHeight); + }; Phaser.Physics.Arcade.Body.prototype = { - setCircle: function (radius) { + /** + * Sets this Body to use a circle of the given radius for all collision. + * The Circle will be centered on the center of the Sprite by default, but can be adjusted via the Body.offset property and the setCircle x/y parameters. + * + * @method Phaser.Physics.Arcade#setCircle + * @param {number} radius - The radius of this circle (in pixels) + * @param {number} [offsetX=0] - The x amount the circle will be offset from the Sprites center. + * @param {number} [offsetY=0] - The y amount the circle will be offset from the Sprites center. + */ + setCircle: function (radius, offsetX, offsetY) { + + if (typeof offsetX === 'undefined') { offsetX = 0; } + if (typeof offsetY === 'undefined') { offsetY = 0; } - this.shape = new SAT.Circle(new SAT.Vector(this.x, this.y), radius); - this.polygons = null; this.type = Phaser.Physics.Arcade.CIRCLE; + this.shape = new SAT.Circle(new SAT.Vector(this.sprite.center.x, this.sprite.center.y), radius); + this.polygon = null; + + this.offset.setTo(offsetX, offsetY); }, - setBox: function () { + /** + * Sets this Body to use a rectangle for all collision. + * If you don't specify any parameters it will be sized to match the parent Sprites current width and height (including scale factor) and centered on the sprite. + * + * @method Phaser.Physics.Arcade#setRectangle + * @param {number} [width] - The width of the rectangle. If not specified it will default to the width of the parent Sprite. + * @param {number} [height] - The height of the rectangle. If not specified it will default to the height of the parent Sprite. + * @param {number} [translateX] - The x amount the rectangle will be translated from the Sprites center. + * @param {number} [translateY] - The y amount the rectangle will be translated from the Sprites center. + */ + setRectangle: function (width, height, translateX, translateY) { + + if (typeof width === 'undefined') { width = this.sprite.width; } + if (typeof height === 'undefined') { height = this.sprite.height; } + if (typeof translateX === 'undefined') { translateX = -this.sprite._cache.halfWidth; } + if (typeof translateY === 'undefined') { translateY = -this.sprite._cache.halfHeight; } - this.shape = new SAT.Box(new SAT.Vector(this.x, this.y), this.width, this.height); - this.polygons = this.shape.toPolygon(); this.type = Phaser.Physics.Arcade.RECT; + this.shape = new SAT.Box(new SAT.Vector(this.sprite.center.x, this.sprite.center.y), width, height); + this.polygon = this.shape.toPolygon(); + this.polygon.translate(translateX, translateY); + + this.offset.setTo(0, 0); + + }, + + /** + * Sets this Body to use a convex polygon for all collision. The points are specified in a counter-clockwise direction and must create a convex polygon. + * It will be centered on the parent Sprite. + * + * @method Phaser.Physics.Arcade#setPolygon + * @param {array} points - An array of vectors representing the points in the polygon, in counter-clockwise order. + * @param {number} [translateX=0] - The x amount the rectangle will be translated by from the Sprites center. + * @param {number} [translateY=0] - The y amount the rectangle will be translated by from the Sprites center. + */ + setPolygon: function (points, translateX, translateY) { + + if (typeof translateX === 'undefined') { translateX = 0; } + if (typeof translateY === 'undefined') { translateY = 0; } + + this.type = Phaser.Physics.Arcade.POLYGON; + this.shape = null; + this.polygon = new SAT.Polygon(new SAT.Vector(this.sprite.center.x, this.sprite.center.y), points); + this.polygon.translate(translateX, translateY); + + this.offset.setTo(0, 0); }, /** * Internal method. * - * @method Phaser.Physics.Arcade#updateBounds - * @protected + * @method Phaser.Physics.Arcade#updateScale + * @private */ - updateBounds: function (centerX, centerY, scaleX, scaleY) { + updateScale: function (scaleX, scaleY) { if (scaleX != this._sx || scaleY != this._sy) { - this.width = this.sourceWidth * scaleX; - this.height = this.sourceHeight * scaleY; - this.halfWidth = Math.floor(this.width / 2); - this.halfHeight = Math.floor(this.height / 2); - - if (this.polygons) + if (this.polygon) { - this.polygons.scale(scaleX / this._sx, scaleY / this._sy); + this.polygon.scale(scaleX / this._sx, scaleY / this._sy); + } + else + { + this.shape.r *= Math.max(scaleX, scaleY); } this._sx = scaleX; this._sy = scaleY; - this.center.setTo(this.x + this.halfWidth, this.y + this.halfHeight); } }, @@ -377,11 +432,20 @@ Phaser.Physics.Arcade.Body.prototype = { this.preX = this.x; this.preY = this.y; - this.preRotation = this.rotation; - this.x = (this.sprite.world.x - (this.sprite.anchor.x * this.width)) + this.offset.x; - this.y = (this.sprite.world.y - (this.sprite.anchor.y * this.height)) + this.offset.y; - this.rotation = this.sprite.angle; + this.x = this.sprite.center.x + this.offset.x; + this.y = this.sprite.center.y + this.offset.y; + + if (this.allowRotation) + { + this.preRotation = this.rotation; + this.rotation = this.sprite.rotation; + + if (this.type !== Phaser.Physics.Arcade.CIRCLE && this.deltaZ() !== 0) + { + this.polygon.rotate(this.deltaZ()); + } + } this.blocked.up = false; this.blocked.down = false; @@ -399,73 +463,11 @@ Phaser.Physics.Arcade.Body.prototype = { if (this.moves) { - if (this.collideWorldBounds) - { - this.checkWorldBounds(); - this.adjustWorldBounds(); - } + this.game.physics.checkBounds(this); this.applyFriction(); } - this.syncPosition(); - - }, - - /** - * Internal method used to check the Body against the World Bounds. - * - * @method Phaser.Physics.Arcade#checkWorldBounds - * @protected - */ - checkWorldBounds: function () { - - if (this.x <= this.game.world.bounds.x) - { - this.blocked.left = true; - } - else if (this.right >= this.game.world.bounds.right) - { - this.blocked.right = true; - } - - if (this.y <= this.game.world.bounds.y) - { - this.blocked.up = true; - } - else if (this.bottom >= this.game.world.bounds.bottom) - { - this.blocked.down = true; - } - - }, - - /** - * Internal method used to adjust the position of the Body against the World Bounds. - * - * @method Phaser.Physics.Arcade#adjustWorldBounds - * @protected - */ - adjustWorldBounds: function () { - - if (this.x < this.game.world.bounds.x) - { - this.x += this.game.world.bounds.x - this.x; - } - else if (this.right > this.game.world.bounds.right) - { - this.x -= this.right - this.game.world.bounds.right; - } - - if (this.y < this.game.world.bounds.y) - { - this.y += this.game.world.bounds.y - this.y; - } - else if (this.bottom > this.game.world.bounds.bottom) - { - this.y -= this.bottom - this.game.world.bounds.bottom; - } - }, /** @@ -506,7 +508,7 @@ Phaser.Physics.Arcade.Body.prototype = { if (x) { - if (rebound) + if (rebound && (this.blocked.left || this.blocked.right)) { this.velocity.x *= -this.bounce.x; } @@ -521,7 +523,7 @@ Phaser.Physics.Arcade.Body.prototype = { if (y) { - if (rebound) + if (rebound && (this.blocked.up || this.blocked.down)) { this.velocity.y *= -this.bounce.y; } @@ -740,7 +742,7 @@ Phaser.Physics.Arcade.Body.prototype = { if (this.type === Phaser.Physics.Arcade.RECT && body.type === Phaser.Physics.Arcade.RECT) { - return SAT.testPolygonPolygon(this.polygons, body.polygons, response); + return SAT.testPolygonPolygon(this.polygon, body.polygon, response); } else if (this.type === Phaser.Physics.Arcade.CIRCLE && body.type === Phaser.Physics.Arcade.CIRCLE) { @@ -748,11 +750,11 @@ Phaser.Physics.Arcade.Body.prototype = { } else if (this.type === Phaser.Physics.Arcade.RECT && body.type === Phaser.Physics.Arcade.CIRCLE) { - return SAT.testPolygonCircle(this.polygons, body.shape, response); + return SAT.testPolygonCircle(this.polygon, body.shape, response); } else if (this.type === Phaser.Physics.Arcade.CIRCLE && body.type === Phaser.Physics.Arcade.RECT) { - return SAT.testCirclePolygon(this.shape, body.polygons, response); + return SAT.testCirclePolygon(this.shape, body.polygon, response); } }, @@ -1032,10 +1034,10 @@ Phaser.Physics.Arcade.Body.prototype = { this.shape.pos.x = this.x; this.shape.pos.y = this.y; - if (this.polygons) + if (this.polygon) { - this.polygons.pos.x = this.x; - this.polygons.pos.y = this.y; + this.polygon.pos.x = this.x; + this.polygon.pos.y = this.y; } }, @@ -1097,24 +1099,11 @@ Phaser.Physics.Arcade.Body.prototype = { if (this.moves) { - if (this.bounce.x !== 0 && (this.blocked.left || this.blocked.right)) - { - this.reboundCheck(true, false, true); - } - - if (this.bounce.y !== 0 && (this.blocked.up || this.blocked.down)) - { - this.reboundCheck(false, true, true); - } + this.reboundCheck(true, true, true); this.integrateVelocity(); - if (this.collideWorldBounds) - { - this.adjustWorldBounds(); - } - - this.syncPosition(); + this.game.physics.checkBounds(this); if (this.deltaX() < 0) { @@ -1134,14 +1123,14 @@ Phaser.Physics.Arcade.Body.prototype = { this.facing = Phaser.DOWN; } - this.sprite.x = this.sprite.worldTransform[2] = this.x - (this.preX - this.sprite.x); - this.sprite.y = this.sprite.worldTransform[5] = this.y - (this.preY - this.sprite.y); - - this.center.setTo(this.x + this.halfWidth, this.y + this.halfHeight); + this.sprite.x = this.x + (this.sprite.x - this.sprite.center.x) - this.offset.x; + this.sprite.y = this.y + (this.sprite.y - this.sprite.center.y) - this.offset.y; if (this.allowRotation) { - this.sprite.angle += this.deltaZ(); + // this.sprite.rotation = this.rotation; + // this.sprite.angle += this.deltaZ(); + // this.sprite.angle = this.angle; } } @@ -1155,13 +1144,12 @@ Phaser.Physics.Arcade.Body.prototype = { * @method Phaser.Physics.Arcade#setSize * @param {number} width - The width of the Body. * @param {number} height - The height of the Body. - * @param {number} offsetX - The X offset of the Body from the Sprite position. - * @param {number} offsetY - The Y offset of the Body from the Sprite position. - */ + * @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) { - offsetX = offsetX || this.offset.x; - offsetY = offsetY || this.offset.y; + if (typeof offsetX === 'undefined') { offsetX = 0; } + if (typeof offsetY === 'undefined') { offsetY = 0; } this.sourceWidth = width; this.sourceHeight = height; @@ -1182,6 +1170,7 @@ Phaser.Physics.Arcade.Body.prototype = { } }, + */ /** * Resets all Body values (velocity, acceleration, rotation, etc) @@ -1206,10 +1195,10 @@ Phaser.Physics.Arcade.Body.prototype = { this.shape.pos.x = this.x; this.shape.pos.y = this.y; - if (this.polygons) + if (this.polygon) { - this.polygons.pos.x = this.x; - this.polygons.pos.y = this.y; + this.polygon.pos.x = this.x; + this.polygon.pos.y = this.y; } this.center.setTo(this.x + this.halfWidth, this.y + this.halfHeight); @@ -1322,36 +1311,87 @@ Object.defineProperty(Phaser.Physics.Arcade.Body.prototype, "right", { }); + /** -* @name Phaser.Physics.Arcade.Body#screenX -* @property {number} screenX - The x position of the physics body translated to screen space. +* @name Phaser.Physics.Arcade.Body#x +* @property {number} x */ -Object.defineProperty(Phaser.Physics.Arcade.Body.prototype, "screenX", { +Object.defineProperty(Phaser.Physics.Arcade.Body.prototype, "x", { /** - * The x position of the physics body translated to screen space. - * @method screenX + * @method x * @return {number} */ get: function () { - return (this.sprite.worldTransform[2] - (this.sprite.anchor.x * this.width)) + this.offset.x; + + if (this.type === Phaser.Physics.Arcade.CIRCLE) + { + return this.shape.pos.x; + } + else + { + return this.polygon.pos.x; + } + + }, + + /** + * @method x + * @param {number} value + */ + set: function (value) { + + if (this.type === Phaser.Physics.Arcade.CIRCLE) + { + this.shape.pos.x = value; + } + else + { + this.polygon.pos.x = value; + } + } }); /** -* @name Phaser.Physics.Arcade.Body#screenY -* @property {number} screenY - The y position of the physics body translated to screen space. +* @name Phaser.Physics.Arcade.Body#y +* @property {number} y */ -Object.defineProperty(Phaser.Physics.Arcade.Body.prototype, "screenY", { +Object.defineProperty(Phaser.Physics.Arcade.Body.prototype, "y", { /** - * The y position of the physics body translated to screen space. - * @method screenY + * @method y * @return {number} */ get: function () { - return (this.sprite.worldTransform[5] - (this.sprite.anchor.y * this.height)) + this.offset.y; + + if (this.type === Phaser.Physics.Arcade.CIRCLE) + { + return this.shape.pos.y; + } + else + { + return this.polygon.pos.y; + } + + }, + + /** + * @method y + * @param {number} value + */ + set: function (value) { + + if (this.type === Phaser.Physics.Arcade.CIRCLE) + { + this.shape.pos.y = value; + } + else + { + this.polygon.pos.y = value; + } + } }); diff --git a/src/utils/Debug.js b/src/utils/Debug.js index 52cad04d..f5549acc 100644 --- a/src/utils/Debug.js +++ b/src/utils/Debug.js @@ -900,6 +900,65 @@ Phaser.Utils.Debug.prototype = { }, + /** + * @method Phaser.Utils.Debug#renderPhysicsBody + * @param {array} body + * @param {string} [color='rgb(255,255,255)'] - The color the polygon is stroked in. + */ + renderPhysicsBody: function (body, color, context) { + + if (this.context === null && context === null) + { + return; + } + + color = color || 'rgb(255,255,255)'; + + var x = body.x; + var y = body.y; + + if (body.type === Phaser.Physics.Arcade.CIRCLE) + { + this.start(0, 0, color); + this.context.beginPath(); + this.context.strokeStyle = color; + this.context.arc(x, y, body.shape.r, 0, Math.PI * 2, false); + this.context.stroke(); + this.context.closePath(); + this.stop(); + } + else + { + var points = body.polygon.points; + + this.start(0, 0, color); + + this.context.beginPath(); + this.context.moveTo(x + points[0].x, y + points[0].y); + + for (var i = 1; i < points.length; i++) + { + this.context.lineTo(x + points[i].x, y + points[i].y); + } + + this.context.closePath(); + this.context.strokeStyle = color; + this.context.stroke(); + + this.context.fillStyle = 'rgb(255,0,0)'; + this.context.fillRect(x + points[0].x - 2, y + points[0].y - 2, 5, 5); + + for (var i = 1; i < points.length; i++) + { + this.context.fillRect(x + points[i].x - 2, y + points[i].y - 2, 5, 5); + } + + this.stop(); + } + + }, + + /** * * @method Phaser.Utils.Debug#renderPolygon