Sign in to follow this  
deathknight2005

Walls and Collision Detection

Recommended Posts

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?

Share this post


Link to post
Share on other sites
Aardvajk    13207
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]

Share this post


Link to post
Share on other sites
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 declarations
LPDIRECT3D9 d3d; // the pointer to our Direct3D interface
LPDIRECT3DDEVICE9 d3ddev; // the pointer to the device class
LPD3DXSPRITE PacSprite;
LPDIRECT3DTEXTURE9 PacTexture = NULL;
LPDIRECT3DTEXTURE9 BackTexture = NULL;
LPDIRECT3DVERTEXBUFFER9 t_buffer = NULL; // the pointer to the vertex buffer
LPDIRECT3DSURFACE9 z_buffer = NULL;
LPDIRECTINPUT8 din; // the pointer to our DirectInput interface
LPDIRECTINPUTDEVICE8 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 prototypes
void initD3D(HWND hWnd); // sets up and initializes Direct3D
void render_frame(void); // renders a single frame
void cleanD3D(void); // closes Direct3D and releases memory
void initDInput(HINSTANCE hInstance, HWND hWnd); // sets up and initializes DirectInput
bool detect_keys(BYTE DIKVal); // gets the current keys being pressed
void 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 prototype
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);


// the entry point for any Windows program
int 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 program
LRESULT 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 use
void 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 frame
void 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 COM
void 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 buffer
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 = 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]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this