My 2D collision code does not work as expected. How do I fix it?

Posted by farmdve on Game Development See other posts from Game Development or by farmdve
Published on 2012-12-12T17:46:53Z Indexed on 2012/12/12 23:22 UTC
Read the original article Hit count: 407

I have a simple 2D game with a tile-based map. I am new to game development, I followed the LazyFoo tutorials on SDL. The tiles are in a bmp file, but each tile inside it corresponds to an internal number of the type of tile(color, or wall).

The game is simple, but the code is a lot so I can only post snippets.

 // Player moved out of the map
if((player.box.x < 0))
    player.box.x += GetVelocity(player, 0);

if((player.box.y < 0))
    player.box.y += GetVelocity(player, 1);

if((player.box.x > (LEVEL_WIDTH - DOT_WIDTH)))
    player.box.x -= GetVelocity(player, 0);

if((player.box.y > (LEVEL_HEIGHT - DOT_HEIGHT)))
    player.box.y -= GetVelocity(player, 1);     

// Now that we are here, we check for collisions
if(touches_wall(player.box))
{
    if(player.box.x < player.prev_x)
    {
        player.box.x += GetVelocity(player, 0);
    }

    if(player.box.x > player.prev_x)
    {
        player.box.x -= GetVelocity(player, 0);
    }

    if(player.box.y < player.prev_y)
    {
        player.box.y += GetVelocity(player, 1);
    }

    if(player.box.y > player.prev_y)
    {
        player.box.y -= GetVelocity(player, 1);
    }   
}


player.prev_x = player.box.x;
player.prev_y = player.box.y;

Let me explain, player is a structure with the following contents

typedef struct {
    Rectangle box; //Player position on a map(tile or whatever).
    int prev_x, prev_y; // Previous positions
    int key_press[3]; // Stores which key was pressed/released. Limited to three keys. E.g Left,right and perhaps jump if possible in 2D

    int velX, velY; // Velocity for X and Y coordinate. 

    //Health
    int health;
    bool main_character;
    uint32_t jump_ticks;
} Player;

And Rectangle is just a typedef of SDL_Rect. GetVelocity is a function that according to the second argument, returns the velocity for the X or Y axis.

This code I have basically works, however inside the if(touches_wall(player.box)) if statement, I have 4 more. These 4 if statements are responsible for detecting collision on all 4 sides(up,down,left,right). However, they also act as a block for any other movement.

Example: I move down the object and collide with the wall, as I continue to move down and still collide with the wall, I wish to move left or right, which is indeed possible(not to mention in 3D games), but remember the 4 if statements? They are preventing me from moving anywhere. The original code on the LazyFoo Productions website has no problems, but it was written in C++, so I had to rewrite most of it to work, which is probably where the problem comes from. I also use a different method of moving, than the one in the examples.

Of course, that was just an example. I wish to be able to move no matter at which wall I collide. Before this bit of code, I had another one that had more logic in there, but it was flawed.

© Game Development or respective owner

Related posts about collision-detection

Related posts about sdl