Thread: Problems with AABB Collision Detection.

  1. #1
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968

    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;}
    	}
    };
    This is my paddle class:
    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
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    I think you have that backwards -- if all four of those are true, then there is a collision.

  3. #3
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968
    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.
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

  4. #4
    Registered User
    Join Date
    Jan 2008
    Posts
    70
    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.

  5. #5
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968
    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
    Last edited by Shamino; 03-30-2009 at 12:41 PM.
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

  6. #6
    Registered User
    Join Date
    Jan 2008
    Posts
    70
    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?

  7. #7
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968
    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.
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

  8. #8
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968
    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;
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

  9. #9
    Registered User
    Join Date
    Jan 2008
    Posts
    70
    I'm still not seeing the part where it changes direction, but there is one dormant issue.
    b_min = gamePaddle.location += gamePaddle.d_min;
    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.

  10. #10
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    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.

  11. #11
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968
    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;
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Collision Detection Problems
    By Dark_Phoenix in forum Game Programming
    Replies: 1
    Last Post: 12-17-2006, 03:25 PM
  2. simple collision detection problems
    By Mr_Jack in forum Game Programming
    Replies: 0
    Last Post: 03-31-2004, 04:59 PM
  3. bounding box collision detection
    By DavidP in forum Game Programming
    Replies: 7
    Last Post: 07-07-2002, 11:43 PM
  4. Replies: 4
    Last Post: 05-03-2002, 09:40 PM
  5. Collision with quads?
    By SyntaxBubble in forum Game Programming
    Replies: 6
    Last Post: 01-18-2002, 06:17 PM