The Practical Guide to Game Development with Pygame---2. Understanding the Surface Object
code_egg
Posted on August 12, 2024
In the previous article, we used the pygame.display.set_mode()
function to get a window object and the pygame.image.load()
function to load an image, resulting in an image object. Both the window object and the image object are actually of the Surface
type, and we collectively refer to them as Surface
objects. The concept of Surface
is crucial in Pygame, and this article will provide a detailed introduction.
Project code download link: https://github.com/la-vie-est-belle/pygame_codes
What is a Surface?
We can think of a Surface
object in Pygame as a canvas. We can fill the canvas with colors or draw any images, text, and lines on it. Let’s briefly look at how to add images to various Surface
objects. See Example Code 2-1.
import sys
import pygame
pygame.init()
surface1 = pygame.display.set_mode((800, 600)) # 1
pygame.display.set_caption('Surface Demo')
surface2 = pygame.image.load('pygame_logo.png') # 2
surface2_rect = surface2.get_rect()
surface2_rect.center = (400, 300)
surface3 = pygame.image.load('python_logo.png') # 3
surface3_rect = surface3.get_rect()
surface3_rect.topleft = (0, 0)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
surface1.fill((0, 255, 0), (0, 0, 400, 600)) # 4
surface1.blit(surface2, surface2_rect) # 5
surface2.blit(surface3, surface3_rect) # 6
pygame.display.flip()
Code Explanation:
#1 Call the pygame.display.set_mode()
function to get a Surface
object that represents the screen.
#2 Call the pygame.image.load()
function to load the Pygame logo, resulting in a Surface
object the same size as the loaded image. The Rect
object's center attribute is used to set the position of the Surface
object. center
specifies the center of the Surface
, so this actually centers the Pygame logo on the screen.
#3 Similarly, load the Python logo image to get a Surface
object the same size as this image. The top-left corner of its coordinates is set to (0, 0)
. Since the Python logo is to be added on top of the Pygame logo, (0, 0)
positions the top-left corner of the Python logo at the origin of the Pygame logo's coordinate system.
Note: The coordinate system in Pygame will be explained in the next section.
#4 Use the fill()
function of the Surface
object to fill the left half of the window with green. This function can take a rectangular region to specify where to fill.
#5 Use the blit()
function of the Surface
object to draw another Surface
object. Here, the Pygame logo Surface
object is added to the window Surface
object.
#6 Add the Python logo Surface
object onto the Pygame logo Surface
object.
Note: The
Surface
objects that are added later will obscure those added earlier.
How to Create a Surface
In Example Code 2-1, we obtained Surface
objects using the pygame.display.set_mode()
and pygame.image.load()
functions. Additionally, we can create a Surface
object directly using pygame.Surface()
by specifying its width and height.
surface = pygame.Surface((1000, 800)) # Create a Surface object with a width of 1000 and height of 800
In Pygame, when we create text, we are essentially creating a Surface
object where the text is rendered.
font = pygame.font.SysFont('Arial', 50) # Set the font
text = font.render('Hello pygame!', True, (0, 0, 0)) # Render the text; 'text' is a Surface object
Common Surface Functions
Here are some commonly used Surface
object functions and properties.
1.
Surface.blit(source, dest, area=None)
The blit()
function is used to draw one Surface
object onto another. source
is the source Surface
object to be drawn, and dest
is the target Surface
object where the source will be drawn. The area
parameter specifies the drawing region and defaults to None
, meaning it will draw at the top-left corner with the width and height of the source Surface
.
2.
Surface.blits(((source, dest, area), ...))
The blits()
function takes a sequence of tuples, each containing a source Surface
, a destination Surface
, and an optional area. This function allows drawing multiple Surface
objects at once.
3.
Surface.convert(Surface=None)
Surface.convert_alpha(Surface=None)
When you use pygame.image.load()
to load an image and then draw it onto a target Surface
using blit()
, if the pixel format of the image does not match the pixel format of the target Surface
, the blit()
function performs an internal format conversion.
Since blit()
is called every frame, performing format conversion every time can be performance-intensive. Therefore, you can call convert()
to convert the pixel format of the image to match the screen Surface
format when loading the image. If no Surface
parameter is specified, it defaults to converting to the format of the screen Surface
. For example:
surface1 = pygame.image.load('demo.jpg').convert()
surface3 = pygame.image.load('demo.png').convert_alpha()
If the image has transparency, use convert_alpha()
to preserve the image's transparency effects.
Note: Pixel format refers to the way pixel data is stored, including color channel arrangement and bit depth, not the file format (.jpg, .png, .gif).
4.
Surface.copy()
Creates a copy of a Surface
object. The copied Surface
has the same pixel format as the original.
5.
Surface.fill(color, rect=None)
Fills the target Surface
object with a color. The rect
parameter specifies the region to fill; if not provided, the entire Surface
is filled.
6.
Surface.get_size()
Gets the width and height of the Surface
object in pixels, returning a tuple (width, height)
.
7.
Surface.get_width()
Gets the width of the Surface
object in pixels.
8.
Surface.get_height()
Gets the height of the Surface
object in pixels.
9.
Surface.get_rect()
Gets the rectangle area of the Surface
object, returning a Rect
object.
In Example Code 2-2, we will demonstrate the use of these functions.
import sys
import pygame
pygame.init()
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption('Surface Demo')
pygame_logo = pygame.image.load('pygame_logo.png').convert_alpha() # 1
pygame_logo_rect = pygame_logo.get_rect()
pygame_logo_rect.center = (400, 300)
print(pygame_logo.get_size()) # 2
print(pygame_logo.get_width())
print(pygame_logo.get_height())
python_logo = pygame.image.load('python_logo.png').convert_alpha()
python_logo_rect = python_logo.get_rect()
python_logo_rect.topleft = (0, 0)
print(python_logo.get_size())
print(python_logo.get_width())
print(python_logo.get_height())
python_logo2 = python_logo.copy() # 3
python_logo_rect2 = python_logo.get_rect()
python_logo_rect2.topright = (600, 100)
print(python_logo2.get_size())
print(python_logo2.get_width())
print(python_logo2.get_height())
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
screen.fill((0, 255, 0), (0, 0, 400, 600))
screen.blit(pygame_logo, pygame_logo_rect)
pygame_logo.blits(((python_logo, python_logo_rect), (python_logo2, python_logo_rect2))) # 4
pygame.display.flip()
Code Explanation:
#1 Call the convert_alpha()
function to convert the image's pixel format and retain its transparency.
#2 Use get_size()
, get_width()
, and get_height()
functions to obtain the dimensions of the Surface object.
#3 Use the copy()
function to create a copy of a Surface
object and set its top-right corner to (600, 100)
.
#4 Use the blits()
function to draw two Python logo images onto the Pygame logo. As observed, part of the Python logo on the right is not displayed because it is outside the rectangle area of the Pygame logo, so it is not rendered.
Summary
In this article, we introduced the Surface
, including its concept, creation methods, and common functions, and demonstrated their usage with examples. The Surface
is a key concept in Pygame, and understanding it will enhance your familiarity with Pygame.
Buy author a cup of coffee if you enjoyed this tutorial. :)
Posted on August 12, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.