[pygame] Improved Sprites System - Call for Suggestions

288 views
Skip to first unread message

Sagie Maoz

unread,
Jun 1, 2012, 9:29:33 AM6/1/12
to pygame...@seul.org
Hi guys,

As part of my GSoC project [1], I've been researching Pygame's sprite.py and equivalents in other libraries, figuring out a list of features I will focus on in my project.

I wanted to get your thoughts and feedback on these items; which of these do you think are necessary, and which more necessary than the others? Do you think implementing any of these would be too difficult for a first-time contributor (me)? Do you have any other ideas?

Suggested improvements for sprite.py:
1. Easier positioning methods: Using tuples or arrays, instead of just Rects.
2. Setting a sprite's anchor points for handling in movement, animation, collision etc.
3. Aggregated sprite class (basically, a sprites group which implements the sprite interface).
4. Automated dirty rendering (existing feature in Spyral [2]).
5. New visual attributes for sprites:
    - Rotation angle
    - Scale
    - Crop rectangle
    - Visible/hidden
    - Collision parameters (smaller hitbox, etc.)
6. Alternative forms of collision detecting (not limited to circles and rectangles).
    Possibly using algorithms such as quadtrees and spatial hashing.
7. Improved layering system.
8. Respecting blendmode flags are handled in all types of sprites.
9. Animated sprites:
    - Setting a group of images to cycle through in a time interval.
    - Animating visual attributes, a-la Kivy [3] or CSS transitions [4].
10. Events dispatching from groups to sprites.

This list was comprised after consulting with mentor Robert Deaton (masquerade) and fellow contributors on the IRC channel.
It's obviously not a final list of the work I'm planning, but more of a list of things to research before I get to coding.

I would love to hear your feedback on these.

Thanks,

[1] Pygame SoC application: Improved Sprite and Scene system http://www.google-melange.com/gsoc/proposal/review/google/gsoc2012/n0nick/28002

-- 
Your friend in time,
Sagie Maoz

Nicholas Seward

unread,
Jun 1, 2012, 10:50:27 AM6/1/12
to pygame...@seul.org
I like all of these ideas. Polygonal collisions would be very useful. (A naive O(n^2) but effective/readable/maintainable approach would be to see if any edges intersect between their vertices after you get a positive rect collision.)

An efficient spatial data structure for rendering and collision detection would really put pygame over the top.  Imagine: you could prototype a scale-able CAD program in a day.  If you could have a million off screen sprites without a performance dip that would be amazing.  A million updates would still cause a lag but if you could turn off updates for off screen sprites except where flagged then you would have a scale-able platform.   This would be one of the hardest thing on your list and most people won't ever know it is there. There is a special place in pygame heaven for the person that makes this happen.

The most useful thing on your list has got to be adding visual attributes.  I personally thought this was a weak area and have extended the Sprite class to hold a reference image and let me scale, rotate, and remask with ease.  I only use the vanilla version when I am teaching students.

Good Luck,
Nicholas Seward

Keith Nemitz

unread,
Jun 1, 2012, 11:54:34 AM6/1/12
to pygame...@seul.org

this could go under the vis/invis or blending. Would love to have pixel and sprite transparency. Would require OpenGL, I suppose.




--- On Fri, 6/1/12, Nicholas Seward <nichola...@gmail.com> wrote:

DR0ID

unread,
Jun 1, 2012, 2:29:35 PM6/1/12
to pygame...@seul.org
On 01.06.2012 15:29, Sagie Maoz wrote:
> Suggested improvements for sprite.py:
> 1. Easier positioning methods: Using tuples or arrays, instead of just
> Rects.
> 2. Setting a sprite's anchor points for handling in movement,
> animation, collision etc.
> 3. Aggregated sprite class (basically, a sprites group which
> implements the sprite interface).
> 4. Automated dirty rendering (existing feature in Spyral [2]).
> 5. New visual attributes for sprites:
> - Rotation angle
> - Scale
> - Crop rectangle
> - Visible/hidden
> - Collision parameters (smaller hitbox, etc.)
> 6. Alternative forms of collision detecting (not limited to circles
> and rectangles).
> Possibly using algorithms such as quadtrees and spatial hashing.
> 7. Improved layering system.
> 8. Respecting blendmode flags are handled in all types of sprites.
> 9. Animated sprites:
> - Setting a group of images to cycle through in a time interval.
> - Animating visual attributes, a-la Kivy [3] or CSS transitions [4].
> 10. Events dispatching from groups to sprites.

Hi

Here my thoughts about your list:

1. the position should be two floats (wrapped either in a tuple or
vector class or just x,y attributes), but since the render position is
anyway different than the position (because of the offset/anchor) I
would suggest to calculate the render position on each draw call
(another pro for this is if you want to add subpixel rendering one day
this can be done with floats, but not with integers of the rect)
2. the sprites anchor point should be just an offset, not limited to
'topleft', 'midtop', 'topright',... and the other rect attributes
3. what would be the use case for this? the only thing I see would be a
hierarchy of sprites, so if you move the root, then all children are
moved too
4. dirty rendering is only useful if you don't scroll and if the area
covered with dirty rects is small compared to the screen, otherwise the
overhead of the dirty handling might eat the performance you want to
gain by dirty rects
5. I don't see how collision parameters fit a sprite? I think the
collision should be done on the model.... (okay, the sprite and the
model might be the same)
6. what should a sprite system really do?
7. layers are important, ideally you would have a 'z' attribute you can
change anytime in the code and that sprite is rendered at the right layer
8. blendmode flags, but also the source area
9. animation is whole other story.... I would just prepare hooks to
integrate easily an animation system. About the attributes: this would
be something to use tweens? Maybe a tweening lib would be better for
that, but as said, not sure if a sprite system should bother with that...
10. why would you bother with events in sprites? (unless the sprites is
model and rendering in one thing, which is not so good)


I think you should limit yourself to sprites stuff, not adding things
like events, animation or collision detection, which are done by an
engine. Also I'm not sure if the current implementation with groups is
the way to go. Because grouping sprites is a simple thing to do (just
use a list, for comfort a class with some methods that apply that
function to all of its sprites), but the hard thing is to have a
renderer that does implement all features and has still some performance.

Here a short list I would want for a sprite rendering system:

a. float position (if using scrolling, then you need a world_to_screen
and screen_to_world conversion methods which should be exchangable)
b. offset (anchor)
c. independent parallax factor for each axis
d. independent z layering
e. easy scrolling (deciding which sprites to draw should be done by the
engine logic because you can use so many different approaches...)
f. multiple viewports/cameras for split screen games
g. simple picking of a sprite from screen (even using scrolling/parallax)
h. hud rendering (those sprites need to be rendered differently because
no coordinate conversion is needed)
i. visibility on/off -> on should add it to the render list / off should
maybe remove the sprite from the render list (so the millions offscreen
sprites are not even known by the renderer until they are turned visible)
j. interpolated rendering (if using a fixed step update loop you might
want to render at a interpolated position, see:
http://gafferongames.com/game-physics/fix-your-timestep/ )
k. special rendering paths for special sprites, maybe you want some
sprites to use its custom 'draw' method
l. the sprite rect attribute should be in screen coordinates so you can
use it for picking (I suggest this because the number of sprites that
are in the render list is somewhat limited which makes the rect
collision methods usable, for a large world with many more entities you
dont want to use those collision method that iterate over all entities,
there you want something more clever like a quadtree or spatial hashing
as you suggested, but this is no concern of the renderer nor sprite
system because only the game logic handling the world can possibly know
which entites are in the visible area... also the collision detection
between the entities should be done by the game logic)
m. maybe an easy text sprite
n. maybe a simply group to apply some function to all of its sprites at
once (those groups might differ from the renderlist or there might be
multiple groups with overlapping contents...)
o. push/pop sprites in the render list (building a stack, is convenient
if you want to have a scene in between, just push the new sprites and
when you are done, just pop it once and the scene is rendered as before)

I admit, that I have a working implementation for most of the points I
listed here. After last pyweek I thought I need somthing that can
already do those things out of the box. I could provide some ideas for
implementation or even code for the interested.

~DR0ID


Radomir Dopieralski

unread,
Jun 1, 2012, 4:40:59 PM6/1/12
to pygame...@seul.org
PyGame handles per-sprite and per-pixel transparency with sprites just fine already.



Szymon

unread,
Jun 2, 2012, 12:41:01 AM6/2/12
to pygame...@seul.org
Float positions would be really nice.
About aggregated sprite class: every sprite could be tree node, with parent and child nodes, position relative to parent and visibility inherited from parent.

2012/6/1 Sagie Maoz <sa...@maoz.info>

Christopher Night

unread,
Jun 2, 2012, 10:46:18 AM6/2/12
to pygame...@seul.org
On Fri, Jun 1, 2012 at 2:29 PM, DR0ID <dr...@bluewin.ch> wrote:
On 01.06.2012 15:29, Sagie Maoz wrote:
2. Setting a sprite's anchor points for handling in movement, animation, collision etc.
5. New visual attributes for sprites:
   - Rotation angle
   - Scale  
2. the sprites anchor point should be just an offset, not limited to 'topleft', 'midtop', 'topright',... and the other rect attributes

I want to be able to specify "center" or "midbottom" for the sprite anchor without knowing the image's dimensions. And I want that anchor point to remain in the appropriate place even if the image is rotated, scaled, or flipped. I'm not sure that an offset would accomplish this, but if so, then that's okay.

-Christopher

Sagie Maoz

unread,
Jun 2, 2012, 1:08:38 PM6/2/12
to pygame...@seul.org
Hi all,

Thanks so much for all of the comments and suggestions. This is extremely helpful for my project at this stage.

I admit I'm not too educated about the whole subject, so let me know if any of my answers below need further research in your opinion.

Regarding adding GUI elements (David's suggestion) - I can see how important that would be, but I'd like to focus on basic game graphics for now. Also, there's another GSoC project by Sam Bull that approaches a GUI framework for Pygame.

As for collision detection (Nicholas' and DR0ID's emails): I agree with DR0ID's concerns about maintaining a clear scope for the project, and I can understand that collisions are more the engine's job than the sprite classes. However, as the current Sprite module includes many of the functions related to that, I thought I could get into that as part of my work.
I'm guessing that implementing a basic and naive code wouldn't be too hard, but the question remains would doing that be an elegant design.
I want to research how this kind of features is done on similar libraries. I would also love to get your thoughts on that. So this is still an open question for now.

Aggregated sprites: I think the use case DR0ID has mentioned is good enough for implementing that. I'm thinking about writing the aliens.py game so that the aliens are a group of sprites moving together, while each one could have a different behavior when needed.

Dirty rendering: Again, this doesn't seem to me as something that's too difficult to implement, and would definitely help any non-scrolling game, which I think is a pretty solid use case.

I gather that the most requested features are probably:

1. Better positioning, particularly using float values.
2. Anchor points.
3. Visual attributes.
4. A smarter layers system.
5. Sprite picking.

I will research each of these during the week.

If you have any more comments or additions please do reply to this thread.
I'll also be idling in #pygame most of the time and would love to chat.

DR0ID - I'll be happy to set a time to chat and learn more about all of your suggestions.

Thanks again,

-- 
Your friend in time,
Sagie Maoz

DR0ID

unread,
Jun 2, 2012, 1:50:31 PM6/2/12
to pygame...@seul.org
Hi

I agree, what I suggested is that both things should be possible: a general offset and/or specifying 'center' or 'midbottom' or....

I'm not sure right now how the math to maintain the point at the appropriate place. Maybe this needs some more specification for the different transformations (rotation, flip, scale).


~DR0ID

Valentine Blacker

unread,
Jun 2, 2012, 7:21:13 PM6/2/12
to pygame...@seul.org
One little thing; as far as item 9. goes, this might be implied, but it would be great if it was set up to easily handle subsurfaces (ie spritesheets) as well as individual images.

Christopher Night

unread,
Jun 2, 2012, 7:47:34 PM6/2/12
to pygame...@seul.org
Well the desired behavior is pretty straightforward to me. Say I specify a sprite's anchor as "midbottom", and the sprite's image has a single orange pixel at its mid-bottom. Then if I ask to draw the sprite at (200, 100), then that orange pixel should wind up at (200, 100) no matter how the sprite is transformed (maybe one pixel off because of rounding). The math shouldn't be too hard to work out from that.

-Christopher

DR0ID

unread,
Jun 4, 2012, 3:47:10 PM6/4/12
to pygame...@seul.org
Hi once again

In the mean time, I have implemented such a system that leaves the anchor where it is, but I run into a problem: the order of applying the transformations. It's not exactly the same if you first flip and then rotate or the other way around, first rotate and then flip. To see better what I'm talking about: http://imagebin.org/215001

What is more useful?

As for now my implementation does first rotate and then flip, because that looks like the behavior I would want if I write a platformer or similar game. I then have thought about how many cases a flip and rotation would be used on the same sprite at the same time and I think there are not that man occasions. But maybe I'm wrong.

As for scaling it does not matter when it occurs, although I use rotozoom (which has an annoying black border when rotate by a multiple of 90 degrees, which looks like the entire image is shifted by 1 or 2 pixels for whatever reason, bug! bug!, also not sure how transparency is handled by it).


~DR0ID

Davy Mitchell

unread,
Jun 18, 2012, 2:16:10 PM6/18/12
to pygame...@seul.org
Sorry if this is a bit late but I ran upon this thread on PyWeek
http://www.pyweek.org/d/3202/

In short, looking for build in way to stop certain sprites overlapping
i.e. specifiy some a solid.

Thanks,
Davy
Reply all
Reply to author
Forward
0 new messages