I am implementing some very basic platforming physics in C++ for a simple tile-based platformer. I am following the algorithm here (https://gamedev.stackexchange.com/questions/18302/2d-platformer-collisions) as exactly as I can yet I am still getting a weird glitch where the player bounces on a tile. I’m not exactly sure what is going on. The code is in C++ using SDL
void Player::update(vector< vector<Tile> > map) {
vector<Tile> collidingTiles;
x += xVel;
y += yVel;
boundingBox = Rect(x,y,16,16);
for(int iy=0;iy<MAPH;iy++) {
for(int ix=0;ix<MAPW;ix++) {
if (map[ix][iy].solid == true) {
if (boundingBox.collide(map[ix][iy].boundingBox)) {
collidingTiles.push_back(map[ix][iy]); // store all colliding tiles, will be used later
Rect intersectingRect = map[ix][iy].boundingBox; // copy the intersecting rect
float xOffset = x-intersectingRect.x; // calculate x-axis offset
float yOffset = y-intersectingRect.y; //calculate y-axis offset
if (abs(xOffset) < abs(yOffset)) {
x += xOffset;
}
else if (abs(xOffset) > abs(yOffset)) {
y += yOffset;
}
boundingBox = Rect(x,y,16,16); // reset bounding box
yVel = 0;
}
}
}
}
if (collidingTiles.size() == 0) {
yVel += gravity;
}
};
In this code, if
abs(xOffset) == abs(yOffset), nothing happens, meaning that the player can enter a solid tile diagonally. Removing the second test should remove the issue and modifyyif the algorithm has to make a choice:Also, I’m wondering if you really want to reset the vertical velocity if a horizontal collision occurs. This also implies that gravity should still apply if the collision was horizontal (otherwise the walls and ceiling would be sticky).
If you want elastic collisions, use
yVel = -yVelinstead ofyVel = 0(and similar for the other direction). You can even doyVel = yVel * restwhererestranges from-1to0(-0.8is a good choice) to get semi-elastic collisions.