More fun with Win32

Started by
13 comments, last by 23yrold3yrold 21 years, 11 months ago
i think i got your bug.

you cant select a bitmap back into hdc. windows will ignore your butt. that bitmap belongs to windows.

or as the knowledge base says:
"(Bitmaps can be selected for memory device contexts only, and for only one device context at a time.)"

the relavent piece being "memory device contexts only" when your talking hdc thats not a memory device context.

So what to do? well ive been through this before. just do all your painting on your own private bitmap (the typical backbuffer) then when your ready bitblt it back to the windows bitmap. its the only way and a pretty good way. So after you get that stretch done you just bitblt it right back.
edit: heeh you might be able to get rid of the middle man there but conceptually i was just pointing out keep a permanent backbuffer that is exactly the same as the hdc's. your code deals with that. you can be sloppy or clean. then on draw time you just copy that whole thing into the hdc via bitblt hdc. its fast. not as fast as true flipping but it does get rid of flicker.



so your finalish line in that will be
bitblt(hdc,...);

and they said i was crazy for making a 2d game without ddraw. little did they know i would learn something.

ps tell me when you try a rotation. the windows bit transfer function doesnt work on 98. it compiles and calls just does nothing. cept down there in the little line at the bottom in the documentation it says not supported on windows 98...

writing my own was slow.. and i suddenly realized that i had never seen bitmap rotations in games like diablo. they are nasty expensive in pure software mode.



oh btw that private bitmap that is just like the screen bitmap. keep it persistant. there is no reason to realloc it every function call.



[edited by - declspec on May 6, 2002 2:32:19 PM]

[edited by - declspec on May 6, 2002 2:34:51 PM]
Advertisement
Here''s my final working version. Look good?


        void ResizeBitmap(int w, int h)      {         HDC temphdc = CreateCompatibleDC(hdc);         hbitmap     = CreateCompatibleBitmap(temphdc, w, h);         HBITMAP tempbitmap = (HBITMAP)SelectObject(hdc, hbitmap);         SelectObject(temphdc, tempbitmap);         ::PatBlt(hdc, 0, 0, w, h, WHITENESS);         BitBlt(hdc, 0, 0, width, height, temphdc, 0, 0, SRCCOPY);         DeleteObject(temphdc);         DeleteObject(tempbitmap);         width  = w;         height = h;      }  


BTW, hdc in that code IS the back buffer It BitBlt''s to the window dc in WM_PAINT. And rotating isn''t that hard using SetPixel, GetPixel and a rotation matrix, right? (famous last words, I''m sure) ....

Chris Barry (crbarry at mts.net)
My Personal Programming Depot

Jesus saves ... the rest of you take 2d4 fire damage.

oh hmm. thats to your starting question.


now to rotations. yes and no. but rotations are lossy. the pixels dont line up if your rotating say 30 degrees. so you have to make some pixels a guesstimate.

ok you can use two approaches.
1) you rotate by taking the position of the original pixel then find its new coordinate via a rotation. change the float to an int in some way. then paint that pixel on the new bitmap. if you do it this way then some pixels are unpainted on the bitmap. looks like a pattern of spots. fix you could paint a few pixels based on the percentage that the original pixel was actually in the target. a sort of sample as you go to get rid of the spots. lots of repainting though.

2) you go hmmm write a harder algo that takes pixels in the final bitmap via math. then rotates back to a pixels in the original bitmap and samples based on percentage that its in that pixel.


so the key concept is that if you just rotate you get pixels in the middle of your bitmap that never got painted. not huge blocks just dots. single pixels where the round off/ rotation math caused it to not get painted. you got to decide what to do with them.

either way painting pixel by pixel from/to a device context is slow slow slow. i mean 1000s of times slower then the equivalent bitblt. very very slow.


so in games youll notice in the older non accelerated games they actually packaged 8 angles of each thing that had to turn in the graphics files. no rotations in older games at all. not even in doom. the only thing that rotated in doom was sprites. again packaged rotations. later 3d had rotations quake for example but even quake in software mode still needed a graphics card...the "software" doesnt refer to every last texture op.



for my game i ended up rotating at load time. that worked. it was uglier but i didnt want to get caught up in artwork.

for you though you have flexibility. you can afford slowness to a point.


One thing I think you missed, from the MSDN library docs on CreateCompatibleDC():

quote:
When you no longer need the memory device context, call the DeleteDC function to delete it.


So you shouldn't do DeleteObject(temphdc), you should be doing DeleteDC(temphdc).

[edited by - cgoat on May 7, 2002 1:04:33 PM]

This topic is closed to new replies.

Advertisement