pygame  committed 1ac23db

examples and tutorials prerelease update

  • Participants
  • Parent commits 16c1fab
  • Branches default

Comments (0)

Files changed (9)

 # BREAK = change breaks existing code
 # BUG	= fixed a bug that was (or could have been) crashing
+December 15, 2001
+	small changes to sprite before release
 December 2, 2001
 	small protection for display Surfaces after display.quit()

File docs/index.html

 <li><a href=tut/MoveIt.html>MoveIt</a> - Help! How Do I Move An Image?
+<li><a href=tut/SpriteInto.html>SpriteInto</a> - Sprite Module Introduction
 <li><a href=tut/SurfarrayIntro.html>SurfarrayIntro</a> - Introduction to the surfarray module
 <li><a href=tut/newbieguide.html>newbieguide</a> - A Newbie Guide To Pygame
 <a href=ref/pygame_sprite.html#Group.copy>pygame.sprite.Group.copy</a> -            copy a group with all the same sprites<br>
 <a href=ref/pygame_sprite.html#Group.empty>pygame.sprite.Group.empty</a> -            remove all sprites<br>
 <a href=ref/pygame_sprite.html#Group.has>pygame.sprite.Group.has</a> -            ask if group has sprite<br>
-<a href=ref/pygame_sprite.html#Group.loop>pygame.sprite.Group.loop</a> -            return an object to loop each sprite<br>
 <a href=ref/pygame_sprite.html#Group.remove>pygame.sprite.Group.remove</a> -            remove sprite from group<br>
+<a href=ref/pygame_sprite.html#Group.sprites>pygame.sprite.Group.sprites</a> -            return an object to loop over each sprite<br>
 <a href=ref/pygame_sprite.html#Group.update>pygame.sprite.Group.update</a> -            call update for all member sprites<br>
 <a href=ref/pygame_sprite.html#Group>pygame.sprite.Group</a> - <b>(class)</b> - the Group class is a container for sprites<br>
 <a href=ref/pygame_sprite.html#GroupSingle>pygame.sprite.GroupSingle</a> - <b>(class)</b> - a group container that holds a single most recent item<br>
 <a href=ref/pygame_sprite.html#Sprite.kill>pygame.sprite.Sprite.kill</a> -            end life of sprite, remove from all groups<br>
 <a href=ref/pygame_sprite.html#Sprite.remove>pygame.sprite.Sprite.remove</a> -            remove a sprite from container<br>
 <a href=ref/pygame_sprite.html#Sprite>pygame.sprite.Sprite</a> - <b>(class)</b> - the base class for your visible game objects.<br>
-<a href=ref/pygame_sprite.html#spritecollide>pygame.sprite.spritecollide</a> -        collision detection between group and group<br>
+<a href=ref/pygame_sprite.html#groupcollide>pygame.sprite.groupcollide</a> -        collision detection between group and group<br>
 <a href=ref/pygame_sprite.html#spritecollide>pygame.sprite.spritecollide</a> -        collision detection between sprite and group<br>
 <a href=ref/pygame_surfarray.html#array2d>pygame.surfarray.array2d</a> - get a 2d array copied from a surface<br>
 <a href=ref/pygame_surfarray.html#array3d>pygame.surfarray.array3d</a> - get a 3d array copied from a surface<br>

File docs/ref/pygame_sprite.html

 containers must also have a member named "_spritegroup",
 which can be set to any dummy value.
-The term "sprite" is a holdover from older computer and
-game machines. These older boxes were unable to draw
-and erase normal graphics fast enough for them to work
-as games. These machines had special hardware to handle
-game like objects that needed to animate very quickly.
-These objects were called 'sprites' and had special
-limitations, but could be drawn and updated very fast.
-They usually existed in special overlay buffers in the
-video. These days computers have become generally fast
-enough to handle sprite like objects without dedicated
-hardware. The term sprite is still used to represent
-just about anything in a 2D game that is animated.
            ask if group has sprite</td></tr>
-<tr><td><a href=#Group.loop>Group.loop</a></td><td> -
-           return an object to loop each sprite</td></tr>
 <tr><td><a href=#Group.remove>Group.remove</a></td><td> -
            remove sprite from group</td></tr>
+<tr><td><a href=#Group.sprites>Group.sprites</a></td><td> -
+           return an object to loop over each sprite</td></tr>
 <tr><td><a href=#Group.update>Group.update</a></td><td> -
            call update for all member sprites</td></tr>
            remove a sprite from container</td></tr>
+<tr><td><a href=#groupcollide>groupcollide</a></td><td> -
+       collision detection between group and group</td></tr>
 <tr><td><a href=#spritecollide>spritecollide</a></td><td> -
        collision detection between sprite and group</td></tr>
-<tr><td><a href=#spritecollide>spritecollide</a></td><td> -
-       collision detection between group and group</td></tr>
            contained in the group
-<a name=Group.loop><font size=+2><b>Group.loop
+<a name=Group.remove><font size=+2><b>Group.remove
 </b></font><br><font size=+1><tt>
-pygame.sprite.Group.loop() -> iterator
+           Remove a sprite or sequence of sprites from a group.
+<a name=Group.sprites><font size=+2><b>Group.sprites
+</b></font><br><font size=+1><tt>
+pygame.sprite.Group.sprites() -> iterator
            Returns an object that can be looped over with
            a 'for' loop. (For now it is always a list, but
            objects, like iterators.)
-<a name=Group.remove><font size=+2><b>Group.remove
-</b></font><br><font size=+1><tt>
-           Remove a sprite or sequence of sprites from a group.
 <a name=Group.update><font size=+2><b>Group.update
 </b></font><br><font size=+1><tt>
            Remove the sprite from a group or sequence of groups.
-<a name=spritecollide><font size=+2><b>spritecollide
+<a name=groupcollide><font size=+2><b>groupcollide
 </b></font><br><font size=+1><tt>
-pygame.sprite.spritecollide(sprite, group, dokill)
-       given a sprite and a group of sprites, this will
-       return a list of all the sprites that intersect.
-       all sprites must have a "rect" method, which is a
-       rectangle of the sprite area. if the dokill argument
-       is true, the sprites that do collide will be
-       automatically removed from all groups.
-<a name=spritecollide><font size=+2><b>spritecollide
-</b></font><br><font size=+1><tt>
-pygame.sprite.spritecollide(sprite, group, dokill)
+pygame.sprite.groupcollide(sprite, group, dokill) -> dict
        given two groups, this will find the intersections
        between all sprites in each group. it returns a
        removed from all groups.
+<a name=spritecollide><font size=+2><b>spritecollide
+</b></font><br><font size=+1><tt>
+pygame.sprite.spritecollide(sprite, group, dokill) -> list
+       given a sprite and a group of sprites, this will
+       return a list of all the sprites that intersect.
+       all sprites must have a "rect" method, which is a
+       rectangle of the sprite area. if the dokill argument
+       is true, the sprites that do collide will be
+       automatically removed from all groups.

File docs/tut/SpriteInto.html

+TUTORIAL:Sprite Module Introduction
+<title>Pygame Tutorials - Sprite Module Intoduction</title>
+<h1 align="center"><font size="-1">Pygame Tutorials</font><br>
+Sprite Module Introduction</h1>
+<h2 align="center">by Pete Shinners<br>
+<font size="-1"></font></h2>
+<h3 align="center">Revision 1.0, December 15th, 2001</h3>
+ <br>
+   Pygame version 1.3 comes with a new module, pygame.sprite. This module
+is written in python and includes some higher level classes to manage your
+game objects. By using this module to it's full potential, you can easily
+manage and draw your game objects. The sprite classes are very optimized,
+so it's likely your game will run faster with the sprite module than without.<br>
+The sprite module is also meant to be very generic. It turns out you can
+use it with nearly any type of gameplay. All this flexibility comes with
+a slight penalty, it needs a little understanding to properly use it. The
+<a href="../ref/pygame_sprite.html">reference documentation</a> for the sprite
+module can keep you running, but you'll probably need a bit more explanation
+of how to use pygame.sprite in your own game.<br>
+Several of the pygame examples (like "chimp" and "aliens") have been updated
+to use the sprite module. You may want to look into those first to see what
+this sprite module is all about. The chimp module even has it's own line-by-line
+tutorial, which may help get more an understanding of programming with python
+and pygame.<br>
+Note that this introduction will assume you have a bit of experience programming
+with python, and are somewhat framiliar with the different parts of creating
+a simple game. In this tutorial the word "reference" is occasianally used.
+This represents a python variable. Variables in python are references, so
+you can have several variables all pointing to the same object.<br>
+<h2>History Lesson</h2>
+ The term "sprite" is a holdover from older computer and game machines. These
+older boxes were unable to draw and erase normal graphics fast enough for
+them to work as games. These machines had special hardware to handle game
+like objects that needed to animate very quickly. These objects were called
+'sprites' and had special limitations, but could be drawn and updated very
+fast. They usually existed in special overlay buffers in the video. These
+days computers have become generally fast enough to handle sprite like objects
+without dedicated hardware. The term sprite is still used to represent just
+about anything in a 2D game that is animated.<br>
+  <br>
+  <br>
+<h2>The Classes</h2>
+The sprite module comes with two main classes. The first is Sprite, which
+should be used as a base class for all your game objects. This class doesn't
+really do anything on its own, it just includes several functions to help
+mange the game object. The other type of class is Group. The Group class
+is a container for different Sprite objects. There are actually several different
+types of group classes. Some of the Groups can draw all the elements they
+contain, for example.<br>
+This is all there really is to it. We'll start with a description of what
+each type of class does, and then discuss the proper ways to use these two
+<h2>The Sprite Class</h2>
+As mentioned before, the Sprite class is designed to be a base class for
+all your game objects. You cannot really use it on its own, as it only has
+several methods to help it work with the different Group classes. The sprite
+keeps track of which groups it belongs to. The class constructor (__init__
+method) takes an argument of a Group (or list of Groups) the Sprite instance
+should belong to. You can also change the Group membership for the Sprite
+with the add() and remove() methods. There is also a groups() method, which
+returns a list of the current groups containing the sprite.<br>
+When using the your Sprite classes. It's best to think of them as "valid"
+or "alive" when they are belonging to one or more Groups. When you remove
+the instance from all groups pygame will clean up the object. (Unless you
+have your own references to the instance somewhere else.) The kill() method
+removes the sprite from all groups it belongs to. This will cleanly delete
+the sprite object. If you've put some little games together, you'll know
+sometimes cleanly deleting a game object can be tricky. The sprite also comes
+with an alive() method, which returns true if it is still a member of any
+<h2>The Group Class</h2>
+The Group class is just a simple container. Similar to the sprite, it has
+an add() and remove() method which can change which sprites belong to the
+group. You also can pass a sprite or list of sprites to the contructor (__init__
+method) to create a Group instance that contains some initial sprites.<br>
+The Group has a few other methods like empty() to remove all sprites from
+the group and copy() which will return a copy of the group with all the same
+members. Also the has() method will quickly check if the Group contains a
+sprite or list of sprites.<br>
+The other function you will use frequently is the sprites() method. This
+returns an object that can be looped on to access every sprite the group
+contains. Currently this is just a list of the sprites, but in later version
+of python this will likely use iterators for better performance.<br>
+As a shortcut, the Group also has an update() method, which will call an
+update() method on every sprite in the group. Passing the same arguments
+to each one. Usually in a game you need some function that updates the state
+of a game object. It's very easy to call your own methods using the Group.loop()
+method, but this is a shortcut that's used enough to be included. Also note
+that the base Sprite class has a "dummy" update() method that takes any sort
+of arguments and does nothing.<br>
+Lastly, the Group has a couple other methods that allow you to use it with
+the builtlin len() method, getting the number of sprites it contains. and
+the "truth" operator, which allows you to do "if mygroup:" to check if the
+group has any sprites.<br>
+<h2>Mixing Them Together</h2>
+At this point the two classes seem pretty basic. Not doing a lot more than
+you can do with a simple list and your own class of game objects. But there
+are some big advantages to using the Sprite and Group together. A sprite
+can belong to as many groups as you want. Remember as soon as it belongs
+to no groups, it will usually be cleared up (unless you have other "non-group"
+references to that object)<br>
+The first big thing is a fast simple way to categorize sprites. For example,
+say we had a pacman-like game. We could make separate groups for the different
+types of objects in the game. Ghosts, Pac, and Pellets. When pac eats a power
+pellet, we can change the state for all ghost objects by effecting everything
+in the Ghost group. This is quicker and simpler than looping through a list
+of all the game objects and checking which ones are ghosts.<br>
+Adding and removing groups and sprites from each other is a very fast operation.
+Much quicker than using lists to store everything. Therefore you can very
+efficiently change group memberships. Therefore you can use groups to work
+like simple attributes for each game object. Instead of tracking some attribute
+like "close_to_player" for a bunch of enemy objects, you could add them to
+a separate group. Then when you need to access all the enemies that are near
+the player, you already have a list of them, instead of going through a list
+of all the enemies, checking for the "close_to_player" flag. Later on your
+game could add multiple players, and instead of adding more "close_to_player2",
+"close_to_player3" attributes, you can easily add them to different groups
+for each player.<br>
+Another important benefit of using the Sprites and Groups, the groups cleanly
+handle the deleting (or killing) of game objects. In a game where many objects
+are referencing other objects, sometimes deleting an object can be the hardest
+part, since it can't go away until it is not referenced by anyone. Say we
+have an object that is "chasing" another object. The chaser can keep a simple
+Group that references the object (or objects) it is chasing. If the object
+is chasee happens to be destroyed, we don't need to worry about notifying
+the chaser to stop chasing. The chaser can see for itself that its group
+is now empty, and perhaps find a new target.<br>
+Again, the thing to remember is that adding and removing sprites from groups
+is a very cheap/fast operation. You may be best off by adding many groups
+to contain and organize your game objects. Some could even be empty for large
+portions of the game, there isn't any penalties for managing your game like
+<h2>The Many Group Types</h2>
+The above examples and reasons to use Sprites and Groups are only a tip of
+the iceberg. The other huge benefit is that the sprite module comes with
+several different type of Groups. These groups all work just like a regular
+old Group, but they also have added functionality (or slightly different
+functionality). Here's a list of the Group classes included with the sprite
+This is the standard "no frills" group mainly explained above. Most of the
+other Groups are derived from this one, but not all.<br>
+  <br>
+  <b>GroupSingle<br>
+  </b>This works exactly like the regular Group class, but it only contains
+the most recently added sprite. Therefore when you add a sprite to this group,
+it "forgets" about any previous sprites it had. Therefore it always contains
+only one or zero sprites.<br>
+  <br>
+  <b>RenderPlain<br>
+  </b>This is a standard group derived from Group. It has a draw() method
+that draws all the sprites it contains to the screen (or any Surface). For
+this to work, it requires all sprites it contains to have a "image" and "rect"
+attributes. It uses these to know what to blit, and where to blit it. <br>
+  <br>
+  <b>RenderClear<br>
+  </b>This is derived from the RenderPlain group, and adds a method named
+clear(). This will erase the previous position of all drawn sprites. It uses
+a background image to fill in the areas where the sprite were. It is smart
+enough to handle deleted sprites and properly clear them from the screen
+when the clear() method is called.<br>
+  <br>
+  <b>RenderUpdates</b><br>
+This is the cadillac of rendering Groups. It is inherited from RenderClear,
+but changes the draw() method to also return a list of Rects, which represent
+all the areas onscreen that have been changed.<br>
+  <br>
+  </blockquote>
+That is the list of different groups available We'll discuss more about these
+rendering groups in the next section. There's nothing stopping you from creating
+your own Group classes as well. They are just python code, so you can inherit
+from one of these and add/change whatever you want. In the future I hope
+we can add a couple more Groups to this list. A GroupMulti which is like
+the GroupSingle, but can hold up to a given number of sprites (in some sort
+of circular buffer?). Also a super-render group that can clear the position
+of the old sprites without needing a background image to do it (by grabbing
+a copy of the screen before blitting). Who knows really, but in the future
+we can add more useful classes to this list.<br>
+  <br>
+  <h2>The Rendering Groups</h2>
+From above we can see there are three different rendering groups. We could
+probably just get away with the RenderUpdates one, but it adds overhead not
+really needed for something like a scrolling game. So we have a couple tools
+here, pick the right one for the right job.<br>
+  <br>
+For a scrolling type game, where the background completely changes every
+frame. We obviously don't need to worry about python's update rectangles
+in the call to display.update(). You should definitely go with the RenderPlain
+group here to manage your rendering.<br>
+  <br>
+For games where the background is more stationary, you definitely don't want
+pygame updating the entire screen (since it doesn't need to). This type of
+game usually involves erasing the old position of each object, then drawing
+it in a new place for each frame. This way we are only changing what is necessary.
+Most of the time you will just want to use the RenderUpdates class here.
+Since you will also want to pass this list of changes to the display.update()
+function. In the case where you have a hardware surface, or hardware doublebuffering,
+you don't need to worry about these types of updates, so you can just use
+the RenderClear, which doesn't have the overhead of calculating changed areas.<br>
+  <br>
+Also note that the RenderUpdates class also does a good job an minimizing
+overalapping areas in the list of updated rectangles. If the previous position
+and current position of an object overlap, it will merge them into a single
+rectangle. Combine this with the fact that is properly handles deleted objects
+and this is one powerful Group class. If you've written a game that manages
+the changed rectangles for the objects in a game, you know this the cause
+for a lot of messy code in your game. Especially once you start to throw
+in objects that can be deleted at anytime. All this work is reduced down
+to a clear() and draw() method with this monster class. Plus with the overlap
+checking, it is likely faster than if you did it yourself.<br>
+  <br>
+  <h2>Collision Detection</h2>
+The sprite module also comes with two very generic collision detection functions.
+For more complex games, these really won't work for you, but you can easily
+grab the sourcecode for them, and modify them as needed.<br>
+Here's a summary of what they are, and what they do.<br>
+  <blockquote><b>spritecollide(sprite, group, dokill) -&gt; list<br>
+    </b>This checks for collisions between a single sprite and the sprites
+in a group. It requires a "rect" attribute for all the sprites used. It returns
+a list of all the sprites that overlap with the first sprite. The "dokill"
+argument is a boolean argument. If it is true, the function will call the
+kill() method on all the sprites. This means the last reference to each sprite
+is probably in the returned list. Once the list goes away so do the sprites.
+A quick example of using this in a loop,<br>
+    <pre>	&gt;&gt;&gt; for bomb in sprite.spritecollide(player, bombs, 1):<br>	...<br>	...     Explosion(bomb, 0)<br></pre>
+This finds all the sprites in the "bomb" group that collide with the player.
+Because of the "dokill" argument it deletes all the crashed bombs. For each
+bomb that did collide, it plays a "boom" sound effect, and creates a new
+Explosion where the bomb was. (Note, the Explosion class here knows to add
+each instance to the appropriate class, so we don't need to store it in a
+variable, that last line might feel a little "funny" to you python programmers.<br>
+    <br>
+    <b>groupcollide(group1, group2, dokill1, dokill2) -&gt; dictionary</b><br>
+This is similar to the spritecollide function, but a little more complex.
+It checks for collisions for all the sprites in one group, to the sprites
+in another. There is a dokill argument for the sprites in each list. When
+dokill1 is true, the colliding sprites in group1 will be kill()ed. When dokill2
+is true, we get the same results for group2. The dictionary it returns works
+like this; each key in the dictionary is a sprite from group1 that had a
+collision. The value for that key is a list of the sprites that it collided
+with. Perhaps another quick code sample explains it best<br>
+    <pre>	&gt;&gt;&gt; for alien in sprite.groupcollide(aliens,&nbsp;shots, 1, 1).keys()<br>	...<br>	...     Explosion(alien, 0)<br>	...     kills += 1<br></pre>
+This code checks for the collisions between player bullets and all the aliens
+they might intersect. In this case we only loop over the dictionary keys,
+but we could loop over the values() or items() if we wanted to do something
+to the specific shots that collided with aliens. If we did loop over the
+values() we would be looping through lists that contain sprites. The same
+sprite may even appear more than once in these different loops, since the
+same "shot" could have collided against multiple "aliens".<br>
+    <br>
+    <br>
+    </blockquote>
+Those are the basic collision functions that come with pygame. It should
+be easy to roll your own that perhaps use something differen than the "rect"
+attribute. Or maybe try to fine-tweak your code a little more by directly
+effecting the collision object, instead of building a list of the collision?
+The code in the sprite collision functions is very optimized, but you could
+speed it up slightly by taking out some functionality you don't need.<br>
+    <br>
+    <h2>Advanced Appendix</h2>
+    <p>The Sprite and Group classes are very flexible, it should be very
+straightforward to derive from then and make your own. Although really there's
+no need to inherit from them. You could create your own class entirely, or
+even use C extension objects. Definitely spend time with the source in the
+sprite module if yo plan to do this sort of thing.&nbsp;Here's a list of
+what's required for a "compatible" Sprite and Group. </p>
+    <p>The sprite objects only "require" two methods. "add_internal" and
+"remove_internal". These are called by the Group classes when they are removing
+a sprite from themselves. The add_internal() and remove_internal() have a
+single argument which is a group. Your sprite also probably will need some
+way to also keep track of the groups it belongs to. You will likely want
+to try to match the other methods and arguments to the real Sprite class,
+but if you're not going to use those methods, you sure don't need them.&nbsp;</p>
+    <p>It is almost the same requirements for creating your own Group. In
+fact, if you look at the source you'll see the GroupSingle isn't derived
+from the Group class, it just implements the same methods so you can't really
+tell the difference. Again you need an "add_internal" and "remove_internal"
+method that the sprites call when they want to belong or remove themselves
+from the group. The add_internal() and remove_internal() have a single argument
+which is a sprite. The only other requirement for the Group classes is they
+have a dummy attribute named "_spritegroup". It doesn't matter what the value
+is, as long as the attribute is present. The Sprite classes can look for
+this attribute to determine the difference between a "group" and any ordinary
+python container. (This is important, because several sprite methods can
+take an argument of a single group, or a sequence of groups. Since they both
+look similar, this is the most flexible way to "see" the difference.)</p>
+    <p>You may just want to read through the code for the sprite module.
+While the code is a bit "tuned", it's got enough comments to help you follow
+along. There's even a todo section in the source if your feeling like contributing.</p>
+    <blockquote><tt><br>
+              </tt></blockquote>
+      </body>
+      </html>

File examples/Readme.txt

     blitting routines are not as optimized as they should/could be,
     but the code is easier to follow, and it plays quick enough.
-winaliens.pyw - Just an example launcher for windows platforms.
-	with the .PYW extension, windows will not open a DOS box
-	for the running python script, giving everything a more
-	professional look. (the script will run fine on linux too)
-	this script launches in fullscreen mode
- - A simple starfield example. You can change the center of
     perspective by leftclicking the mouse on the screen.

File examples/

 #! /usr/bin/env python
-"""This is a pretty full-fledged example of a miniature
-game with pygame. It's not what you'd call commercial grade
-quality, but it does demonstrate just about all of the
-important modules for pygame. Note the methods it uses to
-detect the availability of the font and mixer modules.
-This example actually gets a bit large. A better starting
-point for beginners would be the example."""
+import random, os.path, sys
+#import basic pygame modules
+import pygame, pygame.image, pygame.transform, pygame.sprite
+from pygame.locals import *
-import whrandom, os.path, sys
-import pygame, pygame.image, pygame.transform
-from pygame.locals import *
+#see if we can load more than standard BMP
+if not pygame.image.get_extended():
+    raise SystemExit, "Sorry, extended image module required"
+#try importing pygame optional modules
+    import pygame.font as font
+except ImportError:
+    print 'Warning, no fonts'
+    font = None
     import pygame.mixer
-    pygame.mixer.pre_init(11025)
+except ImportError:
+    print 'Warning, no sound'
     pygame.mixer = None
-#see if we can get some font lovin'
-    import pygame.font
-    font = pygame.font
-except ImportError:
-    font = None
-if not pygame.image.get_extended():
-    raise SystemExit, "Requires the extnded image loading from SDL_image"
+#game constants
+MAX_SHOTS      = 2      #most player bullets onscreen
+ALIEN_ODDS     = 29     #chances a new alien appears
+ALIEN_RELOAD   = 12     #frames between new aliens
+BOMB_ODDS      = 200
+SCREENRECT     = Rect(0, 0, 640, 480)
-MAX_SHOTS      = 2
-SHOT_SPEED     = 9
-BOMB_SPEED     = 9
-MAX_ALIENS     = 30
-ALIEN_ODDS     = 29
-SCREENRECT     = Rect(0, 0, 640, 480)
-ANIMCYCLE      = 12
-BOMB_ODDS      = 130
-DANGER         = 10
-SORRYSCORE     = 15
-GOODSCORE      = 33
-#some globals for friendly access
-dirtyrects = [] # list of update_rects
-class Img: pass # container for images
-class Snd: pass # container for sounds
-#first, we define some utility functions
-class dummysound:
-    def play(self): pass
-def load_image(file, transparent=0):
+def load_image(file):
     "loads an image, prepares it for play"
     file = os.path.join('data', file)
         surface = pygame.image.load(file)
     except pygame.error:
         raise SystemExit, 'Could not load image "%s" %s'%(file, pygame.get_error())
-    if transparent:
-        corner = surface.get_at((0, 0))
-        surface.set_colorkey(corner, RLEACCEL)
     return surface.convert()
+def load_images(*files):
+    return [load_image(file) for file in files]
+class dummysound:
+    def play(self): pass
 def load_sound(file):
     if not pygame.mixer: return dummysound()
     file = os.path.join('data', file)
     except pygame.error:
         print 'Warning, unable to load,', file
     return dummysound()
-last_tick = 0
-ticks_per_frame = int((1.0 / FRAMES_PER_SEC) * 1000.0)
-def wait_frame():
-    "wait for the correct fps time to expire"
-    global last_tick, ticks_per_frame
-    now = pygame.time.get_ticks()
-    wait = ticks_per_frame - (now - last_tick)
-    pygame.time.delay(wait)
-    last_tick = pygame.time.get_ticks()
-# The logic for all the different sprite types
-class Actor:
-    "An enhanced sort of sprite class"
-    def __init__(self, image):
-        self.image = image
-        self.rect = image.get_rect()
-        self.clearrect = self.rect
-    def update(self):
-        "update the sprite state for this frame"
-        pass
-    def draw(self, screen):
-        "draws the sprite into the screen"
-        r = screen.blit(self.image, self.rect)
-        dirtyrects.append(r.union(self.clearrect))
-    def erase(self, screen, background):
-        "gets the sprite off of the screen"
-        r = screen.blit(background, self.rect, self.rect)
-        self.clearrect = r
-class Player(Actor):
-    "Cheer for our hero"
+class Player(pygame.sprite.Sprite):
+    speed = 11
+    bounce = 24
+    gun_offset = 11
+    images = []
     def __init__(self):
-        Actor.__init__(self, Img.player[0])
-        self.alive = 1
+        pygame.sprite.Sprite.__init__(self, self.containers)
+        self.image = self.images[0]
+        self.rect = self.image.get_rect()
         self.reloading = 0
         self.rect.centerx = SCREENRECT.centerx
         self.rect.bottom = SCREENRECT.bottom - 1
         self.origtop =
+        self.facing = -1
+    def update(self): pass
     def move(self, direction):
-        self.rect = self.rect.move(direction*PLAYER_SPEED, 0).clamp(SCREENRECT)
+        if direction: self.facing = direction
+        self.rect.move_ip(direction*self.speed, 0)
+        self.rect = self.rect.clamp(SCREENRECT)
         if direction < 0:
-            self.image = Img.player[0]
+            self.image = self.images[0]
         elif direction > 0:
-            self.image = Img.player[1]
- = self.origtop - (self.rect.left/BOUNCEWIDTH%2)
+            self.image = self.images[1]
+ = self.origtop - (self.rect.left/self.bounce%2)
+    def gunpos(self):
+        pos = self.facing*self.gun_offset + self.rect.centerx
+        return pos,
-class Alien(Actor):
-    "Destroy him or suffer"
+class Alien(pygame.sprite.Sprite):
+    speed = 15 
+    animcycle = 12
+    images = []
     def __init__(self):
-        Actor.__init__(self, Img.alien[0])
-        self.facing = whrandom.choice((-1,1)) * ALIEN_SPEED
+        pygame.sprite.Sprite.__init__(self, self.containers)
+        self.image = self.images[0]
+        self.rect = self.image.get_rect()
+        self.facing = random.choice((-1,1)) * Alien.speed
         self.frame = 0
         if self.facing < 0:
             self.rect.right = SCREENRECT.right
     def update(self):
-        global SCREENRECT
-        self.rect[0] = self.rect[0] + self.facing
+        self.rect.move_ip(self.facing, 0)
         if not SCREENRECT.contains(self.rect):
             self.facing = -self.facing;
    = self.rect.bottom + 1
             self.rect = self.rect.clamp(SCREENRECT)
         self.frame = self.frame + 1
-        self.image = Img.alien[self.frame/ANIMCYCLE%3]
+        self.image = self.images[self.frame/self.animcycle%3]
-class Explosion(Actor):
-    "Beware the fury"
-    def __init__(self, actor, longer=0):
-        Actor.__init__(self, Img.explosion[0])
+class Explosion(pygame.sprite.Sprite):
+    defaultlife = 10
+    animcycle = 3
+    images = []
+    def __init__(self, actor, longer):
+        pygame.sprite.Sprite.__init__(self, self.containers)
+        self.image = self.images[0]
+        self.rect = self.image.get_rect()
+ = self.defaultlife * (longer+1) =
-        if longer:
-   = * 2
     def update(self): = - 1
-        self.image = Img.explosion[]
+        self.image = self.images[]
+        if <= 0: self.kill()
-class Shot(Actor):
-    "The big payload"
-    def __init__(self, player):
-        Actor.__init__(self, Img.shot)
-        self.rect.centerx = player.rect.centerx
- = - 10
-        if player.image is Img.player[0]:
-            self.rect.left = self.rect.left + BULLET_OFFSET
-        elif player.image is Img.player[1]:
-            self.rect.left = self.rect.left - BULLET_OFFSET
+class Shot(pygame.sprite.Sprite):
+    speed = -13
+    images = []
+    def __init__(self, pos):
+        pygame.sprite.Sprite.__init__(self, self.containers)
+        self.image = self.images[0]
+        self.rect = self.image.get_rect()
+        self.rect.midbottom = pos
     def update(self):
-        self.rect = self.rect.move(0, -SHOT_SPEED)
-class Bomb(Actor):
-    "The big payload"
+        self.rect.move_ip(0, self.speed)
+        if <= 0:
+            self.kill()
+class Bomb(pygame.sprite.Sprite):
+    speed = 11
+    images = []
     def __init__(self, alien):
-        Actor.__init__(self, Img.bomb)
+        pygame.sprite.Sprite.__init__(self, self.containers)
+        self.image = self.images[0]
+        self.rect = self.image.get_rect()
         self.rect.centerx = alien.rect.centerx
         self.rect.bottom = alien.rect.bottom + 5
     def update(self):
-        self.rect = self.rect.move(0, BOMB_SPEED)
+        self.rect.move_ip(0, self.speed)
+        if self.rect.bottom >= 470:
+            Explosion(self, 0)
+            self.kill()
-class Danger(Actor):
-    "Here comes trouble"
-    def __init__(self):
-        Actor.__init__(self, Img.danger)
- = 1
-        self.tick = 0
- =[0]-30, 30
-        self.startleft = self.rect.left
-    def update(self):
-        self.tick = self.tick + 1
-        self.rect.left = self.startleft + (self.tick/25%2)*60
 def main(winstyle = 0):
-    "Run me for adrenaline"
-    global dirtyrects
-    # Initialize SDL components
+    # Initialize pygame
-    # Attempt to create a window icon
-    try:
-        icon = pygame.image.load(os.path.join('data', 'alien1.gif'))
-        icon.set_colorkey(icon.get_at((0, 0)))
-        icon = pygame.transform.scale(icon, (32, 32))
-        pygame.display.set_icon(icon)
-    except pygame.error:
-        pass
     # Set the display mode
+    winstyle = 0  #|FULLSCREEN
     bestdepth = pygame.display.mode_ok(SCREENRECT.size, winstyle, 32)
     screen = pygame.display.set_mode(SCREENRECT.size, winstyle, bestdepth)
-    if pygame.joystick.get_init() and pygame.joystick.get_count():
-        joy = pygame.joystick.Joystick(0)
-        joy.init()
-        if not joy.get_numaxes() or not joy.get_numbuttons():
-            print 'warning: joystick disabled. requires at least one axis and one button'
-            joy.quit()
-            joy = None
-    else:
-        joy = None
+    #Load images, assign to sprite classes
+    #(do this before the classes are used, after screen setup)
+    img = load_image('player1.gif')
+    Player.images = [img, pygame.transform.flip(img, 1, 0)]
+    img = load_image('explosion1.gif')
+    Explosion.images = [img, pygame.transform.flip(img, 1, 1)]
+    Alien.images = load_images('alien1.gif', 'alien2.gif', 'alien3.gif')
+    Bomb.images = [load_image('bomb.gif')]
+    Shot.images = [load_image('shot.gif')]
-    # Check that audio actually initialized
-    if pygame.mixer and not pygame.mixer.get_init():
-        pygame.mixer = None
-    if not pygame.mixer:
-        print 'Warning, sound disabled'
+    #decorate the game window
+    icon = pygame.transform.scale(Alien.images[0], (32, 32))
+    pygame.display.set_icon(icon)
+    pygame.display.set_caption('Pygame Aliens')
+    pygame.mouse.set_visible(0)
-    # Load the Resources
-    Img.background = load_image('background.gif', 0)
-    Img.shot = load_image('shot.gif', 1)
-    Img.bomb = load_image('bomb.gif', 1)
-    Img.danger = load_image('danger.gif', 1)
-    Img.alien = load_image('alien1.gif', 1), \
-                load_image('alien2.gif', 1), \
-                load_image('alien3.gif', 1)
-    img = load_image('player1.gif', 1)
-    Img.player = img, pygame.transform.flip(img, 1, 0)
-    img = load_image('explosion1.gif', 1)
-    Img.explosion = img, pygame.transform.flip(img, 1, 1)
-    Img.explosion[0].set_alpha(128, RLEACCEL)
-    Img.explosion[1].set_alpha(128, RLEACCEL)
-    Img.danger.set_alpha(128, RLEACCEL)
-    Snd.explosion = load_sound('boom.wav')
-    Snd.shot = load_sound('car_door.wav')
-    # Create the background
+    #create the background, tile the bgd image
+    bgdtile = load_image('background.gif')
     background = pygame.Surface(SCREENRECT.size)
-    for x in range(0, SCREENRECT.width, Img.background.get_width()):
-        background.blit(Img.background, (x, 0))
+    for x in range(0, SCREENRECT.width, bgdtile.get_width()):
+        background.blit(bgdtile, (x, 0))
     screen.blit(background, (0,0))
-    pygame.mouse.set_visible(0)
-    # Initialize Game Actors
-    player = Player()
-    aliens = [Alien()]
-    shots = []
-    bombs = []
-    explosions = []
-    misc = []
-    alienreload = ALIEN_RELOAD
-    difficulty = DIFFICULTY
-    bomb_odds = BOMB_ODDS
-    kills = 0
-    # Soundtrack
+    #load the sound effects
+    boom_sound = load_sound('boom.wav')
+    shoot_sound = load_sound('car_door.wav')
     if pygame.mixer:
         music = os.path.join('data', 'house_lo.wav')
-    # Main loop
-    while player.alive or explosions:
-        wait_frame()
+    # Initialize Game Groups
+    aliens = pygame.sprite.Group()
+    shots = pygame.sprite.Group()
+    bombs = pygame.sprite.Group()
+    all = pygame.sprite.RenderUpdates()
+    lastalien = pygame.sprite.GroupSingle()
-        # Gather Events
+    #assign default groups to each sprite class
+    Player.containers = all
+    Alien.containers = aliens, all, lastalien
+    Shot.containers = shots, all
+    Bomb.containers = bombs, all
+    Explosion.containers = all
+    #Create Some Starting Values
+    alienreload = ALIEN_RELOAD
+    kills = 0
+    clock = pygame.time.Clock()
+    #initialize our starting sprites
+    player = Player()
+    Alien() #note, this 'lives' because it goes into a sprite group
+    while player.alive():
+        # update keyboard state
         keystate = pygame.key.get_pressed()
         if keystate[K_ESCAPE] or pygame.event.peek(QUIT):
+        # clear/erase the last drawn sprites
+        all.clear(screen, background)
+        #update all the sprites
+        all.update()
-        if difficulty:
-            difficulty = difficulty - 1
-        else:
-            difficulty = DIFFICULTY
-            if bomb_odds > DANGER:
-                bomb_odds = bomb_odds - 1
-                if bomb_odds == DANGER:
-                    misc.append(Danger())
-        # Clear screen and update actors
-        for actor in [player] + aliens + shots + bombs + explosions + misc:
-            actor.erase(screen, background)
-            actor.update()
-        # Clean Dead Explosions and Bullets
-        for e in explosions:
-            if <= 0:
-                dirtyrects.append(e.clearrect)
-                explosions.remove(e)
-        for s in shots:
-            if <= 0:
-                dirtyrects.append(s.clearrect)
-                shots.remove(s)
-        for b in bombs:
-            if b.rect.bottom >= 470:
-                if player.alive:
-                    explosions.append(Explosion(b))
-                dirtyrects.append(b.clearrect)
-                bombs.remove(b)
-        # Handle Input, Control Tank
-        if player.alive:
-            direction = keystate[K_RIGHT] - keystate[K_LEFT]
-            firing = keystate[K_SPACE]
-            if joy:
-                direction = direction + joy.get_axis(0)
-                firing = firing + joy.get_button(0)
-            player.move(direction)
-            if not player.reloading and firing and len(shots) < MAX_SHOTS:
-                shots.append(Shot(player))
-            player.reloading = firing
+        #handle player input
+        direction = keystate[K_RIGHT] - keystate[K_LEFT]
+        player.move(direction)
+        firing = keystate[K_SPACE]
+        if not player.reloading and firing and len(shots) < MAX_SHOTS:
+            Shot(player.gunpos())
+        player.reloading = firing
         # Create new alien
         if alienreload:
-            alienreload = alienreload - 1
-        elif player.alive and not int(whrandom.random() * ALIEN_ODDS):
-            aliens.append(Alien())
+            alienreload -= 1
+        elif not int(random.random() * ALIEN_ODDS):
+            Alien()
             alienreload = ALIEN_RELOAD
         # Drop bombs
-        if player.alive and aliens and not int(whrandom.random() * bomb_odds):
-            bombs.append(Bomb(aliens[-1]))
+        if lastalien and not int(random.random() * BOMB_ODDS):
+            Bomb(lastalien.sprite)
         # Detect collisions
-        alienrects = []
-        for a in aliens: alienrects.append(a.rect)
+        for a in pygame.sprite.spritecollide(player, aliens, 1):
+            Explosion(a, 0)
+            Explosion(player, 1)
+            kills += 1
+            player.kill()
-        hit = player.rect.collidelist(alienrects)
-        if hit != -1:
-            alien = aliens[hit]
-            explosions.append(Explosion(alien))
-            explosions.append(Explosion(player, 1))
-            dirtyrects.append(alien.clearrect)
-            aliens.remove(alien)
-            kills = kills + 1
-            player.alive = 0
-        for shot in shots:
-            hit = shot.rect.collidelist(alienrects)
-            if hit != -1:
-                alien = aliens[hit]
-                explosions.append(Explosion(alien))
-                dirtyrects.append(shot.clearrect)
-                dirtyrects.append(alien.clearrect)
-                shots.remove(shot)
-                aliens.remove(alien)
-                kills = kills + 1
-                break
-        bombrects = []
-        for b in bombs: bombrects.append(b.rect)
+        for alien in pygame.sprite.groupcollide(shots, aliens, 1, 1).keys():
+            Explosion(alien, 0)
+            kills += 1
+        for bomb in pygame.sprite.spritecollide(player, bombs, 1):         
+            Explosion(bomb, 0)
-        hit = player.rect.collidelist(bombrects)
-        if hit != -1:
-            bomb = bombs[hit]
-            explosions.append(Explosion(bomb))
-            explosions.append(Explosion(player, 1))
-            dirtyrects.append(bomb.clearrect)
-            bombs.remove(bomb)
-            player.alive = 0
+        #draw the scene
+        dirty = all.draw(screen)
+        pygame.display.update(dirty)
-        #prune the explosion list
-        diff = len(explosions) - MAX_EXPLOSIONS
-        if diff > 0:
-            for x in range(diff):
-                dirtyrects.append(explosions[x].clearrect)
-            explosions = explosions[diff:]
+        #cap the framerate
+        clock.tick(30)
-        # Draw everybody
-        for actor in [player] + bombs + aliens + shots + explosions + misc:
-            actor.draw(screen)
+    pygame.time.delay(1000)
-        pygame.display.update(dirtyrects)
-        dirtyrects = []
+#no need to clean up, python automatically cleans up after us
-    if pygame.mixer:
-    #attempt to show game over (if font installed)
-    if font:
-        f = font.Font(None, 100) #None means default font
-        f.set_italic(1)
-        text = f.render('Game Over', 1, (200, 200, 200))
-        textrect = Rect((0, 0), text.get_size())
- =
-        screen.blit(text, textrect)
-        pygame.display.flip()
-    #wait a beat
-    if pygame.mixer:
-        while
-            pygame.time.delay(200)
-    else:
-        pygame.time.delay(800)
-    #scoreboard
-    print 'Total Kills =', kills
-    if kills <= SORRYSCORE: print 'Sorry!'
-    elif kills >= GOODSCORE: print 'Excellent!'
-    elif kills >= GOODSCORE-6: print 'Almost Excellent!'
+#call the "main" function if running this script
+if __name__ == '__main__': main()
-#if python says run, let's run!
-if __name__ == '__main__':
-    main()

File examples/

 #/usr/bin/env python
-"""This simple example is used for the line-by-line tutorial
+This simple example is used for the line-by-line tutorial
 that comes with pygame. It is based on a 'popular' web banner.
 Note there are comments here, but for the full explanation, 
-follow along in the tutorial. This code contains little error
-checking to make it a little clearer. The full tutorial explains
-where and how better error checking will help."""
+follow along in the tutorial.
-#Import Modoules
-import os
-import pygame, pygame.font, pygame.image, pygame.mixer
+#Import Modules
+import os, sys
+import pygame, pygame.sprite, pygame.transform, pygame.image
 from pygame.locals import *
+    import pygame.font
+except ImportError:
+    print 'Warning, fonts disabled'
+    pygame.font = None
+    import pygame.mixer
+except ImportError:
+    print 'Warning, sound disabled'
+    pygame.mixer = None
-#Resource Filenames
-chimpfile = os.path.join('data', 'chimp.bmp')
-fistfile = os.path.join('data', 'fist.bmp')
-hitfile = os.path.join('data', 'punch.wav')
-missfile = os.path.join('data', 'whiff.wav')
+#functions to create our resources
+def load_image(name, colorkey=None):
+    fullname = os.path.join('data', name)
+    try:
+        image = pygame.image.load(fullname)
+    except pygame.error, message:
+        print 'Cannot load image:', name
+        raise SystemExit, message
+    image = image.convert()
+    if colorkey is not None:
+        if colorkey is -1:
+            colorkey = image.get_at((0,0))
+        image.set_colorkey(colorkey, RLEACCEL)
+    return image, image.get_rect()
+def load_sound(name):
+    class NoneSound:
+        def play(self): pass
+    if not pygame.mixer:
+        return NoneSound()
+    fullname = os.path.join('data', name)
+    try:
+        sound = pygame.mixer.Sound(fullname)
+    except pygame.error, message:
+        print 'Cannot load sound:', wav
+        raise SystemExit, message
+    return sound
+#classes for our game objects
+class Fist(pygame.sprite.Sprite):
+    """moves a clenched fist on the screen, following the mouse"""
+    def __init__(self):
+        pygame.sprite.Sprite.__init__(self) #call Sprite initializer
+        self.image, self.rect = load_image('fist.bmp', -1)
+        self.rect = self.image.get_rect()
+        self.punching = 0
+    def update(self):
+        "move the fist based on the mouse position"
+        pos = pygame.mouse.get_pos()
+        self.rect.midtop = pos
+        if self.punching:
+            self.rect.move_ip(5, 10)
+    def punch(self, target):
+        "returns true if the fist collides with the target"
+        if not self.punching:
+            self.punching = 1
+            hitbox = self.rect.inflate(-5, -5)
+            return hitbox.colliderect(target.rect)
+    def unpunch(self):
+        "called to pull the fist back"
+        self.punching = 0
+class Chimp(pygame.sprite.Sprite):
+    """moves a monkey critter across the screen. it can spin the
+       monkey when it is punched."""
+    def __init__(self):
+        pygame.sprite.Sprite.__init__(self) #call Sprite intializer
+        self.image, self.rect = load_image('chimp.bmp', -1)
+        screen = pygame.display.get_surface()
+        self.area = screen.get_rect()
+        self.rect.bottomright = self.area.bottomright
+        self.move = 9
+        self.dizzy = 0
+    def update(self):
+        "walk or spin, depending on the monkeys state"
+        if self.dizzy:
+            self._spin()
+        else:
+            self._walk()
+    def _walk(self):
+        "move the monkey across the screen, and turn at the ends"
+        newpos = self.rect.move((self.move, 0))
+        if not self.area.contains(newpos):
+            self.move = -self.move
+            newpos = self.rect.move((self.move, 0))
+            self.image = pygame.transform.flip(self.image, 1, 0)
+        self.rect = newpos
+    def _spin(self):
+        "spin the monkey image"
+        center =
+        self.dizzy += 12
+        if self.dizzy >= 360:
+            self.dizzy = 0
+            self.image = self.original
+        else:
+            rotate = pygame.transform.rotate
+            self.image = rotate(self.original, self.dizzy)
+        self.rect = self.image.get_rect()
+ = center
+    def punched(self):
+        "this will cause the monkey to start spinning"
+        if not self.dizzy:
+            self.dizzy = 1
+            self.original = self.image
 def main():
+    """this function is called when the program starts.
+       it initializes everything it needs, then runs in
+       a loop until the function returns."""
 #Initialize Everything
-    screen = pygame.display.set_mode((468, 60), HWSURFACE|DOUBLEBUF)
+    screen = pygame.display.set_mode((468, 60))
     pygame.display.set_caption('Monkey Fever')
 #Create The Backgound
     background = pygame.Surface(screen.get_size())
     background.fill((250, 250, 250))
 #Put Text On The Background, Centered
-    font = pygame.font.Font(None, 36)
-    text = font.render("Pummel The Chimp, And Win $$$", 1, (10, 10, 10))
-    textpos = text.get_rect()
-    textpos.centerx = background.get_rect().centerx
-    background.blit(text, textpos)
+    if pygame.font:
+        font = pygame.font.Font(None, 36)
+        text = font.render("Pummel The Chimp, And Win $$$", 1, (10, 10, 10))
+        textpos = text.get_rect()
+        textpos.centerx = background.get_rect().centerx
+        background.blit(text, textpos)
-#Display The Background While Setup Finishes
+#Display The Background
     screen.blit(background, (0, 0))
-#Load Resources
-    chimp = pygame.image.load(chimpfile).convert()
-    chimp.set_colorkey(chimp.get_at((0, 0)))
-    fist = pygame.image.load(fistfile).convert()
-    fist.set_colorkey(chimp.get_at((0, 0)))
-    whiffsound = pygame.mixer.Sound(missfile)
-    hitsound = pygame.mixer.Sound(hitfile)
+#Prepare Game Objects
+    clock = pygame.time.Clock()
+    whiff_sound = load_sound('whiff.wav')
+    punch_sound = load_sound('punch.wav')
+    chimp = Chimp()
+    fist = Fist()
+    allsprites = pygame.sprite.RenderPlain((fist, chimp))
-#Prepare To Animate
-    chimppos = chimp.get_rect()
-    chimppos.bottom = screen.get_height()
-    chimpmove = 2
-    reload = 0
 #Main Loop
     while 1:
-    #Handle Input, Check For Quit
-        event = pygame.event.poll()
-        if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
-            break
-    #Move The Monkey
-        chimppos.left = chimppos.left + chimpmove
-        if not screen.get_rect().contains(chimppos):
-            chimpmove = -chimpmove
-    #Move And Punch The Fist
-        fistpos = pygame.mouse.get_pos()    
-        pressed = pygame.mouse.get_pressed()[0]
-        if not reload and pressed:
-            if chimppos.collidepoint(fistpos):
-            else:
-        reload = pressed
-        if not reload:
-            fistpos = fistpos[0] - 20, fistpos[1] - 10
+    #Handle Input Events
+        for event in pygame.event.get():
+            if event.type is QUIT:
+                return
+            elif event.type is KEYDOWN and event.key is K_ESCAPE:
+                return
+            elif event.type is MOUSEBUTTONDOWN:
+                if fist.punch(chimp):
+           #punch
+                    chimp.punched()
+                else:
+           #miss
+            elif event.type is MOUSEBUTTONUP:
+                fist.unpunch()
-    #Draw The Entire Scene
+        allsprites.update()
+    #Draw Everything
         screen.blit(background, (0, 0))
-        screen.blit(chimp, chimppos)
-        screen.blit(fist, fistpos)
+        allsprites.draw(screen)
+        clock.tick(60)
 #Game Over
-#this is python code to kickstart the program if not imported
+#this calls the 'main' function when this script is executed
 if __name__ == '__main__': main()

File examples/winaliens.pyw

-"""Launch aliens fullscreen. the .PYW extension
-will prevent windows from opening a DOS-Box"""
-import aliens

File lib/

 they want add and remove themselves from containers. The
 containers must also have a member named "_spritegroup",
 which can be set to any dummy value.
-The term "sprite" is a holdover from older computer and
-game machines. These older boxes were unable to draw
-and erase normal graphics fast enough for them to work
-as games. These machines had special hardware to handle
-game like objects that needed to animate very quickly.
-These objects were called 'sprites' and had special
-limitations, but could be drawn and updated very fast.
-They usually existed in special overlay buffers in the
-video. These days computers have become generally fast
-enough to handle sprite like objects without dedicated
-hardware. The term sprite is still used to represent
-just about anything in a 2D game that is animated.
            Returns a copy of the group that is the same class
            type, and has the same contained sprites."""
         return self.__class__(self.spritedict.keys())
-    def loop(self):
-        """loop() -> iterator
-           return an object to loop each sprite
+    def sprites(self):
+        """sprites() -> iterator
+           return an object to loop over each sprite
            Returns an object that can be looped over with
            a 'for' loop. (For now it is always a list, but
             return GroupSingle(self.sprite)
         return GroupSingle()
-    def loop(self):
+    def sprites(self):
         return [self.sprite]
     def add(self, sprite):
         return dirty
 def spritecollide(sprite, group, dokill):
-    """pygame.sprite.spritecollide(sprite, group, dokill)
+    """pygame.sprite.spritecollide(sprite, group, dokill) -> list
        collision detection between sprite and group
        given a sprite and a group of sprites, this will
        automatically removed from all groups."""
     spritecollide = sprite.rect.colliderect
     crashed = []
-    for s in group.loop():
+    for s in group.sprites():
         if spritecollide(s.rect):
-            if dokill:
-                s.kill()
+            if dokill: s.kill()
     return crashed
 def groupcollide(groupa, groupb, dokilla, dokillb):
-    """pygame.sprite.spritecollide(sprite, group, dokill)
+    """pygame.sprite.groupcollide(sprite, group, dokill) -> dict
        collision detection between group and group
        given two groups, this will find the intersections
        the sprites from either group will be automatically
        removed from all groups."""
     crashed = {}
-    for s in groupa.loop():
+    for s in groupa.sprites():
         c = spritecollide(s, groupb, dokillb)
         if c:
             crashed[s] = c
-            if dokilla:
-                s.kill()
+            if dokilla: s.kill()
     return crashed