mirror of
https://github.com/photonstorm/phaser
synced 2025-02-16 22:18:29 +00:00
World.separate has been optimized to cut down on the number of calls to intersect
from 3 calls per Game Object collision check, to 2. So if you were colliding 50 sprites it will reduce the call count from 150 to 100 per frame. It also reduces the calls made to seperateX
and seperateY
by the same factor.
Two immovable bodies would never set their overlap data, even if an overlap only check was being made. As this is useful data to have this has been changed. Two immovable bodies will still never separate from each other, but they _will_ have their `overlapX` and `overlapY` properties calculated now.
This commit is contained in:
parent
50e126f59e
commit
cc5361dd6d
3 changed files with 204 additions and 223 deletions
|
@ -333,11 +333,13 @@ You can read all about the philosophy behind Lazer [here](http://phaser.io/news/
|
|||
|
||||
### New Arcade Physics Features
|
||||
|
||||
* Body has two new properties: `left` and `top`. These are the same as `Body.x` and `Body.y` but allow you to pass the Body to geometry level functions such as Circle.contains.
|
||||
* Body.setCircle allows you to define a Body as using a circle to collide with instead of a rectangle. You can set the radius of the collision circle and an offset.
|
||||
* Body.render now renders both circle and rectangle body shapes to the Debug canvas.
|
||||
* World.intersects has been updated to support both circle and rectangle body shapes, and supports quick-paths for circle vs. circle and rect vs. rect checks.
|
||||
* World.circleBodyIntersects is a new method that checks for intersection between a Body that has been defined as a circle, and a normal rectangle based Body. This is used internally by World.intersects, but exposed for direct calls as well.
|
||||
* Body has two new properties: `left` and `top`. These are the same as `Body.x` and `Body.y` but allow you to pass the Body to geometry level functions such as Circle.contains.
|
||||
* World.separate has been optimized to cut down on the number of calls to `intersect` from 3 calls per Game Object collision check, to 2. So if you were colliding 50 sprites it will reduce the call count from 150 to 100 per frame. It also reduces the calls made to `seperateX` and `seperateY` by the same factor.
|
||||
* Two immovable bodies would never set their overlap data, even if an overlap only check was being made. As this is useful data to have this has been changed. Two immovable bodies will still never separate from each other, but they _will_ have their `overlapX` and `overlapY` properties calculated now.
|
||||
|
||||
|
||||
### Updates
|
||||
|
|
|
@ -1000,6 +1000,9 @@ Phaser.Physics.Arcade.Body.render = function (context, body, color, filled) {
|
|||
context.stroke();
|
||||
}
|
||||
|
||||
context.strokeStyle = '#ffff00';
|
||||
context.strokeRect(body.position.x - body.game.camera.x, body.position.y - body.game.camera.y, body.width, body.height);
|
||||
|
||||
context.restore();
|
||||
}
|
||||
else
|
||||
|
|
|
@ -947,29 +947,32 @@ Phaser.Physics.Arcade.prototype = {
|
|||
return false;
|
||||
}
|
||||
|
||||
var resultX = false;
|
||||
var resultY = false;
|
||||
|
||||
// Do we separate on x or y first?
|
||||
|
||||
var result = false;
|
||||
|
||||
// If we weren't having to carry around so much legacy baggage with us, we could do this properly. But alas ...
|
||||
if (this.forceX || Math.abs(this.gravity.y + body1.gravity.y) < Math.abs(this.gravity.x + body1.gravity.x))
|
||||
{
|
||||
result = (this.separateX(body1, body2, overlapOnly) || this.separateY(body1, body2, overlapOnly));
|
||||
resultX = this.separateX(body1, body2, overlapOnly);
|
||||
|
||||
// Are they still intersecting? Let's do the other axis then
|
||||
if (this.intersects(body1, body2))
|
||||
{
|
||||
resultY = this.separateY(body1, body2, overlapOnly);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = (this.separateY(body1, body2, overlapOnly) || this.separateX(body1, body2, overlapOnly));
|
||||
resultY = this.separateY(body1, body2, overlapOnly);
|
||||
|
||||
// Are they still intersecting? Let's do the other axis then
|
||||
if (this.intersects(body1, body2))
|
||||
{
|
||||
resultX = this.separateX(body1, body2, overlapOnly);
|
||||
}
|
||||
}
|
||||
|
||||
if (overlapOnly)
|
||||
{
|
||||
// We already know they intersect from the check above, but by this point we know they've now had their overlapX/Y values populated
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return result;
|
||||
}
|
||||
return (resultX || resultY);
|
||||
|
||||
},
|
||||
|
||||
|
@ -1057,127 +1060,114 @@ Phaser.Physics.Arcade.prototype = {
|
|||
*
|
||||
* @private
|
||||
* @method Phaser.Physics.Arcade#separateX
|
||||
* @param {Phaser.Physics.Arcade.Body} body1 - The Body object to separate.
|
||||
* @param {Phaser.Physics.Arcade.Body} body2 - The Body object to separate.
|
||||
* @param {Phaser.Physics.Arcade.Body} body1 - The first Body to separate.
|
||||
* @param {Phaser.Physics.Arcade.Body} body2 - The second Body to separate.
|
||||
* @param {boolean} overlapOnly - If true the bodies will only have their overlap data set, no separation or exchange of velocity will take place.
|
||||
* @return {boolean} Returns true if the bodies were separated, otherwise false.
|
||||
* @return {boolean} Returns true if the bodies were separated or overlap, otherwise false.
|
||||
*/
|
||||
separateX: function (body1, body2, overlapOnly) {
|
||||
|
||||
// Can't separate two immovable bodies
|
||||
if (body1.immovable && body2.immovable)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var overlap = 0;
|
||||
var maxOverlap = body1.deltaAbsX() + body2.deltaAbsX() + this.OVERLAP_BIAS;
|
||||
|
||||
// Check if the hulls actually overlap
|
||||
if (this.intersects(body1, body2))
|
||||
if (body1.deltaX() === 0 && body2.deltaX() === 0)
|
||||
{
|
||||
var maxOverlap = body1.deltaAbsX() + body2.deltaAbsX() + this.OVERLAP_BIAS;
|
||||
// They overlap but neither of them are moving
|
||||
body1.embedded = true;
|
||||
body2.embedded = true;
|
||||
}
|
||||
else if (body1.deltaX() > body2.deltaX())
|
||||
{
|
||||
// Body1 is moving right and / or Body2 is moving left
|
||||
overlap = body1.right - body2.x;
|
||||
|
||||
if (body1.deltaX() === 0 && body2.deltaX() === 0)
|
||||
if ((overlap > maxOverlap) || body1.checkCollision.right === false || body2.checkCollision.left === false)
|
||||
{
|
||||
// They overlap but neither of them are moving
|
||||
body1.embedded = true;
|
||||
body2.embedded = true;
|
||||
overlap = 0;
|
||||
}
|
||||
else if (body1.deltaX() > body2.deltaX())
|
||||
else
|
||||
{
|
||||
// Body1 is moving right and/or Body2 is moving left
|
||||
overlap = body1.right - body2.x;
|
||||
|
||||
if ((overlap > maxOverlap) || body1.checkCollision.right === false || body2.checkCollision.left === false)
|
||||
{
|
||||
overlap = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
body1.touching.none = false;
|
||||
body1.touching.right = true;
|
||||
body2.touching.none = false;
|
||||
body2.touching.left = true;
|
||||
}
|
||||
body1.touching.none = false;
|
||||
body1.touching.right = true;
|
||||
body2.touching.none = false;
|
||||
body2.touching.left = true;
|
||||
}
|
||||
else if (body1.deltaX() < body2.deltaX())
|
||||
{
|
||||
// Body1 is moving left and/or Body2 is moving right
|
||||
overlap = body1.x - body2.width - body2.x;
|
||||
}
|
||||
else if (body1.deltaX() < body2.deltaX())
|
||||
{
|
||||
// Body1 is moving left and/or Body2 is moving right
|
||||
overlap = body1.x - body2.width - body2.x;
|
||||
|
||||
if ((-overlap > maxOverlap) || body1.checkCollision.left === false || body2.checkCollision.right === false)
|
||||
{
|
||||
overlap = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
body1.touching.none = false;
|
||||
body1.touching.left = true;
|
||||
body2.touching.none = false;
|
||||
body2.touching.right = true;
|
||||
}
|
||||
if ((-overlap > maxOverlap) || body1.checkCollision.left === false || body2.checkCollision.right === false)
|
||||
{
|
||||
overlap = 0;
|
||||
}
|
||||
|
||||
// Resets the overlapX to zero if there is no overlap, or to the actual pixel value if there is
|
||||
body1.overlapX = overlap;
|
||||
body2.overlapX = overlap;
|
||||
|
||||
// Then adjust their positions and velocities accordingly (if there was any overlap)
|
||||
if (overlap !== 0)
|
||||
else
|
||||
{
|
||||
if (overlapOnly || body1.customSeparateX || body2.customSeparateX)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var v1 = body1.velocity.x;
|
||||
var v2 = body2.velocity.x;
|
||||
|
||||
if (!body1.immovable && !body2.immovable)
|
||||
{
|
||||
overlap *= 0.5;
|
||||
|
||||
body1.x = body1.x - overlap;
|
||||
body2.x += overlap;
|
||||
|
||||
var nv1 = Math.sqrt((v2 * v2 * body2.mass) / body1.mass) * ((v2 > 0) ? 1 : -1);
|
||||
var nv2 = Math.sqrt((v1 * v1 * body1.mass) / body2.mass) * ((v1 > 0) ? 1 : -1);
|
||||
var avg = (nv1 + nv2) * 0.5;
|
||||
|
||||
nv1 -= avg;
|
||||
nv2 -= avg;
|
||||
|
||||
body1.velocity.x = avg + nv1 * body1.bounce.x;
|
||||
body2.velocity.x = avg + nv2 * body2.bounce.x;
|
||||
}
|
||||
else if (!body1.immovable)
|
||||
{
|
||||
body1.x = body1.x - overlap;
|
||||
body1.velocity.x = v2 - v1 * body1.bounce.x;
|
||||
|
||||
// This is special case code that handles things like vertically moving platforms you can ride
|
||||
if (body2.moves)
|
||||
{
|
||||
body1.y += (body2.y - body2.prev.y) * body2.friction.y;
|
||||
}
|
||||
}
|
||||
else if (!body2.immovable)
|
||||
{
|
||||
body2.x += overlap;
|
||||
body2.velocity.x = v1 - v2 * body2.bounce.x;
|
||||
|
||||
// This is special case code that handles things like vertically moving platforms you can ride
|
||||
if (body1.moves)
|
||||
{
|
||||
body2.y += (body1.y - body1.prev.y) * body1.friction.y;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
body1.touching.none = false;
|
||||
body1.touching.left = true;
|
||||
body2.touching.none = false;
|
||||
body2.touching.right = true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
// Resets the overlapX to zero if there is no overlap, or to the actual pixel value if there is
|
||||
body1.overlapX = overlap;
|
||||
body2.overlapX = overlap;
|
||||
|
||||
// Can't separate two immovable bodies, or a body with its own custom separation logic
|
||||
if (overlapOnly || overlap === 0 || (body1.immovable && body2.immovable) || body1.customSeparateX || body2.customSeparateX)
|
||||
{
|
||||
// return true if there was some overlap, otherwise false
|
||||
return (overlap !== 0);
|
||||
}
|
||||
|
||||
// Adjust their positions and velocities accordingly (if there was any overlap)
|
||||
var v1 = body1.velocity.x;
|
||||
var v2 = body2.velocity.x;
|
||||
|
||||
if (!body1.immovable && !body2.immovable)
|
||||
{
|
||||
overlap *= 0.5;
|
||||
|
||||
body1.x = body1.x - overlap;
|
||||
body2.x += overlap;
|
||||
|
||||
var nv1 = Math.sqrt((v2 * v2 * body2.mass) / body1.mass) * ((v2 > 0) ? 1 : -1);
|
||||
var nv2 = Math.sqrt((v1 * v1 * body1.mass) / body2.mass) * ((v1 > 0) ? 1 : -1);
|
||||
var avg = (nv1 + nv2) * 0.5;
|
||||
|
||||
nv1 -= avg;
|
||||
nv2 -= avg;
|
||||
|
||||
body1.velocity.x = avg + nv1 * body1.bounce.x;
|
||||
body2.velocity.x = avg + nv2 * body2.bounce.x;
|
||||
}
|
||||
else if (!body1.immovable)
|
||||
{
|
||||
body1.x = body1.x - overlap;
|
||||
body1.velocity.x = v2 - v1 * body1.bounce.x;
|
||||
|
||||
// This is special case code that handles things like vertically moving platforms you can ride
|
||||
if (body2.moves)
|
||||
{
|
||||
body1.y += (body2.y - body2.prev.y) * body2.friction.y;
|
||||
}
|
||||
}
|
||||
else if (!body2.immovable)
|
||||
{
|
||||
body2.x += overlap;
|
||||
body2.velocity.x = v1 - v2 * body2.bounce.x;
|
||||
|
||||
// This is special case code that handles things like vertically moving platforms you can ride
|
||||
if (body1.moves)
|
||||
{
|
||||
body2.y += (body1.y - body1.prev.y) * body1.friction.y;
|
||||
}
|
||||
}
|
||||
|
||||
// If we got this far then there WAS overlap, and separation is complete, so return true
|
||||
return true;
|
||||
|
||||
},
|
||||
|
||||
|
@ -1186,128 +1176,114 @@ Phaser.Physics.Arcade.prototype = {
|
|||
*
|
||||
* @private
|
||||
* @method Phaser.Physics.Arcade#separateY
|
||||
* @param {Phaser.Physics.Arcade.Body} body1 - The Body object to separate.
|
||||
* @param {Phaser.Physics.Arcade.Body} body2 - The Body object to separate.
|
||||
* @param {Phaser.Physics.Arcade.Body} body1 - The first Body to separate.
|
||||
* @param {Phaser.Physics.Arcade.Body} body2 - The second Body to separate.
|
||||
* @param {boolean} overlapOnly - If true the bodies will only have their overlap data set, no separation or exchange of velocity will take place.
|
||||
* @return {boolean} Returns true if the bodies were separated, otherwise false.
|
||||
* @return {boolean} Returns true if the bodies were separated or overlap, otherwise false.
|
||||
*/
|
||||
separateY: function (body1, body2, overlapOnly) {
|
||||
|
||||
// Can't separate two immovable or non-existing bodies
|
||||
if (body1.immovable && body2.immovable)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var overlap = 0;
|
||||
var maxOverlap = body1.deltaAbsY() + body2.deltaAbsY() + this.OVERLAP_BIAS;
|
||||
|
||||
// Check if the hulls actually overlap
|
||||
if (this.intersects(body1, body2))
|
||||
if (body1.deltaY() === 0 && body2.deltaY() === 0)
|
||||
{
|
||||
var maxOverlap = body1.deltaAbsY() + body2.deltaAbsY() + this.OVERLAP_BIAS;
|
||||
// They overlap but neither of them are moving
|
||||
body1.embedded = true;
|
||||
body2.embedded = true;
|
||||
}
|
||||
else if (body1.deltaY() > body2.deltaY())
|
||||
{
|
||||
// Body1 is moving down and/or Body2 is moving up
|
||||
overlap = body1.bottom - body2.y;
|
||||
|
||||
if (body1.deltaY() === 0 && body2.deltaY() === 0)
|
||||
if ((overlap > maxOverlap) || body1.checkCollision.down === false || body2.checkCollision.up === false)
|
||||
{
|
||||
// They overlap but neither of them are moving
|
||||
body1.embedded = true;
|
||||
body2.embedded = true;
|
||||
overlap = 0;
|
||||
}
|
||||
else if (body1.deltaY() > body2.deltaY())
|
||||
else
|
||||
{
|
||||
// Body1 is moving down and/or Body2 is moving up
|
||||
overlap = body1.bottom - body2.y;
|
||||
|
||||
if ((overlap > maxOverlap) || body1.checkCollision.down === false || body2.checkCollision.up === false)
|
||||
{
|
||||
overlap = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
body1.touching.none = false;
|
||||
body1.touching.down = true;
|
||||
body2.touching.none = false;
|
||||
body2.touching.up = true;
|
||||
}
|
||||
body1.touching.none = false;
|
||||
body1.touching.down = true;
|
||||
body2.touching.none = false;
|
||||
body2.touching.up = true;
|
||||
}
|
||||
else if (body1.deltaY() < body2.deltaY())
|
||||
}
|
||||
else if (body1.deltaY() < body2.deltaY())
|
||||
{
|
||||
// Body1 is moving up and/or Body2 is moving down
|
||||
overlap = body1.y - body2.bottom;
|
||||
|
||||
if ((-overlap > maxOverlap) || body1.checkCollision.up === false || body2.checkCollision.down === false)
|
||||
{
|
||||
// Body1 is moving up and/or Body2 is moving down
|
||||
overlap = body1.y - body2.bottom;
|
||||
|
||||
if ((-overlap > maxOverlap) || body1.checkCollision.up === false || body2.checkCollision.down === false)
|
||||
{
|
||||
overlap = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
body1.touching.none = false;
|
||||
body1.touching.up = true;
|
||||
body2.touching.none = false;
|
||||
body2.touching.down = true;
|
||||
}
|
||||
overlap = 0;
|
||||
}
|
||||
|
||||
// Resets the overlapY to zero if there is no overlap, or to the actual pixel value if there is
|
||||
body1.overlapY = overlap;
|
||||
body2.overlapY = overlap;
|
||||
|
||||
// Then adjust their positions and velocities accordingly (if there was any overlap)
|
||||
if (overlap !== 0)
|
||||
else
|
||||
{
|
||||
if (overlapOnly || body1.customSeparateY || body2.customSeparateY)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var v1 = body1.velocity.y;
|
||||
var v2 = body2.velocity.y;
|
||||
|
||||
if (!body1.immovable && !body2.immovable)
|
||||
{
|
||||
overlap *= 0.5;
|
||||
|
||||
body1.y = body1.y - overlap;
|
||||
body2.y += overlap;
|
||||
|
||||
var nv1 = Math.sqrt((v2 * v2 * body2.mass) / body1.mass) * ((v2 > 0) ? 1 : -1);
|
||||
var nv2 = Math.sqrt((v1 * v1 * body1.mass) / body2.mass) * ((v1 > 0) ? 1 : -1);
|
||||
var avg = (nv1 + nv2) * 0.5;
|
||||
|
||||
nv1 -= avg;
|
||||
nv2 -= avg;
|
||||
|
||||
body1.velocity.y = avg + nv1 * body1.bounce.y;
|
||||
body2.velocity.y = avg + nv2 * body2.bounce.y;
|
||||
}
|
||||
else if (!body1.immovable)
|
||||
{
|
||||
body1.y = body1.y - overlap;
|
||||
body1.velocity.y = v2 - v1 * body1.bounce.y;
|
||||
|
||||
// This is special case code that handles things like horizontal moving platforms you can ride
|
||||
if (body2.moves)
|
||||
{
|
||||
body1.x += (body2.x - body2.prev.x) * body2.friction.x;
|
||||
}
|
||||
}
|
||||
else if (!body2.immovable)
|
||||
{
|
||||
body2.y += overlap;
|
||||
body2.velocity.y = v1 - v2 * body2.bounce.y;
|
||||
|
||||
// This is special case code that handles things like horizontal moving platforms you can ride
|
||||
if (body1.moves)
|
||||
{
|
||||
body2.x += (body1.x - body1.prev.x) * body1.friction.x;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
body1.touching.none = false;
|
||||
body1.touching.up = true;
|
||||
body2.touching.none = false;
|
||||
body2.touching.down = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
// Resets the overlapY to zero if there is no overlap, or to the actual pixel value if there is
|
||||
body1.overlapY = overlap;
|
||||
body2.overlapY = overlap;
|
||||
|
||||
// Can't separate two immovable bodies, or a body with its own custom separation logic
|
||||
if (overlapOnly || overlap === 0 || (body1.immovable && body2.immovable) || body1.customSeparateY || body2.customSeparateY)
|
||||
{
|
||||
// return true if there was some overlap, otherwise false
|
||||
return (overlap !== 0);
|
||||
}
|
||||
|
||||
// Adjust their positions and velocities accordingly (if there was any overlap)
|
||||
var v1 = body1.velocity.y;
|
||||
var v2 = body2.velocity.y;
|
||||
|
||||
if (!body1.immovable && !body2.immovable)
|
||||
{
|
||||
overlap *= 0.5;
|
||||
|
||||
body1.y = body1.y - overlap;
|
||||
body2.y += overlap;
|
||||
|
||||
var nv1 = Math.sqrt((v2 * v2 * body2.mass) / body1.mass) * ((v2 > 0) ? 1 : -1);
|
||||
var nv2 = Math.sqrt((v1 * v1 * body1.mass) / body2.mass) * ((v1 > 0) ? 1 : -1);
|
||||
var avg = (nv1 + nv2) * 0.5;
|
||||
|
||||
nv1 -= avg;
|
||||
nv2 -= avg;
|
||||
|
||||
body1.velocity.y = avg + nv1 * body1.bounce.y;
|
||||
body2.velocity.y = avg + nv2 * body2.bounce.y;
|
||||
}
|
||||
else if (!body1.immovable)
|
||||
{
|
||||
body1.y = body1.y - overlap;
|
||||
body1.velocity.y = v2 - v1 * body1.bounce.y;
|
||||
|
||||
// This is special case code that handles things like horizontal moving platforms you can ride
|
||||
if (body2.moves)
|
||||
{
|
||||
body1.x += (body2.x - body2.prev.x) * body2.friction.x;
|
||||
}
|
||||
}
|
||||
else if (!body2.immovable)
|
||||
{
|
||||
body2.y += overlap;
|
||||
body2.velocity.y = v1 - v2 * body2.bounce.y;
|
||||
|
||||
// This is special case code that handles things like horizontal moving platforms you can ride
|
||||
if (body1.moves)
|
||||
{
|
||||
body2.x += (body1.x - body1.prev.x) * body1.friction.x;
|
||||
}
|
||||
}
|
||||
|
||||
// If we got this far then there WAS overlap, and separation is complete, so return true
|
||||
return true;
|
||||
|
||||
},
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue