Bouncing Bitmap Problem

Started by
0 comments, last by PsYcHoPrOg 24 years ago
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
D:
Advertisement
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)

I think you want this code instead:

if(Mover1.mover.top <= 0)
{
MoverDif = Mover1.mover.bottom - Mover1.mover.top;
Mover1.mover.top = 0;
Mover1.mover.bottom += MoverDif;
Mover1.velocityy = -Mover1.velocityy;
}

The same can be done for the other three.

This topic is closed to new replies.

Advertisement