There is this strange issue with the collision in a game I am making. When the player is slightly lower than a block it is colliding with from the side, the player ends up clipping to the top of the block rather than sliding along the side of it down. Do you have an idea how to fix it?
If that description didn't help you at all you can reproduce it here (goes to the website with the game on it). (Use WASD/Space/Arrow Keys to move) To reproduce, stand on the single block and hold the right move button. You will fall off the edge, hit the side of the block, and get clipped to the top of it. You are meant to fall onto the block below instead. (The words and colors are debug info)
The code below is what handles the collision detection. If you need the rest of the code, you can view the source of the page linked above.
this.doCollision = function() {
var tx = Math.floor(this.x),
ty = Math.floor(this.y),
nx = this.x % 1,
ny = this.y % 1,
cell = this.cell = levelStorage.currentLevel.getTileAtPosition(tx, ty),
cellRight = this.cellRight = levelStorage.currentLevel.getTileAtPosition(tx + 1, ty),
cellDown = this.cellDown = levelStorage.currentLevel.getTileAtPosition(tx, ty + 1),
cellDiag = this.cellDiag = levelStorage.currentLevel.getTileAtPosition(tx + 1, ty + 1);
if(this.vy > 0) { // Ground collision
// The !cell checks return if the cell exists or not (null)
if((cellDown && !cell) || (!cellRight && cellDiag && nx)) {
this.y = ty;
this.vy = 0;
this.falling = false;
this.jumping = false;
ny = 0
}
}else
if(this.vy < 0) { // Ceiling collision
if((!cellDown && cell) || (cellRight && !cellDiag && nx)) {
this.y = ty + 1;
this.vy = 0;
cell = this.cell = cellDown;
cellRight = this.cellRight = cellDiag;
ny = 0;
}
}
if(this.vx > 0) { // Right collision
if((cellRight && !cell) || (!cellDown && cellDiag && ny)) {
this.x = tx;
this.vx = 0;
nx = 0;
}
}else
if(this.vx < 0) { // Left collision
if((!cellRight && cell) || (cellDown && !cellDiag && ny)) {
this.x = tx + 1;
this.vx = 0;
cell = this.cell = cellRight;
cellDown = this.cellDown = cellDiag;
nx = 0;
}
}
this.falling = !(cellDown || (nx && cellDiag)); // If player isn't on ground
}
}
Thanks for the help!
EDIT: I should note this also happens with the bottom of blocks as well. The same principles apply as clipping to the top, except you clip to the bottom instead.