Introduction – Pygame Tutorial
This Pygame Tutorial will help you understand the basics and help you to get started with Pygame.
Python is the most advanced and widely-used programming language. There are libraries in python that make it so much flexible and make it thrive in every field of Machine Learning (Numpy, Pandas, Matplotlib), Artificial intelligence (Pytorch, TensorFlow), and Game development (Pygame, Pyglet).
What is Pygame?
Pygame is a set of python modules that were designed to help in writing video games and other multimedia applications.
Before starting to build any kind of game, you need to ask yourself some questions mentioned below:
- What sort of game do you want to build?
- What kind of language do you want to use to build a game?
- What kind of platform do you want to deploy your game to?
For PyGame, let’s assume you have the following answers for the above three questions:
- You want to create a graphical game, not 3D.
- As you already know the basics of python, you want to program it in Python as well.
- You’d like to make a client programme that could be packaged as a standalone executable.
Once you have answers to all the questions mentioned above, you are ready to dive into the world of pygame.
Pygame requires Python. You can download it from python.org.
Command to install pygame:
pip install pygame
Syntax Definitions
Here is a definition of some syntax we will:
import pygame — This is often, in fact, needed to access the PyGame framework.
pygame.init() — Used to initialises all the modules required for pygame. It must be called just after the importing pygame.
pygame.display.set_mode((width, height)): Make a window the size you want. The return value might be a Surface object, which is the object on which you’ll perform graphical operations.
pygame.event.get(): The event queue is now empty. If you do not call this, the windows messages will begin to accumulate, and your game will become sluggish in the OS’s viewpoint.
pygame.QUIT : This is often the event type that’s fired once you click on the close button within the corner of the window.
pygame.display.flip(): This swaps the buffers. All you would like to understand is that this call is required to make any updates that you simply make to the sport Screen appear.
In this Pygame Tutorial blog, we’ll mainly talk about the following topics:
- Geometric Designs
- Fonts and Text
- Input Modules
- Scene Logic
Before diving into the basics of pygame, let’s understand how we can install it into our system. We, generally, prefer PyCharm; however, you can continue with any IDE you are comfortable with.
Geometric Designs
Here, we will discuss the different designs we can create using pygame. It’s pretty simple with just a few lines of code.
- Drawing Rectangle
The syntax for creating the Rectangle:
Pygame.draw.rect(surface, color, pygame.Rect(left, top, width, height)
Let’s start with creating a Rectangle. The command we use:
#importing libraries
import pygame
# initializing the pygame
pygame.init()
# drawing the surface
surface= pygame.display.set_mode((400,300))
#initializing the color
color = (255,0,0)
# drawing the rectangle
pygame.draw.rect(surface, color,pygame.Rect(100,150,200,150))
pygame.display.flip()
- Drawing the circle
The syntax to create a circle:
pygame.draw.circle(surface, color, (150,150), 30)
pygame.display.flip()
Here, after drawing the rectangle and circle in the pygame, there is a small thing on which we need to focus on. It is the thickness of the boundaries.
We can also control the thickness by just adding the parameter at the end of the syntax:
pygame.draw.circle(surface, color, (300, 60), 50, 20)
- Drawing the Polygon
Drawing a polygon is straightforward. It is just the coordinates X and Y of the polygon.
Syntax for polygon:
pygame.draw.polygon(surface, color, point_list)
points = [(200, 200), (150, 120), (250, 120), (280, 140), (210, 150)]
pygame.draw.polygon(surface, (0,255,0), points)
pygame.display.flip()
- Drawing a line
Drawing lines just takes only a few parameters, start point, endpoint and thickness of the line.
The syntax for drawing a line:
pygame.draw.line(surface, (255,0,0), (100, 100), (300, 200), 5)
This will create a line with starting position (100,100), end position (300,200) and thickness of 5.
Fonts and Texts
Rule #1: Never assume that a user’s machine already has a particular font installed. There is a way to define a font hierarchy with CSS as well. If the font of our choice is not available, we can use the alternate one. You should follow the same pattern. Luckily, PyGame has a smart way to enumerate all the fonts available on the system:
all_fonts = pygame.font.receive_fonts()
There’s also a way to have the default system font appear:
font = pygame.font.Font(None, size)
font = pygame.font.Font(None, 50)
Instead of None, you can pass in the name of a font file you include along with your code to guarantee the existence of the font:
pygame.font.Font("myresources/fonts/Papyrus.ttf", 26)
Using a combination of the above, you can easily write a better font creation function.
For example, we will write a function that takes a list of font names, size and will create a font instance for the first available font in the list. If none of the fonts is available, it’ll use the default system font.
def make_font(fonts, size):
available = pygame.font.receive_fonts()
# get fonts() provides a list of lowercase font names with no spaces.
options = map(lambda x:x.lower().replace(' ', ''), fonts)
for option in options:
if options in options:
return pygame.font.SysFont(choice, size)
return pygame.font.Font(None, size)
You can also improve it by caching the font instance by font name and size.
cached_font= {}
def receive_font(font_preferences, size):
global _cached_fonts
key = str(font_preferences) + '|' + str(size)
font = _cached_fonts.get(key, None)
if font == None:
font = make_font(font_preferences, size)
_cached_fonts[key] = font
return font
You can take it a step further and cache the rendered text itself. Storing an image is always cheaper than creating a new one.
def create_texts(text, fonts, size, color):
global _cached_text
key = '|'.join(map(str, (fonts, size, color, text)))
image = _cached_text.get(key, None)
if image == None:
font = receive_font(fonts, size)
image = font.render(text, True, color)
_cached_text[key] = image
return image
Now, putting everything together, here is the “Hello, World” code but with improvised code.
import pygame
def make_font(fonts, size):
available = pygame.font.receive_fonts()
# receive_fonts()return fontnames
choices = map(lambda x: x.lower().replace(' ', ''), fonts)
for choice in choices:
if choice in available:
return pygame.font.SysFont(choice, size)
return pygame.font.Font(None, size)
cached_font= {}
def receive_font(font_preferences, size):
global _cached_fonts
key = str(font_preferences) + '|' + str(size)
font = _cached_fonts.get(key, None)
if font == None:
font = make_font(font_preferences, size)
_cached_fonts[key] = font
return font
_cached_text = {}
def create_texts(text, fonts, size, color):
global _cached_text
key = '|'.join(map(str, (fonts, size, color, text)))
image = _cached_text.get(key, None)
if image == None:
font = receive_font(fonts, size)
image = font.render(text, True, color)
_cached_text[key] = image
return image
pygame.init()
Surface = pygame.display.set_mode((640, 480))
clock = pygame.time.Clock()
done = False
font_preferences = [
& quot;
Bizarre - Ass
Font
Sans
Serif & quot;,
& quot;
They
definitely
dont
have
this
installed
Gothic & quot;,
& quot;
Papyrus & quot;,
& quot;
Comic
Sans
MS & quot;]
text = create_texts( & quot;
Hello, World & quot;, font_preferences, 72, (0, 128, 0))
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
done = True
Surface.fill((255, 255, 255))
Surface.blit(text,
(320 - text.get_width() // 2, 240 - text.get_height() // 2))
pygame.display.flip()
clock.tick(60)
Input Models
There are two techniques to determine the state of any input device: Polling or event queueing. Every time we press any key or button or release it, or the mouse is moved, an event is automatically added to the event queue. We must ensure to empty this event queue each frame by either calling pygame.event.get() or pygame.event.pump().
pygame.event.get()- This will return the list of all the events. How we handle those events depends on the event type a well. We can check the event type by the event.type field
The other way to check events is to poll for the state of key or buttons.
pygame.key.get_pressed() — This will provide a list of Booleans (True/False) that describes the state of each keyboard key.
ame.mouse.get_pos() — Returns the coordinates (x,y) of the mouse cursor. Will return (0, 0) if there is no change in the mouse cursor position.
pygame.mouse.get_pressed(): This returns the status of each mouse button, similar to the pygame.key.get pressed(). A tuple of size 3 is returned, corresponding to the left, middle, and right buttons. Below a little program that has a bit of everything:
- Sliding the mouse causes a trail after it.
- Ctrl + W will close the window. Same for Alt + F4.
- The close (x) button will close the window.
- R, G, B keys will make the trail red, green, and blue, respectively.
• Using the left mouse button will thicken the trail.
• Use the right mouse button to make the trail thinner.
import pygame
def main():
pygame.init()
Surface = pygame.display.set_mode((640, 480))
clock = pygame.time.Clock()
radius = 15
x = 0
y = 0
mode = 'blue'
points = []
while True:
pressed = pygame.key.get_pressed()
alt_held = pressed[pygame.K_LALT] or pressed[pygame.K_RALT]
ctrl_held = pressed[pygame.K_LCTRL] or pressed[pygame.K_RCTRL]
for event in pygame.event.get():
# determin if X was clicked, or Ctrl+W or Alt+F4 was used
if event.type == pygame.QUIT:
return
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_w and ctrl_held:
return
if event.key == pygame.K_F4 and alt_held:
return
if event.key == pygame.K_ESCAPE:
return
# determine if a letter key was pressed
if event.key == pygame.K_r:
mode = 'red'
elif event.key == pygame.K_g:
mode = 'green'
elif event.key == pygame.K_b:
mode = 'blue'
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1: # left click grows radius
radius = min(200, radius + 1)
elif event.button == 3: # right click shrinks radius
radius = max(1, radius - 1)
if event.type == pygame.MOUSEMOTION:
# if mouse moved, add point to list
position = event.pos
points = points + [position]
points = points[-256:]
Surface.fill((0, 0, 0))
# draw all points
i = 0
while i & lt; len(points) - 1:
makealinebetween(Surface, i, points[i], points[i + 1], radius, mode)
i += 1
pygame.display.flip()
clock.tick(60)
def makealinebetween(Surface, index, start, end, width, mode_color):
c1 = max(0, min(255, 2 * index - 256))
c2 = max(0, min(255, 2 * index))
if mode_color == 'blue':
color = (c1, c1, c2)
elif mode_color == 'red':
color = (c2, c1, c1)
elif mode_color == 'green':
color = (c1, c2, c1)
dx = start[0] - end[0]
dy = start[1] - end[1]
iteration = max(abs(dx), abs(dy))
for i in range(iteration):
progress = 1.0 * i / iteration
aprogress = 1 - progress
x = int(aprogress * start[0] + progress * end[0])
y = int(aprogress * start[1] + progress * end[1])
pygame.draw.circle(Surface, color, (x, y), width)
main()
Scene Logic
If you are not aware of the OOP concept ( object-Oriented Programming ) in python, you should be definitely aware of that.
Here is a class for BaseScene:
class BaseScene:
def __init__(self):
self.next = self
def ProcessInput(self, events):
print( & quot;
uh - oh, you
didn
't override this in the child class")
def Update(self):
print( & quot;
uh - oh, you
didn
't override this in the child class")
def Render(self, Surface):
print( & quot;
uh - oh, you
didn
't override this in the child class")
def SwitchToScene(self, next_scene):
self.next = next_scene
When you override this class, you’ve got three method implementations to fill in.
- ProcessInput — this will receive all the events that happened since the last frame.
- Update — your game logic goes here for the scene.
- Render — your render code goes here. It will receive the most Surface Surface as input.
Yes, this class needs the appropriate harness to work. Let’s try an example that does a simple task: It executes the pygame pipeline with a scene with blank red background. When we hit enter, it changes its color to blue.
The code may seem plenty, but at the same time, it does lots of other subtle things while keeping the complexity of your game logic contained into a snazzy OO model.
Once you continue to add more complexity to your game, this model will save you lots of time from debugging and changing code.
def main():
pygame.init()
Surface = pygame.display.set_mode((640, 480))
watch = pygame.time.Clock()
radius = 15
x = 0
y = 0
mode = 'blue'
points = []
while True:
pressed = pygame.key.get_pressed()
alt_held = pressed[pygame.K_LALT] or pressed[pygame.K_RALT]
ctrl_held = pressed[pygame.K_LCTRL] or pressed[pygame.K_RCTRL]
for event in pygame.event.get():
# Checks if the X button was pressed, or if Ctrl + W or Alt+F4 was pressed.
if event.type == pygame.QUIT:
return
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_w and ctrl_held:
return
if event.key == pygame.K_F4 and alt_held:
return
if event.key == pygame.K_ESCAPE:
return
# to see if a letter key has been pushed
if event.key == pygame.K_r:
mode = 'red'
elif event.key == pygame.K_g:
mode = 'green'
elif event.key == pygame.K_b:
mode = 'blue'
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1: # The radius is increased by clicking the left mouse button.
radius = min(200, radius + 1)
elif event.button == 3: # Right-clicking reduces the radius.
radius = max(1, radius - 1)
if event.type == pygame.MOUSEMOTION:
# if the mouse moves, add a new point to the list
position = event.pos
points = points + [position]
points = points[-256:]
Surface.fill((0, 0, 0))
# make a diagram of all the points
i = 0
while i & lt; len(points) - 1:
makealinebetween(Surface, i, points[i], points[i + 1], radius, mode)
i += 1
pygame.display.flip()
clock.tick(60)
def (Surface, index, start, end, width, mode_color):
c1 = max(0, min(255, 2 * index - 256))
c2 = max(0, min(255, 2 * index))
if mode_color == 'blue':
color = (c1, c1, c2)
elif mode_color == 'red':
color = (c2, c1, c1)
elif mode_color == 'green':
color = (c1, c2, c1)
dx = start[0] - end[0]
dy = start[1] - end[1]
iteration = max(abs(dx), abs(dy))
for i in range(iteration):
progress = 1.0 * i / iteration
aprogress = 1 - progress
X = int(aprogress * start[0] + progress * end[0])
Y = int(aprogress * start[1] + progress * end[1])
pygame.draw.circle(Surface, color, (X, Y), width)
main()
We hope this basic PyGame Tutorial helps you to understand the basics of the Pygame. We hope that you have understood the concept comprehensively. To learn more such concepts, join Great Learning’s PGP Artificial Intelligence and Machine Learning Course and upskill today.
The PGP- AIML Course also offers Online Mentorship and Career Support to help you power ahead of your career.