[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
Re: [pygame] FastRenderGroup revised (update4)
Hello again
René Dudfield schrieb:
Hello,
very nice work!
I'm a bit busy myself for the next week. So in two weeks would be a
good time to meet up and finish off the last things before we put it
into pygame.
1.) Change the name: yes, but to what?
Not sure. I'm afraid of using 'Fast' because too many times I have
seen projects where there is a new FastSomething only for it to
eventually not be fast anymore a year later.
Your right, we should not use "fast" in the name. Perhaps
OrderedDirtyGroup or DirtyOrderedGroup? Or DirtyLayeredGroup?
What are the main features of FastRenderGroup?
Well it has the layering system from the LayeredRenderGroup (ist that
name ok?). Then it uses the dirty flag technique, so only things marked
dirty will be redrawn. And the automatic switch between the two
rendering modes is another feature (the idea of all that is that you
stuff your sprites in there and forget about all the complicated
rendering stuff, it will be just done for you). I think there are the 3
main features. Well clipping, you can set a clip, and it will only
render in that area of the surface.
We should definitely let people know in the docs that FastRenderGroup
is the preferred group to use.
Well not sure about that, I would say yes, but its a bit more
complicated to use actually. You will be responsible to set the dirty
flag whenever the sprite has to be redrawn (actually dirty=2 is a
shortcut for sprites that are always dirty, so they do not need to set
the dirty flag all the time, but this should be used with care, because
if you set dirty=2 on every sprite then you can just use the
LayeredRenderGroup).
2.) you really want to be able to pass in different get_ticks()
functions? I can do it, but I do not see the benefit, because I'm still
unhappy with the solution how to decide which method to use. Perhaps I
could use a Exponential back off strategy (do not know how to implement
it), but I'm not sure if that would be good. Any better ideas?
So people can use their own game timers. Say the rest of the game
uses either time.time, or even something from blender, crystalspace, a
real time clock etc etc. Should definitely use a default timer though.
That sounds like a good reason. I have just read Nick Moffitt mail:
"
Consider that when you sample, you have a timing value for the fastest
and the slowest method given a particular data set. Use this to
calculate a threshold, and compare it against the current rendering
time. Keep the rendering time for the previous frame as well, and do
comparisons between successive frames and comparisons relative to the
tests done earlier.
You should also consider attack/sustain values for when to switch, so
that you don't end up with bang-bang switching in cases where the two
methods have similar speeds.
"
Perhaps we should try one of these. I like the idea to store the values
of preceding frames, but on the other hand I do not want to take a
measure at every frame. Instead of counting the frame we could use a
timevalue like Rene proposed, but perhaps not every 10 seconds (too long
in my opinion, see some line below). Perhaps I should implement the
possibility to make it stick with one rendering mode.
The jerking stops for me when I make it not oscillate between update,
and flip modes. I think maybe an Exponential back off strategy might
work... not too sure. I think we should try a few different things
when we meet up in two weeks.
Strange that the jerking stops when you disable the decisioning. Perhaps
another strategy helps here.
Some possible different strategies:
- figure out the best rendering method in the first 1-3 seconds, then
stick with that.
- keep checking to see which is the fastest way. Only change modes at
most once every 10 seconds.
3.) naming of the attributes of the DirtySprite: we can change them, but
to what? Are the current names already used?
Haven't had a chance to research this. Let's look at it in two weeks.
Let's talk about them next time we meet at the minisprint.
4.) I don't think we can make it backwards compatible, so it will not
replace RenderUpdates (unless the pygame.sprite.Sprite becomes the
DirtySprite with dirty=2 as default, but that would be stupid).
Cool, that's fine if we can't.
btw, Gustavo posted about some code he's done for fast sprite usage:
http://renesd.blogspot.com/2007/06/pygame-weekly-mini-sprint-20070620.html#comments
<http://renesd.blogspot.com/2007/06/pygame-weekly-mini-sprint-20070620.html#comments>
I think his approach is to break the screen up into tiles of 8x8.
Then in the sprite code mark each tile as dirty, if the sprite needs
to be updated in those positions. This way there is a constant number
of rectangles passed through to the update function every frame - and
no over draw.
Yes, I stumbled on that some weeks ago and I have already taken a look.
I think we could just extend the rect class in pygame. Perhaps we should
add functionality like splitting two overlapping rects and splitting a
list of rects into a list of rect that do not overlap anymore. I'm not
sure if it would be faster than what I use to merge the rects:
"
for spr in _sprites:
if 0 < spr.dirty:
_union_rect = _rect(spr.rect)
_union_rect_collidelist = _union_rect.collidelist
_union_rect_union_ip = _union_rect.union_ip
i = _union_rect_collidelist(_update)
while -1 < i:
_union_rect_union_ip(_update[i])
del _update[i]
i = _union_rect_collidelist(_update)
_update_append(_union_rect.clip(_clip))
"
I think this is only a O(n^2) in worst case otherwise it is less (but I
cant tell you what it is). The drawback of that method is, that in the
worst case it ends up with a big rect covering the entire screen.
Perhaps using Gustavos rect splitting thing would be better (? faster?).
~DR0ID
On 6/30/07, *DR0ID* <dr0id@xxxxxxxxxx <mailto:dr0id@xxxxxxxxxx>> wrote:
Hi
Today I got the time to do the changes you have suggested in the
last email.
You can download it here:
http://www.mypage.bluewin.ch/DR0ID/pygame_projects.html#fast_dirty1
<http://www.mypage.bluewin.ch/DR0ID/pygame_projects.html#fast_dirty1>
or direct link:
http://www.mypage.bluewin.ch/DR0ID/pygame/FastRenderGroup_v1.1.78.zip
1.) Change the name: yes, but to what?
2.) you really want to be able to pass in different get_ticks()
functions? I can do it, but I do not see the benefit, because I'm
still
unhappy with the solution how to decide which method to use.
Perhaps I
could use a Exponential back off strategy (do not know how to
implement
it), but I'm not sure if that would be good. Any better ideas?
3.) naming of the attributes of the DirtySprite: we can change
them, but
to what? Are the current names already used?
4.) I don't think we can make it backwards compatible, so it will not
replace RenderUpdates (unless the pygame.sprite.Sprite becomes the
DirtySprite with dirty=2 as default, but that would be stupid).
I have modified testsprite.py to use FRG, please test following
configurations:
testsprite.py
testsprite.py -update_rects
testsprite.py -FastRenderGroup
testsprite.py -static
testsprite.py -static -update_rects
testsprite.py -static -FastRenderGroup
What do you think? For that tests I have added a new image, as you
can see.
I have written a demo to demonstrate that all sprites have to be
in the
same FRG to be drawn correctly:
multi_FRG_demo.py
use the same arguments as for testsprite.py and you will see what
happens when using the FRG.
If you run the testsprite.py you will have the frame jerking too,
so it
is not a problem of the FRG. To avoid the jerking you will have to
limit
the Framerate to certain frames per second(or put a sleep(0.001) in
there somewhere).
I can not participate at the next minisprint, but in a week I will
have
time.
~DR0ID