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
I''m not sure where the error is coming from, but you''re code that does bounds checking is wrong.
In the case of the top being less or equall to zero, it''s wrong. Follow along: Lets say top is zero. First you asign to MoverDif this: MoverDif = 0-480) Then you give Mover1.mover.top a zero (O.K. here) Then you assign MoverDiff(which now has -480) to bottom! Then the velocity is reversed(O.K here)