Text & Scoring
Games need text for scores, instructions, and game-over
screens. PyGame's pygame.font module renders text as image surfaces that you blit onto
the screen.
Learning Objectives
- 12.5.2.4 Output text to the application window
- 12.5.3.7 Code score tracking and display
Conceptual Anchor
The Rubber Stamp Analogy
PyGame text works like a rubber stamp: first you create the stamp
(font.render()) — this produces an image of the text. Then you stamp it
onto the canvas (screen.blit()) at a specific position.
Rules & Theory
Font Creation
| Method | Description | Example |
|---|---|---|
pygame.font.SysFont() |
Use a system font | font = pygame.font.SysFont("Arial", 36) |
pygame.font.Font() |
Use a custom .ttf file | font = pygame.font.Font("pixel.ttf", 24) |
pygame.font.Font(None, size) |
PyGame default font | font = pygame.font.Font(None, 48) |
Text Rendering Process
# Step 1: Create font object (do this ONCE, before the loop)
font = pygame.font.SysFont("Arial", 36)
# Step 2: Render text → creates a Surface
text_surface = font.render("Hello!", True, (255, 255, 255))
# text antialias color
# Step 3: Blit (draw) onto screen
screen.blit(text_surface, (x, y))Centering Text
# Get text dimensions
text_rect = text_surface.get_rect()
# Center on screen
text_rect.center = (WIDTH // 2, HEIGHT // 2)
screen.blit(text_surface, text_rect)
# Other anchor points:
# text_rect.topleft = (x, y)
# text_rect.midtop = (x, y)
# text_rect.topright = (x, y)Worked Examples
1 Score Counter
import pygame, sys
pygame.init()
WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Score Demo")
clock = pygame.time.Clock()
font = pygame.font.SysFont("Arial", 32)
score = 0
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
score += 10 # gain points
screen.fill((30, 30, 30))
# Render and display score
score_text = font.render(f"Score: {score}", True,
(255, 255, 0))
screen.blit(score_text, (20, 20))
# Instructions
hint = font.render("Press SPACE for points!", True,
(150, 150, 150))
hint_rect = hint.get_rect(center=(WIDTH//2, HEIGHT//2))
screen.blit(hint, hint_rect)
pygame.display.flip()
clock.tick(60)
pygame.quit()
sys.exit()2 Timer Display
import pygame, sys
pygame.init()
screen = pygame.display.set_mode((800, 600))
clock = pygame.time.Clock()
font = pygame.font.SysFont("Arial", 48)
start_ticks = pygame.time.get_ticks() # ms since start
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# Calculate elapsed seconds
elapsed = (pygame.time.get_ticks() - start_ticks) / 1000
minutes = int(elapsed // 60)
seconds = int(elapsed % 60)
screen.fill((30, 30, 30))
timer_text = font.render(f"{minutes:02d}:{seconds:02d}",
True, (0, 255, 100))
timer_rect = timer_text.get_rect(center=(400, 300))
screen.blit(timer_text, timer_rect)
pygame.display.flip()
clock.tick(60)
pygame.quit()
sys.exit()3 Game Over Screen
def draw_game_over(screen, score):
"""Display centered game-over message."""
overlay = pygame.Surface((800, 600))
overlay.set_alpha(180)
overlay.fill((0, 0, 0))
screen.blit(overlay, (0, 0))
big_font = pygame.font.SysFont("Arial", 72)
small_font = pygame.font.SysFont("Arial", 28)
# "GAME OVER" title
title = big_font.render("GAME OVER", True, (255, 50, 50))
title_rect = title.get_rect(center=(400, 240))
screen.blit(title, title_rect)
# Final score
score_text = small_font.render(f"Final Score: {score}",
True, (255, 255, 255))
score_rect = score_text.get_rect(center=(400, 320))
screen.blit(score_text, score_rect)
# Restart hint
hint = small_font.render("Press R to Restart", True,
(150, 150, 150))
hint_rect = hint.get_rect(center=(400, 380))
screen.blit(hint, hint_rect)Common Pitfalls
Creating Font INSIDE the Loop
Creating fonts is slow. Always create font objects before the game loop — only
render() inside the loop.
Forgetting Anti-aliasing
The second argument of render() is anti-aliasing. Set it to True for
smooth text edges, False for pixel-art style.
Tasks
Create a score display that increases by 10 when clicking the left mouse button and decreases by 5 with right click.
Add a countdown timer (30 seconds → 0) that displays "Time's Up!" when it reaches zero.
Build a full HUD (heads-up display): score in top-left, timer in top-right, lives as hearts in top-center.
Self-Check Quiz
Q1: What two steps are needed to display text?
font.render("text", True, color) — creates a surface. 2)
screen.blit(surface, (x, y)) — draws it on screen.Q2: How do you center text on screen?
text_rect = text_surface.get_rect(center=(WIDTH//2, HEIGHT//2)) then
screen.blit(text_surface, text_rect).Q3: What does the second argument (True/False) in render() do?
True = smooth text edges, False =
jagged/pixelated edges.