Page 1 of 2

Help with Collision

Posted: Mon Aug 23, 2010 4:10 pm
by Techtronic7
Hey guys, Im learning the basics of game making and the one thing I cant get is how one would do collision. Basically, Im just drawing two green squares in Allegro and one is controlled by the arrow keys while the other is static. Here's my code.

Code: Select all

#include <allegro.h>
#include <C:\Dev-Cpp\collfunctions.h>



int main()
{
    allegro_init();
    install_keyboard();
    set_gfx_mode( GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0 );
    set_color_depth( 16 );
    BITMAP *square = load_bitmap( "green square.bmp", NULL );
    BITMAP *buffer;
    buffer = create_bitmap( 640, 480 );
    while( !key[KEY_ESC] )
    {
           masked_blit( square, buffer, 0, 0, x, y, 130, 130 );
           masked_blit( square, buffer, 0, 0, p2x, p2y, 130, 130 );
           blit( buffer, screen, 0, 0, 0, 0, 640, 480 );
           
           
           if( key[KEY_UP] )
           {
               y--;
           }
           else if( key[KEY_DOWN] )
           {
                y++;
           }
           if( key[KEY_LEFT] )
           {
               x--;
           }
           else if( key[KEY_RIGHT] )
           {
                x++;
           }
           clear_bitmap( buffer );
           checkColl1();
           
    }
    clear_bitmap( square );
    return 0;
}
END_OF_MAIN();
I have tried for about a month now to get this to work and nothing. I also had a header file,

Code: Select all

//fuctions.h


//dynamic polygon
int x = 0;
int y = 0;
int p1trcx = 0;
int p1trcy = 0;
int p1blcx = 0;
int p1blcy = 0;
int p1brcx = 0;
int p1brcy = 0;

//static polygon
int p2x = 200;
int p2y = 200;
int p2trcx = 330;
int p2trcy = 330;
int p2blcx = 200;
int p2blcy = 30;
int p2brcx = 330;
int p2brcy = 30;
//collison boolean
bool collision = false;

int popcolllog()



int checkColl1()
{
    if( ( p1brcx > p2x ) and ( p1brcy > p2y ) )
    {
        collision = true;
    }
    else if( (p1brcx < p2x) and (p1brcy < p2y) )
    {
         collision = false;
    }
};



I havent really commented anything so sorry about that one. Oh, the collision is supposed to be edge on edge. Please put this in sorta noob terms, Im not the best. Thanks

Re: Help with Collision

Posted: Mon Aug 23, 2010 4:40 pm
by mv2112
Here is some simple collision code.

Code: Select all


int x1,y1; //player 1's x and y
int x2,y2; //player 2's x and y

int w1,h1; //player 1's width and height
int w2,h2; //player 2's width and height 

 /*
x1+w1>x2 -- if player 1's right side has a greater x value than player 2's left side
x1<x2+w2 -- if player 1's left side has a lesser x value than player 2's right side
if these two statements are true, then the rectangles collide along the x axis.
the same applies to the y axis
y1+h1>y2 -- if player 1's bottom side has a greater y value than player 2's upper side
y1<y2+h2 -- if player 1's upper side has a lesser y value than player 2's bottom side
if these to statements are true, then the rectangles collide along the y axis

if all four statements are true, then the rectangles are colliding
*/

int checkColl()
{
  if(  (x1+w1>x2 and x1<x2+w2) and (y1+h1>y2 and y1<y2+h2) )
  {
  collision=true;
  }
  else
  {
  collision=false;
  }
}
I'm pretty sure this will work, i haven't tested it so tell me if it doesn't work.

Re: Help with Collision

Posted: Mon Aug 23, 2010 4:44 pm
by GroundUpEngine
Another tip, keep the variable names simple ;)

Re: Help with Collision

Posted: Mon Aug 23, 2010 5:00 pm
by Techtronic7
Hey I tried the code and added a function to print the status of int collision and it's always set to 0. I dont think it works.

Re: Help with Collision

Posted: Mon Aug 23, 2010 5:05 pm
by mv2112
Techtronic7 wrote:Hey I tried the code and added a function to print the status of int collision and it's always set to 0. I dont think it works.
You have a boolean named collision in the header file, so i assumed thats what you were using, here, ill edit the function to return true or false on collision:

Code: Select all



int x1,y1; //player 1's x and y
int x2,y2; //player 2's x and y

int w1,h1; //player 1's width and height
int w2,h2; //player 2's width and height

/*
x1+w1>x2 -- if player 1's right side has a greater x value than player 2's left side
x1<x2+w2 -- if player 1's left side has a lesser x value than player 2's right side
if these two statements are true, then the rectangles collide along the x axis.
the same applies to the y axis
y1+h1>y2 -- if player 1's bottom side has a greater y value than player 2's upper side
y1<y2+h2 -- if player 1's upper side has a lesser y value than player 2's bottom side
if these to statements are true, then the rectangles collide along the y axis

if all four statements are true, then the rectangles are colliding
*/

bool checkColl()
{
  if(  (x1+w1>x2 and x1<x2+w2) and (y1+h1>y2 and y1<y2+h2) )
  {
  return true;
  }
  else
  {
   return false;
  }
}
True and false should still work with and integer return, So it should either print 1 or 0 now...

Re: Help with Collision

Posted: Mon Aug 23, 2010 7:18 pm
by Ginto8
well here's how I'd do AABB collision (which is pretty much what you're trying to do):

Code: Select all

inline bool colliding(Rect a,Rect b) { return !(a.x+a.w <= b.x || a.x > b.x+b.w || a.y+a.h <= b.y || a.y > b.y+b.h); }
which is probably the same as what mv put up but I'm too lazy to read his code and I'm pretty sure his isn't as concise.

However, if you're looking for OBB collision, let me tell you, that is a BITCH =P

Re: Help with Collision

Posted: Mon Aug 23, 2010 7:41 pm
by Techtronic7
So origionaly, my idea of assigning assigning values to each corner was to simulate a bounding box because I honestly had no idea what it was, other than a box that aids in collision. So I started doing that. What methods to you guys use other than what I'm doing?
This is all my code at the moment,
main.cpp:

Code: Select all

#include <allegro.h>
#include <C:\Dev-Cpp\collfunctions.h>



int main()
{
    allegro_init();
    install_keyboard();
    set_gfx_mode( GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0 );
    set_color_depth( 16 );
    BITMAP *square = load_bitmap( "green square.bmp", NULL );
    BITMAP *buffer;
    buffer = create_bitmap( 640, 480 );
    while( !key[KEY_ESC] )
    {
           masked_blit( square, buffer, 0, 0, x1, y1, 130, 130 );
           masked_blit( square, buffer, 0, 0, x2, y2, 130, 130 );
           blit( buffer, screen, 0, 0, 0, 0, 640, 480 );
           
           
           if( key[KEY_UP] )
           {
               y1--;
           }
           else if( key[KEY_DOWN] )
           {
                y1++;
           }
           if( key[KEY_LEFT] )
           {
               x1--;
           }
           else if( key[KEY_RIGHT] )
           {
                x1++;
           }
           clear_bitmap( buffer );
           checkColl();
           printcoll();
           
    }
    clear_bitmap( square );
    return 0;
}
END_OF_MAIN();
collfunctions.h:

Code: Select all

//fuctions.h
#include <iostream>

//dynamic polygon
int x1,y1; //player 1's x and y
int w1,h1; //player 1's width and height

//static polygon
int x2,y2 = 100; //player 2's x and y
int w2,h2 = 200; //player 2's width and height 

//collison boolean
bool collision = false;

int printcoll()
{
    std::cout << collision << std::endl;
};




int checkColl()
{
  if(  (x1+w1>x2 and x1<x2+w2) and (y1+h1>y2 and y1<y2+h2) )
  {
  collision=true;
  }
  else
  {
  collision=false;
  }
};



Re: Help with Collision

Posted: Mon Aug 23, 2010 7:46 pm
by GroundUpEngine
Techtronic7 wrote:So origionaly, my idea of assigning assigning values to each corner was to simulate a bounding box because I honestly had no idea what it was, other than a box that aids in collision. So I started doing that. What methods to you guys use other than what I'm doing?
Most of us I believe, use this style of collision. Which is usually called AABB collision, however I was goin to mention OBB but Ginto said it in one :lol:
EDIT: The most common reason to use this method, is simplicity and not being so taxing on the CPU.

Ginto8 wrote:However, if you're looking for OBB collision, let me tell you, that is a BITCH =P

Re: Help with Collision

Posted: Mon Aug 23, 2010 7:58 pm
by Techtronic7
AABB, ok that sounds firmiliar, but I never know that i was doing it. So with the code I've got, I have to squares sitting on the window, one moving on command, the other stationary. Oh, and a shit load of 0's. It cannot detect collision, so what is wrong with it?

Re: Help with Collision

Posted: Mon Aug 23, 2010 8:20 pm
by wearymemory
Ginto8 wrote:well here's how I'd do AABB collision (which is pretty much what you're trying to do):

Code: Select all

inline bool colliding(Rect a,Rect b) { return !(a.x+a.w <= b.x || a.x > b.x+b.w || a.y+a.h <= b.y || a.y > b.y+b.h); }
which is probably the same as what mv put up but I'm too lazy to read his code and I'm pretty sure his isn't as concise.

However, if you're looking for OBB collision, let me tell you, that is a BITCH =P
Yours is more concise in how it clearly shows the function's intent, but not as accurate due to your awkward use of relational operators. I also wonder if it's appropriate for your function to return true when pertaining to a rectangle that is empty (width and height are 0).

By using those if statements for that simple purpose, the function's intent has become more mysterious, mv2112, you should simply return the expression that is to be evaluated.

OP, are you relying on the return value of your checkColl1 function? If so, then make sure that your function returns the value most appropriate for your function. From the examples in this thread, it seems like you're not returning any value, but assigning a value to the collision variable, as mv2112 has mentioned this already.

Re: Help with Collision

Posted: Mon Aug 23, 2010 8:37 pm
by Techtronic7
OP, are you relying on the return value of your checkColl1
I changed the checkColl1() to checkColl when he did, but there are no values assigned. checkColl1 only existed because I thought i needed two checks to test for collision but I realized not and never changed it back.

Re: Help with Collision

Posted: Mon Aug 23, 2010 8:55 pm
by wearymemory
Techtronic7 wrote:
OP, are you relying on the return value of your checkColl1
there are no values assigned...

Code: Select all

int checkColl()
{
  if(  (x1+w1>x2 and x1<x2+w2) and (y1+h1>y2 and y1<y2+h2) )
  {
  collision=true;
  }
  else
  {
  collision=false; 
  }
};
In your new code, you're assigning the value true or false to your collision variable. There is one thing missing, and that is your return statement. The return type of your function is an int, so you should return one.

If you must assign a value to your collision variable, then perhaps you should do the following. It's still mv2112's code.

Code: Select all

int checkColl() {
    return (collision = (x1 + w1 > x2 and x1 < x2 + w2) and
                        (y1 + h1 > y2 and y1 < y2 + h2));
};
Note the use of the return keyword in this function. mv2112's boolean expression is evaluated, and the outcome is stored in collision, and then an integral value that represents the collision variable is returned.

Re: Help with Collision

Posted: Mon Aug 23, 2010 9:46 pm
by Techtronic7
That last one didnt work either. Could someone post a simple thing they made so I can get the whole picture?

Re: Help with Collision

Posted: Mon Aug 23, 2010 9:52 pm
by Ginto8
wearymemory wrote:
Ginto8 wrote:well here's how I'd do AABB collision (which is pretty much what you're trying to do):

Code: Select all

inline bool colliding(Rect a,Rect b) { return !(a.x+a.w <= b.x || a.x > b.x+b.w || a.y+a.h <= b.y || a.y > b.y+b.h); }
which is probably the same as what mv put up but I'm too lazy to read his code and I'm pretty sure his isn't as concise.

However, if you're looking for OBB collision, let me tell you, that is a BITCH =P
Yours is more concise in how it clearly shows the function's intent, but not as accurate due to your awkward use of relational operators. I also wonder if it's appropriate for your function to return true when pertaining to a rectangle that is empty (width and height are 0).
Please point out to me how I awkwardly used relational operators... if you mean the <= and > they make perfect sense, I was simply trying to keep all the a's on one side of the comparisons.

As for when width and height are zero, that's a fairly easy fix:

Code: Select all

inline bool colliding(Rect a,Rect b) { return a.w && a.h && b.w && b.h && !(a.x+a.w <= b.x || a.x > b.x+b.w || a.y+a.h <= b.y || a.y > b.y+b.h); }
Techtronic7 wrote:That last one didnt work either. Could someone post a simple thing they made so I can get the whole picture?
All right. AABB is an abbreviation of axis-aligned bounding box. Basically, this means that the rectangles are correctly lined up. What your collision function should do is return a bool (true or false) that tells whether two rects have collided or not. How my function (above) does it is that it does multiple checks to see if they haven't collided, and if those checks all fail, they must have collided. It is actually an application of the Separating Axis theorem, which is used in OBB, but this use is very simple.

First, we check if Rect a is to the left of Rect b (a.x+a.w <= b.x). If this is true, then they are not colliding. Then, we check if it's to the right (a.x > b.x+b.w), and if it's true they aren't colliding. And so on with the top and bottom. Now, since in an axis-aligned environment (basically, their edges are always on a perpendicular line with the x and y axes) those are the only places they can be without colliding, they must be colliding. OBB collision is basically this on a much more complex scale.

Re: Help with Collision

Posted: Mon Aug 23, 2010 10:14 pm
by wearymemory
Ginto8, I believe your function returns true when Rect a is on the right or bottom sides of Rect b, and is at most one pixel away (with no pixels in between), but if Rect a is to the left or top of Rect b, then your function only returns true if the two are intersecting.

OP, where do you initialize w1 and h1? Also, aren't you only assigning these values to the right-most variable?

Code: Select all

//dynamic polygon
int x1,y1; //player 1's x and y
int w1,h1; //player 1's width and height

//static polygon
int x2,y2 = 100; //player 2's x and y
int w2,h2 = 200; //player 2's width and height
Perhaps you should change it to this:

Code: Select all

//dynamic polygon
int x1 = 0, y1 = 0;     //player 1's x and y
int w1 = 130, h1 = 130; //player 1's width and height

//static polygon
int x2 = 100, y2 = 100; //player 2's x and y
int w2 = 130, h2 = 130; //player 2's width and height
Sometimes it's better to stick to declaring and initializing variables on separate lines. This can possibly make things easier to read and understand in the future.