Home arrow Python arrow Page 4 - A PyGame Working Example, continued

Constructing the Main Loop - Python

In this fourth article in our series covering the creation of a video game using Python and PyGame, we will code the internals of our game.

TABLE OF CONTENTS:
  1. A PyGame Working Example, continued
  2. Setting Things Up
  3. Cleaning Up
  4. Constructing the Main Loop
  5. The Game in Action
By: Peyton McCullough
Rating: starstarstarstarstar / 9
February 14, 2006

print this article
SEARCH DEV SHED

TOOLS YOU CAN USE

advertisement

Now that we've created functions to get things set up for us, we're ready to get into the function containing the main loop of the game. Before we get into our function's actual loop, though, we'll have to do a bit of configuration. First, we'll have to get the size of each position on the screen. This simply involves dividing the height and width of the background by the number of rows and columns. Then, we'll have to define two variables that work with movement. When the user presses a key, the first variable will need to be set to the direction of the movement. When the user releases a key, the second variable will need to be set to True, which will signal movement to stop. This way, a user can hold down a key and see movement rather than have to repeatedly tap the key.

Though we have a list of sprite groups, we also need a list that will store the sprite groups that are actually visible on the screen. This way, we'll know which ones to update. Next, we need to actually draw the player. Finally, we'll have to load custom events into the timer. This is done by setting the timer to trigger our own event IDs at set intervals. The first event will update the player, and the second event will update the objects. The speeds at which things will be updated will be passed as arguments.

Here's all this in action:

def run(playerSpeed = 250, objectSpeed = 1000):

   # Get the row and column widths
   colWidth = background.get_rect().width / columns
   rowHeight = background.get_rect().height / rows

   # Define a variable that stores whether an arrow key is
pressed
   # This is used for continuous/scrolling movement of the player
   moving = False

   # We should also define a variable that signals stops
   # Otherwise, if a player pushes a key in between updates and
releases
   # it, the move will not be registered
   movingStop = False

   # Create a list to store the visible groups
   visible = []

   # Blit the player
   updateRects = player.draw(screen)
   pygame.display.update(updateRects)

   # Load a screen update event into the timer
   # This will update the player only
   pygame.time.set_timer(pygame.USEREVENT + 1, playerSpeed)

   # Load a screen update event into the timer
   # This will update the objects
   pygame.time.set_timer(pygame.USEREVENT + 2, objectSpeed)

With all that done, we're now ready to jump into the main loop. First, we'll need to check for quit events and key presses:

def run(playerSpeed = 250, objectSpeed = 1000):

   ...

   while True:

      for event in pygame.event.get():
         if event.type == pygame.QUIT:
            sys.exit()

         # Check for a key push by the user
         elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_RIGHT:
               moving = 'right'
            elif event.key == pygame.K_LEFT:
               moving = 'left'

         # Check by a key release by the user
         elif event.type == pygame.KEYUP:
            if event.key == pygame.K_RIGHT or pygame.K_LEFT:
               movingStop = True

The above code simply sets the player to move when a key is pressed, and it sets it to stop moving when a key is released. It also enables the player to exit the game.

The next task ahead of us is moving the player around. To do this, we first need to check to see whether our custom player update event has been triggered. If it has, we then need to move the player in the proper direction, if any direction at all. We finally need to check to see whether the player has collided with any of the objects and then redraw the player:

def run(playerSpeed = 250, objectSpeed = 1000):

   ...

         # Check for the update player event
         elif event.type == pygame.USEREVENT + 1:

            # Move the player if needed
            if moving == 'right':
               player.update(colWidth)
            if moving == 'left':
               player.update(-colWidth)

            # Stop movement if needed
            if movingStop:
               moving = False
               movingStop = False

            # Collision detection
            for group in visible:
               if pygame.sprite.spritecollideany(playerSprite,
group):
                  return False

            # Redraw the player
            player.clear(screen, erase) 
            updateRects = player.draw(screen)

            pygame.display.update(updateRects)

As I mentioned earlier, the visible list above will contain a list of all the visible sprite groups. To check for collision, we iterate through this list and use pygame.sprite.spritecollideany. There's no need to use a method that kills the colliding sprites since we want to completely back out of the loop. What object the player hits doesn't really matter to us. As you can see, we return False to get out of the loop.

All that's left now is moving the objects around, an extremely simple task. This is done when our custom object update event has been triggered. If anything remains in the layout list, we add it to our visible list. Likewise, we delete any sprite group that has fallen off the screen. Aside from that, we simply update each sprite group, and if the visible list is empty, then the player has won the level.

def run(playerSpeed = 250, objectSpeed = 1000):

   ...

         # Check for the update object event
         elif event.type == pygame.USEREVENT + 2:

            # Add a row
            if layout:
               visible.append(layout.pop())

            # Delete passed rows
            if visible:
               if visible[0].y >= screen.get_rect().height:
                  visible.pop(0)

            # If there are no visible rows, the player has won
            else:
               return True

            # Make a list of rectangles to be updated
            updateRects = []

            # Update each group
            for group in visible:
               group.clear(screen, erase)
               group.update(rowHeight)
               group.y = group.y + rowHeight
               updateRects.extend(group.draw(screen))

            pygame.display.update(updateRects)



 
 
>>> More Python Articles          >>> More By Peyton McCullough
 

blog comments powered by Disqus
escort Bursa Bursa escort Antalya eskort
   

PYTHON ARTICLES

- Python Big Data Company Gets DARPA Funding
- Python 32 Now Available
- Final Alpha for Python 3.2 is Released
- Python 3.1: String Formatting
- Python 3.1: Strings and Quotes
- Python 3.1: Programming Basics and Strings
- Tuples and Other Python Object Types
- The Dictionary Python Object Type
- String and List Python Object Types
- Introducing Python Object Types
- Mobile Programming using PyS60: Advanced UI ...
- Nested Functions in Python
- Python Parameters, Functions and Arguments
- Python Statements and Functions
- Statements and Iterators in Python

Developer Shed Affiliates

 


Dev Shed Tutorial Topics: