This article is intended for those who are already familiar with the Python programming language, and allows you to learn more about the Pygame library for this language. As an illustrative example, here will be a step-by-step demonstration of the process of programming a simple game in which the player must dodge bouncing balls.
Steps
Part 1 of 8: Installing Pygame
Step 1. Download Pygame
Follow the link and find the correct version of the library for your platform: http://www.pygame.org/download.shtml. Step 2. Run the installer. 3 Verify that the installation completed successfully.
Open Python terminal. Enter "import pygame". If no error messages appear, then Pygame has been successfully installed.
import pygame
Part 2 of 8: Creating the main game window
Step 1. Create a new file. 2 Import Pygame
Pygame is a library that provides access to the graphical functions of the Python programming language. If you would like to learn more about how these functions work, information is available on the Pygame site.
import pygame from pygame.locals import *
Step 3. Set the size of the game window
Create a global variable for the size of the window to refer to from different parts of the game. For convenience, it is better to specify these parameters exactly at the beginning of the file, so that, if necessary, it would be easier to change them in the future. For more complex projects, it will be preferable to place such data in a separate file.
resolution = (400, 300)
Step 4. Define some colors
Colors in Pygame are defined in RGBA format, ranging from 0 to 255. The alpha (A) value can be omitted, but the rest of the colors (red, green, and blue) are required.
white = (255, 255, 255) black = (0, 0, 0) red = (255, 0, 0)
Step 5. Initialize the home screen
Use the resolution variable defined earlier.
screen = pygame.display.set_mode (resolution)
Step 6. Create a game loop
Set the repetition of certain actions in each frame of the game. Create a loop that will do all of these steps in sequence.
while True:
Step 7. Determine the fill color of the screen
screen.fill (white)
Step 8. Display the screen
If you run the program at this stage, the screen will turn white, and then the program will crash. The reason for the failure will be that the operating system sends events to the program, and the program simply does not process them. When a program accumulates too many unhandled events, a crash occurs.
while True:… pygame.display.flip ()
Step 9. Implement event handling
Get a list of all events that occurred between frame rendering. In our example, you should only be concerned about handling one quit event. It occurs when the user closes the game window. Event handling will prevent the program from crashing from causing too many events.
while True:… for event in pygame.event.get (): if event.type == QUIT: pygame.quit ()

Step 10. Try the program
Now the program code should look like this:
import pygame from pygame.locals import * resolution = (400, 300) white = (255, 255, 255) black = (0, 0, 0) red = (255, 0, 0) screen = pygame.display.set_mode (resolution) while True: screen.fill (white) pygame.display.flip () for event in pygame.event.get (): if event.type == QUIT: pygame.quit ()
Part 3 of 8: Creating Game Objects
Step 1. Create a new object class and its constructor
Set all the properties of the object. Also define default values for each of the properties.
class Ball: def __init __ (self, xPos = resolution [0] / 2, yPos = resolution [1] / 2, xVel = 1, yVel = 1, rad = 15): self.x = xPos self.y = yPos self.dx = xVel self.dy = yVel self.radius = rad self.type = "ball"
Step 2. Determine the rendering of the object
Use the object properties set in the constructor to render the ball as a circle on the surface passed as a parameter to the function. The surface will be the screen you created earlier by defining its dimensions.
def draw (self, surface): pygame.draw.circle (surface, black, (self.x, self.y), self.radius)
Step 3. Create an instance of the class and add a task to the game loop to draw a ball at each iteration of the loop
ball = Ball () while True:… ball.draw (screen)
Step 4. Make the object move
Create a function to update the position of the object. Call this function every iteration of the loop.
class Ball:… def update (self): self.x + = self.dx self.y + = self.dy
Step 5. Limit the frame rate
The ball will move very quickly because the game loop repeats hundreds of times per second. Use a Pygame timer to limit your frame rate to 60 fps.
clock = pygame.time. Clock () while True:… clock.tick (60)
class Ball:… def update (self):… if (self.x <= 0 or self.x> = resolution [0]): self.dx * = -1 if (self.y <= 0 or self.y > = resolution [1]): self.dy * = -1

import pygame from pygame.locals import * resolution = (400, 300) white = (255, 255, 255) black = (0, 0, 0) red = (255, 0, 0) screen = pygame.display.set_mode (resolution) class Ball: def __init __ (self, xPos = resolution [0] / 2, yPos = resolution [1] / 2, xVel = 1, yVel = 1, rad = 15): self.x = xPos self.y = yPos self.dx = xVel self.dy = yVel self.radius = rad self.type = "ball" def draw (self, surface): pygame.draw.circle (surface, black, (self.x, self.y), self.radius) def update (self): self.x + = self.dx self.y + = self.dy if (self.x <= 0 or self.x> = resolution [0]): self.dx * = -1 if (self.y <= 0 or self.y> = resolution [1]): self.dy * = -1 ball = Ball () clock = pygame.time. Clock () while True: screen. fill (white) ball.draw (screen) ball.update () pygame.display.flip () clock.tick (60) for event in pygame.event.get (): if event.type == QUIT: pygame.quit ()
Part 4 of 8: Structuring the game
Step 1. Use classes for structuring
In the future, the game will become more difficult. Use object-oriented programming techniques to structure your code. Step 2. Convert the game loop to a classroom.
Since the game currently includes data, including game objects and functions, it makes sense to replace the game loop with a class.
class game ():
Step 3. Add a constructor
With it, you will draw several objects used in the game, create a screen, a timer, and initialize Pygame. Pygame needs to be initialized in order to use features such as text or sound later.
class game (): def __init __ (self): pygame.init () self.screen = pygame.display.set_mode (resolution) self.clock = pygame.time. Clock ()
Step 4. Set up event handling in the function
class game ():… def handleEvents (self): for event in pygame.event.get (): if event.type == QUIT: pygame.quit ()
Step 5. Make the game loop a function
Call the event function on each iteration of the loop.
class game ():… def run (self): while True: self.handleEvents () self.screen.fill (white) self.clock.tick (60) pygame.display.flip ()
Step 6. Set the processing of a set of game objects
At this point, the game code causes the individual objects to be updated and redrawn every frame. With this approach, the game code will turn out to be quite cumbersome and messy, especially if there are many objects in the game. It makes more sense to add objects to the array first, and then update and redraw all objects in the array at each iteration of the loop. Now you can easily add a new object to the game and define a different starting position for it.
class game (): def __init __ (self):… self.gameObjects = [] self.gameObjects.append (Ball ()) self.gameObjects.append (Ball (100))… def run (self): while True: self.handleEvents () for gameObj in self.gameObjects: gameObj.update () self.screen.fill (white) for gameObj in self.gameObjects: gameObj.draw (self.screen) self.clock.tick (60) pygame.display.flip ()

Step 7. Try the program
Now the program code should look like this:
import pygame from pygame.locals import * resolution = (400, 300) white = (255, 255, 255) black = (0, 0, 0) red = (255, 0, 0) screen = pygame.display.set_mode (resolution) class Ball: def __init __ (self, xPos = resolution [0] / 2, yPos = resolution [1] / 2, xVel = 1, yVel = 1, rad = 15): self.x = xPos self.y = yPos self.dx = xVel self.dy = yVel self.radius = rad self.type = "ball" def draw (self, surface): pygame.draw.circle (surface, black, (self.x, self.y), self.radius) def update (self): self.x + = self.dx self.y + = self.dy if (self.x <= 0 or self.x> = resolution [0]): self.dx * = -1 if (self.y <= 0 or self.y> = resolution [1]): self.dy * = -1 class game (): def __init __ (self): pygame.init () self.screen = pygame.display.set_mode (resolution) self.clock = pygame.time. Clock () self.gameObjects = [] self.gameObjects.append (Ball ()) self.gameObjects.append (Ball (100)) def handleEvents (self): for event in pygame.event.get (): if event.type == QUIT: pygame.quit () def run (self): while True: self.handleEvent s () for gameObj in self.gameObjects: gameObj.update () self.screen.fill (white) for gameObj in self.gameObjects: gameObj.draw (self.screen) self.clock.tick (60) pygame.display. flip () game (). run ()
Part 5 of 8: Adding a Player Object
Step 1. Create a player class and constructor
You need to create another circle controlled by the movement of the mouse. Initialize its parameters in the constructor. The only important value will be the radius.
class Player: def __init __ (self, rad = 20): self.x = 0 self.y = 0 self.radius = rad
Step 2. Determine the rendering of the player object
It is drawn in the same way as other game objects were drawn.
class Player:… def draw (self, surface): pygame.draw.circle (surface, red, (self.x, self.y), self.radius)
Step 3. Add mouse control to the player object
In each frame of the game, it is necessary to check the position of the mouse pointer and correlate the position of the player's object with this point.
class Player:… def update (self): cord = pygame.mouse.get_pos () self.x = cord [0] self.y = cord [1]
Step 4. Add a player object to the gameObjects array
Create a new instance of the object and add it to the gameObjects list.
class game (): def __init __ (self):… self.gameObjects.append (Player ())

Step 5. Try the program
Now the program code should look like this:
import pygame from pygame.locals import * resolution = (400, 300) white = (255, 255, 255) black = (0, 0, 0) red = (255, 0, 0) screen = pygame.display.set_mode (resolution) class Ball: def __init __ (self, xPos = resolution [0] / 2, yPos = resolution [1] / 2, xVel = 1, yVel = 1, rad = 15): self.x = xPos self.y = yPos self.dx = xVel self.dy = yVel self.radius = rad self.type = "ball" def draw (self, surface): pygame.draw.circle (surface, black, (self.x, self.y), self.radius) def update (self): self.x + = self.dx self.y + = self.dy if (self.x <= 0 or self.x> = resolution [0]): self.dx * = -1 if (self.y <= 0 or self.y> = resolution [1]): self.dy * = -1 class Player: def __init __ (self, rad = 20): self.x = 0 self.y = 0 self.radius = rad self.type = "player" def draw (self, surface): pygame.draw.circle (surface, red, (self.x, self.y), self.radius) def update (self): cord = pygame.mouse.get_pos () self.x = cord [0] self.y = cord [1] class game (): def __init __ (self): pygame.init () self.screen = pygame.display.set_ mode (resolution) self.clock = pygame.time. Clock () self.gameObjects = [] self.gameObjects.append (Player ()) self.gameObjects.append (Ball ()) self.gameObjects.append (Ball (100)) def handleEvents (self): for event in pygame.event.get (): if event.type == QUIT: pygame.quit () def run (self): while True: self.handleEvents () for gameObj in self.gameObjects: gameObj.update () self.screen.fill (white) for gameObj in self.gameObjects: gameObj.draw (self.screen) self.clock.tick (60) pygame.display.flip () game (). run ()
Part 6 of 8: Creating Object Interactions
Step 1. Change the position update functions
To implement the interaction of objects, you need to provide them with access to each other's properties. Add a new parameter to the Update function to pass the data for the gameObjects list. The parameter needs to be added to the player and ball class functions. If you have many classes defined, inheritance will help keep the parameter list the same.
class Ball:… def update (self, gameObjects):… class Player:… def update (self, gameObjects):
Step 2. Enter the ball collision check
View all the objects and identify among them those that relate to balls. Then, using the radii of the objects and the distance formula, check to see if the objects have collided with each other. Checking for collisions between circles is easy. This is the main reason that other shapes are not used as an example in this game.
class Player:… def update (self, gameObjects):… for gameObj in gameObjects: if gameObj.type == "ball": if (gameObj.x - self.x) ** 2 + (gameObj.y - self.y) ** 2 <= (gameObj.radius + self.radius) ** 2:

Step 3. Set the end of the game when the player hits the ball
At this point, just ask to exit the game.
if (gameObj.x - self.x) ** 2 + (gameObj.y - self.y) ** 2 <= (gameObj.radius + self.radius) ** 2: pygame.quit ()
Step 4. Try the program
Now the program code should look like this:
import pygame from pygame.locals import * resolution = (400, 300) white = (255, 255, 255) black = (0, 0, 0) red = (255, 0, 0) screen = pygame.display.set_mode (resolution) class Ball: def __init __ (self, xPos = resolution [0] / 2, yPos = resolution [1] / 2, xVel = 1, yVel = 1, rad = 15): self.x = xPos self.y = yPos self.dx = xVel self.dy = yVel self.radius = rad self.type = "ball" def draw (self, surface): pygame.draw.circle (surface, black, (self.x, self.y), self.radius) def update (self, gameObjects): self.x + = self.dx self.y + = self.dy if (self.x <= 0 or self.x> = resolution [0]): self.dx * = -1 if (self.y <= 0 or self.y> = resolution [1]): self.dy * = -1 class Player: def __init __ (self, rad = 20): self.x = 0 self.y = 0 self.radius = rad self.type = "player" def draw (self, surface): pygame.draw.circle (surface, red, (self.x, self.y), self.radius) def update (self, gameObjects): cord = pygame.mouse.get_pos () self.x = cord [0] self.y = cord [1] for gameObj in gameObjects: if gameObj.type == "ball": if (gameObj.x - self.x) ** 2 + (gameObj.y - self.y) ** 2 <= (gameObj.radius + self.radius) ** 2: pygame.quit () class game (): def __init __ (self): pygame.init () self.screen = pygame.display.set_mode (resolution) self.clock = pygame.time. Clock () self.gameObjects = [] self.gameObjects.append (Player ()) self.gameObjects.append (Ball ()) self.gameObjects.append (Ball (100)) def handleEvents (self): for event in pygame.event.get (): if event.type == QUIT: pygame.quit () def run (self): while True: self.handleEvents () for gameObj in self.gameObjects: gameObj.update (self.gameObjects) self.screen.fill (white) for gameObj in self.gameObjects: gameObj.draw (self.screen) self.clock.tick (60) pygame.display.flip () game (). run ()
Part 7 of 8: Adding a Game Controller to Create Objects
Step 1. Create a game controller class
Game controllers are responsible for the course of the game. They are not the same as the class of the game itself, which is responsible for rendering and updating all game objects. The controller will periodically add a new ball to the screen and complicate the game. Add a constructor and initialize some starting values. The interval will mean the time after which a new ball will be added.
class GameController: def __init __ (self, interval = 5): self.inter = interval self.next = pygame.time.get_ticks () + (2 * 1000) self.type = "game controller"
Step 2. Add update function
It will check how much time has passed since the previous ball was added or since the start of the game. If the time exceeds the specified interval, then the timer will be reset and a new ball will be added.
class GameController:… def update (self, gameObjects): if self.next <pygame.time.get_ticks (): self.next = pygame.time.get_ticks () + (self.inter * 1000) gameObjects.append (Ball ())
Step 3. Set random speeds for the balls
For the game to behave differently, you must allow it to use random numbers for the speed parameter. Now the speed of the balls will be determined by a floating decimal point number, rather than an integer.
class GameController:… def update (self, gameObjects): if self.next <pygame.time.get_ticks (): self.next = pygame.time.get_ticks () + (self.inter * 1000) gameObjects.append (Ball (xVel = random () * 2, yVel = random () * 2))
Step 4. Correct the rendering function
The draw function does not work with floats. Therefore, it is necessary to express the position of the ball in whole numbers before drawing it.
class Ball:… def draw (self, surface): pygame.draw.circle (surface, black, (int (self.x), int (self.y)), self.radius)
Step 5. Determine the rendering method for the game controller
Since this is also a game object, the main game loop will try to draw it. Therefore, the controller needs to define a render function that does nothing to avoid crashing the game.
class GameController:… def draw (self, screen): pass
Step 6. Add a game controller to gameObjects and remove 2 balls
The game must add a new ball every 5 seconds.
class game (): def __init __ (self):… self.gameObjects = [] self.gameObjects.append (GameController ()) self.gameObjects.append (Player ())

Step 7. Try the program
Now the program code should look like this:
import pygame from random import random from pygame.locals import * resolution = (400, 300) white = (255, 255, 255) black = (0, 0, 0) red = (255, 0, 0) screen = pygame. display.set_mode (resolution) class Ball: def __init __ (self, xPos = resolution [0] / 2, yPos = resolution [1] / 2, xVel = 1, yVel = 1, rad = 15): self.x = xPos self.y = yPos self.dx = xVel self.dy = yVel self.radius = rad self.type = "ball" def draw (self, surface): pygame.draw.circle (surface, black, (int (self. x), int (self.y)), self.radius) def update (self, gameObjects): self.x + = self.dx self.y + = self.dy if (self.x <= 0 or self. x> = resolution [0]): self.dx * = -1 if (self.y <= 0 or self.y> = resolution [1]): self.dy * = -1 class Player: def __init __ (self, rad = 20): self.x = 0 self.y = 0 self.radius = rad self.type = "player" def draw (self, surface): pygame.draw.circle (surface, red, (self.x, self.y), self.radius) def update (self, gameObjects): cord = pygame.mouse.get_pos () self.x = cord [0] self.y = cord [1] for gameObj in game Objects: if gameObj.type == "ball": if (gameObj.x - self.x) ** 2 + (gameObj.y - self.y) ** 2 <= (gameObj.radius + self.radius) * * 2: pygame.quit () class GameController: def __init __ (self, interval = 5): self.inter = interval self.next = pygame.time.get_ticks () + (2 * 1000) self.type = "game controller "def update (self, gameObjects): if self.next <pygame.time.get_ticks (): self.next = pygame.time.get_ticks () + (self.inter * 1000) gameObjects.append (Ball (xVel = random () * 2, yVel = random () * 2)) def draw (self, screen): pass class game (): def __init __ (self): pygame.init () self.screen = pygame.display.set_mode (resolution) self.clock = pygame.time. Clock () self.gameObjects = [] self.gameObjects.append (GameController ()) self.gameObjects.append (Player ()) def handleEvents (self): for event in pygame.event.get (): if event.type == QUIT: pygame.quit () def run (self): while True: self.handleEvents () for gameObj in self.gameObjects: gameObj.update (self.gameObjects) self.screen.fill (white) for gameObj in self.gameO bjects: gameObj.draw (self.screen) self.clock.tick (60) pygame.display.flip () game (). run ()
Part 8 of 8: Adding a Score and Finishing the Game
Step 1. Add the score to the game controller class
Create an object of class Font and a variable score. The Font must be rendered every frame to display the current score and increment every frame when updated.
class GameController: def __init __ (self, interval = 5):… self.score = 0 self.scoreText = pygame.font. Font (None, 12) def update (self, gameObjects):… self.score + = 1 def draw (self, screen): screen.blit (self.scoreText.render (str (self.score), True, black), (5, 5))
Step 2. Change the game completion process
Remove the simple exit from the game when the player hits the ball. Instead, create a variable in the player class that will be checked by the game. When the variable gameOver becomes true, it is necessary to stop updating the objects. All objects will freeze in place, so the player can understand what happened and see his score. The objects will still be displayed on the screen, but will simply stop updating.
class Player: def __init __ (self, rad = 20):… self.gameOver = False def update (self, gameObjects):… for gameObj in gameObjects: if gameObj.type == "ball": if (gameObj.x - self.x) ** 2 + (gameObj.y - self.y) ** 2 <= (gameObj.radius + self.radius) ** 2: self.gameOver = True class game (): def __init __ (self): … Self.gameOver = False def run (self): while True: self.handleEvents () if not self.gameOver: for gameObj in self.gameObjects: gameObj.update (self.gameObjects) if gameObj.type == "player": self.gameOver = gameObj.gameOver

Step 3. Try the program
The final program code should look like this:
import pygame from random import random from pygame.locals import * resolution = (400, 300) white = (255, 255, 255) black = (0, 0, 0) red = (255, 0, 0) screen = pygame. display.set_mode (resolution) class Ball: def __init __ (self, xPos = resolution [0] / 2, yPos = resolution [1] / 2, xVel = 1, yVel = 1, rad = 15): self.x = xPos self.y = yPos self.dx = xVel self.dy = yVel self.radius = rad self.type = "ball" def draw (self, surface): pygame.draw.circle (surface, black, (int (self. x), int (self.y)), self.radius) def update (self, gameObjects): self.x + = self.dx self.y + = self.dy if (self.x <= 0 or self. x> = resolution [0]): self.dx * = -1 if (self.y <= 0 or self.y> = resolution [1]): self.dy * = -1 class Player: def __init __ (self, rad = 20): self.x = 0 self.y = 0 self.radius = rad self.type = "player" self.gameOver = False def draw (self, surface): pygame.draw.circle (surface, red, (self.x, self.y), self.radius) def update (self, gameObjects): cord = pygame.mouse.get_pos () self.x = cord [0] self.y = cord [1] for gameObj in gameObjects: if gameObj.type == "ball": if (gameObj.x - self.x) ** 2 + (gameObj.y - self.y) ** 2 <= (gameObj.radius + self.radius) ** 2: self.gameOver = True class GameController: def __init __ (self, interval = 5): self.inter = interval self.next = pygame.time.get_ticks () + (2 * 1000) self. type = "game controller" self.score = 0 self.scoreText = pygame.font. Font (None, 12) def update (self, gameObjects): if self.next <pygame.time.get_ticks (): self.next = pygame.time.get_ticks () + (self.inter * 1000) gameObjects.append (Ball (xVel = random () * 2, yVel = random () * 2)) self.score + = 1 def draw (self, screen): screen.blit (self.scoreText.render (str (self.score), True, black), (5, 5)) class game (): def __init __ (self): pygame.init () self.screen = pygame.display.set_mode (resolution) self.clock = pygame.time. Clock () self.gameObjects = [] self.gameObjects.append (GameController ()) self.gameObjects.append (Player ()) self.gameOver = False def handleEvents (self): for event in pygame.event.get (): if ev ent.type == QUIT: pygame.quit () def run (self): while True: self.handleEvents () if not self.gameOver: for gameObj in self.gameObjects: gameObj.update (self.gameObjects) if gameObj. type == "player": self.gameOver = gameObj.gameOver self.screen.fill (white) for gameObj in self.gameObjects: gameObj.draw (self.screen) self.clock.tick (60) pygame.display.flip () game (). run ()