Pages

Sunday, June 16, 2013

Python newbie learning notes

I wrote my first pygame event handling thing but it doesn't work.  I google further and found that I know too little about python, not to mention pygame, to be called even a python newbie.  So I decided to go back to square one and learn Python from the very beginning, along with pygame.  Since I am not in linux either, I think it is better to learn in my Win 7 PC, rather than the slower RPi Debian.

I download pygam 1.9.1 for Win32.  My Win7 Home Edition is only Win32, not Win64.  I am glad to find that pygame Win 64 seems not that mature as Win32.  Anyway, my learning environment is the following.

Python 2.7.2 IDLE 2.7.3 Pygame 1.9.1 Win32  

Some 2 years ago when I watched the MIT OCW EECS1 video I thought I would start learning Python in Windows, but I found Python in Windows only 2.7.x, no 3.0, and the command mode looks ugly.  At that time I did not realize that there is GUI called IDLE, and that 2.7.x is the stable thing, there is nothing great about 3.0, at lease for a newbie like me.  In other words, Python 2.7.3 and IDLE 2.7.3, and pygame 1.9.1 should be more than enough for me, ...

Now I cut and paste Python Help and a pygame tutorial below.  The pygame tutorial is almost 10 years old, but I think it is not out of date, ...


Python 2.7.3 IDLE 2.7.3 Help

Python 2.7.3 (Apr 10 2012) [MSC v.1500 32 bit (Intel)] on win32]

...

File Menu:

New Window       -- Create a new editing window
Open...          -- Open an existing file
Recent Files...  -- Open a list of recent files
Open Module...   -- Open an existing module (searches sys.path)
Class Browser    -- Show classes and methods in current file
Path Browser     -- Show sys.path directories, modules, classes
                            and methods
---

Save             -- Save current window to the associated file (unsaved
windows have a * before and after the window title)

Save As...       -- Save current window to new file, which becomes
the associated file

Save Copy As...  -- Save current window to different file without changing 
                       the associated file
---

Print Window     -- Print the current window

---

Close            -- Close current window (asks to save if unsaved)

Exit             -- Close all windows, quit (asks to save if unsaved)

Edit Menu:

Undo             -- Undo last change to current window
                       (A maximum of 1000 changes may be undone)

Redo             -- Redo last undone change to current window

---

Cut              -- Copy a selection into system-wide clipboard,
                       then delete the selection

Copy             -- Copy selection into system-wide clipboard

Paste            -- Insert system-wide clipboard into window

Select All       -- Select the entire contents of the edit buffer

---

Find...          -- Open a search dialog box with many options

Find Again       -- Repeat last search

Find Selection   -- Search for the string in the selection

Find in Files... -- Open a search dialog box for searching files

Replace...       -- Open a search-and-replace dialog box

Go to Line       -- Ask for a line number and show that line

Show Calltip     -- Open a small window with function param hints

Show Completions -- Open a scroll window allowing selection keywords
  and attributes. (see '*TIPS*', below)

Show Parens -- Highlight the surrounding parenthesis

Expand Word      -- Expand the word you have typed to match another
word in the same buffer; repeat to get a different expansion

Format Menu (only in Edit window):

Indent Region       -- Shift selected lines right 4 spaces

Dedent Region       -- Shift selected lines left 4 spaces

Comment Out Region  -- Insert ## in front of selected lines

Uncomment Region    -- Remove leading # or ## from selected lines

Tabify Region       -- Turns *leading* stretches of spaces into tabs
(Note: We recommend using 4 space blocks to 
                        indent Python code.)

Untabify Region     -- Turn *all* tabs into the right number of spaces

New Indent Width... -- Open dialog to change indent width

Format Paragraph    -- Reformat the current blank-line-separated
                          paragraph

Run Menu (only in Edit window):

Python Shell -- Open or wake up the Python shell window

---

Check Module -- Run a syntax check on the module

Run Module   -- Execute the current file in the __main__ namespace

Shell Menu (only in Shell window):

View Last Restart -- Scroll the shell window to the last restart

Restart Shell     -- Restart the interpreter with a fresh environment

Debug Menu (only in Shell window):

Go to File/Line   -- look around the insert point for a filename
and linenumber, open the file, and show the line

Debugger (toggle) -- Run commands in the shell under the debugger

Stack Viewer      -- Show the stack traceback of the last exception

Auto-open Stack Viewer (toggle) -- Open stack viewer on traceback

Options Menu:

Configure IDLE -- Open a configuration dialog.  Fonts, indentation,
                     keybindings, and color themes may be altered.
                     Startup Preferences may be set, and Additional Help
                     Sources can be specified. 
                     ...
---

Code Context --  Open a pane at the top of the edit window which
 shows the block context of the section of code
 which is scrolling off the top or the window.
 (Not present in Shell window.)

Windows Menu:

Zoom Height -- toggles the window between configured size and maximum height.

---

The rest of this menu lists the names of all open windows; select one to bring 
 it to the foreground (deiconifying it if necessary).

Help Menu:

About IDLE  -- Version, copyright, license, credits

IDLE Readme -- Background discussion and change details

---

IDLE Help   -- Display this file

Python Docs -- Access local Python documentation, if
      installed.  Otherwise, access www.python.org.
---

(Additional Help Sources may be added here)


** TIPS **
==========

Additional Help Sources:

Windows users can Google on zopeshelf.chm to access Zope help files in
the Windows help format.  The Additional Help Sources feature of the
configuration GUI supports .chm, along with any other filetypes
supported by your browser.  Supply a Menu Item title, and enter the
location in the Help File Path slot of the New Help Source dialog.  Use
http:// and/or www. to identify external URLs, or download the file and
browse for its path on your machine using the Browse button.

All users can access the extensive sources of help, including
tutorials, available at www.python.org/doc.  Selected URLs can be added
or removed from the Help menu at any time using Configure IDLE.

Basic editing and navigation:

Backspace deletes char to the left; DEL deletes char to the right.

Control-backspace deletes word left, Control-DEL deletes word right.

Arrow keys and Page Up/Down move around.

Control-left/right Arrow moves by words in a strange but useful way.

Home/End go to begin/end of line.

Control-Home/End go to begin/end of file.

Some useful Emacs bindings are inherited from Tcl/Tk:

Control-a     beginning of line
Control-e     end of line
Control-k     kill line (but doesn't put it in clipboard)
Control-l     center window around the insertion point

Standard Windows bindings may work on that platform.

Keybindings are selected in the Settings Dialog, look there.

Automatic indentation:

After a block-opening statement, the next line is indented by 4 spaces
(in the Python Shell window by one tab).  After certain keywords
(break, return etc.) the next line is dedented.  In leading
indentation, Backspace deletes up to 4 spaces if they are there.  Tab
inserts spaces (in the Python Shell window one tab), number depends on
Indent Width.  (N.B. Currently tabs are restricted to four spaces due
to Tcl/Tk issues.)

        See also the indent/dedent region commands in the edit menu.

Completions:

Completions are supplied for functions, classes, and attributes of
classes, both built-in and user-defined.  Completions are also provided
for filenames.

The AutoCompleteWindow (ACW) will open after a predefined delay
(default is two seconds) after a '.' or (in a string) an os.sep is
typed.  If after one of those characters (plus zero or more other
characters) you type a Tab the ACW will open immediately if a possible
continuation is found.

If there is only one possible completion for the characters entered, a
Tab will supply that completion without opening the ACW.

'Show Completions' will force open a completions window.  In an empty
string, this will contain the files in the current directory.  On a
blank line, it will contain the built-in and user-defined functions and
classes in the current name spaces, plus any modules imported.  If some
characters have been entered, the ACW will attempt to be more specific.

If string of characters is typed, the ACW selection will jump to the
entry most closely matching those characters. Entering a Tab will cause
the longest non-ambiguous match to be entered in the Edit window or
Shell.  Two Tabs in a row will supply the current ACW selection, as
will Return or a double click.  Cursor keys, Page Up/Down, mouse
selection, and the scrollwheel all operate on the ACW.

'Hidden' attributes can be accessed by typing the beginning of hidden
name after a '.'.  e.g. '_'.  This allows access to modules with
'__all__' set, or to class-private attributes.

Completions and the 'Expand Word' facility can save a lot of typing!

Completions are currently limited to those in the namespaces.  Names in
an Edit window which are not via __main__ or sys.modules will not be
found.  Run the module once with your imports to correct this
situation.  Note that IDLE itself places quite a few modules in
sys.modules, so much can be found by default, e.g. the re module.

If you don't like the ACW popping up unbidden, simply make the delay
longer or disable the extension.  OTOH, you could make the delay zero.

You could also switch off the CallTips extension.  (We will be adding
a delay to the call tip window.)

Python Shell window:

Control-c interrupts executing command.

Control-d sends end-of-file; closes window if typed at >>> prompt
(this is Control-z on Windows).

    Command history:

Alt-p retrieves previous command matching what you have typed.

Alt-n retrieves next.
     (These are Control-p, Control-n on the Mac) Return while cursor is on a              
       previous command retrieves that command. Expand word is also useful to       
       reduce typing.

    Syntax colors:

The coloring is applied in a background "thread", so you may  occasionally see uncolorized text.  To change the color  scheme, use the Configure IDLE / Highlighting dialog.

    Python default syntax colors:

Keywords orange
Builtins royal purple
Strings green
Comments red
Definitions blue

    Shell default colors:

Console output brown
stdout blue
stderr red
stdin black

Other preferences:

The font preferences, keybinding, and startup preferences can
be changed using the Settings dialog.

Command line usage:

Enter idle -h at the command prompt to get a usage message.

Running without a subprocess:

If IDLE is started with the -n command line switch it will run in a
single process and will not create the subprocess which runs the RPC
Python execution server.  This can be useful if Python cannot create
the subprocess or the RPC socket interface on your platform.  However,
in this mode user code is not isolated from IDLE itself.  Also, the
environment is not restarted when Run/Run Module (F5) is selected.  If
your code has been modified, you must reload() the affected modules and
re-import any specific items (e.g. from foo import baz) if the changes
are to take effect.  For these reasons, it is preferable to run IDLE
with the default subprocess if at all possible.

Extensions:

IDLE contains an extension facility.  See the beginning of
config-extensions.def in the idlelib directory for further information.
The default extensions are currently:

FormatParagraph
AutoExpand
ZoomHeight
ScriptBinding
CallTips
ParenMatch
AutoComplete
CodeContext

.END



Pygame Tutorials Line By Line Chimp by Pete Shinners pete@shinners.org Revision 2.2, June 17, 2004

http://www.pygame.org/docs/tut/chimp/ChimpLineByLine.html

Pygame Windows 32 download - pygame-1.9.1.win32-py2.7.msi 3.1MB

http://www.pygame.org/download.shtml

Pygame Tutorials Line By Line Chimp by Pete Shinners

http://www.pygame.org/docs/tut/chimp/ChimpLineByLine.html

Introduction

In the pygame examples there is a simple example named, "chimp". This example simulates a punchable monkey moving around a small screen with promises of riches and reward. The example itself is very simple, and a bit thin on errorchecking code. This example program demonstrates many of pygame's abilities, like creating a graphics window, loading images and sound files, rendering TTF text, and basic event and mouse handling.

The program and images can be found inside the standard source distribution of pygame. For version 1.3 of pygame, this example was completely rewritten to add a couple more features and correct error checking. This about doubled the size of the original example, but now gives us much more to look at, as well as code the I can recommend reusing for your own projects.

This tutorial will go through the code block by block. Explaining how the code works. There will also be mention of how the code could be improved and what errorchecking could help out.

This is an exellent tutorial for people getting their first look at the pygame code. Once pygame is fully installed, you can find and run the chimp demo for yourself in the examples directory.

Import Modules

This is the code that imports all the needed modules into your program. It also checks for the availability of some of the optional pygame modules.

import os, sys
import pygame
from pygame.locals import *

if not pygame.font: print 'Warning, fonts disabled'
if not pygame.mixer: print 'Warning, sound disabled'

First, we import the standard "os" and "sys" python modules. These allow us to do things like create platform independent file paths.

In the next line, we import the pygame package. When pygame is imported it imports all the modules belonging to pygame. Some pygame modules are optional, and if they aren't found, their value is set to "None".

There is a special pygame module named "locals". This module contains a subset of pygame. The members of this module are commonly used constants and functions that have proven useful to put into your program's global namespace. This locals module includes functions like "Rect" to create a rectangle object, and many constants like "QUIT, HWSURFACE" that are used to interact with the rest of pygame. Importing the locals module into the global namespace like this is entirely optional. If you choose not to import it, all the members of locals are always available in the pygame module.

Lastly, we decide to print a nice warning message if the font or sound modules in pygame are not available.

Loading Resources

Here we have two functions we can use to load images and sounds. We will look at each function individually in this section.

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()
         

This function takes the name of an image to load. It also optionally takes an argument it can use to set a colorkey for the image. A colorkey is used in graphics to represent a color of the image that is transparent.

The first thing this function does is create a full pathname to the file. In this example all the resources are in a "data" subdirectory. By using the os.path.join function, a pathname will be created that works for whatever platform the game is running on.

Next we load the image using the pygame.image.load function. We wrap this function in a try/except block, so if there is a problem loading the image, we can exit gracefully. After the image is loaded, we make an important call to the convert() function. This makes a new copy of a Surface and converts its color format and depth to match the display. This means blitting the image to the screen will happen as quickly as possible.

Last, we set the colorkey for the image. If the user supplied an argument for the colorkey argument we use that value as the colorkey for the image. This would usually just be a color RGB value, like (255, 255, 255) for white. You can also pass a value of -1 as the colorkey. In this case the function will lookup the color at the topleft pixel of the image, and use that color for the colorkey.

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

Next is the function to load a sound file. The first thing this function does is check to see if the pygame.mixer module was imported correctly. If not, it returns a small class instance that has a dummy play method. This will act enough like a normal Sound object for this game to run without any extra error checking.

This function is similar to the image loading function, but handles some different problems. First we create a full path to the sound image, and load the sound file inside a try/except block. Then we simply return the loaded Sound object.

Game Object Classes

Here we create two classes to represent the objects in our game. Almost all the logic for the game goes into these two classes. We will look over them one at a time here.

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.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

Here we create a class to represent the players fist. It is derived from the Sprite class included in the pygame.sprite module. The __init__ function is called when new instances of this class are created. The first thing we do is be sure to call the __init__ function for our base class. This allows the Sprite's __init__ function to prepare our object for use as a sprite. This game uses one of the sprite drawing Group classes. These classes can draw sprites that have an "image" and "rect" attribute. By simply changing these two attributes, the renderer will draw the current image at the current position.

All sprites have an update() method. This function is typically called once per frame. It is where you should put code that moves and updates the variables for the sprite. The update() method for the fist moves the fist to the location of the mouse pointer. It also offsets the fist position slightly if the fist is in the "punching" state.

The following two functions punch() and unpunch() change the punching state for the fist. The punch() method also returns a true value if the fist is colliding with the given target sprite.

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.topleft = 10, 10
        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):
if self.rect.left < self.area.left or \
self.rect.right > self.area.right:
            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.rect.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=center)

    def punched(self):
        "this will cause the monkey to start spinning"
        if not self.dizzy:
            self.dizzy = 1
            self.original = self.image

The chimp class is doing a little more work than the fist, but nothing more complex. This class will move the chimp back and forth across the screen. When the monkey is punched, he will spin around to exciting effect. This class is also derived from the base Sprite class, and is initialized the same as the fist. While initializing, the class also sets the attribute "area" to be the size of the display screen.

The update function for the chimp simply looks at the current "dizzy" state, which is true when the monkey is spinning from a punch. It calls either the _spin or _walk method. These functions are prefixed with an underscore. This is just a standard python idiom which suggests these methods should only be used by the Chimp class. We could go so far as to give them a double underscore, which would tell python to really try to make them private methods, but we don't need such protection. :)

The walk method creates a new position for the monkey by moving the current rect by a given offset. If this new position crosses outside the display area of the screen, it reverses the movement offset. It also mirrors the image using the pygame.transform.flip function. This is a crude effect that makes the monkey look like he's turning the direction he is moving.

The spin method is called when the monkey is currently "dizzy". The dizzy attribute is used to store the current amount of rotation. When the monkey has rotated all the way around (360 degrees) it resets the monkey image back to the original unrotated version. Before calling the transform.rotate function, you'll see the code makes a local reference to the function simply named "rotate". There is no need to do that for this example, it is just done here to keep the following line's length a little shorter. Note that when calling the rotate function, we are always rotating from the original monkey image. When rotating, there is a slight loss of quality. Repeatedly rotating the same image and the quality would get worse each time. Also, when rotating an image, the size of the image will actually change. This is because the corners of the image will be rotated out, making the image bigger. We make sure the center of the new image matches the center of the old image, so it rotates without moving.

The last method is punched() which tells the sprite to enter its dizzy state. This will cause the image to start spinning. It also makes a copy of the current image named "original".
Initialize Everything

Before we can do much with pygame, we need to make sure its modules are initialized. In this case we will also open a simple graphics window. Now we are in the main() function of the program, which actually runs everything.

pygame.init()
screen = pygame.display.set_mode((468, 60))
pygame.display.set_caption('Monkey Fever')
pygame.mouse.set_visible(0)

The first line to initialize pygame takes care of a bit of work for us. It checks through the imported pygame modules and attempts to initialize each one of them. It is possible to go back and check if modules failed to initialize, but we won't bother here. It is also possible to take a lot more control and initialize each specific module by hand. That type of control is generally not needed, but is available if you desire.

Next we set up the display graphics mode. Note that the pygame.display module is used to control all the display settings. In this case we are asking for a simple skinny window. There is an entire separate tutorial on setting up the graphics mode, but if we really don't care, pygame will do a good job of getting us something that works. Pygame will pick the best color depth, since we haven't provided one.

Last we set the window title and turn off the mouse cursor for our window. Very basic to do, and now we have a small black window ready to do our bidding. Usually the cursor defaults to visible, so there is no need to really set the state unless we want to hide it.


Create The Background

Our program is going to have text message in the background. It would be nice for us to create a single surface to represent the background and repeatedly use that. The first step is to create the surface.

background = pygame.Surface(screen.get_size())
background = background.convert()
background.fill((250, 250, 250))

This creates a new surface for us that is the same size as the display window. Note the extra call to convert() after creating the Surface. The convert with no arguments will make sure our background is the same format as the display window, which will give us the fastest results.

We also fill the entire background with a solid white-ish color. Fill takes an RGB triplet as the color argument.


Put Text On The Background, Centered

Now that we have a background surface, lets get the text rendered to it. We only do this if we see the pygame.font module has imported properly. If not, we just skip this section.

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(centerx=background.get_width()/2)
    background.blit(text, textpos)

As you see, there are a couple steps to getting this done. First we must create the font object and render it into a new surface. We then find the center of that new surface and blit (paste) it onto the background.

The font is created with the font module's Font() constructor. Usually you will pass the name of a truetype font file to this function, but we can also pass None, which will use a default font. The Font constructor also needs to know the size of font we want to create.

We then render that font into a new surface. The render function creates a new surface that is the appropriate size for our text. In this case we are also telling render to create antialiased text (for a nice smooth look) and to use a dark grey color.

Next we need to find the centered position of the text on our display. We create a "Rect" object from the text dimensions, which allows us to easily assign it to the screen center.

Finally we blit (blit is like a copy or paste) the text onto the background image.


Display The Background While Setup Finishes

We still have a black window on the screen. Lets show our background while we wait for the other resources to load.

screen.blit(background, (0, 0))
pygame.display.flip()

This will blit our entire background onto the display window. The blit is self explanatory, but what about this flip routine?

In pygame, changes to the display surface are not immediately visible. Normally, a display must be updated in areas that have changed for them to be visible to the user. With double buffered displays the display must be swapped (or flipped) for the changes to become visible. In this case the flip() function works nicely because it simply handles the entire window area and handles both singlebuffered and doublebufferes surfaces.


Prepare Game Object

Here we create all the objects that the game is going to need.

whiff_sound = load_sound('whiff.wav')
punch_sound = load_sound('punch.wav')
chimp = Chimp()
fist = Fist()
allsprites = pygame.sprite.RenderPlain((fist, chimp))
clock = pygame.time.Clock()

First we load two sound effects using the load_sound function we defined above. Then we create an instance of each of our sprite classes. And lastly we create a sprite Group which will contain all our sprites.

We actually use a special sprite group named RenderPlain. This sprite group can draw all the sprites it contains to the screen. It is called RenderPlain because there are actually more advanced Render groups. But for our game, we just need simple drawing. We create the group named "allsprites" by passing a list with all the sprites that should belong in the group. We could later on add or remove sprites from this group, but in this game we won't need to.

The clock object we create will be used to help control our game's framerate. we will use it in the main loop of our game to make sure it doesn't run too fast.

Main Loop

Nothing much here, just an infinite loop.

while 1:
    clock.tick(60)

All games run in some sort of loop. The usual order of things is to check on the state of the computer and user input, move and update the state of all the objects, and then draw them to the screen. You'll see that this example is no different.

We also make a call to our clock object, which will make sure our game doesn't run faster than 60 frames per second.


Handle All Input Events

This is an extremely simple case of working the event queue.

for event in pygame.event.get():
    if event.type == QUIT:
        return
    elif event.type == KEYDOWN and event.key == K_ESCAPE:
        return
    elif event.type == MOUSEBUTTONDOWN:
        if fist.punch(chimp):
            punch_sound.play() #punch
            chimp.punched()
        else:
            whiff_sound.play() #miss
    elif event.type == MOUSEBUTTONUP:
        fist.unpunch()

First we get all the available Events from pygame and loop through each of them. The first two tests see if the user has quit our game, or pressed the escape key. In these cases we just return from the main() function and the program cleanly ends.

Next we just check to see if the mouse button was pressed or released. If the button was pressed, we ask the fist object if it has collided with the chimp. We play the appropriate sound effect, and if the monkey was hit, we tell him to start spinning (by calling his punched() method).


Update the Sprites


allsprites.update()

Sprite groups have an update() method, which simply calls the update method for all the sprites it contains. Each of the objects will move around, depending on which state they are in. This is where the chimp will move one step side to side, or spin a little farther if he was recently punched.



Draw The Entire Scene

Now that all the objects are in the right place, time to draw them.

screen.blit(background, (0, 0))
allsprites.draw(screen)
pygame.display.flip()

The first blit call will draw the background onto the entire screen. This erases everything we saw from the previous frame (slightly inefficient, but good enough for this game). Next we call the draw() method of the sprite container. Since this sprite container is really an instance of the "DrawPlain" sprite group, it knows how to draw our sprites. Lastly, we flip() the contents of pygame's software double buffer to the screen. This makes everything we've drawn visible all at once.


Game Over

User has quit, time to clean up

Cleaning up the running game in pygame is extremely simple. In fact since all variables are automatically destructed, we really don't have to do anything.

.END2

No comments:

Post a Comment