Pygame: How To’s?

This tutorial is the fifth tutorial in a series of five Pygame tutorials:

Now that you have completed your first game you may want to customise it further of or add extra functionalities. The following How-To’s tutorials may become quiet useful.

Also remember that a Pygame game will be based around the main program loop. Make sure you fully understand the structure of your main.py file:

pygame-main-program-loop-flowchart

To gain a better understanding of the pygame library yuou should familiarise yourself with its main modules and classes.
View Pygame Framework

How to Add a Background Picture to the game
This would work for background picture or any other pictures that you want to display on the screen.

Before the main program loop add the following code:

background = pygame.image.load("images/background.png")

In your main program loop add the following code:

screen.blit(background, (0, 0))

In the above code (0,0) represents the (x,y) coordinates of where you would like your picture to appear.

The background has to be saved in your “images” folder.

How to use the transparency of a PNG file
When loading a picture use the convert_alpha() method as follows:

myPicture = pygame.image.load("images/myPicture.png").convert_alpha()
How to display text on the screen
To display text on the screen, use the following code:

font = pygame.font.Font(None, 36)
text = font.render("Hello World!", 1, (10, 10, 10))
screen.blit(text, (50,50))
How to flip your sprite
To flip your sprite horizontally:

mySprite.image = pygame.transform.flip(mySprite.image, True, False)

To flip your sprite vertically:

mySprite.image = pygame.transform.flip(mySprite.image, False, True)
How to find out if a key is pressed
In your “event handling loop” of the main program loop add the following code:

for event in pygame.event.get():
  if event.type == KEYDOWN:
    if event.key == K_RIGHT:
        #do_something_here!
    elif event.key == K_LEFT:
        #do_something_here!
    elif event.key == K_UP:
        #do_something_here!
    elif event.key == K_DOWN:
        #do_something_here!
How to create textboxes
The following code uses a class called TextBox and instantiates two textboxes (objects) called username and password.

import pygame
pygame.init()

#Set the pygame window
screen = pygame.display.set_mode((600, 400))

class TextBox:
    #Constructor
    def __init__(self, x, y, w, h, fontSize=24, maxLength=100, resizable=True, text='', textColor=(0,0,0), borderColor=(40,120,180), activeBorderColor=(200,0,0)):
        self.rect = pygame.Rect(x, y, w, h)
        self.color = borderColor
        self.inactiveColor = borderColor
        self.textColor = textColor
        self.activeColor = activeBorderColor
        self.maxLength = maxLength
        self.resizable = resizable
        self.text = text
        self.fontSize= fontSize
        FONT = pygame.font.Font(None, self.fontSize)
        self.txt_surface = FONT.render(text, True, self.color)
        self.active = False


    def handle_event(self, event):
        if event.type == pygame.MOUSEBUTTONDOWN:
            #Detects when the user clicks on the textbox
            if self.rect.collidepoint(event.pos):
                self.active = True
                self.color = self.activeColor
            else:
                self.active = False
                self.color = self.inactiveColor



        if event.type == pygame.KEYDOWN:
            if self.active:
                if event.key == pygame.K_RETURN:
                    #Clear text box
                    self.text = ''
                elif event.key == pygame.K_BACKSPACE:
                    #Remove last character
                    self.text = self.text[:-1]
                elif event.key in [pygame.K_TAB,pygame.K_ESCAPE]:
                    #Ignore = do nothing
                    pass
                else:
                    #Append character
                    if len(self.text) < self.maxLength:
                        self.text += event.unicode
                #Display text
                FONT = pygame.font.Font(None, self.fontSize)
                self.txt_surface = FONT.render(self.text, True, self.textColor)

    def update(self):
        # Resize the box if the text is too long.
        if self.resizable:
            width = max(200, self.txt_surface.get_width()+10)
            self.rect.w = width

    def draw(self, screen):
        screen.blit(self.txt_surface, (self.rect.x+5, self.rect.y+5))
        pygame.draw.rect(screen, self.color, self.rect, 2)



#Main program starts here

#Textbox (x, y , width, height, fontSize, maxLength, resizeable, text, textColor, borderColor, activeBorderColor)
username = TextBox(200, 96, 200, 24, 24, 20, False)
password = TextBox(200, 146, 200, 24, 24, 20, False)
textboxes = [username, password]

font = pygame.font.Font(None, 24)
labelUsername = font.render("Username:", 1, (10, 10, 10))
labelPassword = font.render("Password:", 1, (10, 10, 10))


clock = pygame.time.Clock()
carryOn = True
#Main program loop
while carryOn:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            carryOn = False

        for textbox in textboxes:
            textbox.handle_event(event)

    screen.fill((255, 255, 255))

    screen.blit(labelUsername, (80,100))
    screen.blit(labelPassword, (80,150))

    for textbox in textboxes:
        textbox.update()
        textbox.draw(screen)

    #print(username.text)
    #print(password.text)

    pygame.display.flip()
    clock.tick(30)

pygame.quit()
How to create a popup input box
pop_up_box_pygame
In your main program, at the very top, just after the import pygame statement add the following code:

from pygame.locals import *

def getKey():
  while 1:
    event = pygame.event.poll()
    if event.type == KEYDOWN:
      return event.key
    else:
      pass

def popup(screen, message, width, height,x , y, bgcolor, textColor):
  #Display a popup box in the middle of the screen
  #This popup will only disappear when the user presses the Return key

  fontobject = pygame.font.Font(None,18)
  pygame.draw.rect(screen, bgcolor,
                   (x - width/2 +2,
                    y - height/2 +2,
                    300,36), 0)
  pygame.draw.rect(screen, (255,255,255),
                   (x - width/2,
                    y - height/2,
                    304,40), 1)
  if len(message) != 0:
    screen.blit(fontobject.render(message, 1, textColor),
                (x - width/2 + 10, y - height/2 + 14))
  pygame.display.flip()

def askQuestion(screen, question, width=300, height=40, x=-1, y=-1, bgColor=(255,0,0), textColor=(255,255,255)):
  #width, height, x, y, bgColor and textColor are optional arguments
  #When x and y are omitted, use the centre of the screen
  if x==-1:
    x = screen.get_width() / 2
  if y==-1:
    y = screen.get_height() / 2

  pygame.font.init()
  current_string = []
  popup(screen, question + ": " + "".join(current_string), width, height, x, y, bgColor, textColor)
  upperCase=False
  while 1:
    inkey = getKey()
    if inkey == K_BACKSPACE:
      current_string = current_string[0:-1]
    elif inkey == K_RETURN:
      break
    elif inkey == K_LSHIFT or inkey == K_RSHIFT:
        upperCase=not upperCase #Switch between lowercase and uppercase when the shift key is pressed
    elif inkey <= 255:
      if (inkey>=97 and inkey<=122) and upperCase==True:
        inkey-=32 #Convert to UPPERCASE
      current_string.append(chr(inkey))
    popup(screen, question + ": " + "".join(current_string), width, height, x, y, bgColor, textColor)

  return "".join(current_string)

Then in your main program, whenever you want a new popup box use the following code:

answer = askQuestion(screen, "Type a question...")

Some arguments can be added:

answer = askQuestion(screen, "Login name?", width=300, height=40, x=100, y=100, bgColor=(255,0,0), textColor=(255,255,255))
How to drag a sprite on the screen using the mouse
Want to create a drag and drop game? Add the following code inside the main programme loop and replace playerCar with the name of your sprite.

if pygame.mouse.get_pressed()[0]:
     mousex,mousey = event.pos
     if playerCar.rect.collidepoint(mousex,mousey):
         playerCar.rect.x=mousex-playerCar.rect.width/2
         playerCar.rect.y=mousey-playerCar.rect.height/2
How to check the color of a pixel at a given position
For instance you may want to check if your sprite is walking on the road or on grass. In this case you could use the get_at(x,y) method which returns the color of a pixel at position x, y.
e.g.

GREEN == (0,255,0)
x=100
y=100
if screen.get_at((x, y)) == GREEN:
    print("This pixel is green")
How to pause the game when the player presses a key (e.g. space bar)
You may want to allow the user to pause the game using a shortcut key (e.g. Space Bar). To do so add the following code in the for loop where you catch user events (for event in pygame.event.get():)
Code to add:

        if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
            while True: #Infinite loop that will be broken when the user press the space bar again
                event = pygame.event.wait()
                if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
                    break #Exit infinite loop
How to detect if the user clicks on a sprite
You can detect if the player has clicked on a Sprite by adding the following code to the for loop where you catch user events (for event in pygame.event.get():):

if event.type == MOUSEMOTION: 
     x,y = event.pos

     if playerCar.rect.collidepoint(x,y):
            print "You clicked on the player's car"

     for srite in all_comming_cars:
           if sprite.rect.collidepoint(x,y): 
                 print "You clicked on a car"
How to use a mask on a sprite for more accurate collision detection
The default collision detection in Pygame uses the rect attribute of the sprites to detect if two sprites are overlapping. This approach works well if your sprites are plain rectangles. However, as you start using graphics for your sprite, you will want the collision detection to use the edges of your graphics. You can do so by creating a mask on all your sprites.

To do so, go in your sprite class (e.g. Car Class) and add the following line of code in the constructor (__init__() of the class):

self.mask = pygame.mask.from_surface(self.image)

For instance:

class Car(pygame.sprite.Sprite):
    #This class represents a car. It derives from the "Sprite" class in Pygame.

    def __init__(self, color, width, height, speed):
        # Call the parent class (Sprite) constructor
        super().__init__()

        ...
       
        self.image = pygame.image.load("car.png").convert_alpha()
        self.mask = pygame.mask.from_surface(self.image)

        ...

In your main code, use the following code to detect collisions:

#Check if there is a car collision
        car_collision_list = pygame.sprite.spritecollide(playerCar,all_coming_cars,False,pygame.sprite.collide_mask)
        for car in car_collision_list:
            print("Car crash!")
            #End Of Game
            carryOn=False
Adding Background Music
To add a background soundtrack, download a wav file or mp3 file into a folder called “Sounds”.

At the start of your code (main.py), after importing the pygame library, add the following lines of code:

pygame.mixer.pre_init(frequency=44100, size=-16, channels=2, buffer=4096)
pygame.mixer.music.load('Sounds/soundtrack.mp3')
pygame.mixer.music.play(-1) #-1 means loops for ever, 0 means play just once)

Note that you can stop the music at any time using the following instruction:

pygame.mixer.music.stop()

You may prefer to pause the music:

pygame.mixer.music.pause()

… or unpause the music:

pygame.mixer.music.unpause()
Adding Sound Effects
To add sound effects, download some wav files into a folder called “Sounds” and add the following code when you want to play the sound effect:

effect = pygame.mixer.Sound('Sounds/beep.wav')
effect.play()

Did you like this challenge?

Click on a star to rate it!

Average rating 4.4 / 5. Vote count: 36

No votes so far! Be the first to rate this post.

As you found this challenge interesting...

Follow us on social media!

Tagged with: