[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