Working through re-integrating tilemap collision. So far, so good.

This commit is contained in:
photonstorm 2014-01-22 16:16:53 +00:00
parent 1370ba52b5
commit 20108e47f3
5 changed files with 3877 additions and 126 deletions

File diff suppressed because one or more lines are too long

69
examples/wip/platform.js Normal file
View file

@ -0,0 +1,69 @@
var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { preload: preload, create: create, update: update, render: render });
function preload() {
game.load.tilemap('map', 'assets/tilemaps/maps/platform.json', null, Phaser.Tilemap.TILED_JSON);
game.load.image('platformer_tiles', 'assets/tilemaps/tiles/platformer_tiles.png');
game.load.spritesheet('gameboy', 'assets/sprites/gameboy_seize_color_40x60.png', 40, 60);
}
var map;
var layer;
var sprite;
function create() {
game.stage.backgroundColor = '#124184';
map = game.add.tilemap('map');
map.addTilesetImage('platformer_tiles');
map.setCollisionBetween(32, 35);
map.setCollisionByIndex(21);
layer = map.createLayer('Tile Layer 1');
// layer.debug = true;
game.physics.gravity.y = 200;
sprite = game.add.sprite(300, 100, 'gameboy', 0);
sprite.name = 'red';
sprite.body.collideWorldBounds = true;
sprite.body.bounce.setTo(0.5, 0.5);
game.input.onDown.add(launch, this);
}
function launch() {
sprite.body.velocity.x = -200;
sprite.body.velocity.y = -200;
}
function hit(face, body1, body2) {
console.log('hit', face);
}
function update() {
game.physics.collide(sprite, layer);
}
function render() {
if (sprite)
{
game.debug.renderBodyInfo(sprite, 20, 30);
}
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 188 KiB

View file

@ -737,8 +737,6 @@ Phaser.Physics.Arcade.prototype = {
if (localOverlapX >= body.deltaX())
{
console.log('m left overlapX', localOverlapX, body.deltaX());
// use touching instead of blocked?
body.blocked.left = true;
body.touching.left = true;
body.touching.none = false;
@ -752,7 +750,6 @@ Phaser.Physics.Arcade.prototype = {
// Distance check
if (localOverlapX <= body.deltaX())
{
console.log('m right overlapX', localOverlapX, body.deltaX());
body.blocked.right = true;
body.touching.right = true;
body.touching.none = false;
@ -767,7 +764,6 @@ Phaser.Physics.Arcade.prototype = {
// Distance check
if (localOverlapY >= body.deltaY())
{
console.log('m up overlapY', localOverlapY, body.deltaY());
body.blocked.up = true;
body.touching.up = true;
body.touching.none = false;
@ -780,7 +776,6 @@ Phaser.Physics.Arcade.prototype = {
if (localOverlapY <= body.deltaY())
{
console.log('m down overlapY', localOverlapY, body.deltaY());
body.blocked.down = true;
body.touching.down = true;
body.touching.none = false;
@ -799,42 +794,7 @@ Phaser.Physics.Arcade.prototype = {
body.overlapY = localOverlapY;
}
if (body.touching.none)
{
return false;
}
if (body.touching.left || body.touching.right)
{
body.x -= body.overlapX;
body.preX -= body.overlapX;
if (body.bounce.x === 0)
{
body.velocity.x = 0;
}
else
{
body.velocity.x = -body.velocity.x * body.bounce.x;
}
}
if (body.touching.up || body.touching.down)
{
body.y -= body.overlapY;
body.preY -= body.overlapY;
if (body.bounce.y === 0)
{
body.velocity.y = 0;
}
else
{
body.velocity.y = -body.velocity.y * body.bounce.y;
}
}
return true;
return this.processTileSeparation(body);
},
@ -850,9 +810,6 @@ Phaser.Physics.Arcade.prototype = {
// Can't separate two immovable objects (tiles are always immovable)
if (body.immovable || Phaser.Rectangle.intersects(body, tile) === false)
{
console.log('no intersects');
// console.log('tx', tile.x, 'ty', tile.y, 'tw', tile.width, 'th', tile.height, 'tr', tile.right, 'tb', tile.bottom);
// console.log('bx', body.x, 'by', body.y, 'bw', body.width, 'bh', body.height, 'br', body.right, 'bb', body.bottom);
return false;
}
@ -877,13 +834,6 @@ Phaser.Physics.Arcade.prototype = {
body.overlapY = 0;
// Remember - this happens AFTER the body has been moved by the motion update, so it needs moving back again
console.log('---------------------------------------------------------------------------------------------');
// console.log(tile);
// console.log('tx', tile.x, 'ty', tile.y, 'tw', tile.width, 'th', tile.height, 'tr', tile.right, 'tb', tile.bottom);
// console.log('bx', body.x, 'by', body.y, 'bw', body.width, 'bh', body.height, 'br', body.right, 'bb', body.bottom);
// console.log(Phaser.Rectangle.intersects(body, tile));
// console.log('dx', body.deltaX(), 'dy', body.deltaY(), 'dax', body.deltaAbsX(), 'day', body.deltaAbsY(), 'cax', Math.ceil(body.deltaAbsX()), 'cay', Math.ceil(body.deltaAbsY()));
if (body.deltaX() < 0 && body.allowCollision.left && tile.tile.faceRight)
{
// LEFT
@ -891,7 +841,6 @@ Phaser.Physics.Arcade.prototype = {
if (body.overlapX >= body.deltaX())
{
console.log('left overlapX', body.overlapX, body.deltaX());
// use touching instead of blocked?
body.blocked.left = true;
body.touching.left = true;
@ -906,7 +855,6 @@ Phaser.Physics.Arcade.prototype = {
// Distance check
if (body.overlapX <= body.deltaX())
{
console.log('right overlapX', body.overlapX, body.deltaX());
body.blocked.right = true;
body.touching.right = true;
body.touching.none = false;
@ -921,7 +869,6 @@ Phaser.Physics.Arcade.prototype = {
// Distance check
if (body.overlapY >= body.deltaY())
{
console.log('up overlapY', body.overlapY, body.deltaY());
body.blocked.up = true;
body.touching.up = true;
body.touching.none = false;
@ -934,7 +881,6 @@ Phaser.Physics.Arcade.prototype = {
if (body.overlapY <= body.deltaY())
{
console.log('down overlapY', body.overlapY, body.deltaY());
body.blocked.down = true;
body.touching.down = true;
body.touching.none = false;
@ -942,16 +888,26 @@ Phaser.Physics.Arcade.prototype = {
}
// Separate in a single sweep
return this.processTileSeparation(body);
},
/**
* Internal function to process the separation of a physics body from a tile.
* @method Phaser.Physics.Arcade#processTileSeparation
* @protected
* @param {Phaser.Physics.Arcade.Body} body1 - The Body object to separate.
* @returns {boolean} Returns true if separated, false if not.
*/
processTileSeparation: function (body) {
if (body.touching.none)
{
return false;
}
// if (body.overlapX !== 0)
if (body.touching.left || body.touching.right)
{
console.log('touch left/r', body.overlapX);
body.x -= body.overlapX;
body.preX -= body.overlapX;
@ -962,13 +918,17 @@ Phaser.Physics.Arcade.prototype = {
else
{
body.velocity.x = -body.velocity.x * body.bounce.x;
// Rebound check
if (Math.abs(body.velocity.x) < body.minVelocity.x)
{
body.velocity.x = 0;
}
}
}
// if (body.overlapY !== 0)
if (body.touching.up || body.touching.down)
{
console.log('touch up/d', body.overlapY);
body.y -= body.overlapY;
body.preY -= body.overlapY;
@ -979,6 +939,12 @@ Phaser.Physics.Arcade.prototype = {
else
{
body.velocity.y = -body.velocity.y * body.bounce.y;
// Rebound check
if (Math.abs(body.velocity.y) < body.minVelocity.y)
{
body.velocity.y = 0;
}
}
}

View file

@ -253,6 +253,18 @@ Phaser.Physics.Arcade.Body = function (sprite) {
*/
this.customSeparateContext = null;
/**
* @property {function} collideCallback - If set this callback will be fired whenever this Body is hit (on any face). It will send three parameters, the face it hit on, this Body and the Body that hit it.
* @default
*/
this.collideCallback = null;
/**
* @property {object} collideCallbackContext - The context in which the collideCallback is called.
* @default
*/
this.collideCallbackContext = null;
/**
* When this body collides with another, the amount of overlap is stored here.
* @property {number} overlapX - The amount of horizontal overlap during the collision.
@ -378,6 +390,11 @@ Phaser.Physics.Arcade.Body.prototype = {
this.blocked.left = false;
this.blocked.right = false;
this.touching.up = false;
this.touching.down = false;
this.touching.left = false;
this.touching.right = false;
this.x = this.preX;
this.y = this.preY;
this.rotation = this.preRotation;
@ -385,8 +402,6 @@ Phaser.Physics.Arcade.Body.prototype = {
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);
this._debug++;
if (this.moves)
{
if (this.collideWorldBounds)
@ -399,17 +414,17 @@ Phaser.Physics.Arcade.Body.prototype = {
this.applyMotion();
}
if (this.deltaX() != 0)
{
this.touching.left = false;
this.touching.right = false;
}
// if (this.deltaX() != 0)
// {
// this.touching.left = false;
// this.touching.right = false;
// }
if (this.deltaY() != 0)
{
this.touching.up = false;
this.touching.down = false;
}
// if (this.deltaY() != 0)
// {
// this.touching.up = false;
// this.touching.down = false;
// }
},
@ -426,31 +441,23 @@ Phaser.Physics.Arcade.Body.prototype = {
if (this.x < this.game.world.bounds.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)
{
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)
{
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)
{
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);
}
},
@ -482,37 +489,27 @@ Phaser.Physics.Arcade.Body.prototype = {
if (this.blocked.left && this.blockedPoint.x > 0)
{
// Separate
// this.x += this.overlapX;
this.x += this.blockedPoint.x;
// console.log(this._debug, 'blocked left', this.x, this.overlapX);
this.velocity.x *= -this.bounce.x;
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)
{
this.x += this._dx;
this.velocity.x += this.motionVelocity.x;
// console.log(this._debug, 'blocked left', this._dx, 'overlap', this.overlapX, 'delta', this.deltaX(), 'newy', this.x);
}
else
{
// Kill it dead :)
this.preX = this.x; // because we don't want any delta from a separation
this.velocity.x = 0;
this.motionVelocity.x = 0;
// console.log(this._debug, 'blocked left KILL', this._dx, 'overlap', this.overlapX, 'delta', this.deltaX(), 'newy', this.x);
}
}
else if (this.blocked.right && this.blockedPoint.x > 0)
{
// Separate
this.x -= this.blockedPoint.x;
// this.x -= this.overlapX;
this.velocity.x *= -this.bounce.x;
this._dx = this.game.time.physicsElapsed * (this.velocity.x + this.motionVelocity.x / 2);
@ -521,15 +518,12 @@ Phaser.Physics.Arcade.Body.prototype = {
{
this.x += this._dx;
this.velocity.x += this.motionVelocity.x;
// console.log(this._debug, 'blocked right', this._dx, 'overlap', this.overlapX, 'delta', this.deltaX(), 'newy', this.x);
}
else
{
// Kill it dead :)
this.preX = this.x; // because we don't want any delta from a separation
this.velocity.x = 0;
this.motionVelocity.x = 0;
// console.log(this._debug, 'blocked right KILL', this._dx, 'overlap', this.overlapX, 'delta', this.deltaX(), 'newy', this.x);
}
}
else
@ -542,52 +536,41 @@ Phaser.Physics.Arcade.Body.prototype = {
if (this.blocked.up && this.blockedPoint.y > 0)
{
// Separate
// 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)
{
this.y += this._dy;
this.velocity.y += this.motionVelocity.y;
}
else
{
// Kill it dead :)
this.preY = this.y; // because we don't want any delta from a separation
this.velocity.y = 0;
this.motionVelocity.y = 0;
// console.log(this._debug, 'void1', this.velocity.y, 'delta', this.deltaY());
}
}
else if (this.blocked.down && this.blockedPoint.y > 0)
{
// Separate
// 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)
{
this.y += this._dy;
this.velocity.y += this.motionVelocity.y;
// console.log(this._debug, 'rb', this._dy, 'delta', this.deltaY(), 'newy', this.y);
}
else
{
// Kill it dead :)
this.preY = this.y; // because we don't want any delta from a separation
this.velocity.y = 0;
this.motionVelocity.y = 0;
// console.log(this._debug, 'void1', this.velocity.y, 'delta', this.deltaY());
}
}
else
@ -616,6 +599,14 @@ Phaser.Physics.Arcade.Body.prototype = {
},
/**
* Checks for an overlap between this Body and the given Body, taking into account the allowCollision flags on both bodies.
* If an overlap occurs the Body.touching flags are set and the results are stored in overlapX and overlapY.
*
* @method Phaser.Physics.Arcade#overlap
* @param {Phaser.Physics.Arcade.Body} body - The Body that collided.
* @return {boolean} True if the two bodies overlap, otherwise false.
*/
overlap: function (body) {
this.overlapX = 0;
@ -650,9 +641,7 @@ Phaser.Physics.Arcade.Body.prototype = {
// 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
// Crudely 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)
@ -674,14 +663,23 @@ Phaser.Physics.Arcade.Body.prototype = {
},
// The left-hand face of this Body was hit (so it gets moved to the right)
// overlapX will be a positive value
/**
* Process a collision with the left face of this Body. If possible the Body will be moved right.
* Uses overlayX which will be positive.
*
* @method Phaser.Physics.Arcade#hitLeft
* @protected
* @param {number} x - The overlapX value.
* @param {Phaser.Physics.Arcade.Body} body - The Body that collided.
* @param {number} nv1 - The new velocity for this Body.
* @param {number} nv2 - The new velocity for the colliding Body.
* @param {number} avg - The new average velocity between the two Bodies.
*/
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;
}
@ -689,7 +687,6 @@ Phaser.Physics.Arcade.Body.prototype = {
{
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;
@ -702,7 +699,6 @@ Phaser.Physics.Arcade.Body.prototype = {
}
else
{
// console.log(this.sprite.name, 'hitLeft', 'shared');
// Share the separation
x *= 0.5;
this.x += x;
@ -725,16 +721,30 @@ Phaser.Physics.Arcade.Body.prototype = {
this.x -= this.right - this.game.world.bounds.right;
}
if (this.collideCallback)
{
this.collideCallback.call(this.collideCallbackContext, Phaser.LEFT, this, body);
}
},
// The right-hand face of this Body was hit (so will be moved to the left)
// overlapX will be a negative value
/**
* Process a collision with the right face of this Body. If possible the Body will be moved left.
* Uses overlayX which will be negative.
*
* @method Phaser.Physics.Arcade#hitRight
* @protected
* @param {number} x - The overlapX value.
* @param {Phaser.Physics.Arcade.Body} body - The Body that collided.
* @param {number} nv1 - The new velocity for this Body.
* @param {number} nv2 - The new velocity for the colliding Body.
* @param {number} avg - The new average velocity between the two Bodies.
*/
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;
}
@ -742,7 +752,6 @@ Phaser.Physics.Arcade.Body.prototype = {
{
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;
@ -755,7 +764,6 @@ Phaser.Physics.Arcade.Body.prototype = {
}
else
{
// console.log(this.sprite.name, 'hitRight', 'shared');
// Share the separation
x *= 0.5;
this.x += x;
@ -778,16 +786,30 @@ Phaser.Physics.Arcade.Body.prototype = {
this.x += this.game.world.bounds.x - this.x;
}
if (this.collideCallback)
{
this.collideCallback.call(this.collideCallbackContext, Phaser.RIGHT, this, body);
}
},
// The top face of this Body was hit (so it will get pushed down)
// overlapY will be a positive value
/**
* Process a collision with the top face of this Body. If possible the Body will be moved down.
* Uses overlayY which will be positive.
*
* @method Phaser.Physics.Arcade#hitUp
* @protected
* @param {number} y - The overlapY value.
* @param {Phaser.Physics.Arcade.Body} body - The Body that collided.
* @param {number} nv1 - The new velocity for this Body.
* @param {number} nv2 - The new velocity for the colliding Body.
* @param {number} avg - The new average velocity between the two Bodies.
*/
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;
}
@ -795,7 +817,6 @@ Phaser.Physics.Arcade.Body.prototype = {
{
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;
@ -808,7 +829,6 @@ Phaser.Physics.Arcade.Body.prototype = {
}
else
{
// console.log(this.sprite.name, 'hitUp', 'shared');
// Share the separation
y *= 0.5;
this.y += y;
@ -831,16 +851,30 @@ Phaser.Physics.Arcade.Body.prototype = {
this.y -= this.bottom - this.game.world.bounds.bottom;
}
if (this.collideCallback)
{
this.collideCallback.call(this.collideCallbackContext, Phaser.UP, this, body);
}
},
// The bottom face of this Body was hit (so it will be pushed up)
// overlapY will be a negative value
/**
* Process a collision with the bottom face of this Body. If possible the Body will be moved up.
* Uses overlayY which will be negative.
*
* @method Phaser.Physics.Arcade#hitDown
* @protected
* @param {number} y - The overlapY value.
* @param {Phaser.Physics.Arcade.Body} body - The Body that collided.
* @param {number} nv1 - The new velocity for this Body.
* @param {number} nv2 - The new velocity for the colliding Body.
* @param {number} avg - The new average velocity between the two Bodies.
*/
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;
}
@ -848,7 +882,6 @@ Phaser.Physics.Arcade.Body.prototype = {
{
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;
@ -861,7 +894,6 @@ Phaser.Physics.Arcade.Body.prototype = {
}
else
{
// console.log(this.sprite.name, 'hitDown', 'shared');
// Share the separation
y *= 0.5;
this.y += y;
@ -884,8 +916,22 @@ Phaser.Physics.Arcade.Body.prototype = {
this.y += this.game.world.bounds.y - this.y;
}
if (this.collideCallback)
{
this.collideCallback.call(this.collideCallbackContext, Phaser.DOWN, this, body);
}
},
/**
* This separates this Body from the given Body unless a customSeparateCallback is set.
* It assumes they have already been overlap checked and the resulting overlap is stored in overlapX and overlapY.
*
* @method Phaser.Physics.Arcade#separate
* @protected
* @param {Phaser.Physics.Arcade.Body} body - The Body to be separated from this one.
* @return {boolean}
*/
separate: function (body) {
if (this.customSeparateCallback)