Walls and Collision Detection

Started by
2 comments, last by deathknight2005 17 years, 4 months ago
I am ready to move on to the next part of my Pacman game. I want to make the walls of the labyrinth next, but I don't know what method I should use to make the walls(keeping collision detection in mind) The two methods that I think may not be the best methods to use, do if there are other methods then just let me know. 1. Having a background image with the level already on it, using it as the background and then just figuring out the positions of the walls on the picture. 2. Using primitives as the walls of the labyrinth by using a vertex buffer. Or is there some better methods to use? And also how can you make the background an image instead of a solid color with DirectX? Also what would be the most effective way of collision detection?
Advertisement
Use a 2d tile grid, mark the "wall" tiles as non walkable and don't allow the player or NPC's go thru tiles marked as non walkable, that way your levels become more flexible as well.
I agree that a 2D tile map is the simplest solution for something like Pacman.

Quote:Original post by deathknight2005
And also how can you make the background an image instead of a solid color with DirectX?


I assume since you mention vertex buffers you are using D3D. The way I did this was to create a 256x256 wraparound texture (i.e. will tessalate on all four sides seamlessly) then render a quad with texture co-ordinates greater than 1 for the background.

So for an 800x600 background, render a 1024x768 quad with texture co-ords of 4 and 3 for the x and y respectivley.

You can of course use a larger texture these days and most hardware will support it. There is always some wastage inherent in this method since the quad will almost always be larger than the screen. Worked okay though and faster than CopyRect-ing a surface onto the screen.

[EDIT] Actually, that was only really needed because I wanted a scrolling background. Really for a static background you could just dump a 800x600 (say) texture on a 1024x1024 texture then just use <1 texture co-ords to copy it to the screen. Sorry. Got a bit overcomplicated.

Quote:Original post by deathknight2005
Also what would be the most effective way of collision detection?


If you use the 2D grid as suggested, you can just divide a screen co-ord by the width and height of the tiles to find out which tile is at any given screen position. This is the basis of grid based collision detection.

[Edited by - EasilyConfused on November 24, 2006 10:16:54 AM]
Thanks a lot for the advice and I'll start working on my walls.
I have tried to render a simple rectangle in the background of my pacman without texture just to get ready but it isn't working and I get an error that says:
Unhandled exception at 0x00412627 in Pacman.exe: 0xC0000005: Access violation reading location 0xfeeefef6.
at the line SAFE_RELEASE(PacTexture);
Here is the code:
// include the basic windows header files and the Direct3D header file#include <windows.h>#include <windowsx.h>#include <d3d9.h>#include <d3dx9.h>#include <dinput.h>// define the screen resolution and keyboard macros#define SCREEN_WIDTH  640#define SCREEN_HEIGHT 480#define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)#define KEY_UP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)#define SAFE_RELEASE(n) if(n != NULL) {n->Release(); n = NULL;}#define CUSTOMFVF (D3DFVF_XYZRHW | D3DFVF_DIFFUSE) // include the Direct3D Library file#pragma comment (lib, "d3d9.lib")#pragma comment (lib, "d3dx9.lib")#pragma comment (lib, "dinput.lib")#pragma comment (lib, "dinput8.lib")#pragma comment (lib, "dxguid.lib")// global declarationsLPDIRECT3D9 d3d; // the pointer to our Direct3D interfaceLPDIRECT3DDEVICE9 d3ddev; // the pointer to the device classLPD3DXSPRITE PacSprite;LPDIRECT3DTEXTURE9 PacTexture = NULL;LPDIRECT3DTEXTURE9 BackTexture = NULL;LPDIRECT3DVERTEXBUFFER9 t_buffer = NULL;    // the pointer to the vertex bufferLPDIRECT3DSURFACE9 z_buffer = NULL;LPDIRECTINPUT8 din;    // the pointer to our DirectInput interfaceLPDIRECTINPUTDEVICE8 dinkeyboard;struct CUSTOMVERTEX {FLOAT X, Y, Z, RHW; DWORD COLOR;};FLOAT posX, posY, posZ;FLOAT speed;FLOAT sChange = 0;FLOAT sChange2 = 0;bool movingLeft, movingRight, movingUp, movingDown;bool fullscreen = true;bool firstTime = true;HWND hWnd;// function prototypesvoid initD3D(HWND hWnd); // sets up and initializes Direct3Dvoid render_frame(void); // renders a single framevoid cleanD3D(void); // closes Direct3D and releases memoryvoid initDInput(HINSTANCE hInstance, HWND hWnd);    // sets up and initializes DirectInputbool detect_keys(BYTE DIKVal);    // gets the current keys being pressedvoid cleanDInput(void);void wrapRoom();void switchMode();void setLogic(void);void movementLogic(void);void TranslationLogic(void);void switchPacPics(void);void init_graphics(void); void draw_background(void);// the WindowProc function prototypeLRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);// the entry point for any Windows programint WINAPI WinMain(HINSTANCE hInstance,                   HINSTANCE hPrevInstance,                   LPSTR lpCmdLine,                   int nCmdShow){    WNDCLASSEX wc;    ZeroMemory(&wc, sizeof(WNDCLASSEX));    wc.cbSize = sizeof(WNDCLASSEX);    wc.style = CS_HREDRAW | CS_VREDRAW;    wc.lpfnWndProc = (WNDPROC)WindowProc;    wc.hInstance = hInstance;    wc.hCursor = LoadCursor(NULL, IDC_ARROW);    // wc.hbrBackground = (HBRUSH)COLOR_WINDOW;    // not needed any more    wc.lpszClassName = L"WindowClass1";    RegisterClassEx(&wc);    hWnd = CreateWindowEx(NULL,                          L"WindowClass1",                          L"Our Direct3D Program",                          WS_EX_TOPMOST | WS_POPUP,    // fullscreen values                          0, 0,    // the starting x and y positions should be 0                          SCREEN_WIDTH, SCREEN_HEIGHT,    // set the window to 640 x 480                          NULL,                          NULL,                          hInstance,                          NULL);    ShowWindow(hWnd, nCmdShow);    // set up and initialize Direct3D    initD3D(hWnd);    initDInput(hInstance, hWnd);      // enter the main loop:    MSG msg;    while(TRUE)    {        DWORD starting_point = GetTickCount();        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))        {            if (msg.message == WM_QUIT)                break;            TranslateMessage(&msg);            DispatchMessage(&msg);        }        render_frame();        if(detect_keys(DIK_SPACE)) 			switchMode();        // check the 'escape' key        if(KEY_DOWN(VK_ESCAPE))            PostMessage(hWnd, WM_DESTROY, 0, 0);        while ((GetTickCount() - starting_point) < 25);    }    // clean up DirectX and COM    cleanD3D();    cleanDInput();    return msg.wParam;}// this is the main message handler for the programLRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){    switch(message)    {        case WM_DESTROY:            {                PostQuitMessage(0);                return 0;            } break;    }    return DefWindowProc (hWnd, message, wParam, lParam);}// this function initializes and prepares Direct3D for usevoid initD3D(HWND hWnd){    d3d = Direct3DCreate9(D3D_SDK_VERSION); // create the Direct3D interface    D3DPRESENT_PARAMETERS d3dpp; // create a struct to hold various device information    ZeroMemory(&d3dpp, sizeof(d3dpp));    // clear out the struct for use    d3dpp.Windowed = FALSE;    // program fullscreen, not windowed    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;    // discard old frames    d3dpp.hDeviceWindow = hWnd;    // set the window to be used by Direct3D    d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;    // set the back buffer format to 32-bit    d3dpp.BackBufferWidth = SCREEN_WIDTH;    // set the width of the buffer    d3dpp.BackBufferHeight = SCREEN_HEIGHT;    // set the height of the buffer    d3dpp.EnableAutoDepthStencil = TRUE;    d3dpp.AutoDepthStencilFormat = D3DFMT_D16;     // create a device class using this information and the info from the d3dpp stuct    d3d->CreateDevice(D3DADAPTER_DEFAULT,                      D3DDEVTYPE_HAL,                      hWnd,                      D3DCREATE_SOFTWARE_VERTEXPROCESSING,                      &d3dpp,                      &d3ddev);		D3DXIMAGE_INFO d3dxImageInfo;	D3DXCreateTextureFromFileEx(d3ddev, L"pacman.bmp", 		                         67, 60,								 1, 		                         D3DPOOL_DEFAULT,                                 D3DFMT_UNKNOWN,                                 D3DPOOL_DEFAULT,                                 D3DX_DEFAULT,                                 D3DX_DEFAULT,                                 D3DCOLOR_COLORVALUE(0.0f,0.0f,0.0f,1.0f),                                 &d3dxImageInfo,                                 NULL,                                 &PacTexture);    D3DXIMAGE_INFO d3dxImageInfo2;	D3DXCreateTextureFromFileEx(d3ddev, L"PacBack.bmp", 		                         640, 480,								 1, 		                         D3DPOOL_DEFAULT,                                 D3DFMT_UNKNOWN,                                 D3DPOOL_DEFAULT,                                 D3DX_DEFAULT,                                 D3DX_DEFAULT,                                 D3DCOLOR_COLORVALUE(0.0f,0.0f,0.0f,1.0f),                                 &d3dxImageInfo2,                                 NULL,                                 &BackTexture);	d3ddev->CreateDepthStencilSurface(SCREEN_WIDTH,    // the z-buffer width                                  SCREEN_HEIGHT,    // the z-buffer height                                  D3DFMT_D16,    // 16-bit pixel format for the z-buffer                                  D3DMULTISAMPLE_NONE,    // no multisampling                                  0,    // no multisampling quality                                  TRUE,    // discard old buffer data                                  &z_buffer,    // the address of the buffer                                  NULL);    // reserved...we don't use this.    d3ddev->SetRenderState(D3DRS_ZENABLE, TRUE);	 init_graphics();    	D3DXCreateSprite(d3ddev, &PacSprite);	    return;}// this is the function used to render a single framevoid render_frame(void){    // clear the window to a deep blue    d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 40, 100), 1.0f, 0);    d3ddev->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);    d3ddev->BeginScene();    // begins the 3D scene    draw_background();    PacSprite->Begin(D3DXSPRITE_ALPHABLEND);       setLogic();    switchPacPics();	movementLogic();	TranslationLogic();	D3DXVECTOR3 vPosition(posX, posY, posZ);    PacSprite->Draw(PacTexture, NULL, NULL, &vPosition, D3DCOLOR_COLORVALUE(1.0f,1.0f,1.0f,1.0f));    	PacSprite->End();           d3ddev->EndScene();    // ends the 3D scene    d3ddev->Present(NULL, NULL, NULL, NULL);   // displays the created frame on the screen    return;}// this is the function that cleans up Direct3D and COMvoid cleanD3D(void){    SAFE_RELEASE(d3ddev); // close and release the 3D device    SAFE_RELEASE(d3d); // close and release Direct3D    SAFE_RELEASE(PacSprite);		SAFE_RELEASE(PacTexture);	SAFE_RELEASE(BackTexture);	SAFE_RELEASE(z_buffer);	    return;}void initDInput(HINSTANCE hInstance, HWND hWnd){    // create the DirectInput interface    DirectInput8Create(hInstance,    // the handle to the application                       DIRECTINPUT_VERSION,    // the compatible version                       IID_IDirectInput8,    // the DirectInput interface version                       (void**)&din,    // the pointer to the interface                       NULL);    // COM stuff, so we'll set it to NULL    // create the keyboard device    din->CreateDevice(GUID_SysKeyboard,    // the default keyboard ID being used                      &dinkeyboard,    // the pointer to the device interface                      NULL);    // COM stuff, so we'll set it to NULL    dinkeyboard->SetDataFormat(&c_dfDIKeyboard); // set the data format to keyboard format    // set the control you will have over the keyboard    dinkeyboard->SetCooperativeLevel(hWnd,                                     DISCL_NONEXCLUSIVE | DISCL_BACKGROUND);      return;    // return to WinMain()}bool detect_keys(BYTE DIKVal){    static BYTE keystate[256];    // create a static storage for the key-states    dinkeyboard->Acquire();    // get access if we don't have it already    dinkeyboard->GetDeviceState(256, (LPVOID)keystate);    // fill keystate with values    return (keystate[DIKVal] & 0x80);    // if the 'A' key was pressed...}void cleanDInput(void){    dinkeyboard->Unacquire();    // make sure the keyboard is unacquired    SAFE_RELEASE(din);    // close DirectInput before exiting    return;}void switchMode(void){	if(fullscreen == true)	{PacSprite->OnLostDevice();PacTexture->Release();BackTexture->Release();D3DPRESENT_PARAMETERS d3dpp; // create a struct to hold various device information    ZeroMemory(&d3dpp, sizeof(d3dpp));    // clear out the struct for use    d3dpp.Windowed = TRUE;    // program fullscreen, not windowed    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;    // discard old frames    d3dpp.hDeviceWindow = hWnd;    // set the window to be used by Direct3D    d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;    // set the back buffer format to 32-bit    d3dpp.BackBufferWidth = SCREEN_WIDTH;    // set the width of the buffer    d3dpp.BackBufferHeight = SCREEN_HEIGHT;    // set the height of the buffer    d3dpp.EnableAutoDepthStencil = TRUE;    d3dpp.AutoDepthStencilFormat = D3DFMT_D16;	d3ddev->Reset(&d3dpp);PacSprite->OnResetDevice();D3DXIMAGE_INFO d3dxImageInfo;	D3DXCreateTextureFromFileEx(d3ddev, L"pacman.bmp", 		                         67, 60,								 1, 		                         D3DPOOL_DEFAULT,                                 D3DFMT_UNKNOWN,                                 D3DPOOL_DEFAULT,                                 D3DX_DEFAULT,                                 D3DX_DEFAULT,                                 D3DCOLOR_COLORVALUE(0.0f,0.0f,0.0f,1.0f),                                 &d3dxImageInfo,                                 NULL,                                 &PacTexture); D3DXIMAGE_INFO d3dxImageInfo2;	D3DXCreateTextureFromFileEx(d3ddev, L"PacBack.bmp", 		                         640, 480,								 1, 		                         D3DPOOL_DEFAULT,                                 D3DFMT_UNKNOWN,                                 D3DPOOL_DEFAULT,                                 D3DX_DEFAULT,                                 D3DX_DEFAULT,                                 D3DCOLOR_COLORVALUE(0.0f,0.0f,0.0f,1.0f),                                 &d3dxImageInfo2,                                 NULL,                                 &BackTexture);fullscreen = false;}	else	{PacSprite->OnLostDevice();PacTexture->Release();BackTexture->Release(); D3DPRESENT_PARAMETERS d3dpp; // create a struct to hold various device information    ZeroMemory(&d3dpp, sizeof(d3dpp));    // clear out the struct for use    d3dpp.Windowed = FALSE;    // program fullscreen, not windowed    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;    // discard old frames    d3dpp.hDeviceWindow = hWnd;    // set the window to be used by Direct3D    d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;    // set the back buffer format to 32-bit    d3dpp.BackBufferWidth = SCREEN_WIDTH;    // set the width of the buffer    d3dpp.BackBufferHeight = SCREEN_HEIGHT;    // set the height of the bufferd3ddev->Reset(&d3dpp);PacSprite->OnResetDevice();D3DXIMAGE_INFO d3dxImageInfo;	D3DXCreateTextureFromFileEx(d3ddev, L"pacman.bmp", 		                         67, 60,								 1, 		                         D3DPOOL_DEFAULT,                                 D3DFMT_UNKNOWN,                                 D3DPOOL_DEFAULT,                                 D3DX_DEFAULT,                                 D3DX_DEFAULT,                                 D3DCOLOR_COLORVALUE(0.0f,0.0f,0.0f,1.0f),                                 &d3dxImageInfo,                                 NULL,                                 &PacTexture);	 D3DXIMAGE_INFO d3dxImageInfo2;	D3DXCreateTextureFromFileEx(d3ddev, L"PacBack.bmp", 		                         640, 480,								 1, 		                         D3DPOOL_DEFAULT,                                 D3DFMT_UNKNOWN,                                 D3DPOOL_DEFAULT,                                 D3DX_DEFAULT,                                 D3DX_DEFAULT,                                 D3DCOLOR_COLORVALUE(0.0f,0.0f,0.0f,1.0f),                                 &d3dxImageInfo2,                                 NULL,                                 &BackTexture);	fullscreen = true;	}	DWORD dwstyle = fullscreen ? WS_POPUP : WS_OVERLAPPEDWINDOW;SetWindowLong(hWnd, GWL_STYLE, dwstyle);SetWindowPos(hWnd, NULL, 0, 0, 0, 0,SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);}void setLogic(void){ if (firstTime == true)	{	posX = 200.0f;	posY = 300.0f;	posZ = 1.0f;	 movingRight = false;	movingLeft = false;	movingUp = false;	movingDown = false;	firstTime = false;	speed = 3.0f;	}   if(detect_keys(DIK_LEFT))	{    movingRight = false;	movingLeft = true;	movingUp = false;	movingDown = false;    	}  else if(detect_keys(DIK_RIGHT))	{    movingRight = true;	movingLeft = false;	movingUp = false;	movingDown = false;	}  else if(detect_keys(DIK_UP))	{     movingRight = false;	movingLeft = false;	movingUp = true;	movingDown = false;	}  else if(detect_keys(DIK_DOWN))	{    movingRight = false;	movingLeft = false;	movingUp = false;	movingDown = true;	}}void movementLogic(void){if(movingRight == true)	{posX += speed;	}	else if (movingLeft == true)	{  posX -= speed;	}	else if (movingUp == true)	{    posY -= speed;	}	else if (movingDown == true)	{    posY += speed;	}	}void TranslationLogic(void){  if (posX < -70.0f)  {	posX = SCREEN_WIDTH;  }  else if (posX > SCREEN_WIDTH)  {    posX = -70.0f;  }  else if (posY < -70.0f)  {   posY = SCREEN_HEIGHT;  }  else if (posY > SCREEN_HEIGHT)  {  posY = -70.0f;  }}void switchPacPics(void){	SAFE_RELEASE(PacTexture);		if (movingRight == true)	{D3DXIMAGE_INFO d3dxImageInfo;	D3DXCreateTextureFromFileEx(d3ddev, L"pacman.bmp", 		                         67, 60,								 1, 		                         D3DPOOL_DEFAULT,                                 D3DFMT_UNKNOWN,                                 D3DPOOL_DEFAULT,                                 D3DX_DEFAULT,                                 D3DX_DEFAULT,                                 D3DCOLOR_COLORVALUE(0.0f,0.0f,0.0f,1.0f),                                 &d3dxImageInfo,                                 NULL,                                 &PacTexture);	}	else if (movingLeft == true)	{D3DXIMAGE_INFO d3dxImageInfo;	D3DXCreateTextureFromFileEx(d3ddev, L"pacman2.bmp", 		                         67, 60,								 1, 		                         D3DPOOL_DEFAULT,                                 D3DFMT_UNKNOWN,                                 D3DPOOL_DEFAULT,                                 D3DX_DEFAULT,                                 D3DX_DEFAULT,                                 D3DCOLOR_COLORVALUE(0.0f,0.0f,0.0f,1.0f),                                 &d3dxImageInfo,                                 NULL,                                 &PacTexture);	}	else if (movingUp == true)	{D3DXIMAGE_INFO d3dxImageInfo;	D3DXCreateTextureFromFileEx(d3ddev, L"pacman3.bmp", 		                         67, 60,								 1, 		                         D3DPOOL_DEFAULT,                                 D3DFMT_UNKNOWN,                                 D3DPOOL_DEFAULT,                                 D3DX_DEFAULT,                                 D3DX_DEFAULT,                                 D3DCOLOR_COLORVALUE(0.0f,0.0f,0.0f,1.0f),                                 &d3dxImageInfo,                                 NULL,                                 &PacTexture);	}	else if (movingDown == true)	{     D3DXIMAGE_INFO d3dxImageInfo;	D3DXCreateTextureFromFileEx(d3ddev, L"pacman4.bmp", 		                         67, 60,								 1, 		                         D3DPOOL_DEFAULT,                                 D3DFMT_UNKNOWN,                                 D3DPOOL_DEFAULT,                                 D3DX_DEFAULT,                                 D3DX_DEFAULT,                                 D3DCOLOR_COLORVALUE(0.0f,0.0f,0.0f,1.0f),                                 &d3dxImageInfo,                                 NULL,                                 &PacTexture);	}	else {    D3DXIMAGE_INFO d3dxImageInfo;	D3DXCreateTextureFromFileEx(d3ddev, L"pacman5.bmp", 		                         67, 60,								 1, 		                         D3DPOOL_DEFAULT,                                 D3DFMT_UNKNOWN,                                 D3DPOOL_DEFAULT,                                 D3DX_DEFAULT,                                 D3DX_DEFAULT,                                 D3DCOLOR_COLORVALUE(0.0f,0.0f,0.0f,1.0f),                                 &d3dxImageInfo,                                 NULL,                                 &PacTexture);	}}void init_graphics(void){    // create the vertices using the CUSTOMVERTEX struct    CUSTOMVERTEX t_vert[] =     {        { 0.0f, 0.0f, 2.0f, 1.0f, D3DCOLOR_XRGB(0, 0, 255), },        { 0.0f, 480.0f, 2.0f,1.0f, D3DCOLOR_XRGB(0, 255, 0), },        { 640.f, 0.0f, 2.0f,1.0f, D3DCOLOR_XRGB(255, 0, 0), },		{ 640.f, 480.0f, 2.0f,1.0f, D3DCOLOR_XRGB(255, 0, 0), },    };    // create a vertex buffer interface called t_buffer    d3ddev->CreateVertexBuffer(3*sizeof(CUSTOMVERTEX),                               0,                               CUSTOMFVF,                               D3DPOOL_MANAGED,                               &t_buffer,                               NULL);    VOID* pVoid;    // a void pointer    // lock t_buffer and load the vertices into it    t_buffer->Lock(0, 0, (void**)&pVoid, 0);    memcpy(pVoid, t_vert, sizeof(t_vert));    t_buffer->Unlock();    return;}void draw_background(void){d3ddev->SetFVF(CUSTOMFVF);d3ddev->SetStreamSource(0, t_buffer, 0, sizeof(CUSTOMVERTEX));d3ddev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);}

But it isn't working!

[Edited by - deathknight2005 on November 25, 2006 9:40:03 PM]

This topic is closed to new replies.

Advertisement