Circle - Circle Collision

Hey, im new here, just like to say hello to you all before I begin my post about code :slight_smile:

below is some basic openGl code which creates 2 circles on the screen, has them following a circluar path, im trying to get the circle - circle collision detection working (whict is almost does) and when the circles collide, i try and reverse the direction of the circles, only problem is the circles overlap each other and get stuck…ive tried everything here to get it working and the only reason i can see for it not working is the actual frame which the collision occurs…as I think both circles are trying to change directions but because they are overlapping, they cannot break free of each other, any help pls? thanks :slight_smile:

   
#include<windows.h>
#include<gl/gl.h>
#include<gl/glu.h>
#include<math.h>


bool exiting = false;
long windowWidth = 800;
long windowHeight = 600;
long windowBits = 32;
bool fullscreen = false;
HDC hDC;

#define PI 3.14159

//-------------------------------------------------------------------------------------------------//
//-------------------------------------------------------------------------------------------------//
//-------------------------------------------------------------------------------------------------//


float x_1		= 2.0; // x position of circle 1 
float x_2		= -2.0; // x position of circle 2

float y_1		= 2.0;  // y position of circle 1 
float y_2		= -2.0;  // y position of circle 2

float length	= 4;    // used to set the length of the arc the looping circles create  

float angle1	= 0.0;  // angle of first circle
float angle2	= 180.0;  // angle of second circle

float r1		= 0.5;  // radius of circle 1
float r2		= 0.5;  // radius of circle 2

float D			= 0.0; // to hold value of distance between the 2 circles centers 

bool r			= false; // boolean to see if circles have collided 


void DrawCircle(float radius, float R, float G, float B)
{
			glBegin(GL_POLYGON);
			glColor3f(R,G,B); // colour
			
				// calculate each vertex on the circle
				for (int vertex = 0; vertex < 50; vertex++)
				{
					// calculate the angle of the current vertex
					float angle = (float)vertex * (2.0f * (float)PI)/50;

					// draw the current vertex at the correct radius
					glVertex3d(cosf(angle)*radius, 0.0, sinf(angle)*radius);
				
				} // end for 
										
			glEnd();

		
} // end DrawCircle()

//-------------------------------------------------------------------------------------------------//
//-------------------------------------------------------------------------------------------------//
//-------------------------------------------------------------------------------------------------//

void SetupPixelFormat(HDC hDC)
{
	int pixelFormat;

	PIXELFORMATDESCRIPTOR pfd =
	{	
		sizeof(PIXELFORMATDESCRIPTOR),	// size
			1,							// version
			PFD_SUPPORT_OPENGL |		// OpenGL window
			PFD_DRAW_TO_WINDOW |		// render to window
			PFD_DOUBLEBUFFER,			// support double-buffering
			PFD_TYPE_RGBA,				// color type
			32,							// prefered color depth
			0, 0, 0, 0, 0, 0,			// color bits (ignored)
			0,							// no alpha buffer
			0,							// alpha bits (ignored)
			0,							// no accumulation buffer
			0, 0, 0, 0,					// accum bits (ignored)
			16,							// depth buffer
			0,							// no stencil buffer
			0,							// no auxiliary buffers
			PFD_MAIN_PLANE,				// main layer
			0,							// reserved
			0, 0, 0,					// no layer, visible, damage masks
	};

	pixelFormat = ChoosePixelFormat(hDC, &pfd);
	SetPixelFormat(hDC, pixelFormat, &pfd);
}

LRESULT CALLBACK MainWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	static HDC hDC;
	static HGLRC hRC;
	int height, width;

	// dispatch messages
	switch (uMsg)
	{	
	case WM_CREATE:			// window creation
		hDC = GetDC(hWnd);
		SetupPixelFormat(hDC);
		//SetupPalette();
		hRC = wglCreateContext(hDC);
		wglMakeCurrent(hDC, hRC);
		break;

	case WM_DESTROY:			// window destroy
	case WM_QUIT:
	case WM_CLOSE:					// windows is closing

		// deselect rendering context and delete it
		wglMakeCurrent(hDC, NULL);
		wglDeleteContext(hRC);

		// send WM_QUIT to message queue
		PostQuitMessage(0);
		break;

	case WM_SIZE:
		height = HIWORD(lParam);		// retrieve width and height
		width = LOWORD(lParam);

		break;

	case WM_ACTIVATEAPP:		// activate app
		break;

	case WM_PAINT:				// paint
		PAINTSTRUCT ps;
		BeginPaint(hWnd, &ps);
		EndPaint(hWnd, &ps);
		break;

	case WM_LBUTTONDOWN:		// left mouse button
		break;

	case WM_RBUTTONDOWN:		// right mouse button
		break;

	case WM_MOUSEMOVE:			// mouse movement
		break;

	case WM_LBUTTONUP:			// left button release
		break;

	case WM_RBUTTONUP:			// right button release
		break;

	case WM_KEYUP:
		break;

	case WM_KEYDOWN:
		int fwKeys;
		LPARAM keyData;
		fwKeys = (int)wParam;    // virtual-key code 
		keyData = lParam;          // key data 

		switch(fwKeys)
		{
		case VK_ESCAPE:
			PostQuitMessage(0);
			break;
					
		default:
			break;
		}

		break;

	default:
		break;
	}
	return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
	WNDCLASSEX windowClass;		// window class
	HWND	   hwnd;			// window handle
	MSG		   msg;				// message
	DWORD	   dwExStyle;		// Window Extended Style
	DWORD	   dwStyle;			// Window Style
	RECT	   windowRect;


	windowRect.left=(long)0;						// Set Left Value To 0
	windowRect.right=(long)windowWidth;	// Set Right Value To Requested Width
	windowRect.top=(long)0;							// Set Top Value To 0
	windowRect.bottom=(long)windowHeight;	// Set Bottom Value To Requested Height

	// fill out the window class structure
	windowClass.cbSize			= sizeof(WNDCLASSEX);
	windowClass.style			= CS_HREDRAW | CS_VREDRAW;
	windowClass.lpfnWndProc		= MainWindowProc;
	windowClass.cbClsExtra		= 0;
	windowClass.cbWndExtra		= 0;
	windowClass.hInstance		= hInstance;
	windowClass.hIcon			= LoadIcon(NULL, IDI_APPLICATION);	// default icon
	windowClass.hCursor			= LoadCursor(NULL, IDC_ARROW);		// default arrow
	windowClass.hbrBackground	= NULL;								// don't need background
	windowClass.lpszMenuName	= NULL;								// no menu
	windowClass.lpszClassName	= "GLClass";
	windowClass.hIconSm			= LoadIcon(NULL, IDI_WINLOGO);		// windows logo small icon

	

	// register the windows class
	if (!RegisterClassEx(&windowClass))
		return 0;

	if (fullscreen)								// fullscreen?
	{
		DEVMODE dmScreenSettings;					// device mode
		memset(&dmScreenSettings,0,sizeof(dmScreenSettings));
		dmScreenSettings.dmSize = sizeof(dmScreenSettings);	
		dmScreenSettings.dmPelsWidth = windowWidth;			// screen width
		dmScreenSettings.dmPelsHeight = windowHeight;			// screen height
		dmScreenSettings.dmBitsPerPel = windowBits;				// bits per pixel
		dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;

		// 
		if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
		{
			// setting display mode failed, switch to windowed
			MessageBox(NULL, "Display mode failed", NULL, MB_OK);
			fullscreen = FALSE;	
		}
	}

	if (fullscreen)								// Are We Still In Fullscreen Mode?
	{
		dwExStyle=WS_EX_APPWINDOW;					// Window Extended Style
		dwStyle=WS_POPUP;						// Windows Style
		ShowCursor(FALSE);						// Hide Mouse Pointer
	}
	else
	{
		dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;			// Window Extended Style
		dwStyle=WS_OVERLAPPEDWINDOW;					// Windows Style
	}

	AdjustWindowRectEx(&windowRect, dwStyle, FALSE, dwExStyle);		// Adjust Window To True Requested Size

	// class registered, so now create our window
	hwnd = CreateWindowEx(NULL,									// extended style
		"GLClass",							// class name
		"Circle - Circle Collision",		// app name
		dwStyle | WS_CLIPCHILDREN |
		WS_CLIPSIBLINGS,
		0, 0,								// x,y coordinate
		windowRect.right - windowRect.left,
		windowRect.bottom - windowRect.top, // width, height
		NULL,									// handle to parent
		NULL,									// handle to menu
		hInstance,							// application instance
		NULL);								// no extra params

	hDC = GetDC(hwnd);

	// check if window creation failed (hwnd would equal NULL)
	if (!hwnd)
		return 0;

	ShowWindow(hwnd, SW_SHOW);			// display the window
	UpdateWindow(hwnd);					// update the window


//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

	glViewport(0, 0, 800, 600);		// reset the viewport to new dimensions
	glMatrixMode(GL_PROJECTION);			// set projection matrix current matrix
	glLoadIdentity();						// reset projection matrix

	// calculate aspect ratio of window
	gluPerspective(52.0f,(GLfloat)800/(GLfloat)600,1.0f,1000.0f);

	glMatrixMode(GL_MODELVIEW);				// set modelview matrix
	glLoadIdentity();						// reset modelview matrix

	
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
	
	while (!exiting)
	{

//--------------------------------------------------------------------------------		
//--------------------------------------------------------------------------------


	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);		// clear screen and depth buffer
	glLoadIdentity();
	gluLookAt(0.0, 10.0, 0.1, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
	
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
	

	x_1		= cosf(angle1)*length; // assign new value to circle 1 x position
	y_1		= sinf(angle1)*length; // assign new value to circle 1 y position

	x_2		= cosf(angle2)*length; // assign new value to circle 2 x position
	y_2		= sinf(angle2)*length; // assign new value to circle 2 y position

	
	// calculate the distance between the two centers of the circles
	D = sqrt((((x_2+r2)-(x_1+r1))*((x_2+r2)-(x_1+r1))) + (((y_2+r2)-(y_1+r1))*((y_2+r2)-(y_1+r1))));
	
	// if the distance between the centers is less than the two circles
	// radii summed up - we have a collision!!
	
	if( D <= r1+r2 )
	{
		r = true;		
	}

    if( D >= r1+r2)
	{
		r = false;
	}
		
	if( r )
	{
		angle1  -= 0.05; // increment angle for circle 1 in clockwise direction
		angle2  += 0.05; // decrement angle for circle 2 in anti - clockwise direction 
	}
	
	if( !r )
	{
		angle1  += 0.05; // increment angle for circle 1 in clockwise direction
		angle2  -= 0.05; // decrement angle for circle 2 in anti - clockwise direction 
	}
	
//--------------------------------------------------------------------------------
//-------------------------------- CIRCLE 1---------------------------------------

	// push matrix onto the stack
	glPushMatrix();
	
	// create new x and y position for circle 1
	glTranslatef(x_1, 0, y_1);
	
	// call circle function to draw it
	DrawCircle(r1, 255, 0, 0);
	
	// pop matrix off the stack
	glPopMatrix();

//--------------------------------------------------------------------------------
//--------------------------------- CIRCLE 2--------------------------------------


	// push matrix onto the stack
	glPushMatrix();
	
	// create new x and y position for circle 2
	glTranslatef(x_2, 0, y_2);
	
	// call circle function to draw it
	DrawCircle(r2, 0, 0, 255);
	
	// pop matrix off the stack
	glPopMatrix();

		
//--------------------------------------------------------------------------------
//------------------------------------------------------------------------------

	
	

	
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

		SwapBuffers(hDC);

		while (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
		{
			if (!GetMessage (&msg, NULL, 0, 0))
			{
				exiting = true;
				break;
			}

			TranslateMessage (&msg);
			DispatchMessage (&msg);
		}
	}

	

	if (fullscreen)
	{
		ChangeDisplaySettings(NULL,0);					// If So Switch Back To The Desktop
		ShowCursor(TRUE);						// Show Mouse Pointer
	}

	return (int)msg.wParam;
}

Originally posted by johnnyp05:
[b]

// calculate the distance between the two centers of the circles
D = sqrt((((x_2+r2)-(x_1+r1))*((x_2+r2)-(x_1+r1))) + (((y_2+r2)-(y_1+r1))*((y_2+r2)-(y_1+r1))));

[/b]
Why are you including the radii when you want the distance of the centers? This should be

D = sqrt((x_2-x_1)*(x_2-x_1) + (y_2-y_1)*(y_2-y_1));

To your original problem: You are reversing the movement of your circles as long as there is a collision. Which means that, as soon as the collision is resolved, you go back to the original movement, which brings you right back to your collision.

Try something like

if( D <= r1+r2 )
{
  r = !r
}

Aaaah thanks, I feel such a n00b :rolleyes: they reverse directions when they collide now.

Yea i know what the distance formula is originally, its just they’d overlap each other if i dont add the radius to the formula, therefore i get an edge to edge collision, not a center to center collision - it was just trying stuff to see what happened, and that worked, dunno why, wierd huh? funnily enough i dont need to add the radius to it now to get edge/edge collision, man…this is wierd…pff who’d be a programmer :slight_smile: thanks for help, although its kinda embrassing needing help on something that simple, should have guessed that straight away, doh! :mad: