Pygame Drawing and Animation

Animation in Pygame

So far, we have learned:

  • How to display an image on the screen
  • How to display an image and text together

Now let’s write an app that will move an image on the display screen continuously without keyboard or mouse events. This is called animation.

Similar to the boundary checks in the Event programs, our animation programs will check the screen’s boundary limits. 

We will use a soccer ball as the image of the object.

If the object goes beyond the boundary limit on the right-hand side of the surface (x = 640), the program sets x = 0, so the ball appears on the left-hand side of the screen and then continues to move to the right.

PROGRAM EXAMPLE: ANIMATION IN PYGAME

Program: pygame_animation_with_boundary_check.py

import pygame
from pygame.locals import *			# 1
# pygame module needs to be imported before we can use.
pygame.init()
# Initialize all imported pygame modules. 
width = 640
height = 320
screen = pygame.display.set_mode((width, height)) #2
# Define colors RGB value			# 3
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
# Define the width of the ball so we can calculate 
# when the left side of the ball reaches boundary.
ball_width = 100				# 4
# The caption below will appear on top of the 
# python shell window.
pygame.display.set_caption('AnimationWithBoundaryCheck') #5
clock = pygame.time.Clock()			# 6
#
ballImage = pygame.image.load('ball.png')	# 7
# Set the initial location of the ball		# 8
x = 0
y = 50
# x_move is the amount the ball will move every clock tick.
# Initialize x_move variable. The ball will move by 
# x_move pixels every frame.
x_move = 5					# 9
    
#Main Loop
while True:					# 10
    x = x + x_move
# Fill the surface with WHITE COLOR background.
    screen.fill(WHITE)				# 11
    screen.blit(ballImage, (x, y))		# 12
# Check for surface boundary limit of 640 - ball width.
    if x > width - ball_width:			# 13
        x = 0
    
# Update the display with the ball image        
    pygame.display.update()			# 14
    clock.tick(60)

pygame.quit()
quit()

Below is the program output.

Pygame Animation with screen boundary check.
ANIMATION IN PYGAME WITH BOUNDARY CHECK

Detailed line-by-line Program Explanation:

1) import pygame and from pygame.locals import *

Import the pygame module and constant variables.

2) screen = pygame.display.set_mode((width, height)).

Create a display Surface object called ‘screen’ of width = 640 pixels and height = 480 pixels.

3) Define colors RGB values

4) ball_width = 100

Define a variable “ball_width” and assign it a value of 100. In step 13), we will use this value to calculate when the ball has reached the right boundary of the Screen.

5) pygame.display.set_caption

Set the caption for the app window.

6) clock = pygame.time.Clock()

Clock() function provides the clock for the app.

7) ballImage = pygame.image.load(‘ball.png’).

Define a variable called “ballImage”.

Call the pygame.image.load(‘ball.png’) function that returns a new Surface object with the loaded image. The image name (“ball.png”) is specified within the parenthesis in the function as a parameter.

8) Initialize the starting location of the ball.

9) x_move = 5.

Define a variable x_move and assign is a value of 5.  x_move is the number of pixels the ball moves in each clock.tick.

10) while True: 

x = x + x_move

This is the app’s main loop. In each loop, the image moves 5 pixels by calculating the image’s new location by the statement x = x +x_move.

11) screen.fill(WHITE)

In the while loop, this statement fills the screen with WHITE color in each iteration of the loop.  This is necessary, otherwise, you will see the image’s all locations from the previous loops, resulting in a trail of the images as it moves across the screen.

12) screen.blit(ballImage, (x, y))

The blit function copies the “ballImage” to the destination location defined by the tuple (x,y).

13) if x > 640 – ball_width: 

x = 0

This if condition tests if the image has reached the right boundary of the Screen. If the if condition evaluates ‘True’, the program sets the ball location at x=0, the left edge of the display screen.

14) pygame.display.update()

clock.tick(60)

The display.update() function updates the display with the image, we wrote in step 7). 

clock.tick(60) sets the frames to 60 per second making the while loop traverse the loop 60 times per second.

Animation With Random() Module

Now that we have learned how to do simple animation, let us make a more interesting animation program. You learned about the random() module in the Python Modules chapter.  We will use the random() module to randomize ball movement.

Program Example: ANIMATION USING random() MODULE

Program Name: pygame_animation_with_boundary_check_random.py

Image: ball.png

import pygame
from pygame.locals import *			#1
# Initialize all imported pygame modules.
pygame.init()
import random
# Define the surface 640 pixels wide, 
# and 480 pixel high to draw on.
width = 640
height = 480
screen = pygame.display.set_mode((width, height)) #2
# Define colors RGB value			#3
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
# Define of the ball so we can check if the 
# image reaches screen's boundaries.
ball_width = 100				# 4
# This caption will appear on top of the python shell window.
pygame.display.set_caption('AnimationWithBoundaryCheckRandom')	# 5
clock = pygame.time.Clock()			# 6
#
ballImage = pygame.image.load('ball.png')	# 7
# Set the initial location of the ball.
x = 320						# 8
y = 240

# Define ball function				# 9
def ball(x, y):
    screen.blit(ballImage, (x, y))		#12
    
#Main Loop
while True:										
    x = x + random.randint(-50, 50)		#10
    y = y + random.randint(-50, 50)
# Fill the surface with WHITE COLOR background.
# And call ball(x, y) function.
    screen.fill(WHITE)				#11
    ball(x, y)					#11a
# Check for surface boundary limit (x-direction) 
# screen width - ball width or 0.
    if x > width - ball_width:			#13
        x = 0
    elif x < 0:
        x = width - ball_width
# Check for Surface boundary limits in the y-direction	# 13a
    if y > height - ball_width:
        y = 0
    elif y < 0:
        y = height - ball_width
    
# Update the display with the ball image
    pygame.display.update()			#14
    clock.tick(60)
# Call time.delay() at the end of the loop to 
# slow down the program.
# Otherwise ball motion will be too fast and you 
# would not see the ball.
    pygame.time.delay(250)  # delay 250 msec (1/4 second) # 15

pygame.quit()
quit()

Detailed Line-by-line Explanation of the Program

1) through 8) as the same as in the previous program.  The only difference is that we import the random() module in Step 1).

9) def ball(x,y):

12) screen.blit(ballImage, (x, y))

Define function “ball”. The statement 12) in this function copies the ball image to the screen Surface object using function ballDisplay.blit(ballImage, (x, y))

10)   x = x + random.randint(-50, 50)

y = y + random.randint(-50, 50)

Create a random location coordinates (x,y) of the image.

11) screen.fill(WHITE)

11a) ball(x, y)

Call the function ‘ball’.

13) Check if the image has reached to screen’s boundary in the x-direction. If the ball reaches the right edge of the screen, that is x > (screen width – ball width), set  x= 0, so that the ball appears at the left edge of the screen. If the ball reaches the left edge of the screen, that is x < 0, then set x = (screen width – ball width), so that the ball appears at the right of the screen.

13a) The logic similar to step 13) is used to check if the ball has reached the screen boundary in the y-direction.

14) pygame.display.update()

This function updates the display with the image, as we wrote in step 7).  clock.tick(60) sets the frame rate to 60 frames per second meaning the while loop is traversed 60 times per second.

15) pygame.time.delay(250).

Introduce a delay of 250 msec (1/4 second) between each loop, otherwise, the image will move too fast to see.

Animation With Boundary Bounce

We will write a program such that when the ball reaches the boundary of the screen window, the ball will bounce off the edge of the screen.

To bounce the image off the edge of the screen, we will use a new function that we have not used.

This new function is called pygame.rect.move(x,y).  This function returns a rectangle, which is the original rectangle moved by the specified amount (x, y).

We will also use the Rect object’s attributes .left and .right, which give us the x-coordinate of the left side of the rectangle and the right side of the rectangle respectively.  These attributes were discussed in Section on Rect Object.

PROGRAM EXAMPLE: ANIMATION WITH SURFACE BOUNDARY BOUNCE

Name of the Program: pygame_animation_with_boundary_bounce.py

Image: ball.png

import pygame
from pygame.locals import *			#1
pygame.init()
width = 640
height = 480
screen = pygame.display.set_mode((width, height)) #2		

# Define RGB colors				#3
BLACK = ( 0, 0, 0)
WHITE = (255, 255, 255)
pygame.display.set_caption('animationBoundaryBounce') # 5

clock = pygame.time.Clock()			#6

#######  Load ball image ######
img = pygame.image.load("ball.png")		#7
imgRect = img.get_rect() 			#8
#  Returns a Rect object that tells us the dimensions 
# and location of the ball.

# Ball movement per loop (iteration): Move 2 pixels in 
# x-direction
# and 2 pixels in y-direction per each loop iteration.
x = 2						#9 
y = 2
# Main loop
while True:
# Move the imgRect x pixels horizontally and y pixels vertically
# in each loop iteration). (x,y) is a tuple.
    imgRect = imgRect.move(x, y) 		#10
    if imgRect.left < 0 or imgRect.right > width: #11a
# Check if the image has moved beyond the left boundary 
# of the screen
# or the right boundary of the screen. Reverse the 
# direction, if so.        
        x = -x

    if imgRect.top < 0 or imgRect.bottom > height: #11b
# Check if the image has moved beyond the top boundary 
# of the screen
# or the bottom boundary of the screen.  Reverse the 
# direction, if so.        
        y = -y
# Fill the screen WHITE after each loop iteration (frame).
    screen.fill(WHITE)				#12
    screen.blit(img, imgRect)			#13
# Copy pixels from one Surface to another to draw 
# images to the screen.
# First parameter is the source Surface; the second 
# parameter is the destination Rect.
# The entire source Surface is copied to the area of 
# the destination Surface
# specified by the Rect in the second argument 
    pygame.display.flip() 
# This method updates the full display Surface to the screen #14   
    clock.tick(60)				#15

pygame.quit()

Below is the output of the program.

Pygame Animation with Image bouncing off the Screen Boundaries.
ANIMATION IN PYGAME WITH BOUNDRY BOUNCE

Detailed Line-by-line Explanation of the Program:

1) through 7) are the same as in the program “AnimationWithBoundaryCheck.py'”.

8) imgRect = img.get_rect()

The get_rect() function returns a Rect object that gives us the dimensions and the location of the ball.

This Rect object is used in step 10) to move the ball across the screen by an amount (x,y).

9) Set (x,y) = (2,2) 

This is the amount the rect.move(x,y) will move the image in each iteration of the loop.

10) imgRect = imgRect.move(x, y)

imgRect.move(x,y) function returns a new rectangle, which is the original rectangle moved by the specified amount (x, y).

11a) if imgRect.left < 0 or imgRect.right > width:

11b) if imgRect.top < 0 or imgRect.bottom > height:

These if statements test if the image has reached the x or y boundary.

12) screen.fill(WHITE)

Fill the screen with WHITE color at the beginning of each loop to avoid seeing the ball trace from the previous loops.

13) screen.blit(img, imgRect)

The blit function copies the “ballImage” object to the destination location created by imgRect.move(x,y) function in Step 10).

14) pygame.display.flip()

This method updates the whole screen display.

15) clock.tick(60)

This function sets the frames per second to 60 so that the while loop iterates 60 times per second.

Verified by MonsterInsights