Walls and Collision Detection
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?
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.
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.
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]
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:
But it isn't working!
[Edited by - deathknight2005 on November 25, 2006 9:40:03 PM]
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
Popular Topics
Advertisement