Module 3 of 20 Phase: Core Graphics

Drawing Graphics
with pygame.draw

Before you load a single image, Pygame lets you draw directly onto the screen with plain shapes. In this module you'll learn RGB color, every function in pygame.draw, and how anti-aliasing and screen updates actually work under the hood.

🎨
12 Lessons
This module
~2 hrs
Estimated time
📊
Beginner
Difficulty
🐍
pygame.draw
Primary module
Section 1

RGB Colors & the Screen Background

Every color in Pygame is an RGB tuple — three integers from 0 to 255 for red, green and blue. (255,0,0) is pure red, (0,0,0) is black, (255,255,255) is white. You can also pass a 4th value (alpha) on surfaces that support transparency.

Filling the background every frame is done with screen.fill(color) — it must happen before you draw anything else, otherwise your shapes get painted over.

colors.py
WHITE  = (255, 255, 255)
BLACK  = (0, 0, 0)
RED    = (220, 20, 60)
GREEN  = (52, 211, 153)
BLUE   = (79, 158, 255)
NAVY   = (5, 9, 26)

screen.fill(NAVY)   # clear the frame before drawing anything
💡
Key insight: Forgetting to fill the screen each frame is the #1 beginner bug — old frames "smear" across the screen because nothing erases them first.
Section 2

Lines, Circles & Rectangles

These three functions cover most of what you'll draw before you start using images. Each one takes the target surface, a color, then shape-specific position arguments.

shapes_basic.py
# pygame.draw.line(surface, color, start_pos, end_pos, width)
pygame.draw.line(screen, WHITE, (50, 50), (300, 50), 4)

# pygame.draw.circle(surface, color, center, radius, width=0)
pygame.draw.circle(screen, GREEN, (400, 300), 40)          # filled
pygame.draw.circle(screen, GREEN, (400, 300), 40, 3)       # outline only

# pygame.draw.rect(surface, color, rect, width=0, border_radius=0)
pygame.draw.rect(screen, BLUE, (100, 150, 200, 100))                 # filled
pygame.draw.rect(screen, BLUE, (100, 150, 200, 100), 2, border_radius=8)

Notice the width parameter: 0 (the default) fills the shape solid; any positive number draws only an outline that many pixels thick. Rectangles take a 4-tuple (x, y, width, height) — or a real pygame.Rect object, which is almost always the better choice once you start moving things.

Section 3

Ellipses, Polygons & Arcs

For anything that isn't a perfect circle or rectangle, Pygame gives you three more shape functions:

🥚
Ellipse
pygame.draw.ellipse(surface, color, rect, width=0) — draws an oval that fits exactly inside the given bounding rectangle. A square rect always produces a circle.
🔷
Polygon
pygame.draw.polygon(surface, color, point_list, width=0) — connects a list of (x, y) points in order, closing the shape back to the first point. Great for triangles, arrows, and custom terrain.
🌙
Arc
pygame.draw.arc(surface, color, rect, start_angle, stop_angle, width=1) — draws a curved segment of an ellipse. Angles are in radians, measured counter-clockwise from the 3 o'clock position.
✏️
Border Width
Every pygame.draw function shares the same width convention: 0 = filled, N = outline of N pixels. Consistent across shapes, so learn it once.
shapes_advanced.py
import math

# Ellipse: fits inside the bounding rect
pygame.draw.ellipse(screen, RED, (150, 400, 180, 90))

# Polygon: a triangle from 3 points
pygame.draw.polygon(screen, GREEN, [(500, 400), (560, 500), (440, 500)])

# Arc: half a circle, from 0 to pi radians
pygame.draw.arc(screen, BLUE, (600, 380, 120, 120), 0, math.pi, 4)
Section 4

Anti-Aliasing & Updating the Screen

Standard pygame.draw shapes have jagged, "pixel-stepped" edges — this is normal for a fast, low-level 2D library. For smoother lines and circles, Pygame provides anti-aliased variants in pygame.gfxdraw (an extra module you import separately), which blend edge pixels with the background color instead of leaving them hard-edged.

FunctionEdgesSpeedWhen to use
pygame.draw.circleJaggedFastestGameplay objects, hitboxes, prototypes
pygame.gfxdraw.aacircleSmoothSlightly slowerMenus, logos, polished UI

Finally, nothing you draw appears on screen until you call pygame.display.flip() (redraws the whole screen) or pygame.display.update() (can redraw just specific rects for performance). This must happen once per frame, at the very end of your game loop, after every draw call.

🎯
Frame order matters: 1) screen.fill() → 2) all your pygame.draw calls → 3) pygame.display.flip(). Get this order wrong and you'll see flicker or nothing at all.
Graphics Challenge

Put It All Together

Here's a complete mini-scene combining every shape from this module into one drawing pass — a simple "sun over hills" scene using only pygame.draw calls:

scene_demo.py
def draw_scene(screen):
    screen.fill((135, 206, 235))                              # sky
    pygame.draw.circle(screen, (255, 221, 87), (700, 90), 50) # sun
    pygame.draw.ellipse(screen, (34, 139, 34), (-50, 380, 500, 260))
    pygame.draw.ellipse(screen, (34, 139, 34), (300, 400, 500, 260))
    pygame.draw.rect(screen, (139, 69, 19), (370, 300, 60, 100))   # tree trunk
    pygame.draw.polygon(screen, (0, 100, 0), [(400, 180), (460, 300), (340, 300)])
Visual Reference

Pygame's Coordinate System

Every position you pass to pygame.draw is measured from the top-left corner of the window — that's (0, 0). X increases as you move right, and — unlike math class — Y increases as you move down, not up. Keeping this flipped Y-axis in mind is what makes "gravity pulls down" mean "increase y" once you start writing movement code.

x → y ↓ (0, 0) (220, 110) (400, 180) (480, 240)
The origin (0, 0) sits at the top-left. X grows rightward, Y grows downward — so a point further down the screen has a larger y-value, not a smaller one.

🧠 Quick Knowledge Check

1. What does passing width=0 to a pygame.draw function do?
2. What must you call before any drawing happens, at the start of each frame?
3. Which function actually makes your drawings visible on screen?
4. What units does pygame.draw.arc() use for its start/stop angles?
5. What determines the size and shape of an ellipse drawn with pygame.draw.ellipse()?
Finished Module 3?

Mark it complete to track your progress through Complete Pygame Mastery 2026.

🗒 Cheat Sheet 📝 Worksheet