Jump to content
  • Advertisement
Sign in to follow this  
FtG

Very unexpected solution to a strange DirectX issue

This topic is 2659 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

This solution is something i stumbled across while having an issue with a code example from JHarbour's Beginning Game Programming. I have no idea why it fixes the problem and would really like some help understanding what is going on.

The example was for a static scrolling tile map using StretchRect(), however when the program ran on my machine only the 1st indexed tile would be blitted to the top left corner of my surface and the rest would be black. The same exact code runs perfectly on my girlfriend's computer however.

I tried a few things with the help of the DirectX boards but i didn't fully understand many of the suggestions such as how to check the DirectX CAPS for limitations on my machine.

Anyways, i stumbled across the D3DXSaveSurfaceToFile() function thanks to Google and i used it to see if my surfaces were being loaded correctly. Strangely enough, as soon as i put this function into my code to test it, the program begins to work no problem. Comment the test function out and wallah the issue comes back. I solved my problem and i could easily move on to the next example in the book, but i don't feel like that would accomplish anything because i don't understand why the fix worked.

Can I please get some input as to what might be going on? Thanks a ton!!

Here's some of the code...
the D3DXSaveSurfaceToFile() fix is called right after LoadSurface() call in the BuildGameWorld() function

void DrawTile(LPDIRECT3DSURFACE9 source, // source surface image
int tilenum, // tile #
int width, // tile width
int height, // tile height
int columns, // columns of tiles
LPDIRECT3DSURFACE9 dest, // destination surface
int destx, // destination x
int desty) // destination y
{

//create a RECT to describe the source image
HRESULT result;
RECT r1;
r1.left = (tilenum % columns) * width;
r1.top = (tilenum / columns) * height;
r1.right = r1.left + width;
r1.bottom = r1.top + height;

//set destination rect
RECT r2 = {destx,desty,destx+width,desty+height};

//draw the tile
result = d3ddev->StretchRect(source, &r1, dest, &r2, D3DTEXF_NONE);
if (result != D3D_OK)
{
MessageBox(NULL,"Error drawing the tile","Error",0);
return;
}
}





void BuildGameWorld()
{
HRESULT result;
int x, y;
LPDIRECT3DSURFACE9 tiles;

//load the bitmap image containing all the tiles
tiles = LoadSurface("groundtiles.bmp");
D3DXSaveSurfaceToFile("test.bmp", D3DXIFF_BMP, tiles, NULL, NULL);

//create the scrolling game world bitmap
result = d3ddev->CreateOffscreenPlainSurface(
GAMEWORLDWIDTH, //width of the surface
GAMEWORLDHEIGHT, //height of the surface
D3DFMT_X8R8G8B8,
D3DPOOL_DEFAULT,
&gameworld, //pointer to the surface
NULL);

if (result != D3D_OK)
{
MessageBox(NULL,"Error creating working surface!","Error",0);
return;
}

//fill the gameworld bitmap with tiles
for (y=0; y < MAPHEIGHT; y++)
for (x=0; x < MAPWIDTH; x++)
DrawTile(tiles, MAPDATA[y * MAPWIDTH + x], 64, 64, 16,
gameworld, x * 64, y * 64);

//now the tiles bitmap is no longer needed
tiles->Release();
}



LPDIRECT3DSURFACE9 LoadSurface(string filename)
{
LPDIRECT3DSURFACE9 image = NULL;

//get width and height from bitmap file
D3DXIMAGE_INFO info;
HRESULT result = D3DXGetImageInfoFromFile(filename.c_str(), &info);
if (result != D3D_OK)
return NULL;

//create surface
result = d3ddev->CreateOffscreenPlainSurface(
info.Width, //width of the surface
info.Height, //height of the surface
D3DFMT_X8R8G8B8, //surface format
D3DPOOL_DEFAULT, //memory pool to use
&image, //pointer to the surface
NULL); //reserved (always NULL)

if (result != D3D_OK) return NULL;

//load surface from file into newly created surface
result = D3DXLoadSurfaceFromFile(
image, //destination surface
NULL, //destination palette
NULL, //destination rectangle
filename.c_str(), //source filename
NULL, //source rectangle
D3DX_DEFAULT, //controls how image is filtered
D3DCOLOR_XRGB(0,0,0), //for transparency (0 for none)
NULL); //source image info (usually NULL)

//make sure file was loaded okay
if (result != D3D_OK) return NULL;

return image;
}

Share this post


Link to post
Share on other sites
Advertisement

Strangely enough, as soon as i put this function into my code to test it, the program begins to work no problem. Comment the test function out and wallah the issue comes back.

Off the bat, this always suggests me of using uninitialized variable. Symptoms are:
- Program works and crashes randomly when you modify it.
- Program works and crashes randomly in different computers.
- Program works and crashes randomly with different project settings (release, debug)
- Program works and crashes randomly if you launch it in IDE or normally from disk.
- Program works and crashes randomly if you reboot.
Or maybe even writing in memory you should not write to. Sorry haven't checked the code yet :)

Share this post


Link to post
Share on other sites
My hunch is on MAPDATA array being all 0 for the bugged run. That would make it draw only top left tile.

Share this post


Link to post
Share on other sites

My hunch is on MAPDATA array being all 0 for the bugged run. That would make it draw only top left tile.




when the MAPDATA array is filled with 0s, or even just a single 0 the program will print the 0 tile in every position. The bugged run will only print the 0 tile once in the top left while the rest of the surface is black.

I don't understand how inserting D3DXSaveSurfaceToFile("test.bmp", D3DXIFF_BMP, tiles, NULL, NULL); into my code would change the MAPDATA array. : \

Share this post


Link to post
Share on other sites
could it be that directx is not finished uploading or rendering before you do stuff with the data?
ie. are you deallocating data being uploaded before its finished?
that would account for randomly working, etc.
a simple test would be to start another game up in windowed mode, and let it consume most of your resources
then start your game, if it fails _all the time_ then it should be obvious
im assuming the saving to file means directx will wait for an operation to complete before it can continue

Share this post


Link to post
Share on other sites

could it be that directx is not finished uploading or rendering before you do stuff with the data?
ie. are you deallocating data being uploaded before its finished?
that would account for randomly working, etc.
a simple test would be to start another game up in windowed mode, and let it consume most of your resources
then start your game, if it fails _all the time_ then it should be obvious
im assuming the saving to file means directx will wait for an operation to complete before it can continue


it's not really random though. It works ALL THE TIME on the 2nd computer and NEVER on the 1st unless i insert the save to file function.

Wouldn't testing for D3D_OK after loading/rendering etc. determine whether or not DX was finished?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!