From: Sascha on 7 Jun 2010 22:11 Hello I have made a simple 2d Game engine in Win32 C++. I use double buffering to draw the objects onto the client HDC. But I think I maybe drawing too many times to a HDC causing an error or something? [b]I have the executable that really simply shows my problem so I really encourage you to download it instead of having to read all the below. It shows exactly where the drawing fails at loop 50 (see the console window).[/b] PS how do you add links in this forum? http://www.mediafire.com/?gz0xzktmryt The 2d engine works pretty well, each object controls its own movement then informs the 2d engine saying "Draw me, Audio me, Keep me in the action/input queue etc." And the 2d engine draws an object's new position every loop well. [b]But One funny problem I am getting is:[/b] - If I have n objects to draw, after the n*100th gameloop the drawing onto the window HDC of each objects new coordinates stops. The game loop is still looping perfectly, the actual code/function to draw the objects onto the Buffer hdc still runs(I checked), the function to copy the BufferHDC to the WindowHDC still runs BUT the window is not displaying the new HDC image therefore each objects new position(they are moving). So in the case when I have [b]5[/b] objects to draw & they all are moving to the same point on the window (100,100): - For the 1st 500 game loops the 2d engine draws all the objects (every loop) perfectly(in their new position, coloured etc.) But then the window doesn't get updated after the 501st loop? In the case when I have [b]55[/b] objects to draw & they all are moving to the same point on the window (100,100): - For the 1st 50 game loops the 2d engine draws all the objects (every loop) perfectly(in their new position, coloured etc.) But then the window doesn't get updated after the 51st loop & the window HDC just continually shows the HDC image of the 50th frame? [b]So after that long winded explaination I have come to believe that maybe I can only[/b] draw on a HDC so many times OR I can only copy to the window HDC so many times OR maybe I am overloading the variables or system concerned with copying the BufferHDC to the WindowHDC? My algorithm is simple: - The graphic engine has a draw queue that contains all the objects that need to be drawn in the next game loop - When the next loop begins I call the function ExecuteDrawLogic(). Where every object inside the Draw Queue is told "I am passing you the BufferHDC, draw over your old position with the bK colour, draw yourself at your new position" then I remove the object from the queue. - After all objects have done their drawing I copy the BufferHDC to the main WindowHDC which has/shows each objects new position & makes it look they r moving. So again after this really long explanation, do you know why the WindowHDC does not get updated after nth game loop? Am I overloading the bufferHDC or something? Graphic Engine Class: [source lang="cpp"] class GraphicEngine { public: GraphicEngine( Engine2d *ParentEng, HWND Hwnd ); ~GraphicEngine(); void StoreSiblingEngines( SystemEngine *SystemEng, InputEngine *InputEng, AudioEngine *AudioEng ); void SetHwnd( HWND Hwnd ); void CopyWindowHDC( HWND Hwnd, HDC WindowHDC ); void Clear(); int AddToDrawQueue( Object *Obj ); bool ExecuteDrawLogic( HDC WindowHDC ); private: HWND hwnd; RECT ClientRect; HDC BufferCanvas; HBITMAP hBlt; HGDIOBJ hMCBmp; queue <Object*> DrawQueue; }; [/source] Functions associated with double buffering: [source lang="cpp"] void GraphicEngine :: CopyWindowHDC( HWND Hwnd, HDC WindowHDC) { // Post: Copy Window HDC to Buffer canvas. This function is done once, when // the 1st WM_PAINT message is sent when the window is created. It also is // called again if the window is resized/minimised etc. GetClientRect( Hwnd, &ClientRect ); BufferCanvas = CreateCompatibleDC( WindowHDC ); hBlt = CreateCompatibleBitmap( WindowHDC, ClientRect.right, ClientRect.bottom ); hMCBmp = SelectObject( BufferCanvas, hBlt ); BitBlt(BufferCanvas, ClientRect.left, ClientRect.top, ClientRect.right, ClientRect.bottom, WindowHDC, 0, 0, SRCCOPY ); } bool GraphicEngine :: ExecuteDrawLogic( HDC WindowHDC ) { // Post: Draw all 'Dirty' Objects onto window using Double Buffering (avoids // flicker affect). hMCBmp = SelectObject( BufferCanvas, hBlt ); // Draw objects onto Buffer Canvas while ( !DrawQueue.empty() ) { DrawQueue.front()-> EraseSelf( BufferCanvas ); DrawQueue.front()-> DrawSelf( BufferCanvas ); DrawQueue.pop(); } // Copy BufferCanvas HDC to WindowCanvas HDC BitBlt( WindowHDC, ClientRect.left, ClientRect.top, ClientRect.right, ClientRect.bottom, BufferCanvas, 0, 0, SRCCOPY ); } int GraphicEngine :: AddToDrawQueue( Object *Obj ) { // Post: Add Object to Graphic Engine's draw queue. At the next clock step // the Graphic Engine will call this objects' DrawSelf() function // TODO: Arrange/Add Objects in queue according to depth eg an airplane should // be drawn last coz its higher DrawQueue.push( Obj ); } [/source]
From: Leo Davidson on 8 Jun 2010 03:20 On Jun 8, 3:11 am, Sascha <nill...(a)yahoo.com> wrote: > I have made a simple 2d Game engine in Win32 C++. I use double > buffering to draw the objects onto the client HDC. But I think I maybe > drawing too many times to a HDC causing an error or something? I suspect your code is leaking GDI objects/handles and that's why things stop working. Open Task Manager and turn on the GDI Objects column to see if the count is ridiculously high or ever-increasing. It could also be some other kind of bug, but there's definitely no limit on the number of times you can draw to a device context (else almost every app in the world would stop being able to update its window after a short time since almost all apps ultimately put stuff on the screen via GDI).
From: Ulrich Eckhardt on 8 Jun 2010 03:31 Sascha wrote: > I have the executable that really simply shows my problem so I > really encourage you to download it instead of having to read all > the below. I hope nobody is foolish enough to follow that request or at least runs it in a sandbox. Otherwise, downloading random executables from unknown persons is a ticket to the next botnet drama. And even if that executable is completely harmless, I wouldn't ask others to download it, exactly for that reason. > class GraphicEngine > { > public: > GraphicEngine( Engine2d *ParentEng, HWND Hwnd ); > ~GraphicEngine(); > void StoreSiblingEngines( SystemEngine *SystemEng, > InputEngine *InputEng, > AudioEngine *AudioEng ); > void SetHwnd( HWND Hwnd ); > void CopyWindowHDC( HWND Hwnd, HDC WindowHDC ); > void Clear(); > int AddToDrawQueue( Object *Obj ); > bool ExecuteDrawLogic( HDC WindowHDC ); > > private: > > HWND hwnd; > RECT ClientRect; > HDC BufferCanvas; > HBITMAP hBlt; > HGDIOBJ hMCBmp; > queue <Object*> DrawQueue; > }; Several points here: 1. Your GraphicEngine class is both copyable and assignable, those functions are compiler-generated. You probably don't want that, so you should prevent it. Check the C++ FAQ at parashift's. 2. Who owns all those objects you pass handles or pointers to around? Which of these can be NULL? You can and should use C++ references, because those implicitly say that the parameter can't be left out. > BufferCanvas = CreateCompatibleDC( WindowHDC ); > hBlt = CreateCompatibleBitmap( WindowHDC, ClientRect.right, > ClientRect.bottom ); > hMCBmp = SelectObject( BufferCanvas, hBlt ); > > BitBlt(BufferCanvas, ClientRect.left, ClientRect.top, > ClientRect.right, ClientRect.bottom, > WindowHDC, 0, 0, SRCCOPY ); Where are you releasing the resources you allocated here (DC, bitmap)? If you allocate more and more of those, that resource leak will cause further allocations to fails, which you completely ignore here. Check for errors, and if it's only that you output a message to stderr and exit or something like that. Also, what do you need hMCBmp for after leaving this function? In other words, why do you store this in a membervariable? Start with error checking, I guess you will then see where your program fails. Then, think about ownership and proper allocation/deallocation of resources, that will then probably fix your program. Uli -- Sator Laser GmbH Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932
From: Heck on 9 Jun 2010 08:45 On Tue, 08 Jun 2010 09:31:29 +0200, Ulrich Eckhardt <eckhardt(a)satorlaser.com> wrote: >Sascha wrote: >> I have the executable that really simply shows my problem so I >> really encourage you to download it instead of having to read all >> the below. > >I hope nobody is foolish enough to follow that request or at least runs it >in a sandbox. Otherwise, downloading random executables from unknown >persons is a ticket to the next botnet drama. And even if that executable >is completely harmless, I wouldn't ask others to download it, exactly for >that reason. I think he's relatively young and inexperienced. And trusting. >[b]...[/b] PS how do you add links in this forum? Try alt.religion.kibology. Or am I the gullible one?
|
Pages: 1 Prev: gtk+ and Visual C++ Next: Installing Windows XP using F6 in a PC without a floppy drive? |