[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [pygame] Dirty Rectangle Processing



DR0ID wrote:

Thank you for that. It's astonishing fast! Congratulations!

You're welcome, I'm glad you found it useful!

I tested your code:
I have ~412 fps in windowed mode and ~610 fps in fullscreen on a PentiumM 1.5Ghz with 1GB ram and WinXP Prof.

Here's some more timings you'll find interesting:

1.4 ghz PowerMac G4 10.3.7 512 megs ram (sandwich Mac) - 432 fps
350 mhz Compaq Presario 160 megs ram, shared video - 51 fps
2.6 gHz Compaq Presario 1 gig ram, shared video - 604 fps

And note - alt-enter even works on the Mac, though the Mac doesn't have an alt key and it's the option key instead.

The target frame range on my game engine is 12 fps - as long as the slowest machine can stay above that, they'll be able to play the game no problem.

(my LCD display is slow so I can see 4-6 rects lined up in the moving direction!!)

Mine too, in fullscreen mode! In windowed mode it's slow enough it doesn't do that.


I looked at your code and noticed, that I had forgotten about the clipping on a surface. That can make some thing faster.

Yeah... really only DRAW the bit you need, instead of overdrawing and expecting the clipping area to throw away the unnecessary bits. In my opinion, the current clipping rectangle is a crutch for those who don't want to finish the calculations.


A bit more info:

The frame rate is actually better than this on my actual engine, because I don't have any sprites move every timer tick, as in this example. My 'real' engine frame rate SAYS over 40,000 fps, but that's misleading, because unless you have something being drawn every frame, you don't really know what the FPS is. When I add some 'maximum velocity' sprites (sprites that draw every frame), the frame rates drop to what I posted here.

Still, while I'm developing the engine, I display the FPS at all times even though it's misleading, so if the frame rate drops sharply, I'll know I just implemented something stupid.

Overall, those sprite classes are easy to implement, and don't have to worry about the dirty rect calculations. Basically, just subclass from sprite and override the paint method. The text class is a little more involved because until the text is painted, I don't know how big it is. Once it's been painted, you need to update the 'size' with the final size, so the SetRect calculation will be correct.

Now that you have the example, these points will make more sense:

1. On __init__, paint the sprite immediately (no paint flag involvement).

2. When the sprite moves, dirty the screen by calling 'SetRect' ONLY - its appearance hasn't changed, only its position. SetRect is the magic function behind the dirty rectangle processing, and handles dirtying the screen without errors.

3. When the sprite changes appearance (such as size or text), mark the sprite as needing to be repainted (set the paint flag to 1) and dirty its area on the screen. That's a minor bug in the code I posted - when the text changes in the text class, add 'self.SetRect()' right after the 'self.paint = 1' line. I extracted this from a much larger engine, and that got overlooked. Setting the paint flag and executing self.SetRect always go hand in hand.

4. Finally - the end of paint ALWAYS calls SetRect. ALWAYS. If you create a new class with drawing bugs, look for that error first - forgetting to include a 'SetRect' at the end of Paint.

--Kamilche