Tilemap collision finally getting closer.

This commit is contained in:
photonstorm 2014-03-13 22:49:08 +00:00
parent e955145707
commit 5297497632
5 changed files with 201 additions and 64 deletions

View file

@ -36,7 +36,6 @@ function create() {
game.camera.follow(sprite);
// game.physics.arcade.gravity.y = 500;
// sprite.body.velocity.x = 100;
cursors = game.input.keyboard.createCursorKeys();
@ -51,27 +50,32 @@ function update() {
if (cursors.up.isDown)
{
sprite.body.velocity.y = -100;
sprite.body.velocity.y = -200;
}
else if (cursors.down.isDown)
{
sprite.body.velocity.y = 100;
sprite.body.velocity.y = 200;
}
if (cursors.left.isDown)
{
sprite.body.velocity.x = -100;
sprite.body.velocity.x = -200;
}
else if (cursors.right.isDown)
{
sprite.body.velocity.x = 100;
sprite.body.velocity.x = 200;
}
}
function render() {
game.debug.text(sprite.body.velocity.x, 32, 32);
game.debug.text(sprite.body.velocity.y, 64, 32);
// game.debug.text(sprite.body.deltaAbsX(), 32, 32);
// game.debug.text(sprite.body.deltaAbsY(), 32, 64);
// game.debug.text(sprite.body.deltaX(), 400, 32);
// game.debug.text(sprite.body.deltaY(), 400, 64);
game.debug.body(sprite);
}

View file

@ -632,12 +632,12 @@ Phaser.Physics.Arcade.Body.render = function (context, body, filled, color) {
if (filled)
{
context.fillStyle = color;
context.fillRect(body.x - body.game.camera.x, body.y - body.game.camera.y, body.width, body.height);
context.fillRect(body.position.x - body.game.camera.x, body.position.y - body.game.camera.y, body.width, body.height);
}
else
{
context.strokeStyle = color;
context.strokeRect(body.x - body.game.camera.x, body.y - body.game.camera.y, body.width, body.height);
context.strokeRect(body.position.x - body.game.camera.x, body.position.y - body.game.camera.y, body.width, body.height);
}
}

View file

@ -606,7 +606,8 @@ Phaser.Physics.Arcade.prototype = {
*/
collideSpriteVsTilemapLayer: function (sprite, tilemapLayer, collideCallback, processCallback, callbackContext) {
this._mapData = tilemapLayer.getIntersectingTiles(sprite.body.position.x, sprite.body.position.y, sprite.body.width, sprite.body.height, sprite.body.right, sprite.body.bottom);
// this._mapData = tilemapLayer.getIntersectingTiles(sprite.body.position.x, sprite.body.position.y, sprite.body.width, sprite.body.height, sprite.body.right, sprite.body.bottom);
this._mapData = tilemapLayer.getTiles(sprite.body.position.x, sprite.body.position.y, sprite.body.width, sprite.body.height, false, true);
if (this._mapData.length === 0)
{
@ -616,6 +617,8 @@ Phaser.Physics.Arcade.prototype = {
for (var i = 0; i < this._mapData.length; i++)
{
// console.log('-------------------------------------- tile', this._mapData[i].faceLeft, this._mapData[i].faceRight, this._mapData[i].faceTop, this._mapData[i].faceBottom);
// console.log('-------------------------------------- tile', i, 'of', this._mapData.length, 'xy', this._mapData[i].x, this._mapData[i].y);
if (this.separateTile(i, sprite.body, this._mapData[i]))
{
// They collided, is there a custom process callback?
@ -743,7 +746,9 @@ Phaser.Physics.Arcade.prototype = {
}
else
{
body1.touching.none = false;
body1.touching.right = true;
body2.touching.none = false;
body2.touching.left = true;
}
}
@ -758,7 +763,9 @@ Phaser.Physics.Arcade.prototype = {
}
else
{
body1.touching.none = false;
body1.touching.left = true;
body2.touching.none = false;
body2.touching.right = true;
}
}
@ -852,7 +859,9 @@ Phaser.Physics.Arcade.prototype = {
}
else
{
body1.touching.none = false;
body1.touching.down = true;
body2.touching.none = false;
body2.touching.up = true;
}
}
@ -867,7 +876,9 @@ Phaser.Physics.Arcade.prototype = {
}
else
{
body1.touching.none = false;
body1.touching.up = true;
body2.touching.none = false;
body2.touching.down = true;
}
}
@ -1023,8 +1034,8 @@ Phaser.Physics.Arcade.prototype = {
*/
separateTile: function (i, body, tile) {
// we re-check for collision in case body was separated in a previous step
if (i > 0 && !tile.intersects(body.position.x, body.position.y, body.right, body.bottom))
// We re-check for collision in case body was separated in a previous step
if (!tile.intersects(body.position.x, body.position.y, body.right, body.bottom))
{
// no collision so bail out (separted in a previous step)
return false;
@ -1048,60 +1059,73 @@ Phaser.Physics.Arcade.prototype = {
var ox = 0;
var oy = 0;
var minX = 0;
var minY = 1;
if (tile.faceLeft || tile.faceRight)
if (body.deltaAbsX() > body.deltaAbsY())
{
if (body.deltaX() < 0 && !body.blocked.left && tile.collideRight && body.checkCollision.left)
{
// Body is moving LEFT
if (tile.faceRight && body.x < tile.right)
{
ox = body.x - tile.right;
}
}
else if (body.deltaX() > 0 && !body.blocked.right && tile.collideLeft && body.checkCollision.right)
{
// Body is moving RIGHT
if (tile.faceLeft && body.right > tile.left)
{
ox = body.right - tile.left;
}
}
if (ox !== 0)
{
this.processTileSeparationX(body, ox);
}
// That's horizontal done, check if we still intersects? If not then we can return now
if (!tile.intersects(body.position.x, body.position.y, body.right, body.bottom))
{
return (ox !== 0);
}
// Moving faster horizontally, check X axis first
minX = -1;
}
else if (body.deltaAbsX() < body.deltaAbsY())
{
// Moving faster vertically, check Y axis first
minY = -1;
}
if (tile.faceTop || tile.faceBottom)
if (body.deltaX() !== 0 && body.deltaY() !== 0 && (tile.faceLeft || tile.faceRight) && (tile.faceTop || tile.faceBottom))
{
if (body.deltaY() < 0 && !body.blocked.up && tile.collideDown && body.checkCollision.up)
{
// Body is moving UP
if (tile.faceBottom && body.y < tile.bottom)
{
oy = body.y - tile.bottom;
}
}
else if (body.deltaY() > 0 && !body.blocked.down && tile.collideUp && body.checkCollision.down)
{
// Body is moving DOWN
if (tile.faceTop && body.bottom > tile.top)
{
oy = body.bottom - tile.top;
}
}
// We only need do this if both axis have checking faces AND we're moving in both directions
minX = Math.min(Math.abs(body.position.x - tile.right), Math.abs(body.right - tile.left));
minY = Math.min(Math.abs(body.position.y - tile.bottom), Math.abs(body.bottom - tile.top));
if (oy !== 0)
// console.log('checking faces', minX, minY);
// var distLeft = Math.abs(body.position.x - tile.right);
// var distRight = Math.abs(body.right - tile.left);
// var distTop = Math.abs(body.position.y - tile.bottom);
// var distBottom = Math.abs(body.bottom - tile.top);
// minX = Math.min(distLeft, distRight);
// minY = Math.min(distTop, distBottom);
// console.log('dist left', distLeft, 'right', distRight, 'top', distTop, 'bottom', distBottom, 'minX', minX, 'minY', minY);
// console.log('tile lr', tile.left, tile.right, 'tb', tile.top, tile.bottom);
// console.log('body lr', body.x, body.right, 'tb', body.y, body.bottom);
}
if (minX < minY)
{
if (tile.faceLeft || tile.faceRight)
{
this.processTileSeparationY(body, oy);
ox = this.tileCheckX(body, tile);
// That's horizontal done, check if we still intersects? If not then we can return now
if (ox !== 0 && !tile.intersects(body.position.x, body.position.y, body.right, body.bottom))
{
return true;
}
}
if (tile.faceTop || tile.faceBottom)
{
oy = this.tileCheckY(body, tile);
}
}
else
{
if (tile.faceTop || tile.faceBottom)
{
oy = this.tileCheckY(body, tile);
// That's vertical done, check if we still intersects? If not then we can return now
if (oy !== 0 && !tile.intersects(body.position.x, body.position.y, body.right, body.bottom))
{
return true;
}
}
if (tile.faceLeft || tile.faceRight)
{
ox = this.tileCheckX(body, tile);
}
}
@ -1109,6 +1133,86 @@ Phaser.Physics.Arcade.prototype = {
},
tileCheckX: function (body, tile) {
var ox = 0;
if (body.deltaX() < 0 && !body.blocked.left && tile.collideRight && body.checkCollision.left)
{
// Body is moving LEFT
if (tile.faceRight && body.x < tile.right)
{
ox = body.x - tile.right;
if (ox < -this.OVERLAP_BIAS)
{
ox = 0;
}
}
}
else if (body.deltaX() > 0 && !body.blocked.right && tile.collideLeft && body.checkCollision.right)
{
// Body is moving RIGHT
if (tile.faceLeft && body.right > tile.left)
{
ox = body.right - tile.left;
if (ox > this.OVERLAP_BIAS)
{
ox = 0;
}
}
}
if (ox !== 0)
{
this.processTileSeparationX(body, ox);
}
return ox;
},
tileCheckY: function (body, tile) {
var oy = 0;
if (body.deltaY() < 0 && !body.blocked.up && tile.collideDown && body.checkCollision.up)
{
// Body is moving UP
if (tile.faceBottom && body.y < tile.bottom)
{
oy = body.y - tile.bottom;
if (oy < -this.OVERLAP_BIAS)
{
oy = 0;
}
}
}
else if (body.deltaY() > 0 && !body.blocked.down && tile.collideUp && body.checkCollision.down)
{
// Body is moving DOWN
if (tile.faceTop && body.bottom > tile.top)
{
oy = body.bottom - tile.top;
if (oy > this.OVERLAP_BIAS)
{
oy = 0;
}
}
}
if (oy !== 0)
{
this.processTileSeparationY(body, oy);
}
return oy;
},
/**
* Internal function to process the separation of a physics body from a tile.
* @method Phaser.Physics.Arcade#processTileSeparationX

View file

@ -244,6 +244,36 @@ Phaser.Tile.prototype = {
},
/**
* Is this tile interesting?
*
* @method Phaser.Tile#isInteresting
* @param {boolean} collides - If true will check any collides value.
* @param {boolean} faces - If true will check any face value.
* @return {boolean} True if the Tile is interesting, otherwise false.
*/
isInteresting: function (collides, faces) {
if (collides && faces)
{
// Does this tile EITHER collide OR have an interesting face?
return (this.collideLeft || this.collideRight || this.collideUp || this.collideDown || this.faceTop || this.faceBottom || this.faceLeft || this.faceRight);
}
else if (collides)
{
// Does this tile collide?
return (this.collideLeft || this.collideRight || this.collideUp || this.collideDown);
}
else if (faces)
{
// Does this tile have an interesting face?
return (this.faceTop || this.faceBottom || this.faceLeft || this.faceRight);
}
return false;
},
/**
* Copies the tile data and properties from the given tile to this tile.
*

View file

@ -541,12 +541,14 @@ Phaser.TilemapLayer.prototype.getTilesX = function (x, y, width, height, collide
* @param {number} width - Width of the area to get.
* @param {number} height - Height of the area to get.
* @param {boolean} [collides=false] - If true only return tiles that collide on one or more faces.
* @param {boolean} [interestingFace=false] - If true only return tiles that have interesting faces.
* @return {array} Array with tiles informations (each contains x, y, and the tile).
*/
Phaser.TilemapLayer.prototype.getTiles = function (x, y, width, height, collides) {
Phaser.TilemapLayer.prototype.getTiles = function (x, y, width, height, collides, interestingFace) {
// Should we only get tiles that have at least one of their collision flags set? (true = yes, false = no just get them all)
if (typeof collides === 'undefined') { collides = false; }
if (typeof interestingFace === 'undefined') { interestingFace = false; }
// adjust the x,y coordinates for scrollFactor
x = this._fixX(x);
@ -577,7 +579,7 @@ Phaser.TilemapLayer.prototype.getTiles = function (x, y, width, height, collides
{
if (this.layer.data[wy] && this.layer.data[wy][wx])
{
if (collides === false || (collides && this.layer.data[wy][wx].canCollide))
if ((!collides && !interestingFace) || this.layer.data[wy][wx].isInteresting(collides, interestingFace))
{
this._results.push(this.layer.data[wy][wx]);
}
@ -585,9 +587,6 @@ Phaser.TilemapLayer.prototype.getTiles = function (x, y, width, height, collides
}
}
// DEBUG ONLY - REMOVE
this.layer.dirty = true;
return this._results;
}