Sign in to follow this  
game mercenary

rate my collision detection system

Recommended Posts

game mercenary    102
this is for a 2d rpg I am making in SDL. I needed a way to make semi-advanced (3 pixels off max) collision detection for many maps without doing each pixel and spending days doing it with debugging. I came up with this: declarations.h
struct col
{
       bool hit;
       int xpos,ypos;
};

col maphit[159][119];
//enough to grid it every 5 pixels

int currentx,currenty;



init.h
for(loop1 = 1;loop1<79;loop1++)
{
          for(loop2=1;loop2<59;loop2++)
          {
          
                maphit[loop1][loop2].xpos = (loop1*10)+1;
                maphit[loop1][loop2].ypos = (loop2*10)+1;
                maphit[loop1][loop2].hit = false;
          }
}
}

//now assign each one (read on before commenting on this)
collisionsetup();


you.xpos = maphit[0][0].xpos;
you.ypos = maphit[0][0].ypos;
currentx = 0;
currenty = 0;



keyhandle.h
//this is calculated to do collision detection for rectangle that is about 50x40
//so it can move without the feet going through something
//this goes with the length of my sprite
    if ( keys[SDLK_UP])
    if ( !maphit[currentx][currenty-1].hit&&
    !maphit[currentx+1][currenty-1].hit &&
    !maphit[currentx+2][currenty-1].hit &&
    !maphit[currentx+3][currenty-1].hit &&
    !maphit[currentx+4][currenty-1].hit &&
    !maphit[currentx+5][currenty-1].hit 
    )
    { you.ypos =maphit[currentx][currenty-1].ypos; currenty--; dir=1; }
    
    
    if ( keys[SDLK_DOWN] )
        if ( !maphit[currentx][currenty+6].hit && 
        !maphit[currentx][currenty+6].hit && 
        !maphit[currentx+1][currenty+6].hit && 
        !maphit[currentx+2][currenty+6].hit && 
        !maphit[currentx+3][currenty+6].hit &&
        !maphit[currentx+4][currenty+6].hit )
    {you.ypos =maphit[currentx][currenty+1].ypos; currenty++; dir=2; }
    
    
    if ( keys[SDLK_LEFT] )
        if ( !maphit[currentx-1][currenty].hit &&
        !maphit[currentx-1][currenty-1].hit && 
        !maphit[currentx-1][currenty-2].hit && 
        !maphit[currentx-1][currenty-3].hit && 
        !maphit[currentx-1][currenty-4].hit &&
        !maphit[currentx-1][currenty-5].hit)
    { you.xpos =maphit[currentx-1][currenty].xpos; currentx--; dir = 3; }
    
    
    if ( keys[SDLK_RIGHT] ) 
    if ( !maphit[currentx+5][currenty].hit &&
        !maphit[currentx+5][currenty-1].hit && 
        !maphit[currentx+5][currenty-2].hit && 
        !maphit[currentx+5][currenty-3].hit && 
        !maphit[currentx+5][currenty-4].hit &&
        !maphit[currentx+4][currenty-5].hit)
    { you.xpos =maphit[currentx+1][currenty].xpos; currentx++; dir = 0; }
}



now you must be thinking, cool, but how the **** are you going to be able to find and do each 5x5 square to go with the image. simple, make an engine, this is what I added to it: at the at the end of every sucessful keypress
cout << "maphit[" <<  currentx << "] [" << currenty << "].hit = true;\n";



but now I start at 0x0 and I have to go there? how do I know when I should start? I put this at the end of the key handling file
    if(keys[SDLK_SPACE])
    {
                        flip = true;
    }
    
    if(!keys[SDLK_SPACE])
    {
                        flip = false;
    }



and in the main loop, if flip it true it doesnt flip the screen and delayes a half second (to avoid errors). so you see a red streak (i have a 5x5 pixel box) where you will bump into. when you finish just copy stdout into collisionsetup(). it takes a second at startup but it works and I can make huge maps with semi-advanced collision detection in minutes. no debugging, it is all there perfect. of course the map has to be made accordingly to, but I dont like using other peoples full maps so that is a fine thing.

Share this post


Link to post
Share on other sites
Kylotan    10013
I really don't understand what you're trying to say. A lot of that code should be moved into loops, anyway. You also shouldn't usually have code in header files, either. And usually it's easier to use rectangle intersection tests for collision detection.

Share this post


Link to post
Share on other sites
chad_420    290
I dont think very highly of it... It's only useful for your game, and even then its hardly flexible as you have hard coded values everywhere. I dont even feel like going on, I'll just end up looking lke a harsh jerk. My recomendation:
Spend more time coding and less time creating pointless threads.

Edit: I feel the need to justify myself. When I was programming in 2d awhile back when I first began tinkering with games(though I have programmed quite awhile longer) I came up with many ways to do alot of things, the old reinvent the wheel syndrome. So here I present to you an example of something I wrote I find more elegant. This is the single function that handle the bullet collision in my asteroids game, there is one of these for the player as well. And, I by no means consider this some of my best work, or really worthy of showing off I just thought That if Im going to be so harsh I should atleast be able back it up a little. For this function to work you just need a std::list of objects(the bullets in this case) that have a gpos() member that returns its position and a std::vector of objects with a bool returning Collide(vector2d).


template<typename T>
void DoBulletCollision(std::vector<T> &v, std::list<bullet> &bl, player &p)
{
std::list<bullet>::iterator bi = bl.begin();

while(bi != bl.end())
{
bool dead = false;
std::vector<T>::iterator vi = v.begin();
while(vi != v.end())
{
if(vi->collide(bi->gpos()))
{
p.score += 10;
dead = true;
}
vi++;
}

if(dead)
bi = bl.erase(bi);
else bi++;

}
}




[Edited by - chad_420 on June 4, 2005 3:46:15 PM]

Share this post


Link to post
Share on other sites
chad_420    290
No you're mistaken my template works in way dependant on what object you feed it. For example if I pass it a list of triangle object whos member function collide does pixel perfect detection then thats what it does, without changing it I can pass it an object whos collide does bounding sphere it will do that too, no change in the code at all. If you want some example of how this works I'd be glad to show.

The only limitation is that you must pass it an object that has a member call collide that takes a 2dvector and returns a bool. The method is all upto the object.

Heres is a couple example from my asteroids game...

these are two classes collide functions, suitable for my template...
both happen to use bounding circle for collision but you could put what ever code you wanted in collide() as long as it takes a 2dvector and returns a bool.
bool tri::collide(C2DVector inc)
{
C2DVector t = inc - pos;
t = t.Vabs();

switch(size)
{
case 0:
if(t.GetLength() <= 16)
{
dead = true;
return true;
}
break;
case 1:
if(t.GetLength() <= 32)
{
dead = true;
return true;
}
break;
}

return false;
}

//and another one...

bool circ::collide(C2DVector inc)
{
C2DVector t = inc - pos;

t = t.Vabs();
if(t.GetLength() <= r)
{
r-=2;
return true;
}

if(r < 10)
{
dead = true;
}
return false;
}



To use these is pretty easy load up a list of bullet(points to collide with) and a std::vector of objects. then call my template like so:

std::list<bullet> bl;
std::vector<tri> tv;
std::vector<circ> cv;

//bullet collsion
DoBulletCollision<tri>(tv,bl,p);
DoBulletCollision<circ>(cv,bl,p);

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this