Whoosh!

Started by
6 comments, last by PsYcHoPrOg 24 years, 1 month ago
I ran the following code and got this streak across the top of my screen as if something is flying past me. I am just trying to get a little bitmap to bounce around the screen. Help! Here''s the code: #define WIN32_LEAN_AND_MEAN //include important stuff #include #include #include #include #include //#include "Blitex.h" #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(); //declarations struct Mover { int bitheight; int bitwidth; int locationx; int locationy; int velocityx; int velocityy; RECT mover; }MOVER; Mover Mover1; int mainloop = 0; int locx; int locy; int velx; int vely; int bh; int hw; 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; HRESULT hr; 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 // 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 // WINMAIN //////////////////////////////////////////////// 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 = "class"; winclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION); // save hinstance in global instance = hinstance; // register the window class if (!RegisterClassEx(&winclass)) return(0); // create the window if (!(hwnd = CreateWindowEx(NULL, // extended style "class", // class "BlitMove", // 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); ShowCursor(FALSE); // save main window handle 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 WinM bool LoadBMP(LPDIRECTDRAWSURFACE4 surface, LPSTR filename) { HBITMAP hbm; HDC imagedc; HDC surfacedc; DDSURFACEDESC2 ddsd2; DDSCAPS2 ddscaps2; memset(&ddsd2, 0, sizeof(ddsd2)); ddsd2.dwSize = sizeof(ddsd2); if(FAILED(surface->GetSurfaceDesc(&ddsd2))) return FALSE; memset(&ddscaps2, 0, sizeof(ddscaps2)); if(FAILED(surface->GetCaps(&ddscaps))) return FALSE; hbm = (HBITMAP)LoadImage(NULL, filename, IMAGE_BITMAP, ddsd2.dwWidth, ddsd2.dwHeight, LR_LOADFROMFILE/ LR_CREATEDIBSECTION); imagedc = CreateCompatibleDC(NULL); SelectObject(imagedc, hbm); if(FAILED(surface->GetDC(&surfacedc))) return FALSE; if(!(BitBlt(surfacedc, 0, 0, ddsd2.dwWidth, ddsd2.dwHeight, imagedc, 0, 0, SRCCOPY))) return FALSE; if(surfacedc) surface->ReleaseDC(surfacedc); if(imagedc) DeleteDC(imagedc); if(hbm) DeleteObject(hbm); return TRUE; }//end LoadBMP int GameInit() { if(FAILED(DirectDrawCreate(NULL, &lpdd, NULL))) return(0); if(FAILED(lpdd->QueryInterface(IID_IDirectDraw4, (LPVOID *)&lpdd4))) return(0); if(FAILED(lpdd4->SetCooperativeLevel(window_handle, DDSCL_FULLSCREEN/ DDSCL_EXCLUSIVE/DDSCL_ALLOWREBOOT))) return(0); if(FAILED(lpdd4->SetDisplayMode(640, 480, 16, 0, 0))) return(0); memset(&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS/DDSD_BACKBUFFERCOUNT; ddsd.dwBackBufferCount = 1; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE/ DDSCAPS_COMPLEX/ DDSCAPS_FLIP; if(FAILED(lpdd4->CreateSurface(&ddsd, &pbuff, NULL))) return(0); //********************************* // You were using the ddsd instead of ddscaps // ie. ddsd.ddsCaps.dwCaps = ... // should be: // ddscaps.dwCaps = ... // The back buffer uses the ddscaps while the primary uses the ddsd memset(&ddscaps, 0, sizeof(ddscaps)); ddscaps.dwCaps = DDSCAPS_BACKBUFFER; if(FAILED(pbuff->GetAttachedSurface(&ddscaps, &bbuff))) return(0); memset(&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS/DDSD_HEIGHT/DDSD_WIDTH; ddsd.dwWidth = 640; ddsd.dwHeight = 480; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; if(FAILED(lpdd4->CreateSurface(&ddsd, &Bitmap, NULL))) return (0); LoadBMP(Bitmap, "image.bmp"); //***************************** // Make sure to return a value return 1; }//end GameInit() inline int CreateMover(Mover create) { create.mover.top = 200; create.mover.left = 320; create.mover.bottom = 232; create.mover.right = 352; create.velocityx = rand()%5; create.velocityy = rand()%5; return(1); } int UpdateMover(LPDIRECTDRAWSURFACE4 surface,Mover update) { velx = update.velocityx;//the x velocity of the "mover" vely = update.velocityy;//the y velocity of the "mover" //Update the location of the "mover" update.mover.top += vely; update.mover.left += velx; update.mover.bottom += vely; update.mover.right += velx; if(update.mover.right >= 640) velx = -velx; if(update.mover.left <= 0) velx = -velx; if(update.mover.top <= 0) vely = -vely; if(update.mover.bottom >= 480) vely = -vely; //Blit the mover''s new location if(FAILED(surface->Blt(NULL, Bitmap, &update.mover, DDBLT_WAIT, NULL))) return(0); return (1); } int GameMain() { if(KEYDOWN(VK_ESCAPE)) PostMessage(window_handle, WM_CLOSE, 0, 0); if(mainloop == 0) { CreateMover(Mover1); UpdateMover(bbuff, Mover1); } else { UpdateMover(bbuff, Mover1); } if(FAILED(pbuff->Flip(NULL, DDFLIP_WAIT))) return(0); mainloop++; return(1); Sleep(500); } 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); } "Remember, I'm the monkey, and you're the cheese grater. So no fooling around." -Grand Theft Auto, London
D:
Advertisement

There are several problems in your UpdateMover function.

First, you copy your Mover''s velocity values into local
variables and then when you change those values you
don''t change them in the Mover struct.

Second, if your rectangle moves off the edge of the screen,
your flip the velocity but you don''t adjust the rectangle
so it fits on the screen again.

Third, you don''t pass appropriate rectangles to the
BLT call.

Try changing it like this:


int UpdateMover(LPDIRECTDRAWSURFACE4 surface,Mover update)
{
velx = update.velocityx;
vely = update.velocityy;

update.mover.top += vely;
update.mover.left += velx;
update.mover.bottom += vely;
update.mover.right += velx;

if( update.mover.right >= 640 )
{
update.mover.left -= (update.mover.right - 640);
update.mover.right = 640;
update.velocityx = -velx;
}
else if( update.mover.left <= 0 )
{
update.mover.right -= update.mover.left;
update.mover.left = 0;
update.velocityx = -velx;
}

if( update.mover.bottom >= 480 )
{
update.mover.top -= (update.mover.bottom - 480);
update.mover.bottom = 480;
update.velocityy = -vely;
}
else if( update.mover.top <= 0 )
{
update.mover.bottom -= update.mover.top;
update.mover.top = 0;
update.velocityy = -vely;
}

RECT image_rect = { 0, 0, 32, 32 };
//Blit the mover''s new location
if(FAILED(surface->Blt(&update.mover,Bitmap,
ℑ_rect,DDBLT_WAIT,NULL)))
return 0;

return 1;
}
Thanks. I should have seen that, however, I still get the same problem. If You e-mail me, I could send you the .exe so you can see the results of the code.

"Remember, I'm the monkey, and you're the cheese grater. So no fooling around."
-Grand Theft Auto, London

Edited by - psychoprog on 2/29/00 1:32:43 PM
D:
Any help would be great.

"Remember, I'm the monkey, and you're the cheese grater. So no fooling around."
-Grand Theft Auto, London
D:
PsYcHoPrOg: Will you PLEASE stop posting these huge source code listings here? If you can''t narrow it down to a small section of code, then you aren''t spending enough time trying to figure things out on your own.
Sorry, I''ll make an attempt to narrow down my code.

"Remember, I'm the monkey, and you're the cheese grater. So no fooling around."
-Grand Theft Auto, London
D:
Ok. After a brief (ok, I spent some time here ) look at that code I can see some problems.

1) CreateMover(Mover & create)
Otherwise create is just a copy and is destroyed when the function returns.

2) Same deal in UpdateMover(... , Mover & update)

3) In UpdateMover(...) you don't set the new velocity on the edge hit. Need

update.velocityx = velx;
update.velocityy = vely;

before you leave the function to keep track of any changes.

4) In UpdateMove(...) when you BLT the image I think that you are getting the source and destination rects mixed up.

update.mover is where to draw the bitmap.
testRect is where to look on the surface for the bitmap.


RECT testRect;
testRect.top = 0;
testRect.left = 0;
testRect.bottom = 64; //My test image 64,64
testRect.right = 64;

if(FAILED(surface->Blt(&update.mover, Bitmap,&testRect, DDBLT_WAIT, NULL)))


5) You don't clean out the back buffer so all the crap from the last frame and stuff in memory is shown. Try


DDBLTFX ddBltFx;
ddBltFx.dwSize = sizeof(DDBLTFX); ddBltFx.dwFillColor = 0; // 0 = black;
bbuff->Blt(NULL, NULL, NULL,DDBLT_WAIT / DDBLT_COLORFILL, &ddBltFx);


as soon as you enter the GameMain().


Ok. I think I spent more time on this then I should have but what the hey it's good training.


If you want I can mail you the code and .exe that I have got working on my machine. You could also look at CDX since it is all open source and very well organized.

Andrew
acraig@engr.mun.ca


Edited by - acraig on 3/1/00 6:31:35 PM
Thanks for the help! I really appreciate it! If you could, could you please send me the code?

"Remember, I'm the monkey, and you're the cheese grater. So no fooling around."
-Grand Theft Auto, London
D:

This topic is closed to new replies.

Advertisement