DirectX 9 teething problems

Started by
4 comments, last by chris2307 11 years, 12 months ago
Hi all,

I am attempting to learn DirectX 9 in an attempt to make a simple little 2D shooter game. I am currently trying to get a sprite on to the screen. Unfortunately, the sprite is not displayed on the screen when I run the program. When I end the program and sprite->Release() is called, I reviece an access violation exception so I am thinking that the sprite object is not being set up properly. Below is my code, can anyone see what I am doing wrong?


#include <windows.h>
#include <windowsx.h>
#include <d3d9.h>
#include <d3dx9.h>

// include the Direct3D Library file
#pragma comment (lib, "d3d9.lib")
#pragma comment (lib, "d3dx9.lib")

LPDIRECT3D9 d3d; // the pointer to our Direct3D interface
LPDIRECT3DDEVICE9 d3ddev; // the pointer to the device class
LPD3DXSPRITE d3dspt; // the pointer to our Direct3D Sprite interface
LPDIRECT3DTEXTURE9 sprite; // the pointer to the sprite

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

// define the screen resolution
#define SCREEN_WIDTH 1024
#define SCREEN_HEIGHT 768

// 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)
{
// the handle for the window, filled by a function
HWND hWnd;
// this struct holds information for the window class
WNDCLASSEX wc;

// clear out the window class for use
ZeroMemory(&wc, sizeof(WNDCLASSEX));

// fill in the struct with the needed information
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
// wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpszClassName = "WindowClass1";

// register the window class
RegisterClassEx(&wc);

// create the window and use the result as the handle
hWnd = CreateWindowEx(NULL,
"WindowClass1", // name of the window class
"Comet Blast!", // title of the window
WS_EX_TOPMOST | WS_POPUP, // fullscreen style
0, 0, // x and y position of the window
SCREEN_WIDTH, SCREEN_HEIGHT, // set window to new resolution
NULL, // we have no parent window, NULL
NULL, // we aren't using menus, NULL
hInstance, // application handle
NULL); // used with multiple windows, NULL

// display the window on the screen
ShowWindow(hWnd, nCmdShow);

//Set up Direct3D
initD3D(hWnd);

// this struct holds Windows event messages
MSG msg = {0};

// Enter the infinite message loop
while(TRUE)
{
// Check to see if any messages are waiting in the queue
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
// translate keystroke messages into the right format
TranslateMessage(&msg);
// send the message to the WindowProc function
DispatchMessage(&msg);
// check to see if it's time to quit
if(msg.message == WM_QUIT)
break;
render_frame();
}
else
{
// Run game code here
// ...
// ...
}
}

// clean up DirectX and COM
cleanD3D();
// return this part of the WM_QUIT message to Windows
return msg.wParam;
}

// this is the main message handler for the program
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
// sort through and find what code to run for the message given
switch(message)
{
// this message is read when the window is closed
case WM_DESTROY:
{
// close the application entirely
PostQuitMessage(0);
return 0;
} break;
}

// Handle any messages the switch statement didn't
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 windowed, not fullscreen
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

// create a device class using this information and information from the d3dpp stuct
d3d->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,
&d3ddev);

D3DXCreateSprite(d3ddev, &d3dspt); // create the Direct3D Sprite object
D3DXCreateTextureFromFile(d3ddev, "arrow.png", &sprite);
}

// 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->BeginScene();

// perform 3D rendering here

d3dspt->Begin(NULL); // begin sprite drawing
D3DXVECTOR3 center(0.0f, 0.0f, 0.0f); // center at the upper-left corner
D3DXVECTOR3 position(50.0f, 50.0f, 0.0f); // position at 50, 50 with no depth
d3dspt->Draw(sprite, NULL, &center, &position, D3DCOLOR_XRGB(255, 255, 255));
d3dspt->End(); // end sprite drawing

d3ddev->EndScene();
d3ddev->Present(NULL, NULL, NULL, NULL); // displays the created frame
}

// this is the function that cleans up Direct3D and COM
void cleanD3D(void)
{
sprite->Release();
d3ddev->Release(); // close and release the 3D device
d3d->Release(); // close and release Direct3D
}


Many thanks
Advertisement
You'll probably get the best help from DirectX debug runtimes, see for example http://legalizeadult...-debug-runtime/

(And you should check the return values of DirectX functions if you don't know which function works and which fails.)
I have had similar problems before i think that maybe your sprite isnt being loaded maybe the path name is wrong or the sprite is in the wrong folder.

i think this is where the problem is

D3DXCreateTextureFromFile(d3ddev, "arrow.png", &sprite);


maybe try to get the code to break at this point if it fails to load then you can see if the sprite is loaded.
The problem is that you're not checking any return values; there's any number of things that could go wrong - particularly with CreateDevice(). As thestien implied; there's a good chance that D3DXCreateTextureFromFile is failing.

this is why I really, really dislike directxtutorial.com...
To clarify a bit what are we all saying: most of the DirectX calls can fail without actually stopping your program, so you won't notice it. For example if D3DXCreateTextureFromFile fails to find the specified file/path, the debugger won't stop at the line, the code will continue as if nothing wrong happened. The function will simply return an error code (which you aren't reading at all, yet) and the resource will be "empty".
When you later try to use this empty resource, it again most probably won't stop/crash your program, you'll just get another D3D call failing silently, you'll get no rendering etc, simply some unexpected behaviour.
Of course, it can crash when you try to Release the resource, because it was never created - but this happens at the end of the code.

Enabling the DX Debug Runtimes (see my previous post) will notify you if any D3D call fails, even if you don't read the return value in your code. But you SHOULD read the return values anyway, because you won't be using Debug Runtimes all the time, they are just for debugging, after all.
Brilliant, thank you. I assumed that if a DirectX function failed, I would know about it straight away!

I shall try your suggestions and hopefully find out what is going wrong. I also have a feeling that it is D3DXCreateTextureFromFile which is failing.

This topic is closed to new replies.

Advertisement