[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [pygame] y-Sorted RenderGroup



If there's no reason to keep the sprites in a dict (sorry, haven't had 
time to look at the code, just going by Frank's comments), then using a 
bisect-based approach can be very fast.

Basically, you store the data in a sorted-order list and use the bisect 
module to add new items (which maintains sort order).  If you really do 
need the objects in a dict, you can do the work of pushing them into 
both dict and list and deleting them when adding/removing items.  The 
key is that you store the objects in the list as (sortParam, object), so 
that the standard Python sorting and comparison automatically works for 
the items.

The (sortParam,object) storage means you need to access objects as 
list[item][1] (or wrap that in an accessor method), but compared to 
calling a Python function (lambda or not) huge numbers of times (which 
is pretty darn slow) to do a sort, it should be much faster.

For the common case (wanting all objects), you can use
	map( operator.getitem, sortedlist, [1]*len(sortedlist))
to get all second items (the objects in sorted order) very fast.

Asides:
	cmp is a built-in, very fast.

	list.sort using a custom function is often much slower than building a 
temporary list of (sortValue, object) tuples, using default sort, then 
doing the operator.getitem (also a built-in) trick above to get the results.

	for changed values, simply remove the sprite, then re-insert with bisect. 
  There is overhead in finding the entry in the sorted list (use 
bisect.bisect( previousY, object) to get the index).  That means your 
sprite class needs to know to call the group with both previous and new 
y values, of course.

HTH,
Mike

Frank Raiser wrote:
> On Tue, Jun 04, 2002 at 10:52:02AM -0700, steve wrote:
...
>>   As you can see, I sort when I paint the sprites, because Python's 
>>dictionaries return their items in random order, sorting the dictionary 
>>would be pointless (you can't anyways).  After I sort, I paint the 
>>sorted list of sprites instead of spritedict.items(), #3 below.  I use 
>>my own sorting routine called y_sort(a, b).
...
>>   My question is, is creating an iternal list inside draw(), "y" in #1 
>>below, the right way of doing this?  Since draw is called so frequently, 
>>should I worry about garbage, and make this sorted list a class variable 
>>(self.y)?  Is there a better way of doing this within the existing 
>>Sprite classes, or am I on track here?
> 
> 
> The problem with the class variable is to keep it up2date when you change
> the group. I've tested a little (very little actually :) with your script
> and found that it doesn't make much of a difference unless you expand the
> group to several hundred sprites. And even then the difference is almost
> neglectable. I wouldn't say it's worth the effort of keeping the group
> updated.
> I'm not sure if you could get an improvement by keeping an internal flag
> for the sorting. As you sort all your sprites each time draw() is called
> this might be an overhead one could eliminate by keeping a flag that
> triggers the sorting only when a sprite has actually moved in the y
> direction. But then again I don't know how the sort routine works and how
> much work is actually done in case of an already sorted list. I think it'll
> be just another minor improvement only relevant to a group with hundreds
> of sprites.
> 
> hth,


-- 
_______________________________________
   Mike C. Fletcher
   http://members.rogers.com/mcfletch/


____________________________________
pygame mailing list
pygame-users@seul.org
http://pygame.seul.org