UMPSA STEM LAB · Step 1 of 10
Understand pixels, colours and data types — then write the code that opens your Snake game window.
By the end of this step you will have a working Python program that opens a dark game window — the blank canvas your Snake game will be drawn on.
Understand pixels, screen coordinates, RGB colours, Python data types, and how to store values in variables.
Every constant you write here (GRID_COLS, CELL_SIZE, colours) is used in all nine steps. Get them right once, use them everywhere.
Every image on a screen is made of tiny coloured squares called pixels. Pygame uses an (x, y) coordinate system to identify each one.
Unlike a maths graph, the Pygame y-axis is flipped: (0, 0) is the top-left corner, and y increases downward.
The snake game uses a grid of cells, not individual pixels. Each cell is CELL_SIZE × CELL_SIZE pixels. To find the pixel position of a cell:
pixel_x = col * CELL_SIZE # e.g. column 3 → 3 × 30 = 90 px from left pixel_y = row * CELL_SIZE # e.g. row 2 → 2 × 30 = 60 px from top
(col, row), you multiply by CELL_SIZE to get the actual screen coordinates before calling pygame.draw.rect().When you run the Step 1 program, Pygame opens a 600 × 450 pixel window, fills it with the dark background colour, holds for 3 seconds, then closes.
Instead of typing 600 and 450 directly, we calculate them from the grid constants. This way, changing GRID_COLS automatically changes the window — we only update one number:
GRID_COLS = 20 CELL_SIZE = 30 WINDOW_W = GRID_COLS * CELL_SIZE # 20 × 30 = 600 pixels WINDOW_H = GRID_ROWS * CELL_SIZE # 15 × 30 = 450 pixels
Every colour on a screen is mixed from three light channels: Red, Green, and Blue. Each channel is an integer from 0 (off) to 255 (full brightness).
🔴 Red = 0 → no red
🟢 Green = 200 → lots of green
🔵 Blue = 80 → a little blue
| Variable | Tuple | Swatch | Used for |
|---|---|---|---|
GREEN | (0, 200, 80) |
Snake body segments | |
DKGREEN | (0, 160, 50) |
Snake head (darker so it stands out) | |
RED | (220, 50, 50) |
Food circle | |
WHITE | (255, 255, 255) |
Score text on screen | |
BG | (30, 30, 30) |
Background fill every frame |
Python automatically assigns a type to every value. The type determines what you can do with the value. Step 1 uses three types.
A whole number. Used for grid dimensions, speed, and pixel sizes.
GRID_COLS = 20
CELL_SIZE = 30
SNAKE_SPEED = 8
An unchangeable sequence in ( ). Perfect for RGB colours and later for (col, row) positions.
GREEN = (0, 200, 80)
BG = (30, 30, 30)
Text in quotes. Used for the window title and later for direction names like "RIGHT".
"Snake"
"RIGHT"
"GAME OVER"
(col, row) too, for the same reason: a cell's identity shouldn't accidentally mutate.You can always ask Python what type a value is:
print(type(20)) # <class 'int'>
print(type((0, 200, 80))) # <class 'tuple'>
print(type("Snake")) # <class 'str'>
print(type(3.14)) # <class 'float'> ← decimals
When Python runs GRID_COLS = 20, it sets aside a slot in memory, labels it GRID_COLS, and stores the value 20 there. Any time the program needs that value, it reads it by name.
Every variable you define in Step 1 is reused unchanged in Steps 2–9. Changing a constant here changes the whole game.
col × CELL_SIZE gives the screen x position.
Used in: every step that draws anything (Steps 1–9)clock.tick(SNAKE_SPEED)pygame.draw.rect()pygame.draw.circle().
Used in: Steps 4–9screen.fill(BG) every frame to erase the previous frame before redrawing.
Used in: Steps 2–9 — essential for animationType this into Thonny and run it. A dark window titled "Snake" will appear for 3 seconds, then close.
# Step 1-1: Import the Pygame library so we can use its functions
import pygame
pygame.init()
# Step 1-2: Constants — grid size (never change these mid-game)
GRID_COLS = 20 # 20 columns → 20 cells wide
GRID_ROWS = 15 # 15 rows → 15 cells tall
CELL_SIZE = 30 # each cell is 30 × 30 pixels
SNAKE_SPEED = 8 # game loop runs 8 times per second
# Step 1-3: Colour constants — tuples of (Red, Green, Blue), 0-255 each
WHITE = (255, 255, 255) # score text
GREEN = ( 0, 200, 80) # snake body
DKGREEN = ( 0, 160, 50) # snake head (darker)
RED = (220, 50, 50) # food
BG = ( 30, 30, 30) # background — very dark grey
# Step 1-4: Calculate window size in pixels
WINDOW_W = GRID_COLS * CELL_SIZE # 20 × 30 = 600 px wide
WINDOW_H = GRID_ROWS * CELL_SIZE # 15 × 30 = 450 px tall
# Step 1-5: Create the window and set its title
screen = pygame.display.set_mode((WINDOW_W, WINDOW_H))
pygame.display.set_caption("Snake")
# Step 1-6: Fill with background colour and show the window
screen.fill(BG)
pygame.display.flip()
# Step 1-7: Wait 3 seconds so you can see it, then quit
pygame.time.wait(3000)
pygame.quit()
import pygame + pygame.init()Loads the Pygame library and initialises all its subsystems (graphics, sound, input). Always the first two lines.
GRID_COLS = 20 stores the integer 20 in a variable. UPPER_CASE names signal "don't change this". These four values define the entire playing field.
Each colour is a tuple of three integers. Pygame uses (R, G, B). BG = (30, 30, 30) is a very dark grey — just enough to see the grid cells.
WINDOW_W = GRID_COLS * CELL_SIZEPython evaluates the right side first: 20 × 30 = 600. Then it stores 600 in WINDOW_W. The * operator multiplies two integers.
pygame.display.set_mode((WINDOW_W, WINDOW_H))Opens the OS window. Note the double brackets: the outer ones are the function call; the inner (600, 450) is a tuple — the size argument. Returns a surface object stored in screen.
screen.fill(BG) + pygame.display.flip()Paints every pixel of the surface the BG colour. flip() pushes the surface to the physical screen. Without flip, nothing appears.
pygame.time.wait(3000) + pygame.quit()Pauses for 3000 milliseconds (3 seconds) so you can see the window. quit() shuts down Pygame cleanly. In later steps, the game loop replaces the wait.
You've covered all the concepts for Step 1. Time to apply them.
Start Activities → Tier 1 → 2 → 3 → 4