Hello
Yes I do dirty rect animation. If you read the code of the RenderUpdate
(in pygame.sprite.Sprite.RenderUpdates) then you will see that this
group does something like this:
dirty = [ ]
if old rect and new rect overlap:
dirty_rect = old_rect.union(new_rect)
dirty.append(dirty_rect)
else
dirty.append(old_rect)
dirty.append(new_rect
This is done fore each sprite and give an performance boost. But if you
have many sprite that overlap then the code above lead still to many
overlapping areas. Therefore I use little different approach:
# 1. I have to find out the dirty areas on screen because you have to
know the old_rect and the new_rect
rect_list = [old_rect, new_rect, .... ] # all rect that affect the
screen, afterward it will contain the dirty rects
for rect in rect_list:
_unionR = pygame.Rect(rect) # make a copy because
_uionR will be modified
i = _unionR.collidelist(rect_list) # find first other
rect that collides
while -1< i: # repeat it as long there is
an colliding rect
_unionR.union_ip(rect_list[i]) # union the
overlapping rects in place
del rect_list[i] #remove
the on from the list
i = _unionR_collidelist(rect_list) # check if there
are still overlapping rects in the list
rect_list.append(_unionR.clip(_clip)) # at the end append the
new rect to the rect_list (dirty rects now)
This code will handle any overlapping rects on screen. There is one draw
back though. If you have a high and small rect and a another with a
small hight and a big width then nearly the entire screen will be
updated. Parts of the screen will be updated too, which did not change,
so you will have to redraw them again (that is a strong reason against
that update() should optimize the rects in that way, if it should do it
then it should split the overlapping rects into two or three different
rects such that only areas in the rects will be updated on screen, see
below).
Especially in combination of a dirty flag the second code snippet is
useful. I have used it in the FastRenderGroup I have written, here it
goes (if you subscribe to the RSS feed then you will stay informed about
updates):
http://www.mypage.bluewin.ch/DR0ID/pygame_projects.html#fast_dirty1
In the new release (soon today) I have written a separated
LayeredRenderGroup (which is somewhat untested! sorry, had no time to
test it) and the FastRenderGroup. The FastRenderGroup can handle about
130 sprites doing dirty rects animation (on a PentiumM 1.5GHz), but with
more sprites a full screen update will be faster, so it switches
automatically to that mode.
Another approach would be to split the overlapping rects into single,
non-overlapping rects. To know how to split rects see (some time ago I
have found the following link, but have not tested it and I do not know
how fast it really is):
http://barbieri-playground.googlecode.com/svn/pygame/smart_render/smart_render.py
I hope I could help.
~DR0ID
Peter Shinners schrieb:
John Cabral wrote:
I was working on some code for my game and read about the optimization
of feeding a list of rects to the update function. I was curious if
it would be worthwhile to try to optimize the list that is fed to the
function. Specifically, I would try to shorten the list by merging
rects that had significant areas of overlap. However, I can't tell if
the function itself might perform this work itself. Does anyone
know?
I've found that generally many small rectangles aren't slower than
fewer big ones. The most important thing is the area effected.
And yes, overlapping rectangles are processed multiple times, so that
can cost big on performance. A little effort to keep big areas from
overlapping will pay off.