Collision Detection Help

I'm trying to create a general function for collision detection that I can use in a variety of my programs so I don't have to try to make one every time. I've already started work on it and am testing it with a program that just shows a person walking up and then down a hill, but I need help improving the function. Right now it has two major problems:
1.) It's too specific to this program. It isn't as general as I need it to be. I need a general way for checking if the two rects are close enough to even collide.
2.) It doesn't return as much info as need be. I need to from what side the objects collided.

My code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
bool Outside(SDL_Rect A, SDL_Rect B)
{
    return ( A.x + A.w <= B.x or A.x >= B.x + B.w || A.y >= B.y + B.h or A.y + A.h <= B.y );
}

//CD is short for Collision Detection
enum CD{ A_above_B = 0, A_below_B = 1, A_left_of_B = 2, A_right_of_B = 3 };

struct CD_Info
{
    bool Detected;
    SDL_Rect* A; SDL_Rect* B; ///The two colliding rects
    CD Identifier;
};

CD_Info CollisionDetection( vector<SDL_Rect> *A, vector<SDL_Rect> *B )
 {
     CD_Info Return = { false, NULL, NULL };
     for ( int MemberA = 0; MemberA < A->size(); MemberA++ )
     {
         if ( Return.Detected )
            continue;

         int TopA = (*A)[MemberA].y;
         int LeftA = (*A)[MemberA].x;
         int RightA = (*A)[MemberA].x + (*A)[MemberA].w;
         int BottomA = (*A)[MemberA].y + (*A)[MemberA].h;

         for ( int MemberB = 0; MemberB < B->size(); MemberB++ )
         {
            if ( Return.Detected )
                continue;

            int TopB = (*B)[MemberB].y;
            int LeftB = (*B)[MemberB].x;
            int RightB = (*B)[MemberB].x + (*B)[MemberB].w;
            int BottomB = (*B)[MemberB].y + (*B)[MemberB].h;
/** Wasn't working properly
            if (  TopA < BottomB and TopA > TopB )
                Return = { true, &(*A)[MemberA], &(*B)[MemberB], A_below_B };
            else if ( BottomA < BottomB and BottomA > TopB )
                Return = { true, &(*A)[MemberA], &(*B)[MemberB], A_above_B };
            else if ( LeftA > LeftB and LeftA < RightB )
                Return = { true, &(*A)[MemberA], &(*B)[MemberB], A_left_of_B };
            else if ( RightA > LeftB and RightA < RightB )
                Return = { true, &(*A)[MemberA], &(*B)[MemberB], A_right_of_B };
/**/
/**/
            if ( !Outside( (*A)[MemberA],(*B)[MemberB] ) and fabs(BottomA - BottomB) <= 4  )
                Return = { true, &(*A)[MemberA], &(*B)[MemberB], A_left_of_B /* Just a placeholder*/ };
/**/
         }
     }

     return Return;
 }


Does anyone have any ideas for improvement?
Last edited on
bump
closed account (o1vk4iN6)
Not really sure how you are suppose to know what side of two rectangles collided if they are not moving then they can only simply intersect one another and doesn't really give any information regarded to which side was hit.
Here's some pseudo-code, however, it'll only work if your rectangle class is structured in such a way that (x,y,z) is the center of the rectangle and where width, height and depth are just half-lengths.
In other words, for a 2D rectangle, the distance from the bottom right corner to the top right corner is 2*height;

Anyways, here it is, haven't tested it but it should work:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
bool isColliding(Rect r1, Rect r2, vec3& collisionVector) {
	collisionVector=vec3(0, 0, 0);
	float xIntersect = ((r1.width+r2.width)-(fabs(r1.x-r2.x)));
	float yIntersect = ((r1.height+r2.height)-(fabs(r1.y-r2.y)));
	float zIntersect = ((r1.depth+r2.depth)-(fabs(r1.z-r2.z)));

	if(xIntersect<=0) {return false;}
	if(yIntersect<=0) {return false;}
	if(zIntersect<=0) {return false;}

	if((xIntersect<=yIntersect)&&(xIntersect<=zIntersect)) {
		r1.x<r2.x?collisionVector.x-=xIntersect:collisionVector.x+=xIntersect;
	}else if((yIntersect<=xIntersect)&&(yIntersect<=zIntersect)) {
		r1.x<r2.x?collisionVector.y-=yIntersect:collisionVector.y+=yIntersect;
	}else {
		r1.z<r2.z?collisionVector.z-=zIntersect:collisionVector.z+=zIntersect;
	}
	return true;
}


You can use the collisionVector to add or subtract the... collision vector, from either colliding entity, or do whatever you want with it.
Last edited on
Thanks for the code. I think with just a few modifications it could be exactly what I need, or at least better than what I have right now.
Topic archived. No new replies allowed.