Finally getting there! Body collision almost as good as it can be (without a full-on physics system). Just a few last tweaks to do.

This commit is contained in:
photonstorm
2014-01-21 16:12:50 +00:00
parent c9d07c7346
commit 15a002e720
11 changed files with 779 additions and 684 deletions
+60 -9
View File
@@ -14,6 +14,7 @@ function preload() {
var sprite;
var sprite2;
var sprite3;
var group;
var bmd;
@@ -30,24 +31,60 @@ function create() {
}
function test4() {
game.physics.gravity.y = 50;
sprite = game.add.sprite(300, 0, 'gameboy', 0);
sprite.name = 'red';
sprite.body.collideWorldBounds = true;
sprite.body.bounce.setTo(0.9, 0.9);
sprite2 = game.add.sprite(310, 500, 'gameboy', 2);
sprite2.name = 'green';
sprite2.body.collideWorldBounds = true;
// sprite2.body.bounce.setTo(0.9, 0.9);
game.input.onDown.add(launch4, this);
}
function launch4() {
sprite.body.velocity.y = 200;
}
function test3() {
// game.physics.gravity.y = 100;
game.physics.gravity.y = 50;
// group = game.add.group();
sprite = game.add.sprite(500, 400, 'gameboy', 0);
sprite.name = 'red';
sprite.body.collideWorldBounds = true;
sprite.body.bounce.setTo(0.5, 0.5);
sprite.body.bounce.setTo(0.9, 0.9);
sprite2 = game.add.sprite(0, 400, 'gameboy', 2);
sprite2 = game.add.sprite(100, 400, 'gameboy', 2);
sprite2.name = 'green';
sprite2.body.collideWorldBounds = true;
sprite2.body.bounce.setTo(0.9, 0.9);
// sprite2.body.immovable = true;
// sprite2.body.bounce.setTo(0.5, 0.5);
sprite3 = game.add.sprite(700, 400, 'gameboy', 3);
sprite3.name = 'yellow';
sprite3.body.collideWorldBounds = true;
sprite3.body.bounce.setTo(0.5, 0.5);
sprite.body.velocity.x = -300;
// sprite.body.velocity.x = -300;
// sprite.body.velocity.y = -200;
// group.add(sprite);
// group.add(sprite2);
// group.add(sprite3);
game.input.onDown.add(launch3, this);
@@ -55,7 +92,8 @@ function test3() {
function launch3() {
sprite.body.velocity.x *= 10;
sprite.body.velocity.x = -200;
sprite.body.velocity.y = -200;
}
@@ -116,11 +154,18 @@ function launch1() {
function update() {
// game.physics.collide(sprite, sprite2);
// game.physics.collide(sprite2, sprite3);
game.physics.collideArray(sprite, [sprite2, sprite3]);
// game.physics.collide(group, group);
if (sprite3)
{
game.physics.collideArray(sprite, [sprite2, sprite3]);
game.physics.collide(sprite2, sprite3);
}
else
{
game.physics.collide(sprite, sprite2);
}
// sprite.rotation = sprite.body.angle;
if (sprite)
{
@@ -134,6 +179,12 @@ function update() {
bmd.fillRect(sprite2.body.center.x, sprite2.body.center.y, 2, 2);
}
if (sprite3)
{
bmd.fillStyle('#0000ff');
bmd.fillRect(sprite3.body.center.x, sprite3.body.center.y, 2, 2);
}
}
function render() {
+43 -3
View File
@@ -95,6 +95,20 @@
return this;
};
// Rotate this vector (counter-clockwise) by the specified angle (in radians) which has already been calculated into sin and cos.
/**
* @param {number} sin - The Math.sin(angle)
* @param {number} cos - The Math.cos(angle)
* @return {Vector} This for chaining.
*/
Vector.prototype['rotatePrecalc'] = Vector.prototype.rotatePrecalc = function (sin, cos) {
var x = this['x'];
var y = this['y'];
this['x'] = x * cos - y * sin;
this['y'] = x * sin + y * cos;
return this;
};
// Reverse this vector.
/**
* @return {Vector} This for chaining.
@@ -318,10 +332,36 @@
var edges = this['edges'];
var normals = this['normals'];
var len = points.length;
// Calc it just the once, rather than 4 times per array element
var cos = Math.cos(angle);
var sin = Math.sin(angle);
for (i = 0; i < len; i++) {
points[i].rotate(angle);
edges[i].rotate(angle);
normals[i].rotate(angle);
points[i].rotatePrecalc(sin, cos);
edges[i].rotatePrecalc(sin, cos);
normals[i].rotatePrecalc(sin, cos);
}
return this;
};
// Rotates this polygon counter-clockwise around the origin of *its local coordinate system* (i.e. `pos`).
//
// Note: You do **not** need to call `recalc` after rotation.
/**
* @param {number} angle The angle to rotate (in radians)
* @return {Polygon} This for chaining.
*/
Polygon.prototype['scale'] = Polygon.prototype.scale = function(x, y) {
var i;
var points = this['points'];
var edges = this['edges'];
var normals = this['normals'];
var len = points.length;
for (i = 0; i < len; i++) {
points[i].scale(x,y);
edges[i].scale(x,y);
normals[i].scale(x,y);
}
return this;
};
+38
View File
@@ -0,0 +1,38 @@
var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { preload: preload, create: create, render: render });
function preload() {
// game.load.image('atari1', 'assets/sprites/atari130xe.png');
// game.load.image('atari2', 'assets/sprites/atari800xl.png');
// game.load.image('atari4', 'assets/sprites/atari800.png');
// game.load.image('sonic', 'assets/sprites/sonic_havok_sanity.png');
// game.load.image('duck', 'assets/sprites/darkwing_crazy.png');
// game.load.image('firstaid', 'assets/sprites/firstaid.png');
// game.load.image('diamond', 'assets/sprites/diamond.png');
game.load.image('mushroom', 'assets/sprites/mushroom2.png');
}
var group;
var sprite;
function create() {
var images = game.cache.getImageKeys();
group = game.add.group();
// for (var i = 0; i < 20; i++)
// {
sprite = group.create(200, game.world.randomY, game.rnd.pick(images));
// }
group.x = 200;
}
function render() {
game.debug.renderText('sx: ' + sprite.x + ' wx: ' + sprite.world.x, 32, 32);
}
-1
View File
@@ -85,7 +85,6 @@
$f = $_GET['f'];
?>
<script src="wip/<?php echo $f?>" type="text/javascript"></script>
<script src="wip/SAT.js" type="text/javascript"></script>
<?php
}
?>
+17 -4
View File
@@ -5,9 +5,11 @@ function preload() {
game.load.image('arrow', 'assets/sprites/asteroids_ship.png');
game.load.image('ball', 'assets/sprites/shinyball.png');
game.load.spritesheet('gameboy', 'assets/sprites/gameboy_seize_color_40x60.png', 40, 60);
}
var gameboy;
var sprites;
var bmd;
@@ -24,23 +26,34 @@ function create() {
sprites = game.add.group();
for (var i = 0; i < 50; i++)
for (var i = 0; i < 100; i++)
{
var s = sprites.create(game.rnd.integerInRange(100, 700), game.rnd.integerInRange(32, 200), 'ball');
s.body.velocity.x = game.rnd.integerInRange(-400, 400);
s.body.velocity.y = game.rnd.integerInRange(-200, 200);
s.name = 'ball' + i;
}
sprites.setAll('body.collideWorldBounds', true);
sprites.setAll('body.bounce.x', 0.8);
sprites.setAll('body.bounce.y', 0.8);
sprites.setAll('body.bounce.x', 0.9);
sprites.setAll('body.bounce.y', 0.9);
sprites.setAll('body.minBounceVelocity', 0.8);
console.log(sprites._container.children);
gameboy = game.add.sprite(300, 50, 'gameboy', 0);
gameboy.name = 'gameboy';
gameboy.body.collideWorldBounds = true;
gameboy.body.bounce.setTo(0.9, 0.9);
gameboy.body.velocity.x = game.rnd.integerInRange(-400, 400);
gameboy.body.velocity.y = game.rnd.integerInRange(-200, 200);
}
function update() {
// game.physics.collide(sprites, sprites);
// game.physics.collide(gameboy, sprites);
game.physics.collide(sprites);
// sprite.rotation = sprite.body.angle;
+62 -15
View File
@@ -21,8 +21,7 @@ var r;
function create() {
// game.stage.backgroundColor = '#124184';
game.stage.backgroundColor = '#000';
game.stage.backgroundColor = '#124184';
test1();
@@ -38,9 +37,21 @@ function create() {
function test1() {
sprite = game.add.sprite(500, 400, 'gameboy', 0);
// sprite = game.add.sprite(0, 0, 'gameboy', 0);
sprite.name = 'red';
// sprite.pivot.x = 20;
// sprite.pivot.y = 30;
// sprite.anchor.setTo(0.5, 0.5);
// sprite.body.polygon.translate(20, 20);
// sprite.body.polygon.rotate(game.math.degToRad(45));
// sprite.angle = 45;
// sprite.scale.setTo(2, 2);
// sprite.body.polygon.scale(2, 2);
sprite.body.bounce.x = 0.8;
// sprite.body = null;
sprite2 = game.add.sprite(0, 400, 'gameboy', 2);
sprite2.name = 'green';
@@ -50,13 +61,13 @@ function test1() {
sprite3.name = 'yellow';
// sprite3.body = null;
b1 = new SAT.Box(new SAT.Vector(sprite.x, sprite.y), sprite.width, sprite.height);
b2 = new SAT.Box(new SAT.Vector(sprite2.x, sprite2.y), sprite2.width, sprite2.height);
b3 = new SAT.Box(new SAT.Vector(sprite3.x, sprite3.y), sprite3.width, sprite3.height);
// b1 = new SAT.Box(new SAT.Vector(sprite.x, sprite.y), sprite.width, sprite.height);
// b2 = new SAT.Box(new SAT.Vector(sprite2.x, sprite2.y), sprite2.width, sprite2.height);
// b3 = new SAT.Box(new SAT.Vector(sprite3.x, sprite3.y), sprite3.width, sprite3.height);
r = new SAT.Response();
// r = new SAT.Response();
console.log(b2);
// console.log(b2);
game.input.onDown.add(launch1, this);
@@ -64,9 +75,10 @@ function test1() {
function launch1() {
// console.log(b1);
sprite.body.velocity.x = -200;
sprite.body.velocity.x = -100;
// sprite2.body.velocity.x = -225;
}
@@ -74,6 +86,10 @@ function launch1() {
function update() {
// sprite.angle += 0.5;
// sprite.body.polygon.rotate(game.math.degToRad(0.5));
/*
b1.pos.x = sprite.x;
b1.pos.y = sprite.y;
@@ -83,6 +99,8 @@ function update() {
b3.pos.x = sprite3.x;
b3.pos.y = sprite3.y;
r.clear();
if (SAT.testPolygonPolygon(b1.toPolygon(), b2.toPolygon(), r))
{
console.log(r, b1.pos, b2.pos);
@@ -96,36 +114,65 @@ function update() {
console.log('sprite moved to', sprite.x);
// sprite.x = b1.pos.x;
// sprite.y = b1.pos.y;
}
*/
sprite.body.collide(sprite2.body);
bmd.clear();
if (sprite)
{
bmd.fillStyle('rgba(255,0,0,0.8');
bmd.fillRect(b1.pos.x, b1.pos.y, b1.w, b1.h);
renderPolygon(sprite.body.polygon);
// bmd.fillStyle('rgba(255,0,0,0.8');
// bmd.fillRect(sprite.body.polygon.pos.x, sprite.body.polygon.pos.y, sprite.body.shape.w, sprite.body.shape.h);
}
if (sprite2)
{
bmd.fillStyle('rgba(0,255,0,0.8');
bmd.fillRect(b2.pos.x, b2.pos.y, b2.w, b2.h);
renderPolygon(sprite2.body.polygon);
// bmd.fillStyle('rgba(0,255,0,0.8');
// bmd.fillRect(sprite2.body.polygon.pos.x, sprite2.body.polygon.pos.y, sprite2.body.shape.w, sprite2.body.shape.h);
}
if (sprite3)
{
bmd.fillStyle('rgba(0,0,255,0.8');
bmd.fillRect(b3.pos.x, b3.pos.y, b3.w, b3.h);
renderPolygon(sprite3.body.polygon);
// bmd.fillStyle('rgba(0,0,255,0.8');
// bmd.fillRect(sprite3.body.polygon.pos.x, sprite3.body.polygon.pos.y, sprite3.body.shape.w, sprite3.body.shape.h);
}
}
function renderPolygon (polygon, color) {
// console.log(polygon);
// this.start(0, 0, color);
bmd.context.beginPath();
bmd.context.moveTo(polygon.pos.x + polygon.points[0].x, polygon.pos.y + polygon.points[0].y);
for (var i = 1; i < polygon.points.length; i++)
{
bmd.context.lineTo(polygon.pos.x + polygon.points[i].x, polygon.pos.y + polygon.points[i].y);
}
bmd.context.closePath();
bmd.context.strokeStyle = 'rgba(255, 255, 255, 1)';
// bmd.context.strokeStyle = color;
bmd.context.stroke();
}
function render() {
if (sprite)
{
// game.debug.renderBodyInfo(sprite, 16, 24);
game.debug.renderText(sprite.name + ' x: ' + sprite.x, 16, 500);
game.debug.renderText(sprite.name + ' world x: ' + sprite.world.x, 16, 520);
}
if (sprite2)
+1 -1
View File
@@ -340,7 +340,7 @@ Phaser.Math = {
},
/**
* Set an angle within the bounds of -&pi; to&pi;.
* Set an angle within the bounds of -&pi; to &pi;.
* @method Phaser.Math#normalizeAngle
* @param {number} angle
* @param {boolean} radians - True if angle size is expressed in radians.
+42 -327
View File
@@ -386,6 +386,12 @@ Phaser.Physics.Arcade.prototype = {
collideHandler: function (object1, object2, collideCallback, processCallback, callbackContext) {
// Only collide valid objects
if (typeof object2 === 'undefined' && object1.type === Phaser.GROUP)
{
this.collideGroupVsSelf(object1, collideCallback, processCallback, callbackContext, false);
return;
}
if (object1 && object2 && object1.exists && object2.exists)
{
// SPRITES
@@ -510,6 +516,34 @@ Phaser.Physics.Arcade.prototype = {
},
/**
* An internal function. Use Phaser.Physics.Arcade.collide instead.
*
* @method Phaser.Physics.Arcade#collideGroupVsSelf
* @private
*/
collideGroupVsSelf: function (group, collideCallback, processCallback, callbackContext, overlapOnly) {
if (group.length === 0)
{
return;
}
var len = group._container.children.length;
for (var i = 0; i < len; i++)
{
for (var j = i + 1; j <= len; j++)
{
if (group._container.children[i] && group._container.children[j] && group._container.children[i].exists && group._container.children[j].exists)
{
this.collideSpriteVsSprite(group._container.children[i], group._container.children[j], collideCallback, processCallback, callbackContext, overlapOnly);
}
}
}
},
/**
* An internal function. Use Phaser.Physics.Arcade.collide instead.
*
@@ -646,342 +680,23 @@ Phaser.Physics.Arcade.prototype = {
return false;
}
var r = false;
if (body1.deltaX() === 0 && body2.deltaX() === 0)
if (overlapOnly)
{
// They overlap but neither of them are moving
body1.embedded = true;
body2.embedded = true;
}
else if (body1.deltaX() != 0 && body2.deltaX() === 0)
{
r = body1.separate(body2);
}
else if (body2.deltaX() != 0 && body1.deltaX() === 0)
{
r = body2.separate(body1);
return body1.overlap(body2);
}
else
{
// Dual motion thingy
r = body1.separate(body2);
}
return r;
// return body2.separate(body1);
/*
// We got this far, so the bodies overlap and our process was good, which means we can separate ...
this._overlap = 0;
this._maxOverlap = body1.deltaAbsX() + body2.deltaAbsX() + this.OVERLAP_BIAS;
if (body1.deltaX() === 0 && body2.deltaX() === 0)
{
// 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
this._overlap = body1.x + body1.width - body2.x;
if ((this._overlap > this._maxOverlap) || body1.allowCollision.right === false || body2.allowCollision.left === false)
if (body1.overlap(body2))
{
this._overlap = 0;
}
else
{
body1.touching.right = true;
body2.touching.left = true;
}
}
else if (body1.deltaX() < body2.deltaX())
{
// Body1 is moving left and/or Body2 is moving right
this._overlap = body1.x - body2.width - body2.x;
// console.log('-----------------------------------------------------------------------------');
// console.log(body1.sprite.name, 'overlaps', body2.sprite.name, 'x', body1.overlapX, 'y', body1.overlapY);
if ((-this._overlap > this._maxOverlap) || body1.allowCollision.left === false || body2.allowCollision.right === false)
{
this._overlap = 0;
}
else
{
body1.touching.left = true;
body2.touching.right = true;
body1.separate(body2);
return true;
}
}
// Then adjust their positions and velocities accordingly (if there was any overlap)
if (this._overlap !== 0)
{
body1.overlapX = this._overlap;
body2.overlapX = this._overlap;
if (!overlapOnly && !body1.customSeparateX && !body2.customSeparateX)
{
this._velocity1 = body1.velocity.x;
this._velocity2 = body2.velocity.x;
if (!body1.immovable && !body2.immovable)
{
// If either of the bodies are blocked on either side then we don't exchange velocity but treat it like an immovable collision
if (body1.blocked.left || body1.blocked.right)
{
if (body1.blocked.left && body2.deltaX() < 0)
{
body2.x += this._overlap;
body2.velocity.x *= -body2.bounce.x;
}
else if (body1.blocked.right && body2.deltaX() > 0)
{
body2.x -= this._overlap;
body2.velocity.x *= -body2.bounce.x;
}
}
else if (body2.blocked.left || body2.blocked.right)
{
if (body2.blocked.left && body1.deltaX() < 0)
{
body1.x += this._overlap;
body1.velocity.x *= -body1.bounce.x;
}
else if (body2.blocked.right && body1.deltaX() > 0)
{
body1.x -= this._overlap;
body1.velocity.x *= -body1.bounce.x;
}
}
else
{
// Exchange velocities
this._overlap *= 0.5;
body1.overlapX = this._overlap;
body2.overlapX = this._overlap;
this._newVelocity1 = Math.sqrt((this._velocity2 * this._velocity2 * body2.mass) / body1.mass) * ((this._velocity2 > 0) ? 1 : -1);
this._newVelocity2 = Math.sqrt((this._velocity1 * this._velocity1 * body1.mass) / body2.mass) * ((this._velocity1 > 0) ? 1 : -1);
this._average = (this._newVelocity1 + this._newVelocity2) * 0.5;
this._newVelocity1 -= this._average;
this._newVelocity2 -= this._average;
if (body1.deltaX() < 0)
{
body1.x += this._overlap;
}
else
{
body1.x -= this._overlap;
}
if (body2.deltaX() < 0)
{
body2.x += this._overlap;
}
else
{
body2.x -= this._overlap;
}
body1.velocity.x = this._average + this._newVelocity1 * body1.bounce.x;
body2.velocity.x = this._average + this._newVelocity2 * body2.bounce.x;
}
}
else if (!body1.immovable)
{
if (body1.deltaX() < 0)
{
body1.x += this._overlap;
}
else
{
body1.x -= this._overlap;
}
body1.velocity.x = this._velocity2 - this._velocity1 * body1.bounce.x;
}
else if (!body2.immovable)
{
if (body2.deltaX() < 0)
{
body2.x += this._overlap;
}
else
{
body2.x -= this._overlap;
}
body2.velocity.x = this._velocity1 - this._velocity2 * body2.bounce.x;
}
}
}
// Now for the vertical
this._overlap = 0;
this._maxOverlap = body1.deltaAbsY() + body2.deltaAbsY() + this.OVERLAP_BIAS;
if (body1.deltaY() === 0 && body2.deltaY() === 0)
{
// 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
this._overlap = body1.y + body1.height - body2.y;
if ((this._overlap > this._maxOverlap) || body1.allowCollision.down === false || body2.allowCollision.up === false)
{
this._overlap = 0;
}
else
{
body1.touching.down = true;
body2.touching.up = true;
}
}
else if (body1.deltaY() < body2.deltaY())
{
// Body1 is moving up and/or Body2 is moving down
this._overlap = body1.y - body2.height - body2.y;
if ((-this._overlap > this._maxOverlap) || body1.allowCollision.up === false || body2.allowCollision.down === false)
{
this._overlap = 0;
}
else
{
body1.touching.up = true;
body2.touching.down = true;
}
}
// Then adjust their positions and velocities accordingly (if there was any overlap)
if (this._overlap !== 0)
{
body1.overlapY = this._overlap;
body2.overlapY = this._overlap;
if (!overlapOnly && !body1.customSeparateY && !body2.customSeparateY)
{
this._velocity1 = body1.velocity.y;
this._velocity2 = body2.velocity.y;
if (!body1.immovable && !body2.immovable)
{
// If either of the bodies are blocked on either side then we don't exchange velocity but treat it like an immovable collision
if (body1.blocked.up || body1.blocked.down)
{
if (body1.blocked.up && body2.deltaY() < 0)
{
body2.y += this._overlap;
body2.velocity.y *= -body2.bounce.y;
}
else if (body1.blocked.down && body2.deltaY() > 0)
{
body2.y -= this._overlap;
body2.velocity.y *= -body2.bounce.y;
}
}
else if (body2.blocked.up || body2.blocked.down)
{
if (body2.blocked.up && body1.deltaY() < 0)
{
body1.y += this._overlap;
body1.velocity.y *= -body1.bounce.y;
}
else if (body2.blocked.down && body1.deltaY() > 0)
{
body1.y -= this._overlap;
body1.velocity.y *= -body1.bounce.y;
}
}
else
{
// Exchange velocities
this._overlap *= 0.5;
body1.overlapY = this._overlap;
body2.overlapY = this._overlap;
this._newVelocity1 = Math.sqrt((this._velocity2 * this._velocity2 * body2.mass) / body1.mass) * ((this._velocity2 > 0) ? 1 : -1);
this._newVelocity2 = Math.sqrt((this._velocity1 * this._velocity1 * body1.mass) / body2.mass) * ((this._velocity1 > 0) ? 1 : -1);
this._average = (this._newVelocity1 + this._newVelocity2) * 0.5;
this._newVelocity1 -= this._average;
this._newVelocity2 -= this._average;
if (body1.deltaY() < 0)
{
body1.y += this._overlap;
}
else
{
body1.y -= this._overlap;
}
if (body2.deltaY() < 0)
{
body2.y += this._overlap;
}
else
{
body2.y -= this._overlap;
}
body1.velocity.y = this._average + this._newVelocity1 * body1.bounce.y;
body2.velocity.y = this._average + this._newVelocity2 * body2.bounce.y;
}
}
else if (!body1.immovable)
{
if (body1.deltaY() < 0)
{
body1.y += this._overlap;
}
else
{
body1.y -= this._overlap;
}
body1.velocity.y = this._velocity2 - this._velocity1 * 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.preX;
}
}
else if (!body2.immovable)
{
if (body2.deltaY() < 0)
{
body2.y += this._overlap;
}
else
{
body2.y -= this._overlap;
}
body2.velocity.y = this._velocity1 - this._velocity2 * 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.preX;
}
}
}
}
return true;
*/
return false;
},
+426 -54
View File
@@ -60,16 +60,50 @@ Phaser.Physics.Arcade.Body = function (sprite) {
*/
this.preRotation = sprite.angle;
/**
* @property {number} screenX - The x position of the physics body translated to screen space.
* @readonly
*/
this.screenX = sprite.x;
/**
* @property {number} screenY - The y position of the physics body translated to screen space.
* @readonly
*/
this.screenY = sprite.y;
/**
* @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 {number} height - The calculated height of the physics body.
* @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.
*/
@@ -81,12 +115,12 @@ Phaser.Physics.Arcade.Body = function (sprite) {
this.motionVelocity = new Phaser.Point();
/**
* @property {Phaser.Point} velocity - The velocity in pixels per second sq. of the Body.
* @property {Phaser.Point} velocity - The velocity of the Body.
*/
this.velocity = new Phaser.Point();
/**
* @property {Phaser.Point} acceleration - The velocity in pixels per second sq. of the Body.
* @property {Phaser.Point} acceleration - The acceleration in pixels per second sq. of the Body.
*/
this.acceleration = new Phaser.Point();
@@ -103,12 +137,12 @@ Phaser.Physics.Arcade.Body = function (sprite) {
/**
* @property {number} minBounceVelocity - The minimum bounce velocity (could just be the bounce value?).
*/
// this.minBounceVelocity = 0.5;
this.minBounceVelocity = 0.5;
this._debug = 0;
/**
* @property {Phaser.Point} gravity - The gravity applied to the motion of the Body.
* @property {Phaser.Point} gravity - The gravity applied to the motion of the Body. This works in addition to any gravity set on the world.
*/
this.gravity = new Phaser.Point();
@@ -121,22 +155,22 @@ Phaser.Physics.Arcade.Body = function (sprite) {
* @property {Phaser.Point} minVelocity - When a body rebounds off another the minVelocity is checked, if the new velocity is lower than the minVelocity the body is stopped.
* @default
*/
this.minVelocity = new Phaser.Point(20, 20);
this.minVelocity = new Phaser.Point(10, 10);
/**
* @property {Phaser.Point} maxVelocity - The maximum velocity in pixels per second sq. that the Body can reach.
* @property {Phaser.Point} maxVelocity - The maximum velocity that the Body can reach.
* @default
*/
this.maxVelocity = new Phaser.Point(10000, 10000);
/**
* @property {number} angularVelocity - The angular velocity in pixels per second sq. of the Body.
* @property {number} angularVelocity - The angular velocity of the Body.
* @default
*/
this.angularVelocity = 0;
/**
* @property {number} angularAcceleration - The angular acceleration in pixels per second sq. of the Body.
* @property {number} angularAcceleration - The angular acceleration of the Body.
* @default
*/
this.angularAcceleration = 0;
@@ -148,7 +182,7 @@ Phaser.Physics.Arcade.Body = function (sprite) {
this.angularDrag = 0;
/**
* @property {number} maxAngular - The maximum angular velocity in pixels per second sq. that the Body can reach.
* @property {number} maxAngular - The maximum angular velocity that the Body can reach.
* @default
*/
this.maxAngular = 1000;
@@ -173,6 +207,18 @@ Phaser.Physics.Arcade.Body = function (sprite) {
*/
this.touching = { none: true, up: false, down: false, left: false, right: false };
/**
* This object is populated with previous touching values from the bodies previous collision.
* @property {object} wasTouching - An object containing previous touching results.
*/
this.wasTouching = { none: true, up: false, down: false, left: false, right: false };
/**
* @property {number} facing - A const reference to the direction the Body is traveling or facing.
* @default
*/
this.facing = Phaser.NONE;
/**
* @property {boolean} immovable - An immovable Body will not receive any impacts or exchanges of velocity from other bodies.
* @default
@@ -180,7 +226,7 @@ Phaser.Physics.Arcade.Body = function (sprite) {
this.immovable = false;
/**
* @property {boolean} moves - Set to true to allow the Physics system to move this Body, other false to move it manually.
* @property {boolean} moves - Set to true to allow the Physics system to move this Body, or false to move it manually.
* @default
*/
this.moves = true;
@@ -237,6 +283,12 @@ Phaser.Physics.Arcade.Body = function (sprite) {
*/
this.friction = 0;
/**
* If a body is overlapping with another body, but neither of them are moving (maybe they spawned on-top of each other?) this is set to true.
* @property {boolean} embedded - Body embed value.
*/
this.embedded = false;
/**
* 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?
@@ -250,6 +302,8 @@ Phaser.Physics.Arcade.Body = function (sprite) {
*/
this.blocked = { up: false, down: false, left: false, right: false };
this.blockedPoint = new Phaser.Point(0, 0);
/**
* @property {number} _dx - Internal cache var.
* @private
@@ -274,6 +328,10 @@ Phaser.Physics.Arcade.Body = function (sprite) {
*/
this._sy = sprite.scale.y;
this._newVelocity1 = 0;
this._newVelocity2 = 0;
this._average = 0;
};
Phaser.Physics.Arcade.Body.prototype = {
@@ -286,16 +344,16 @@ Phaser.Physics.Arcade.Body.prototype = {
*/
updateBounds: function (centerX, centerY, 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);
// this._sx = scaleX;
// this._sy = scaleY;
// this.center.setTo(this.x + this.halfWidth, this.y + this.halfHeight);
// }
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);
this._sx = scaleX;
this._sy = scaleY;
this.center.setTo(this.x + this.halfWidth, this.y + this.halfHeight);
}
},
@@ -307,18 +365,26 @@ Phaser.Physics.Arcade.Body.prototype = {
*/
preUpdate: function () {
// this.screenX = (this.sprite.worldTransform[2] - (this.sprite.anchor.x * this.width)) + this.offset.x;
// this.screenY = (this.sprite.worldTransform[5] - (this.sprite.anchor.y * this.height)) + this.offset.y;
// Store and reset collision flags
// this.wasTouching.none = this.touching.none;
// this.wasTouching.up = this.touching.up;
// this.wasTouching.down = this.touching.down;
// this.wasTouching.left = this.touching.left;
// this.wasTouching.right = this.touching.right;
this.screenX = (this.sprite.worldTransform[2] - (this.sprite.anchor.x * this.width)) + this.offset.x;
this.screenY = (this.sprite.worldTransform[5] - (this.sprite.anchor.y * this.height)) + this.offset.y;
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 all needs to move - because a body may start the preUpdate already touching something
// this.blocked.up = false;
// this.blocked.down = false;
// this.blocked.left = false;
// this.blocked.right = false;
this.blocked.up = false;
this.blocked.down = false;
this.blocked.left = false;
this.blocked.right = false;
// this.embedded = false;
this.x = this.preX;
this.y = this.preY;
@@ -341,6 +407,18 @@ Phaser.Physics.Arcade.Body.prototype = {
this.applyMotion();
}
if (this.deltaX() != 0)
{
this.touching.left = false;
this.touching.right = false;
}
if (this.deltaY() != 0)
{
this.touching.up = false;
this.touching.down = false;
}
},
/**
@@ -351,34 +429,38 @@ Phaser.Physics.Arcade.Body.prototype = {
*/
checkWorldBounds: function () {
if (this.x <= this.game.world.bounds.x)
this.blockedPoint.setTo(0, 0);
if (this.x < this.game.world.bounds.x)
{
this.overlapX = this.game.world.bounds.x - this.x;
this.blockedPoint.x = this.game.world.bounds.x - this.x;
// this.overlapX = this.game.world.bounds.x - this.x;
this.blocked.left = true;
// console.log(this._debug, 'cwl', this.overlapX, this.x, this.game.world.bounds.x);
}
else if (this.right >= this.game.world.bounds.right)
else if (this.right > this.game.world.bounds.right)
{
this.overlapX = this.right - this.game.world.bounds.right;
this.blockedPoint.x = this.right - this.game.world.bounds.right;
// this.overlapX = this.right - this.game.world.bounds.right;
this.blocked.right = true;
// console.log(this._debug, 'cwr', this.overlapX, this.x, this.game.world.bounds.x);
}
if (this.y <= this.game.world.bounds.y)
if (this.y < this.game.world.bounds.y)
{
this.overlapY = this.game.world.bounds.y - this.y;
this.blockedPoint.y = this.game.world.bounds.y - this.y;
// this.overlapY = this.game.world.bounds.y - this.y;
this.blocked.up = true;
// console.log(this._debug, 'cwu', this.overlapY, this.y, this.height, this.bottom, this.game.world.bounds.bottom);
}
else if (this.bottom >= this.game.world.bounds.bottom)
else if (this.bottom > this.game.world.bounds.bottom)
{
this.overlapY = this.bottom - this.game.world.bounds.bottom;
this.blockedPoint.y = this.bottom - this.game.world.bounds.bottom;
// this.overlapY = this.bottom - this.game.world.bounds.bottom;
this.blocked.down = true;
// console.log(this._debug, 'cwd', this.overlapY, this.y, this.height, this.bottom, this.game.world.bounds.bottom);
}
this.blockedPoint.setTo(this.x, this.y);
},
/**
@@ -405,10 +487,11 @@ Phaser.Physics.Arcade.Body.prototype = {
}
// overlapX/Y values at this point will be penetration into the bounds and DELTA WILL BE ZERO
if (this.blocked.left)
if (this.blocked.left && this.blockedPoint.x > 0)
{
// Separate
this.x += this.overlapX;
// this.x += this.overlapX;
this.x += this.blockedPoint.x;
// console.log(this._debug, 'blocked left', this.x, this.overlapX);
@@ -416,8 +499,8 @@ Phaser.Physics.Arcade.Body.prototype = {
this._dx = this.game.time.physicsElapsed * (this.velocity.x + this.motionVelocity.x / 2);
// if (this._dx > this.minBounceVelocity)
if (Math.abs(this.velocity.x) > this.minVelocity.x)
if (this._dx > this.minBounceVelocity)
// if (Math.abs(this.velocity.x) > this.minVelocity.x)
{
this.x += this._dx;
this.velocity.x += this.motionVelocity.x;
@@ -432,10 +515,11 @@ Phaser.Physics.Arcade.Body.prototype = {
// console.log(this._debug, 'blocked left KILL', this._dx, 'overlap', this.overlapX, 'delta', this.deltaX(), 'newy', this.x);
}
}
else if (this.blocked.right)
else if (this.blocked.right && this.blockedPoint.x > 0)
{
// Separate
this.x -= this.overlapX;
this.x -= this.blockedPoint.x;
// this.x -= this.overlapX;
this.velocity.x *= -this.bounce.x;
@@ -463,17 +547,18 @@ Phaser.Physics.Arcade.Body.prototype = {
}
// overlapX/Y values at this point will be penetration into the bounds and DELTA WILL BE ZERO
if (this.blocked.up)
if (this.blocked.up && this.blockedPoint.y > 0)
{
// Separate
this.y += this.overlapY;
// this.y += this.overlapY;
this.y += this.blockedPoint.y;
this.velocity.y *= -this.bounce.y;
this._dy = this.game.time.physicsElapsed * (this.velocity.y + this.motionVelocity.y / 2);
// if (this._dy > this.minBounceVelocity)
if (Math.abs(this.velocity.y) > this.minVelocity.y)
if (this._dy > this.minBounceVelocity)
// if (Math.abs(this.velocity.y) > this.minVelocity.y)
{
this.y += this._dy;
this.velocity.y += this.motionVelocity.y;
@@ -487,17 +572,18 @@ Phaser.Physics.Arcade.Body.prototype = {
// console.log(this._debug, 'void1', this.velocity.y, 'delta', this.deltaY());
}
}
else if (this.blocked.down)
else if (this.blocked.down && this.blockedPoint.y > 0)
{
// Separate
this.y -= this.overlapY;
// this.y -= this.overlapY;
this.y -= this.blockedPoint.y;
this.velocity.y *= -this.bounce.y;
this._dy = this.game.time.physicsElapsed * (this.velocity.y + this.motionVelocity.y / 2);
// if (this._dy < -this.minBounceVelocity)
if (Math.abs(this.velocity.y) > this.minVelocity.y)
if (this._dy < -this.minBounceVelocity)
// if (Math.abs(this.velocity.y) > this.minVelocity.y)
{
this.y += this._dy;
this.velocity.y += this.motionVelocity.y;
@@ -538,6 +624,242 @@ Phaser.Physics.Arcade.Body.prototype = {
},
overlap: function (body) {
this.overlapX = 0;
this.overlapY = 0;
if (this.x < body.x && this.allowCollision.right && body.allowCollision.left)
{
// Negative = body touched this one on the right face
this.overlapX = body.x - this.right;
this.touching.right = true;
}
else if (this.x > body.x && this.allowCollision.left && body.allowCollision.right)
{
// Positive means body touched this one on the left face
this.overlapX = body.right - this.x;
this.touching.left = true;
}
if (this.y < body.y && this.allowCollision.down && body.allowCollision.up)
{
// Negative = body touched this one on the bottom face
this.overlapY = body.y - this.bottom;
this.touching.down = true;
}
else if (this.y > body.y && this.allowCollision.up && body.allowCollision.down)
{
// Positive means body touched this one on the top face
this.overlapY = body.bottom - this.y;
this.touching.up = true;
}
// Which is the largest?
if (this.overlapX !== 0 && this.overlapY !== 0)
{
// console.log('pcheck', Math.abs(this.overlapX), Math.abs(this.overlapY));
// find out which is the largest penetration side
if (Math.abs(this.overlapX) > Math.abs(this.overlapY))
{
// Vertical penetration (as x is larger than y)
this.overlapX = 0;
this.touching.left = false;
this.touching.right = false;
}
else
{
// Horizontal penetration (as y is larger than x)
this.overlapY = 0;
this.touching.up = false;
this.touching.down = false;
}
}
// overlapX/Y now contains either zero or a positive value containing the overlapping area
return (this.overlapX !== 0 || this.overlapY !== 0);
},
// The left-hand face of this Body was hit
// overlapX will be a positive value
hitLeft: function (x, body, nv1, nv2, avg) {
// This body isn't moving horizontally, so it was hit by something moving right
if (this.immovable || this.blocked.right)
{
// console.log(this.sprite.name, 'hitLeft', 'immovable');
body.x -= x;
body.velocity.x = this.velocity.x - body.velocity.x * body.bounce.x;
}
else
{
if (body.immovable || body.blocked.left)
{
// console.log(this.sprite.name, 'hitLeft', 'full');
// We take the full separation as what hit is isn't moveable
this.x += x;
this.velocity.x = body.velocity.x - this.velocity.x * this.bounce.x;
}
else
{
// console.log(this.sprite.name, 'hitLeft', 'shared');
// Share the separation
x *= 0.5;
this.x += x;
body.x -= x;
this.velocity.x = avg + nv1 * this.bounce.x;
body.velocity.x = avg + nv2 * body.bounce.x;
}
}
},
// The right-hand face of this Body was hit
// overlapX will be a negative value
hitRight: function (x, body, nv1, nv2, avg) {
// This body isn't moving horizontally, so it was hit by something moving right
if (this.immovable || this.blocked.left)
{
// console.log(this.sprite.name, 'hitRight', 'immovable');
body.x -= x;
body.velocity.x = this.velocity.x - body.velocity.x * body.bounce.x;
}
else
{
if (body.immovable || body.blocked.right)
{
// console.log(this.sprite.name, 'hitRight', 'full');
// We take the full separation as what hit is isn't moveable
this.x += x;
this.velocity.x = body.velocity.x - this.velocity.x * this.bounce.x;
}
else
{
// console.log(this.sprite.name, 'hitRight', 'shared');
// Share the separation
x *= 0.5;
this.x += x;
body.x -= x;
this.velocity.x = avg + nv1 * this.bounce.x;
body.velocity.x = avg + nv2 * body.bounce.x;
}
}
},
// The top face of this Body was hit
// overlapY will be a positive value
hitUp: function (y, body, nv1, nv2, avg) {
// This body isn't moving horizontally, so it was hit by something moving right
if (this.immovable || this.blocked.down)
{
// console.log(this.sprite.name, 'hitUp', 'immovable');
body.y -= y;
body.velocity.y = this.velocity.y - body.velocity.y * body.bounce.y;
}
else
{
if (body.immovable || body.blocked.up)
{
// console.log(this.sprite.name, 'hitUp', 'full');
// We take the full separation as what hit is isn't moveable
this.y += y;
this.velocity.y = body.velocity.y - this.velocity.y * this.bounce.y;
}
else
{
// console.log(this.sprite.name, 'hitUp', 'shared');
// Share the separation
y *= 0.5;
this.y += y;
body.y -= y;
this.velocity.y = avg + nv1 * this.bounce.y;
body.velocity.y = avg + nv2 * body.bounce.y;
}
}
},
// The bottom face of this Body was hit
// overlapY will be a negative value
hitDown: function (y, body, nv1, nv2, avg) {
// This body isn't moving horizontally, so it was hit by something moving right
if (this.immovable || this.blocked.up)
{
// console.log(this.sprite.name, 'hitDown', 'immovable');
body.y -= y;
body.velocity.y = this.velocity.y - body.velocity.y * body.bounce.y;
}
else
{
if (body.immovable || body.blocked.down)
{
// console.log(this.sprite.name, 'hitDown', 'full');
// We take the full separation as what hit is isn't moveable
this.y += y;
this.velocity.y = body.velocity.y - this.velocity.y * this.bounce.y;
}
else
{
// console.log(this.sprite.name, 'hitDown', 'shared');
// Share the separation
y *= 0.5;
this.y += y;
body.y -= y;
this.velocity.y = avg + nv1 * this.bounce.y;
body.velocity.y = avg + nv2 * body.bounce.y;
}
}
},
separate: function (body) {
// We already know the overlap in this.overlapX/Y
if (this.overlapX !== 0)
{
this._newVelocity1 = Math.sqrt((body.velocity.x * body.velocity.x * body.mass) / this.mass) * ((body.velocity.x > 0) ? 1 : -1);
this._newVelocity2 = Math.sqrt((this.velocity.x * this.velocity.x * this.mass) / body.mass) * ((this.velocity.x > 0) ? 1 : -1);
this._average = (this._newVelocity1 + this._newVelocity2) * 0.5;
this._newVelocity1 -= this._average;
this._newVelocity2 -= this._average;
if (this.overlapX < 0)
{
this.hitLeft(this.overlapX, body, this._newVelocity1, this._newVelocity2, this._average);
}
else if (this.overlapX > 0)
{
this.hitRight(this.overlapX, body, this._newVelocity1, this._newVelocity2, this._average);
}
}
if (this.overlapY !== 0)
{
this._newVelocity1 = Math.sqrt((body.velocity.y * body.velocity.y * body.mass) / this.mass) * ((body.velocity.y > 0) ? 1 : -1);
this._newVelocity2 = Math.sqrt((this.velocity.y * this.velocity.y * this.mass) / body.mass) * ((this.velocity.y > 0) ? 1 : -1);
this._average = (this._newVelocity1 + this._newVelocity2) * 0.5;
this._newVelocity1 -= this._average;
this._newVelocity2 -= this._average;
if (this.overlapY < 0)
{
this.hitDown(this.overlapY, body, this._newVelocity1, this._newVelocity2, this._average);
}
else if (this.overlapY > 0)
{
this.hitUp(this.overlapY, body, this._newVelocity1, this._newVelocity2, this._average);
}
}
},
/**
* Internal method. This is called directly before the sprites are sent to the renderer.
*
@@ -548,8 +870,29 @@ Phaser.Physics.Arcade.Body.prototype = {
if (this.moves)
{
// this.sprite.x += this.deltaX();
// this.sprite.y += this.deltaY();
if (this.deltaX() < 0)
{
this.facing = Phaser.LEFT;
}
else if (this.deltaX() > 0)
{
this.facing = Phaser.RIGHT;
}
if (this.deltaY() < 0)
{
this.facing = Phaser.UP;
}
else if (this.deltaY() > 0)
{
this.facing = Phaser.DOWN;
}
this.sprite.x += this.deltaX();
this.sprite.y += this.deltaY();
this.sprite.worldTransform[2] += this.deltaX();
this.sprite.worldTransform[5] += this.deltaY();
this.center.setTo(this.x + this.halfWidth, this.y + this.halfHeight);
@@ -561,6 +904,35 @@ 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 - The X offset of the Body from the Sprite position.
* @param {number} offsetY - 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;
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);
},
/**
* Resets all Body values (velocity, acceleration, rotation, etc)
*
@@ -60,50 +60,16 @@ Phaser.Physics.Arcade.Body = function (sprite) {
*/
this.preRotation = sprite.angle;
/**
* @property {number} screenX - The x position of the physics body translated to screen space.
* @readonly
*/
this.screenX = sprite.x;
/**
* @property {number} screenY - The y position of the physics body translated to screen space.
* @readonly
*/
this.screenY = sprite.y;
/**
* @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
* @property {number} height - The calculated height of the physics body.
*/
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.
*/
@@ -206,19 +172,6 @@ Phaser.Physics.Arcade.Body = function (sprite) {
* @property {object} touching - An object containing touching results.
*/
this.touching = { none: true, up: false, down: false, left: false, right: false };
this.touchingPoint = new Phaser.Point(this.x, this.y);
/**
* This object is populated with previous touching values from the bodies previous collision.
* @property {object} wasTouching - An object containing previous touching results.
*/
this.wasTouching = { none: true, up: false, down: false, left: false, right: false };
/**
* @property {number} facing - A const reference to the direction the Body is traveling or facing.
* @default
*/
this.facing = Phaser.NONE;
/**
* @property {boolean} immovable - An immovable Body will not receive any impacts or exchanges of velocity from other bodies.
@@ -284,12 +237,6 @@ Phaser.Physics.Arcade.Body = function (sprite) {
*/
this.friction = 0;
/**
* If a body is overlapping with another body, but neither of them are moving (maybe they spawned on-top of each other?) this is set to true.
* @property {boolean} embedded - Body embed value.
*/
this.embedded = false;
/**
* 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?
@@ -302,7 +249,6 @@ Phaser.Physics.Arcade.Body = function (sprite) {
* @property {object} blocked - An object containing on which faces this Body is blocked from moving, if any.
*/
this.blocked = { up: false, down: false, left: false, right: false };
this.blockedPoint = new Phaser.Point();
/**
* @property {number} _dx - Internal cache var.
@@ -328,6 +274,10 @@ Phaser.Physics.Arcade.Body = function (sprite) {
*/
this._sy = sprite.scale.y;
this.shape = new SAT.Box(new SAT.Vector(this.x, this.y), this.width, this.height);
this.polygon = this.shape.toPolygon();
this.response = new SAT.Response();
};
Phaser.Physics.Arcade.Body.prototype = {
@@ -340,16 +290,16 @@ Phaser.Physics.Arcade.Body.prototype = {
*/
updateBounds: function (centerX, centerY, 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);
this._sx = scaleX;
this._sy = scaleY;
this.center.setTo(this.x + this.halfWidth, this.y + this.halfHeight);
}
// 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);
// this._sx = scaleX;
// this._sy = scaleY;
// this.center.setTo(this.x + this.halfWidth, this.y + this.halfHeight);
// }
},
@@ -361,42 +311,23 @@ Phaser.Physics.Arcade.Body.prototype = {
*/
preUpdate: function () {
// Store and reset collision flags
this.wasTouching.none = this.touching.none;
this.wasTouching.up = this.touching.up;
this.wasTouching.down = this.touching.down;
this.wasTouching.left = this.touching.left;
this.wasTouching.right = this.touching.right;
this.screenX = (this.sprite.worldTransform[2] - (this.sprite.anchor.x * this.width)) + this.offset.x;
this.screenY = (this.sprite.worldTransform[5] - (this.sprite.anchor.y * this.height)) + this.offset.y;
// this.screenX = (this.sprite.worldTransform[2] - (this.sprite.anchor.x * this.width)) + this.offset.x;
// this.screenY = (this.sprite.worldTransform[5] - (this.sprite.anchor.y * this.height)) + this.offset.y;
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.preRotation = this.sprite.angle;
this.preRotation = this.sprite.rotation;
// This all needs to move - because a body may start the preUpdate already touching something
// See if we can reduce this down?
this.blocked.up = false;
this.blocked.down = false;
this.blocked.left = false;
this.blocked.right = false;
this.embedded = false;
this.x = this.preX;
this.y = this.preY;
this.rotation = this.preRotation;
// if (this.deltaX() == 0 && (this.touchingPoint.x !== this.x || this.touchingPoint.y !== this.y))
// {
// console.log('touch reset', this.x, this.y, this.touchingPoint);
// this.touching.none = true;
// this.touching.up = false;
// this.touching.down = false;
// this.touching.left = false;
// this.touching.right = false;
// }
// this.rotation = this.preRotation;
this.speed = Math.sqrt(this.velocity.x * this.velocity.x + this.velocity.y * this.velocity.y);
this.angle = Math.atan2(this.velocity.y, this.velocity.x);
@@ -415,6 +346,16 @@ Phaser.Physics.Arcade.Body.prototype = {
this.applyMotion();
}
this.polygon.pos.x = this.x;
this.polygon.pos.y = this.y;
if (this.deltaZ() !== 0)
{
// this.polygon.rotate(this.sprite.rotation);
// console.log(this.sprite.rotation);
}
// this.polygon.rotate(this.game.math.degToRad(this.rotation));
},
/**
@@ -612,142 +553,31 @@ Phaser.Physics.Arcade.Body.prototype = {
},
// This body is the one that is checking against 'body'
separateX: function (body) {
collide: function (body) {
// Doesn't matter if this is moving or not
console.log('--- separateX -----------------------------------------------------------------------------');
console.log(this.sprite.name, 'testing against', body.sprite.name);
console.log(this.sprite.name, 'moving left:', (this.deltaX() < 0), 'moving right:', (this.deltaX() > 0));
this.response.clear();
this.overlapX = 0;
// if (this._debug === 100)
// {
// console.log(this.sprite.name, this.polygon);
// }
if (this.x < body.x)
if (SAT.testPolygonPolygon(this.polygon, body.polygon, this.response))
{
this.overlapX = this.right - body.x;
// b1.pos.sub(r.overlapV);
// sprite.body.velocity.x *= -sprite.body.bounce.x;
this.velocity.x = 0;
// separate
this.x += Math.ceil(Math.abs(this.response.overlapV.x));
this.y += Math.ceil(Math.abs(this.response.overlapV.y));
console.log(this.response, this.deltaX());
console.log('sprite moved to', this.x, this.deltaX());
}
else
{
this.overlapX = body.right - this.x;
}
// There are 5 possible collisions taking place
// if (this.deltaX() === 0 && body.deltaX())
// if (this.deltaX() < 0 )
// if (this.deltaX() < 0 && this.allowCollision.left && body.allowCollision.right)
// This body is moving, the body it collided with is not
},
separate: function (body) {
console.log('-----------------------------------------------------------------------------');
console.log(this.sprite.name, 'testing against', body.sprite.name);
console.log(this.sprite.name, 'moving left:', (this.deltaX() < 0), 'moving right:', (this.deltaX() > 0));
this.overlapX = 0;
this.overlapY = 0;
if (this.deltaX() < 0 && this.allowCollision.left && body.allowCollision.right)
{
// LEFT (will create a negative overlapX value)
this.overlapX = this.x - body.right;
console.log(this.sprite.name, 'check left', body.right, this.overlapX);
}
else if (this.deltaX() > 0 && this.allowCollision.right && body.allowCollision.left)
{
// RIGHT (will create a positive overlapX value)
this.overlapX = this.right - body.x;
console.log(this.sprite.name, 'check right', this.overlapX);
}
if (this.deltaY() < 0 && this.allowCollision.up && body.allowCollision.down)
{
// UP (will create a negative overlapY value)
this.overlapY = this.y - body.bottom;
}
else if (this.deltaY() > 0 && this.allowCollision.down && body.allowCollision.up)
{
// DOWN
this.overlapY = this.bottom - body.y;
}
if (this.overlapX === 0 && this.overlapY === 0)
{
return false;
}
else
{
this.overlapHandler(this.overlapX, this.overlapY, body);
body.overlapHandler(this.overlapX, this.overlapY, this);
return true;
}
},
overlapHandler: function (x, y, body) {
if (x !== 0)
{
// Both moving, so let's cut the overlap in half
if (this.deltaX() != 0 && body.deltaX() != 0)
{
console.log(this.sprite.name, 'both overlap, halving');
x * 0.5;
}
if (this.deltaX() !== 0)
{
// Not moving, caught impact from another object
}
else
{
}
if (this.deltaX() < 0 && !this.blocked.right)
{
// This body is moving left
this.x += x;
console.log(this.sprite.name, 'touch h-left', this.x, x);
}
else if (this.deltaX() > 0 && !this.body.blocked.left)
{
this.x -= x;
console.log(this.sprite.name, 'touch h-right', this.x);
}
else
{
}
if (this.bounce.x === 0)
{
this.velocity.x = 0;
}
else
{
this.velocity.x = -this.velocity.x * this.bounce.x;
if (Math.abs(this.velocity.x) < this.minVelocity.x)
{
this.velocity.x = 0;
}
}
}
this.sprite.x += this.deltaX();
this.sprite.y += this.deltaY();
console.log(this.sprite.name, 'separate finished. Sprite.x', this.sprite.x, 'body x', this.x);
// reset delta ready for next collision
this.preX = this.x;
this.preY = this.y;
},
@@ -761,68 +591,24 @@ Phaser.Physics.Arcade.Body.prototype = {
if (this.moves)
{
// if (this.deltaX() < 0)
// {
// this.facing = Phaser.LEFT;
// }
// else if (this.deltaX() > 0)
// {
// this.facing = Phaser.RIGHT;
// this.sprite.x += this.deltaX();
// }
// if (this.deltaY() < 0)
// {
// this.facing = Phaser.UP;
// this.sprite.y += this.deltaY();
// }
// else if (this.deltaY() > 0)
// {
// this.facing = Phaser.DOWN;
// }
this.sprite.x += this.deltaX();
this.sprite.y += this.deltaY();
this.sprite.worldTransform[2] += this.deltaX();
this.sprite.worldTransform[5] += this.deltaY();
this.center.setTo(this.x + this.halfWidth, this.y + this.halfHeight);
this.rotation = this.preRotation;
if (this.allowRotation)
{
this.sprite.angle += this.deltaZ();
// this.sprite.angle += this.deltaZ();
}
}
},
/**
* 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 - The X offset of the Body from the Sprite position.
* @param {number} offsetY - 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;
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);
},
/**
* Resets all Body values (velocity, acceleration, rotation, etc)
*
+34
View File
@@ -922,6 +922,40 @@ Phaser.Utils.Debug.prototype = {
},
/**
* Renders the corners and point information of the given Sprite.
* @method Phaser.Utils.Debug#renderPolygon
* @param {array} polygon
* @param {string} [color='rgb(255,255,255)'] - The color the polygon is stroked in.
*/
renderPolygon: function (polygon, color, context) {
if (this.context === null && context === null)
{
return;
}
color = color || 'rgb(255,255,255)';
this.start(0, 0, color);
this.context.beginPath();
this.context.moveTo(polygon[0].x, polygon[0].y);
for (var i = 1; i < polygon.length; i++)
{
this.context.lineTo(polygon[i].x, polygon[i].y);
}
this.context.closePath();
// this.context.strokeStyle = 'rgba(255, 0, 255, 0.7)';
this.context.strokeStyle = color;
this.context.stroke();
this.stop();
},
/**
* Dumps the Linked List to the console.
*