Original Post
I have tried to get a little 32x32 bitmap to bounce around the screen but have failed miserably. I took several months off of the project to see if I could see what''s wron later. I revised some points, but It still doesn''t work. My window only takes over half the screen, and I get this weird error:
WindowClassFirst-chance exception in BlitMove.exe (DDRAW.DLL): 0xC0000005: Access Violation.
Here is the code for it, it may be a bit long, but you need to see all of it to understand it. Try compiling it. The problem will not go away! What am I doing wrong?
#define WIN32_LEAN_AND_MEAN
//include important stuff
#include
#include
#include
#include
#include
//#include "Blitex.h"
#define Rgb16Bit565(r,g,b) ((b%32) + ((g%64) << 6) + ((r%32) << 11))
#define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEYUP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)
int GameInit();
int GameMain();
int GameEnd();
int MoverDif;
int gameloop;
HWND main_window_handle = NULL;
HINSTANCE hinstance_app = NULL;
//declarations
struct Mover
{
int bitheight;
int bitwidth;
int velocityx;
int velocityy;
RECT mover;
}MOVER;
Mover Mover1;
BOOL LoadBMP(LPDIRECTDRAWSURFACE4 surface,
LPSTR filename);
HWND window_handle = NULL;
HINSTANCE instance = NULL;
LPDIRECTDRAW lpdd = NULL;
LPDIRECTDRAW4 lpdd4 = NULL;
LPDIRECTDRAWSURFACE4 pbuff = NULL;
LPDIRECTDRAWSURFACE4 bbuff = NULL;
LPDIRECTDRAWSURFACE4 Bitmap = NULL;
DDSURFACEDESC2 ddsd;
DDSCAPS2 ddscaps;
LRESULT CALLBACK WindowProc(HWND hwnd,
UINT msg,
WPARAM wparam,
LPARAM lparam)
{
// this is the main message handler of the system
PAINTSTRUCT ps; // used in WM_PAINT
HDC hdc; // handle to a device context // used to print strings
// what is the message
switch(msg)
{
case WM_CREATE:
{
// do initialization stuff here
// return success
return(0);
} break;
case WM_PAINT:
{
// simply validate the window
hdc = BeginPaint(hwnd,&ps);
// end painting
EndPaint(hwnd,&ps);
// return success
return(0);
} break;
case WM_DESTROY:
{
// kill the application, this sends a WM_QUIT message
PostQuitMessage(0);
// return success
return(0);
} break;
default:break;
} // end switch
// process any messages that we didn''t take care of
return (DefWindowProc(hwnd, msg, wparam, lparam));
} // end WinProc
int WINAPI WinMain( HINSTANCE hinstance,
HINSTANCE hprevinstance,
LPSTR lpcmdline,
int ncmdshow)
{
WNDCLASSEX winclass; // this will hold the class we create
HWND hwnd; // generic window handle
MSG msg; // generic message
HDC hdc; // graphics device context
// first fill in the window class stucture
winclass.cbSize = sizeof(WNDCLASSEX);
winclass.style = CS_DBLCLKS / CS_OWNDC /
CS_HREDRAW / CS_VREDRAW;
winclass.lpfnWndProc = WindowProc;
winclass.cbClsExtra = 0;
winclass.cbWndExtra = 0;
winclass.hInstance = hinstance;
winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
winclass.hCursor = LoadCursor(NULL, IDC_ARROW);
winclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
winclass.lpszMenuName = NULL;
winclass.lpszClassName = "WindowClass";
winclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
// save hinstance in global
hinstance_app = hinstance;
// register the window class
if (!RegisterClassEx(&winclass))
return(0);
// create the window
if (!(hwnd = CreateWindowEx(NULL, // extended style
"WindowClass", // class
"Mover", // title
WS_POPUP / WS_VISIBLE,
0,0, // initial x,y
640,480, // initial width, height
NULL, // handle to parent
NULL, // handle to menu
hinstance,// instance of this application
NULL))) // extra creation parms
return(0);
// save main window handle
main_window_handle = hwnd;
// initialize game here
GameInit();
// enter main event loop
while(TRUE)
{
// test if there is a message in queue, if so get it
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
// test if this is a quit
if (msg.message == WM_QUIT)
break;
// translate any accelerator keys
TranslateMessage(&msg);
// send the message to the window proc
DispatchMessage(&msg);
} // end if
// main game processing goes here
GameMain();
} // end while
// closedown game here
GameEnd();
// return to Windows like this
return(msg.wParam);
} // end WinMain
///////////////////////////////////////////////////////////
int GameInit()
{
if(FAILED(DirectDrawCreate(NULL, &lpdd, NULL)))
return(0);
//query the interface
if(FAILED(lpdd->QueryInterface(IID_IDirectDraw4, (LPVOID*)lpdd4)))
return(0);
//now that we''re done with the object,
//we can release it
lpdd->Release();
lpdd = NULL;
//set the cooperative mode for the new object
if(FAILED(lpdd4->SetCooperativeLevel(main_window_handle,
DDSCL_ALLOWREBOOT/
DDSCL_EXCLUSIVE/
DDSCL_FULLSCREEN)))
return (0); //error
if(lpdd4->SetDisplayMode(640, 480, 16, 0, 0))
return(0); //error
//now we get ready to create a primary surface
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = 0;
ddsd.dwFlags = DDSD_CAPS/DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE/
DDSCAPS_FLIP/
DDSCAPS_COMPLEX;
ddsd.dwBackBufferCount = 1;
//create the actual surface
if(FAILED(lpdd4->CreateSurface(&ddsd, &pbuff, NULL)))
return(0);//error
//now prepare to create the backbuffer
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS;
ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
//again, actually create the surface
if(FAILED(pbuff->GetAttachedSurface(&ddscaps, &bbuff)))
return(0); //error
//get ready to create the offscreen surface
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags =DDSD_CAPS/
DDSD_WIDTH/
DDSD_HEIGHT;
ddsd.dwWidth =32;
ddsd.dwHeight=32;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
//create the surface
if(FAILED(lpdd4->CreateSurface(&ddsd, &Bitmap, NULL)))
return(0);//error
LoadBMP(Bitmap, "image.bmp");
return (1);
}//end GameInit
BOOL LoadBMP(LPDIRECTDRAWSURFACE4 loadsurface, LPSTR filename)
{
HDC imagedc;
HDC surfacedc;
HBITMAP hbm;
DDSURFACEDESC2 ddsd2;
DDSCAPS2 ddscaps2;
//set the surfacedesc to zero
memset(&ddsd2, 0, sizeof(ddsd2));
ddsd2.dwSize = sizeof(ddsd2);
//get the caps
if(FAILED(loadsurface->GetSurfaceDesc(&ddsd2)))
return FALSE;//error
memset(&ddscaps2, 0, sizeof(ddscaps2));
//get the surface caps
if(FAILED(loadsurface->GetCaps(&ddscaps2)))
return FALSE;
//load the image into the bitmap handle
hbm = (HBITMAP)LoadImage(NULL, filename,
IMAGE_BITMAP, ddsd2.dwWidth,
ddsd2.dwHeight,
LR_CREATEDIBSECTION/
LR_LOADFROMFILE);
//check to see if the loading worked
if(hbm == NULL)
return FALSE; //error
//create a compatile device context
imagedc = CreateCompatibleDC(NULL);
SelectObject(imagedc, hbm);
//lock the surface
if(FAILED(loadsurface->GetDC(&surfacedc)))
return FALSE;
//blit the bitmap to the surface
BitBlt(surfacedc, 0, 0, ddsd2.dwWidth, ddsd2.dwHeight,
imagedc, 0, 0, SRCCOPY);
//release all stuff
if(surfacedc)
loadsurface->ReleaseDC(surfacedc);
if(hbm)
DeleteObject(hbm);
if(imagedc)
DeleteDC(imagedc);
return TRUE;
}//end LoadImage
int GameMain()
{
if(KEYDOWN(VK_ESCAPE))
PostMessage(window_handle, WM_CLOSE, 0, 0);
if(gameloop == 0)
{
Mover1.mover.bottom = 216;
Mover1.mover.top = 184;
Mover1.mover.left = 324;
Mover1.mover.right = 356;
Mover1.velocityx = 5;
Mover1.velocityy = 5;
}
else
{
if(Mover1.mover.bottom >= 480)
{
MoverDif = Mover1.mover.bottom - 480;//Find the difference between the mover''s bottom
//and the bottom of the screen
Mover1.mover.bottom = 480;//move the bottom to the screen''s bottom
Mover1.mover.top -= MoverDif;//match the top with the bottom to maintain shape
Mover1.velocityy = -Mover1.velocityy;//Bounce the mover
}
if(Mover1.mover.top <= 0)
{
MoverDif = Mover1.mover.top - 480;//Find the difference between the Mover''s top and
//the top of the screen
Mover1.mover.top = 0;//make the top equal to the top of the screen
Mover1.mover.bottom += MoverDif;//move the bottom according to the top''s change
Mover1.velocityy = -Mover1.velocityy;//Bounce the mover
}
if(Mover1.mover.right >= 640)
{
MoverDif = Mover1.mover.right - 640;//Find how far off the screen the right side
//of the mover is
Mover1.mover.right = 640;//fix the mover''s right side
Mover1.mover.left -= MoverDif;//move the left side according to the left side
Mover1.velocityx = -Mover1.velocityx;//bounce the mover
}
if(Mover1.mover.left <= 0)
{
MoverDif = -Mover1.mover.left;//Find how far off the screen the left side of the
//mover is
Mover1.mover.top = 0;//move the left side to the screen''s left
Mover1.mover.right += MoverDif;//move the right side according to the left''s change
Mover1.velocityx = -Mover1.velocityx;//bounce it
}
//move the mover
Mover1.mover.bottom += Mover1.velocityy;
Mover1.mover.top += Mover1.velocityy;
Mover1.mover.left += Mover1.velocityx;
Mover1.mover.right += Mover1.velocityx;
if (FAILED(bbuff->Blt(&Mover1.mover, // pointer to dest RECT
Bitmap, // pointer to source surface
NULL, // pointer to source RECT
DDBLT_WAIT,
// do a color fill and wait if you have to
NULL))) // pointer to DDBLTFX holding info
return(0);
if (FAILED(pbuff->Flip(NULL, DDFLIP_WAIT)))
return(0);
}
return(1);
}//end Game Init
int GameEnd()
{
if(Bitmap)
{
Bitmap->Release();
Bitmap = NULL;
}
if(bbuff)
{
bbuff->Release();
bbuff = NULL;
}
if(pbuff)
{
pbuff->Release();
pbuff = NULL;
}
if(lpdd4)
{
lpdd4->Release();
lpdd4 = NULL;
}
return(1);
}//end GameEnd
"Remember, I'm the monkey, and you're the cheese grater. So no messing around."
-Grand Theft Auto, London
"It's not whether I win or lose, as long as I piss you off"
-Morrigan, Super Puzzle Fighter II Turbo