# Problems with AABB Collision Detection.

• 03-30-2009
Shamino
Problems with AABB Collision Detection.
Hey everyone I just recently learned the mechanics of AABB collision detection. I have a problem where it seems to be that my collision detection function doesn't seem to detect the thing it was designed to (with the help of a friend).
I expect a true for no collision and a false for a collision, I think this is true?

Code:

```#include "vector2.h" bool collision2d(vector2 a_min, vector2 a_max, vector2 b_min, vector2 b_max) {         return (a_min.x <= b_max.x) && (a_min.y <= b_max.y) && (a_max.x >= b_min.x) && (a_max.y >= b_min.y);}```
This is where I use the function:
Code:

```#include "Paddle.h" #include "Ball.h" #include "Collision2d.h" #include "vector2.h" Paddle paddle1, paddle2; Ball ball; class Mechanics { public:         void move_paddle(vector2 direction, Paddle & gamePaddle){gamePaddle.location += direction;}         void check_and_set_ball(Ball & gameBall, Paddle & gamePaddle)         {                 if (collision2d(gameBall.d_min, gameBall.d_max, gamePaddle.d_min, gamePaddle.d_max))                 {                         ball.location += moveRight;                 }                 else{ball.location += moveLeft;}         } };```
Code:

```#include "vector2.h" class Paddle { public:         vector2 location;         vector2 d_min;         vector2 d_max;                 Paddle()         {                 location.x = 10;                 location.y = 0;                 d_min.x = -1;                 d_min.y = -5;                 d_max.x = 1;                 d_max.y = 5;         }         const vector2 & get_position() const { return location; }         void draw(vector2 vec)         {                 glPushMatrix();                 glTranslatef(vec.x,vec.y,-100.0f);                 glBegin(GL_QUADS);                                                // Start Drawing Quads                         glVertex3f( d_min.x, d_min.y,  1.0f);        // Bottom Left Of The Texture and Quad                         glVertex3f( d_max.x, d_min.y,  1.0f);        // Bottom Right Of The Texture and Quad                         glVertex3f( d_max.x, d_max.y,  1.0f);        // Top Right Of The Texture and Quad                         glVertex3f(        d_min.x, d_max.y,  1.0f);        // Top Left Of The Texture and Quad                 glEnd();                 glPopMatrix();         } };```
And this is my ball
Code:

```#include "vector2.h" class Ball { public:         vector2 location;         vector2 d_min;         vector2 d_max;         Ball()         {                 location.x = 0;                 location.y = 0;                 d_min.x = -1;                 d_min.y = -1;                 d_max.x = 1;                 d_max.y = 1;         }         void draw(vector2 vec)         {                 glPushMatrix();                 glTranslatef(vec.x,vec.y,-50.0f);                 glBegin(GL_QUADS);                                                // Start Drawing Quads                         glVertex3f(-1.0f, -1.0f,  1.0f);        // Bottom Left Of The Texture and Quad                         glVertex3f( 1.0f, -1.0f,  1.0f);        // Bottom Right Of The Texture and Quad                         glVertex3f( 1.0f,  1.0f,  1.0f);        // Top Right Of The Texture and Quad                         glVertex3f(-1.0f,  1.0f,  1.0f);        // Top Left Of The Texture and Quad                 glEnd();                 glPopMatrix();         } };```
When I compile and run my app the ball seems to go straight through the paddle and on it's merry way off into the depths of virtual reality.

BTW I'm performing the check right here:
Code:

```        while(!done)                                                                        // Loop That Runs While done=FALSE         {                 if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))        // Is There A Message Waiting?                 {                         if (msg.message==WM_QUIT)                                // Have We Received A Quit Message?                         {                                 done=TRUE;                                                        // If So done=TRUE                         }                         else                                                                        // If Not, Deal With Window Messages                         {                                 TranslateMessage(&msg);                                // Translate The Message                                 DispatchMessage(&msg);                                // Dispatch The Message                         }                 }                 else                                                                                // If There Are No Messages                 {                         // Draw The Scene.  Watch For ESC Key And Quit Messages From DrawGLScene()                         if (active)                                                                // Program Active?                         {                                 if (keys[VK_ESCAPE])                                // Was ESC Pressed?                                 {                                         done=TRUE;                                                // ESC Signalled A Quit                                 }                                 else                                                                // Not Time To Quit, Update Screen                                 {                                         game.check_and_set_ball(ball, paddle1);                                         DrawGLScene();                                        // Draw The Scene                                         SwapBuffers(hDC);                                // Swap Buffers (Double Buffering)                                 }                         }                         if (keys[VK_F1])                                                // Is F1 Being Pressed?                         {                                 keys[VK_F1]=FALSE;                                        // If So Make Key FALSE                                 KillGLWindow();                                                // Kill Our Current Window                                 fullscreen=!fullscreen;                                // Toggle Fullscreen / Windowed Mode                                 // Recreate Our OpenGL Window                                 if (!CreateGLWindow("NeHe's OpenGL Framework",640,480,16,fullscreen))                                 {                                         return 0;                                                // Quit If Window Was Not Created                                 }                                                        }                         if (keys[VK_UP]){game.move_paddle(moveUp, paddle1);}                         if (keys[VK_DOWN]){game.move_paddle(moveDown, paddle1);}                         if (keys[VK_LEFT]){game.move_paddle(moveLeft, paddle1);}                         if (keys[VK_RIGHT]){game.move_paddle(moveRight, paddle1);}                 }         }```
Any pointers in the right direction would be appreciated :)
• 03-30-2009
tabstop
I think you have that backwards -- if all four of those are true, then there is a collision.
• 03-30-2009
Shamino
Okay, simple mistake, but it's still not functioning properly :\
Code:

```class Mechanics { public:         void move_paddle(vector2 direction, Paddle & gamePaddle){gamePaddle.location += direction;}         void check_and_set_ball(Ball & gameBall, Paddle & gamePaddle)         {                 if (collision2d(gameBall.d_min, gameBall.d_max, gamePaddle.d_min, gamePaddle.d_max))                 {ball.location += moveLeft;}                 else{ball.location += moveRight;}         }```
It appears to be moving only to the left.
• 03-30-2009
Drac
So if it is colliding it moves right, and if it isn't colliding it moves left. Unless it is colliding a lot it seems like it will be moving left most of the time.
• 03-30-2009
Shamino
I figured out my problem, I stepped through debug and found that my collision2d function is ALWAYS returning true.

Unless of course I manipulate the values of my amin/amax && bmin/bmax so that they are in no way equal to each other.

right now my collision function is checking if amin is less than bmax, as of right now these numbers are pretty much constant as amin and amax determine the dimensions of my rectangles, thus they will always return true unless I add something to their dimension information, which in this case would be the CURRENT LOCATION OF THE RECTANGLE + my amin/amax
• 03-30-2009
Drac
Oh I got my conditions flipped around didn't I, it should always be moving right. I still don't quite get the logic for check and set ball. Don't you want to change the direction of the ball upon collision?
• 03-30-2009
Shamino
yes
and it does that,

I just have a small bug where they always collide no matter what.

The collision function is just checking their dimensions purely without any translation involved so as they are they will collide no matter what.
• 03-30-2009
Shamino
FIXED: My solution in action :d
Code:

```#include "Paddle.h" #include "Ball.h" #include "Collision2d.h" #include "vector2.h" Paddle paddle1, paddle2; Ball ball; class Mechanics { public:         vector2 a_min, a_max, b_min, b_max;         Mechanics()         {                 a_min.x = 0;                 a_min.y = 0;                 a_max.x = 0;                 a_max.y = 0;                 b_min.x = 0;                 b_min.y = 0;                 b_min.x = 0;                 b_min.y = 0;         }         void move_paddle(vector2 direction, Paddle & gamePaddle){gamePaddle.location += direction;}         void check_and_set_ball(Ball & gameBall, Paddle & gamePaddle)         {                 b_min = gamePaddle.location += gamePaddle.d_min;                 b_max = gamePaddle.location += gamePaddle.d_max;                 a_min = gameBall.location += gameBall.d_min;                 a_max = gameBall.location += gameBall.d_max;                 if (collision2d(a_min, a_max, b_min, b_max))                 {ball.location += moveLeft;}                 else{ball.location += moveRight;}         } }; Mechanics game;```
• 03-30-2009
Drac
I'm still not seeing the part where it changes direction, but there is one dormant issue.
Quote:

You want to be using '+' not '+='. By using += you are changing the value of gamePaddle.location. The only reason this is working is because d_min and d_max are inverse so they cancel each other. If you change d_min to say (-1,-3) gamePaddle.location would have (0,2) added to it each time you performed this check.

Also you can move b_min, b_max, etc... to local scope.
ex.
Code:

```class Mechanics { public:                 Mechanics()         {}         void move_paddle(vector2 direction, Paddle & gamePaddle){gamePaddle.location += direction;}         void check_and_set_ball(Ball & gameBall, Paddle & gamePaddle)         {                 vector2 a_min, a_max, b_min, b_max;                 b_min = gamePaddle.location += gamePaddle.d_min;                 b_max = gamePaddle.location += gamePaddle.d_max;                 a_min = gameBall.location += gameBall.d_min;                 a_max = gameBall.location += gameBall.d_max;                 if (collision2d(a_min, a_max, b_min, b_max))                       ball.location += moveLeft;                 else ball.location += moveRight;         } };```
You want variables to be declared as close to where you use them as possible.
• 03-30-2009
VirtualAce
As long as you are checking AABB collision based on position rather than time intervals your solution will be subject to failure at high velocities. There will be a velocity at which the object in question will pass through or jump over the AABB.
• 03-30-2009
Shamino
Well, I really wanted to get a working model up, somethin' to be a little proud of y'know? Here's what I have so far.

Code:

```#include "Paddle.h" #include "Ball.h" #include "Textures.h" #include "Boundaries.h" #include "vector2.h" Paddle paddle1; Paddle paddle2; Ball ball; Boundaries border; class Mechanics { public:         Mechanics(){paddle1.location = Player_1_Start; paddle2.location = Player_2_Start;}         void move_paddle(vector2 direction, Paddle & gamePaddle){gamePaddle.location += direction;}         void check_ball_collision(){                 vector2 a_min, a_max, b_min, b_max;                 if(ball.velocity.x > 0){                         a_min = ball.location += ball.d_min;                         a_max = ball.location += ball.d_max;                         b_min = paddle1.location += paddle1.d_min;                         b_max = paddle1.location += paddle1.d_max;                         if (collision2d(a_min, a_max, b_min, b_max))                                 {reverse_velocity(ball);}                         else if(ball.location.x > 75)                                 {reverse_velocity(ball);}}                 if(ball.velocity.x < 0){                         a_min = ball.location += ball.d_min;                         a_max = ball.location += ball.d_max;                         b_min = paddle2.location += paddle2.d_min;                         b_max = paddle2.location += paddle2.d_max;                         if (collision2d(a_min, a_max, b_min, b_max))                                 {reverse_velocity(ball);}                         else if(ball.location.x < -75)                                 {reverse_velocity(ball);}}                 if(ball.velocity.y > 0){                         if (ball.location.y > 75)                                 {reverse_velocity(ball);}}                 if(ball.velocity.y < 0){                         if (ball.location.y < -75)                                 {reverse_velocity(ball);}}} private:                bool collision2d(vector2 & a_min, vector2 & a_max, vector2 & b_min, vector2 & b_max) {         return (a_min.x <= b_max.x) && (a_min.y <= b_max.y) && (a_max.x >= b_min.x) && (a_max.y >= b_min.y);}         void reverse_velocity(Ball & ball)         {ball.velocity *= -1;} }; Mechanics game;```