Collission Detection

In deze tutorial ga ik wat uitleggen over Collission Detection. Het gaat er om dat je een beetje het idee krijgt hoe je dat kan doen en waar je op moet letten.

Allereerst laat ik je de hele source zien, dan ga ik hem kort bespreken.

// NO MFC/////////////////////////////////////

#define WIN32_LEAN_AND_MEAN

#define WINDOW_CLASS_NAME "winclass1"
#define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x08000) ? 1 : 0)

#define SCREEN_WIDTH	600
#define SCREEN_HEIGHT	600
///////////////////////////////////////////////////////

// INLUDES ////////////////////////////////////////////

#include 
#include 
#include 

//////////////////////////////////////////////////////

// GLOBALS //////////////////////////////////////////////////////////

HWND main_window_handle = NULL;
HINSTANCE main_instance = NULL;

int g_rechtx = SCREEN_WIDTH / 2;
int g_rechty = SCREEN_HEIGHT / 2;
int g_rheight = 100;
int g_rwidth = 100;

int g_cirkelx = 50;
int	g_cirkely = 50;
int g_cwidth = 30;
int g_cheight = 30;


bool exit = false;
char ErrStr[30]; // Error string kan 30 tekens bevatten
//////////////////////////////////////////////////////////////////////

// FUNCTIONS ////////////////////////////////////////////////////////

void Game_Init();
void Game_Main();
void DrawObjects();

void ErrBox( char ErrStr[30] )
{
	MessageBox(main_window_handle,ErrStr,"Error", MB_OK);
}


LRESULT CALLBACK WindowProc(HWND hwnd,
          UINT msg,
                                   WPARAM wparam,
                                    LPARAM lparam)
{
// this is the main message handler of the system
PAINTSTRUCT ps; // used in WM_PAINT
HDC hdc; // handle to a device context

// what is the message
switch(msg)
  {
  case WM_CREATE:
        {
    // do initialization stuff here

        // return success
    return(0);
    } break;

  case WM_PAINT:
    {
    // simply validate the window
    hdc = BeginPaint(hwnd,&ps);
    // you would do all your painting here
        EndPaint(hwnd,&ps);

        // return success
    return(0);
       } break;

  case WM_DESTROY:
    {
    // kill the application, this sends a WM_QUIT message
    PostQuitMessage(0);

        // return success
    return(0);
    } break;

  default:break;

    } // end switch

// process any messages that we didn't take care of
return (DefWindowProc(hwnd, msg, wparam, lparam));

} // end WinProc


////////////////////////////////////////////////////////////

// WINMAIN /////////////////////////////////////////////////

int WINAPI WinMain( HINSTANCE hinstance,
          HINSTANCE hprevinstance,
          LPSTR lpcmdline,
          int ncmdshow)
{

WNDCLASSEX winclass; // this will hold the class we create
HWND hwnd; // generic window handle
MSG msg; // generic message

// first fill in the window class stucture
winclass.cbSize = sizeof(WNDCLASSEX);
winclass.style = CS_DBLCLKS | CS_OWNDC |
                          CS_HREDRAW | CS_VREDRAW;
winclass.lpfnWndProc = WindowProc;
winclass.cbClsExtra = 0;
winclass.cbWndExtra = 0;
winclass.hInstance = hinstance;
winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
winclass.hCursor = LoadCursor(NULL, IDC_ARROW);
winclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
winclass.lpszMenuName = NULL;
winclass.lpszClassName = WINDOW_CLASS_NAME;
winclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

// register the window class
if (!RegisterClassEx(&winclass))
  return(0);

// create the window
if (!(hwnd = CreateWindowEx(NULL, // extended style
                            WINDOW_CLASS_NAME, // class
                "Collision Detection", // title
                WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                 0,0, // initial x,y
                600,600, // initial width, height
                NULL, // handle to parent
                NULL, // handle to menu
                hinstance,// instance of this application
                NULL))) // extra creation parms
return(0);

// save the handles
main_window_handle = hwnd;
main_instance = hinstance;

// begin main event loop

Game_Init();

while(exit == false)
 {
    // test if there is a message in queue, if so get it
  if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
     {
     // test if this is a quit
       if (msg.message == WM_QUIT)
           break;

     // translate any accelerator keys
     TranslateMessage(&msg);

     // send the message to the window proc
     DispatchMessage(&msg);
     } // end if

  Game_Main();
  Sleep(30);
  } // end while

// return to Windows like this
return(msg.wParam);

} // end WinMain

void Game_Init()
{
	// allereerst gaan we de rechthoeken tekenen

	 DrawObjects();

}

void DrawObjects()
{
 HDC	hdc;
 PAINTSTRUCT	ps;

 InvalidateRect(main_window_handle,NULL, FALSE);

 hdc = BeginPaint(main_window_handle, &ps);

 RECT rect = { 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT } ;
 FillRect(hdc,&rect,(HBRUSH)GetStockObject(WHITE_BRUSH));

 HPEN red_pen = CreatePen(PS_SOLID, 1, RGB(255,0,0));

 SelectObject(hdc,red_pen);

 int r_width = g_rechtx + g_rwidth;
 int r_height = g_rechty + g_rheight;

 Rectangle(hdc, g_rechtx, g_rechty, r_width, r_height);

 DeleteObject(red_pen);

	HPEN blue_pen = CreatePen(PS_SOLID, 1, RGB(0,0,255));

	SelectObject(hdc, blue_pen);

	int c_width = g_cirkelx + g_cwidth;
	int c_height = g_cirkely + g_cheight;

	Rectangle(hdc, g_cirkelx, g_cirkely, c_width, c_height);


	DeleteObject(blue_pen);

	EndPaint(main_window_handle, &ps);
}

void Game_Main()
{
	int rlijn = g_rechtx + g_rwidth; // stel rechterlijn van de rechthoek vast

	if(KEY_DOWN(VK_ESCAPE))
	{
		exit = true;
	}
	if(KEY_DOWN(VK_LEFT))
	{
		g_cirkelx -=6;

		if(g_cirkelx < 1)
		{
			g_cirkelx = 0;
		}
		else if ( (g_cirkelx < rlijn) && ( (g_cirkely + g_cheight) 
                         > g_rechty) &&  ( g_cirkely < (g_rechty + g_rheight)))
		{
			g_cirkelx = g_rechtx + g_rwidth;
		}

	}
	if(KEY_DOWN(VK_RIGHT))
	{
		g_cirkelx = g_cirkelx + 6;

		if((g_cirkelx + g_cwidth) >= SCREEN_WIDTH)
		{
			g_cirkelx = SCREEN_WIDTH - g_cwidth;
		}
		else if( (g_cirkelx + g_cwidth > g_rechtx) && ( g_cirkely > 
        		  g_rechty) && ( g_cirkely < g_rechty + g_rheight))
		{
			g_cirkelx = (g_rechtx - g_cwidth);
		}
	}
	if(KEY_DOWN(VK_UP))
	{
		g_cirkely = g_cirkely - 6;

		if( g_cirkely < 0 )
		{
			g_cirkely = 0;
		}
		else if( (g_cirkely >= g_rechty) && ( (g_cirkelx + g_cwidth) > 
			  g_rechtx) && ( g_cirkelx < (g_rechtx + g_rwidth)))
		{
			g_cirkely = g_rechty + g_rheight;
		}
	}
	if(KEY_DOWN(VK_DOWN))
	{
		g_cirkely = g_cirkely + 6;

		if( g_cirkely >= SCREEN_HEIGHT )
		{
			g_cirkely = (SCREEN_HEIGHT - g_cheight);
		}
		else if( (g_cirkely <= g_rechty) && ( g_cirkelx + g_cheight > 
			  g_rechtx) && ( g_cirkelx < g_rechtx + g_rwidth))
		{
			g_cirkely = g_rechty - g_cheight;
		}
	}

	DrawObjects();
}

Goed dit is dus de hele source voor onze tutorial. De functie waar het om gaat is DrawObjects en Game_Main(). In DrawObjects() worden de rechthoeken getekend. Ik neem aan dat je dit al snapt, zoniet stel een vraag in het forum.

Owkay, Game_Main() is de functie waar de coordinaten van de rechthoeken worden bijgewerkt. Daarnaast word er gekeken of ze niet ergens tegen opbotsen.

if(KEY_DOWN(VK_RIGHT))
	{
		g_cirkelx = g_cirkelx + 6;

		if((g_cirkelx + g_cwidth) >= SCREEN_WIDTH)
		{
			g_cirkelx = SCREEN_WIDTH - g_cwidth;
		}
		else if( (g_cirkelx + g_cwidth > g_rechtx) && ( g_cirkely > 
			  g_rechty) && ( g_cirkely < g_rechty + g_rheight))
		{
			g_cirkelx = (g_rechtx - g_cwidth);
		}
	}

Als je nu met je pijltjestoets naar rechts gaat. Dan word de rechthoek 6 pixels naar rechts getekend. Dan wordt er gekeken of hij niet buiten het scherm valt. Gebeurt dat wel, dan wordt hij tegen de rand aan getekend. Zo niet, dan gaat hij gewoon 6 pixels naar rechts.
Dan word er gekeken of hij niet tegen de rechthoek opbotsts. Zowel, dan wordt hij tegen de rand van de rechthoek aan getekend.

De else if kijkt 2 dingen na.
1. Of hij tegen de linkerkant opknalt van de rechthoek.
2. Of hij tussen de rechthoek zit, en bijvoorbeeld niet boven de rechthoek. Want dan mag hij wel gewoon naar rechts.

De rest werkt het zelfde. Als je nog wat info wil, kan je altijd vragen stellen in het forum.

Groetjes, InSiEj