I’ve been very busy in the past couple of months. It’s been very educating, very productive - yet the time flew way too quickly!
Outside of my GSoC Pygame project, I have been finishing the semester and stepping into a final tests period which proves to be the hardest yet. I don’t remember ever being so exhausted day after day when I get home.
This is the main reason I have to admit that my project doesn’t quiet meet the plans to have most of the new Sprite class ready for the midterm evaluations.
Still, I have some good progress to show for, plus I’m fairly sure that after these hectic finals will pass, I will be able to catch up with my plans.
Let’s show off, then.
The sprites work plan consisted of adding 7 new features to Pygame’s Sprite class.
I wrote about implementing 2 of these (Anchor points and Better positioning) in my last post, Baby steps with Pygame sprites.
Since then, I have finished implementing 2 more, Visual attributes and Aggregated Sprite, which I’ll describe below, and also wrote most of the underlying code needed for the rest of the features.
You can check out my work in progress, including everything described here, in the
pygame-sprites GitHub repository.
New visual attributes
Sprite class now has several few new properties:
rotate, which control the way the sprite’s image is drawn on the screen:
visibilitydecides whether the image should be rendered or not. Default is
scaleis a float value determining the ratio between the size of the originally supplied image and the required size on the screen. Default is
rotateis an integer defining the degree by which to rotate the original image. Default is
To implement these attributes I used Python’s
property notation, which allows me to set custom getters and setters for standard class properties.
In addition to the visual attributes, the sprite’s
image attribute also uses the new notation, so that its custom getter function would return the transformed image, if a transformation is needed.
The visual transformations are done using
Sprites drawing themselves
In order to support features such as the
visibility attribute, automatic dirty rendering and others, I changed the way we actually draw the sprites, implementing the composite pattern.
Sprite’s new method
draw gets a surface as an argument and is responsible to draw the current sprite onto it.
draw method now uses the group’s sprites’
draw method if it’s available. Legacy code is still supported by preserving the old functionality if no
draw method is found.
I wrote a new class,
AggregatedSprite, which extends my
Sprite class and adds the functionality of holding a list of child sprites and propagating any change to them.
In a sense, an aggregated sprite is something between a sprite and a sprites group.
AggregatedSprite class has a
sprites property which holds the list of child sprites. This is a basic Python list which could be modified normally.
draw method calls all of the child sprites’
draw, like a group.
Setting a value to a visual attribute of an aggregated sprite would propagate this value down to all the child sprites.
This was done in
Sprite by wrapping the visual attributes’ setters with a method that would call an
on_visual_set callback if one exists.
AggregatedSprite uses this callback to set the make the same attribute change to all the child sprites.
Setting an aggregated sprite’s
(x, y) would use these values as offsets for all of the child sprites, that is, move them all from their original position by
I’m still missing 3 features here: Automatic dirty rendering, Sprite picking and Smarter layers.
The move to composite drawing of sprites holds most of the major changes needed for dirty rendering and layered groups, and so there’s little work left for these two to be done as well.
I still have to do some research on implementing Sprite picking, but I’m sure it will be pretty simple to do.
Early on, I saw that going full TDD is slowing me down, and I wanted to get stuff working as soon as possible. So I ditched writing tests until everything is more stable.
On of my most important tasks once I’m done with my last final would be to write tests for all of my changes.
This is a big task, but hopefully I could make use code of the demo games I wrote for each feature.
Some other TODOs:
- Anchor points: Use Rect’s anchor constants instead of my own.
- Anchor points: Handle negative values.
- Positions: Handle float values.
- Visual attributes: Add crop rectangle attribute.
- Some code cleanup, and way more documentation.
That’s about it.
I can’t wait until I’m done with my finals so that I can take this project to the next level (and the one after that, too).
Oh, one more TODO note to self: Blog about the project more. It helps.
As always, feel free to contact me with any question or idea, either here, by email or on #pygame in Freenode.