tirsdag 29. april 2014

[ SDL2 - Part 5 ] Collision detection and our first game!

Collision detection

Collision detection is one of the key aspects of game programming. For all non-rectangular objects it gets harder and harder the more accurate you want it to be. But today we're gonna continue just using rectangles. This part describes a simple algorithm to check for intersections.

After we've created a functions that does rectangle-rectangle collision detections, we'll use all of what we've learned so far and make a simple game!

Rectangle - rectangle collisions

Instead of checking if two rectangles are inside or touching each other, we're gonna check for the opposite; if they are outside of each other. The algorithm to do so consists of two steps.

  1. Find the x coordinate of the left and right and the y coordinate for top and bottom.

    Say we have two rectangles, rect1, and rect2.
    SDL_Rect rect1;
    SDL_Rect rect2;
    Finding the x/y of left/right/top/bottom is very easy.
    int left1 = rect1.x;
    int right1 = rect1.x + rect2.w;
    int top1 = rect1.y;
    int bottom1 = rect1.y + rect2.h;
    The process is exactly the same for the second rect.

  2. Use the 8 edges to check if they are not colliding

    Take a look at the below drawing

    As you can see, the red rectangle is farther to the right than the blue one. But how do can we easily check that? Simply by checking if redLeft is further to the right than blueRight. If it is ( like it is in our case ) there is no collision. Then it's just a simple matter of repeating it for the other edges. So we end up with something like this :

    SDL_Rect rect1;
    SDL_Rect rect2;

    // Find edges of rect1
    int left1 = rect1.x;
    int right1 = rect1.x + rect1.w;
    int top1 = rect1.y;
    int bottom1 = rect1.y + rect1.h;

    // Find edges of rect2
    int left2 = rect2.x;
    int right2 = rect2.x + rect2.w;
    int top2 = rect2.y;
    int bottom2 = rect2.y + rect2.h;

    // Check edges
    if ( left1 > right2 )// Left 1 is right of right 2
        return false; // No collision

    if ( right1 < left2 ) // Right 1 is left of left 2
        return false; // No collision

    if ( top1 > bottom2 ) // Top 1 is below bottom 2
        return false; // No collision

    if ( bottom1 < top2 ) // Bottom 1 is above top 2
        return false; // No collision

    // None of the above test were true, collision! return true;

The resulting function

So here's the final function for you to copy and test out.

If you want to shorten the code, you can remove the comments and replace the variables with the rect x / y / w / h values like so :

if ( rect1.x > ( rect2.x + rect2.w ) )// Left 1 is right of right 2
    return false; // No collision

I chose to not do this as the longer version is a bit easier to read and understand.

Our first game!

Our first game is of the "lead the chicken safely across the road" kind of things. Or, as in our case, "lead the square from the rectangle, past all the other square and to the other rectangle." You control the square with the arrow keys. If you hit a red square, you'll end up where you started. If you make it to the other side, you'll also end up where you started, but at least you have that tiny sense of victory for helping our poor little square!

The code just uses the different things we've learned so far, so I won't explain it other than in code comments and ( hopefully ) descriptive names.

So without further ado, here's the code :

Feel free to comment if you have anything to say or ask questions if anything is unclear. I always appreciate getting comments.

For a full list of my tutorials / posts, click here.

2 kommentarer:

  1. Hi, Great article. I believe you have made a mistake here:

    if ( top1 > bottom2 ) // Top 1 is below bottom 2
    return false; // No collision

    if ( bottom1 < top2 ) // Bottom 1 is above top 2
    return false; // No collision

    I think it should be:

    if ( top1 < bottom2 ) // Top 1 is below bottom 2
    return false; // No collision

    if ( bottom1 > top2 ) // Bottom 1 is above top
    return false; // No collision

    Am I right?

    1. Hello!

      Remember that the SDL2 coordinate system is opposite. Higher y value means further down. So the code is correct. You can also verify this by running it, you'll see that the collisions are working properly.

      By the way, this is my old blog and I don't update it anymore. Please check out my new blog : headerphile.com.