Box platform collision

I'm working on a platform game and my collision code is to picky. I can't exactly do aabb(?) because the map is represented as metatiles. (23-24 16x16 tiles make up a 300ish pixel resolution.) My game thus far simply takes the player's x/y coords and divides them by 16 to check the current tile the player is in. Thus far the only thing I have managed is a very picky collision by simply checking the divided values against weather the tile in the map is solid or not and setting a bool to the player being blocked in that direction. It works, but not solid as the x and y velocity of the player changes so much the hit point of the collision does as well. For example going left at a small speed seems pixel perfect yet full speed results in the collision taking place 5 pixels before the actual collision.

Can anyone point me in the right direction on this?

• If you really want good collisions in 2d use a velocity vector for you character and calculate if the player collide on the next Frame before moving it. Derivative + integration is a really good way of calculation the players next position using its velocity. Then you can look at the 9999 ways of calculating collision available from a simple google search – Antoine Apr 24 '15 at 17:38
• Game development will make you wish you had listened in those calculus classes :) – Antoine Apr 24 '15 at 17:42
• It's a simple platformer, I'm not really going for a next frame type system. I'm limiting myself to the basics so a simple explanation of the late 80s early 90s console style way of doing it would be dandy. – thatoneguy2 Apr 24 '15 at 17:46
• You won't be able to get pixel perfect collision at high speed without checking collision one frame in advance. – Antoine Apr 24 '15 at 17:50
• The velocity / integration is advanced methods but checking collision one frame in advance is kind of mandatory – Antoine Apr 24 '15 at 17:52

Here is what I usually use.

I have not checked it, but I hope it does not contain any mistakes.

Yes, it's a bit complex, but it gives very nice platformer physics.

int x = /*...*/, y = /*...*/; // Player coords.
int xv = 0, yv = 0; // Player horisontal and vertical speed.

/// Returns true if left key is being held.
bool LeftKeyHold() {/*...*/}
/// Returns true if right key is being held.
bool RightKeyHold() {/*...*/}
/// Returns true if jump key is was pressed at previous tick.
bool JumpKeyPressed() {/*...*/}

/// This func tests if point at specific coords can be passed through.
bool IsSolidAt(int xpos, int ypos) {/*...*/}
// Just divide xpos and ypos by tile size and check if tile at this position
// is solid. If so, return true, else false. Don't forget to check if these
// coordinates are in correct range, and if they are not, return false.
// (Or true if you want solid map border.)

/// This func tests if player would be inside a wall at specific location
bool IsPosSolidForPlayer(int xpos, int ypos)
{
return IsSolidAt(xpos - 5, ypos - 5) ||
IsSolidAt(xpos + 5, ypos - 5) ||
IsSolidAt(xpos + 5, ypos + 5) ||
IsSolidAt(xpos - 5, ypos + 5);
// These are "collision points" of a character. They are relative to
// player's center.
// Usually they are just corner points of a character. In this case
// character is 11x11 pixels.
// If character is larger than tile, you MUST add more points, look at
// image below.
// Distance between two nearest points MUST be smaller than tile size.
// If it is larger, add more points. Toooo many points is bad because
// it can become slow.

//     Character exapmples
//              |
//     +--------+-----+
//     |              |
//     V              |          'o's are collision points.
//                    |
// o'''o'''o          V
// :       :
// o   x   o        o'''o    #####
// :       :        : x :    ##### <-- Tile
// o...o...o        o...o    #####
//
//     ^              ^
//     |              |
//     |              +-- No extra points needed if character is small.
//     +-- Notice the extra points at sides' centers. You would need
//         more if character is bigger.
}

/* ... */

while (true) // Main loop.
{
/*...*/

yv += 1;
// Use another number if you want different gravity acceleration.
// Remove completely if you don't need gravity.
// Also modify xv if you want horisontal gravity too.
// I assume you have fixed FPS. If not, you must add 'tick delta'
// multiplied by some number instead of fixed number.

// Code below controls horisontal movement, remove if not needed.
const int movementvel = 5; // Maximum movement velocity, pixels per tick.
int hc = (RightKeyHold() - LeftKeyHold()) * 1; // Replace 1 with desired
// player acceleration or leave it as 1 if you don't care.
if (!hc)
{
// Speed at which player loses it's velocity if he is not
// controlled. You can replace 1 with any number or leave it as 1
// if you don't care.
xv -= ((xv > 0) - (xv < 0)) * 1;
}
else
{
xv += hc;
if (xv > movementvel) xv = movementvel;
else if (xv < -movementvel) xv = -movementvel;
}

// Code below controls jumps, remove if not needed.
if (JumpKeyPressed() && IsPosSolidForPlayer(x, y+1))
yv = -10; // Replace -10 with desired jump power. It should be negative.

// Code below moves player depending on his velocity. Collision is
// pixel-perfect, character can't stuck inside a wall with it.
const int maxvel = 10; // Maximum velocity, pixels per tick.
if (xv)
{
int v = xv;
if (v > 0)
{
if (v > maxvel) v = maxvel;
while (v--)
{
if (!IsPosSolidForPlayer(x+1, y))
x += 1;
else
{
xv = 0;
break;
}
}
if (v && IsPosSolidForPlayer(x+1, y)) xv = 0;
}
else
{
if (v < -maxvel) v = -maxvel;
while (v++)
{
if (!IsPosSolidForPlayer(x-1, y))
x -= 1;
else
{
xv = 0;
break;
}
}
if (v && IsPosSolidForPlayer(x-1, y)) xv = 0;
}
}
if (yv)
{
int v = yv;
if (v > 0)
{
if (v > maxvel) v = maxvel;
while (v--)
{
if (!IsPosSolidForPlayer(x, y+1))
y += 1;
else
{
yv = 0;
break;
}
}
if (v && IsPosSolidForPlayer(x, y+1)) yv = 0;
}
else
{
if (v < -maxvel) v = -maxvel;
while (v++)
{
if (!IsPosSolidForPlayer(x, y-1))
y -= 1;
else
{
yv = 0;
break;
}
}
if (v && IsPosSolidForPlayer(x, y-1)) yv = 0;
}
}

/*...*/
}