Simple SDL 2d Collision detection

I am trying to find a way to detect a collision between two sprites in a 2d SDL space shooter game. I figured if I use the height and width from the 0,0 pixel than i can map out the location of each sprite. And if they overlap in both the x and y axis, then they will set Collide to true. Does this make any sense to anyone? Here is the code I started. Something seems wrong with it. But I am just learning C++ and SDL. I don't have a whole lot of time to teach myself.
Here is the code:
Declaration in the class
1
2
3
4
5
6
7
class CEvent
{
public:
    void Collision(int Vertical_Axis_1, int Horizontal_Axis_1, int Vertical_Axis_2, int Horizontal_Axis_2);
private:
    bool Collided;
};

Definition
1
2
3
4
5
6
7
8
9
10
void CEvent::Collision(int Vertical_Axis_1, int Horizontal_Axis_1, int Vertical_Axis_2, int Horizontal_Axis_2)
{
    if(Vertical_Axis_1 >= Vertical_Axis_2 && (Vertical_Axis_1 + PLAYER_WIDTH) <= (Vertical_Axis_2 + PLAYER_WIDTH))
    {
        if(Horizontal_Axis_1 >= Horizontal_Axis_2 && (Horizontal_Axis_1 + PLAYER_HEIGHT) <= (Horizontal_Axis_2 + PLAYER_HEIGHT))
        {
            Collided = true;
        }
    }
}


I have yet to code in the variables where they need to go in the rest of my program but I don't think this will cut it. I just can't see the purpose of code clearly. It seems like a jumble of alphabet soup when I look at even my own code. Thanks for your time.
Although the algorithm as you describe it makes sense, the code doesn't seem to match it.
I think it would make more sense if you turned the class into a function and got rid of the global variables.

In order to pass the position and size of each sprite to the function, I'll create a structure:
1
2
3
4
5
struct sprite_t {
  int x, y; //Horizontal  and vertical position, respectively. I assume these refer to the upper left corner of the sprite.
  int w, h; //Width and height of sprite, respectively.
  //Pointer(s) to the images, other data about the sprite, etc...
};

To keep the following code simple, I (naively) assume that sprite_2 is the same size or larger than sprite_1. To make it detect cases where sprite_2 is smaller, run the same tests again but swap sprite_2 and sprite_1.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
bool collision(sprite_t sprite_1, sprite_t sprite_2){
  //Let's examine the x axis first:
  //If the leftmost or rightmost point of the first sprite lies somewhere inside the second, continue.
  if( (sprite_1.x >= sprite_2.x && sprite_1.x <= (sprite_2.x + sprite_2.w)) ||
      ((sprite_1.x + sprite_1.w) >= sprite_2.x && (sprite_1.x + sprite_1.w) <= (sprite_2.x + sprite_2.w)) ){
    //Now we look at the y axis:
    if( (sprite_1.y >= sprite_2.y && sprite_1.y <= (sprite_2.y + sprite_2.h)) ||
        ((sprite_1.y + sprite_1.h) >= sprite_2.y && (sprite_1.y + sprite_1.h) <= (sprite_2.y + sprite_2.h)) ){
      //The sprites appear to overlap.
      return true;
    }
  }
  //The sprites do not overlap:
  return false;
}
So what your saying is my math theory was on the right track, just incorrectly done? I think your saying I needed to move the variables to the correct spots. I'm happy to see that I was at least checking for both axis's. Or at least attempting to do so. My global variables control a number of functions in this class and are meant for more than 1 sprite. This is all being done with very little knowledge and no experience. Would this still work with multiple sprites? I'm still confused about the game loop. Perhaps you would like the working version? I would love any direction you may be willing to offer. Thank you for your response. :o)
I just made a space shooter game not too long ago, and I would like to throw my collision detection method out there.

This method is fairly simple and easy to code (<5 lines), however, it doesn't work well with rectangular objects. It works best with more square-like objects (width and height close to being equal) or circular objects. It can be used for an object of any size.

It works by calculating the straight line distance between the 2 objects being tested, then subtracts the result by the "radius" of both objects(if you had a 20x20 sprite, then the radius would be about 10). If it is <=0, there is a collision.

i.e:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class ship {
    public:
    int x, y, dir; //direction var i use
    int radius;
    }ship1, ship2;


int sqrd(int num){ //squares a number
    return (num*num);}

bool check_col(ship* s1, ship*s2){
    int dis; //distance

    dis = abs( sqrt( sqrd(s1->x - s2->x) + sqrd(s1->y - s2->y))); //include cmath
    dis -= s1->radius;
    dis -= s2->radius;

    if (dis<=0) //collision
    return true;

    //no collision
    return false;}
Last edited on
Your description of your algorithm is a bit vague, so it's hard to tell if it'll work. The only way to know for sure is to test it.

The original function that I wrote couldn't detect collisions if the second sprite was smaller than the first. I've written and tested an improved version, which fixes the problem: http://pastebin.com/TMkER9p8

If you want, I've also posted the code I used to test the function: http://pastebin.com/56QjZVmR Please note that this is C code. To compile it on a C++ compiler you'll need to remove the two defines and the typedef int bool.

I'm curious to see what you have so far, if you don't mind posting it.

As for general advice, I recommend that you design a core sprite structure/class and design your program around that. Be sure to provide a way to automatically keep track of sprites (linked list, dynamic array, etc.), so that you can render all of them with a single function call. This will give you most of what you need; to complete the main loop, just add enemy movements and user input.
Last edited on
try watching this, it should help a lot:
http://www.youtube.com/watch?v=_n2A0s6e6u0
Here is the code for the whole program as it is:

http://pastebin.com/swJZGebd

P.S. Laughs are on me. :o)
The crashing you mention on line 127 is caused by the Draw() code trying to access the sprite surface after it has been freed, which is a big no-no. You should add a variable to control the visibility of the sprite, and use the 5 key to toggle that variable. Then, only render the sprite when visible == true.

bahahha nice todo list
I've been working on this non stop for over a week. About 10-20% of it is original. The rest comes from tutorials from around the web. I took care of the crash problem. I will be moving my TODO list to my next learning project. I am not quite comfortable with a space shooter yet. I am going to dial it back a smidgen. I will post my new project and updates to the aforementioned site semi-regularly. Here's the new updated version:
http://pastebin.com/RYi1cHzt

P.S. I almost forgot to ask...Is this a valid fix for the crashing problem? The draw() is basically ignored if a variable is set to false after I hit the 5 key.
Last edited on
I'm looking at your code and saying "this is how the pros do collision detection???" Lol I don't use cmath, or any classes, I just have four+ global variables for the two sprites (eg. monsterX, monsterY and heroX, heroY), and if certain variables are equal, or close enough, then return true... why do you guys make it so complicated on yourselves :P
@desoxena:
Global variables? No classes? Sounds highly disorganized, messy and inefficient. Classes are ways of grouping variables and methods (functions) in logical ways. Also, my way is no more complicated than yours, it just utilizes the more advanced features of C++ and has a formula using functions from cmath.
@lare26:
That looks perfectly valid.
I appreciate all your help. With the information given, I can further my research on efficient collision detection. I will be putting my source code on a free web site to save space on forums, from now on. Again, I appreciate all of you help. :o) Message me if you want credit for my continued c++ education. LOL
Topic archived. No new replies allowed.