Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I've been trying to program a tile based game, and I'm stuck at the collision detection.

Here is my code (not the best ^^):

void checkTile(Character *c, int **map)
{
     int x1,x2,y1,y2;

     /* Character position in the map */
     c->upY     = (c->y)                / TILE_SIZE; // Top left corner
     c->downY   = (c->y + c->h)         / TILE_SIZE; // Bottom left corner
     c->leftX   = (c->x)                / TILE_SIZE; // Top right corner
     c->rightX  = (c->x + c->w)         / TILE_SIZE; // Bottom right corner

     x1         = (c->x + 10)           / TILE_SIZE; // 10px from left side point
     x2         = (c->x + c->w - 10)    / TILE_SIZE; // 10px from right side point
     y1         = (c->y + 10)           / TILE_SIZE; // 10px from top side point
     y2         = (c->y + c->h - 10)    / TILE_SIZE; // 10px from bottom side point


     /* Top */
     if (map[c->upY][x1] > 2 || map[c->upY][x2] > 2)
         c->topCollision = 1;
     else c->topCollision = 0;

     /* Bottom */
     if ((map[c->downY][x1] > 2 || map[c->downY][x2] > 2))
         c->downCollision = 1;
     else c->downCollision = 0;

     /* Left */
     if (map[y1][c->leftX] > 2 || map[y2][c->leftX] > 2)
         c->leftCollision = 1;
     else c->leftCollision = 0;

     /* Right */
     if (map[y1][c->rightX] > 2 || map[y2][c->rightX] > 2)
         c->rightCollision = 1;
     else c->rightCollision = 0;
 }

That calculates 8 collision points

My moving function is like that:

 void movePlayer(Character *c, int **map)
 {
    if ((c->dirX == LEFT && !c->leftCollision) || (c->dirX == RIGHT && !c->rightCollision))
    c->x += c->vx;

    if ((c->dirY == UP && !c->topCollision) || (c->dirY == DOWN && !c->downCollision))
        c->y += c->vy;

    checkPosition(c, map);
 }

and the checkPosition:

void checkPosition(Character *c, int **map)
{
checkTile(c, map);

if (c->downCollision) {
    if (c->state != JUMPING) {
        c->vy = 0;
        c->y = (c->downY * TILE_SIZE - c->h);
    }
}

if (c->leftCollision) {
    c->vx = 0;
    c->x = (c->leftX) * TILE_SIZE + TILE_SIZE;
}

if (c->rightCollision) {
    c->vx = 0;
    c->x = c->rightX * TILE_SIZE - c->w;
}
}

This works, but sometimes, when the player is landing on ground, right and left collision points become equal to 1. So it's as if there were collision coming from left or right.

Does anyone know why this is doing this?

share|improve this question
    
As far as I can tell the problem should only be for one frame because checkTile was run before the character was moved up in checkPosition. You could run checkTile again at the end of checkPosition to prevent this. –  eBusiness Apr 9 '12 at 11:31
    
Thank you for your answer :) Running the checkTile again isn't a bad idea, I should also run it at the begining of movePlayer. Although, this hasn't fixed the problem. I tried putting a grid on the tileset, and it appears, that the character collides when he's beween 2 tiles. Weird... :S –  iNbdy Apr 9 '12 at 13:46
    
At first I thought you hadn't got any move back in place for when the character falls too far on a single tick, but I see that you have just implemented it using integer division. If the visuals confirm that the character isn't positioned lower than otherwise when this happens that wouldn't seem to be the problem. Can you get out of this lock by jumping? –  eBusiness Apr 9 '12 at 14:04
    
I'm not stuck at all, I can jump and move. The thing is that when the Character lands, there's left and right collision (not all the time), putting vx = 0 and replaces the Character either on top of the tile at his right or his left. Thank you for your answers :) –  iNbdy Apr 9 '12 at 14:08
add comment

1 Answer

up vote 0 down vote accepted

Got it, once you get the complete problem description it is elemental.

What happens is that the character end up penetrating the ground by more than 10px after landing due to the speed being greater than 10px per frame, thus causing the lower right and left collision checks to hit the ground. You do move the character up again, but you still decide to stop horizontal movement based on a collision check made before this move. You could just insert another checkTile in the middle of checkPosition.

You should also check before resetting speed to 0 that the character is actually moving in the expected direction, otherwise you can in rare cases get a situation where the character collide with and is halted by an object behind it.

Ain't you supposed to do something about roof collisions in the checkPosition code?

share|improve this answer
    
Alright, that makes sense :) Thank you very much, the problem is solved. I'll do it for the top collision, if there is one, Vy will be set to 0. –  iNbdy Apr 9 '12 at 14:47
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.