Learning Goals
3 minBy the end of this lesson you can:
- Describe the RGB colour model and write any colour as an
(r, g, b)tuple with values 0–255. - Use both named colours (e.g.
"tomato") and RGB tuples withscreen.fillandscreen.draw. - Build a vertical gradient background by drawing many 1-pixel-tall rectangles in a
forloop.
Warm-Up · How Many Colours?
5 minRGB uses three numbers, each from 0 to 255. How many unique colours can you make? Predict the result of this calculation:
red_options = 256 green_options = 256 blue_options = 256 total = red_options * green_options * blue_options print("Total colours:", total)
Show the answer
Output
Total colours: 16777216
Over 16 million colours — more than the human eye can distinguish. That is why 8-bit-per-channel colour (the kind screens use) looks smooth and continuous.
New Concept · RGB Tuples & Named Colours
12 minThink of an RGB colour like a smoothie recipe: three ingredients (red, green, blue), each measured from 0 (none) to 255 (maximum). Mixing them gives you any colour on screen.
Two ways to write a colour
# Named colour — easy to read screen.fill("midnightblue") # RGB tuple — precise control screen.fill((25, 25, 112)) # same midnight blue as a triple
Both lines fill the screen with the same colour. Named colours use CSS colour names — there are about 140 of them built in.
Useful RGB recipes
| Colour | RGB tuple | Named version |
|---|---|---|
| Pure red | (255, 0, 0) | "red" |
| Bright sky blue | (0, 191, 255) | "deepskyblue" |
| Warm sunset orange | (255, 140, 0) | "darkorange" |
| Pure black | (0, 0, 0) | "black" |
| Pure white | (255, 255, 255) | "white" |
Gradient trick — interpolating between two colours
A gradient is just many thin strips, each slightly different in colour. To blend from colour A at the top to colour B at the bottom, calculate how far down each strip is (as a fraction from 0.0 to 1.0) and mix:
# For one strip at row y in a HEIGHT-pixel window: fraction = y / HEIGHT r = int(top_r + (bot_r - top_r) * fraction) g = int(top_g + (bot_g - top_g) * fraction) b = int(top_b + (bot_b - top_b) * fraction)
Worked Example · Sunset Gradient Sky
12 minThe story
Kavitha wants a sunset sky that fades from deep orange at the top to dark purple at the bottom. Save as sunset.py:
# sunset.py — vertical gradient background import pgzrun WIDTH = 600 HEIGHT = 400 TITLE = "Sunset Sky" # Top colour (orange) and bottom colour (purple) TOP = (255, 120, 0) BOT = (80, 0, 120) def draw(): for y in range(HEIGHT): fraction = y / HEIGHT r = int(TOP[0] + (BOT[0] - TOP[0]) * fraction) g = int(TOP[1] + (BOT[1] - TOP[1]) * fraction) b = int(TOP[2] + (BOT[2] - TOP[2]) * fraction) screen.draw.filled_rect(Rect((0, y), (WIDTH, 1)), (r, g, b)) pgzrun.go()
The loop runs 400 times — once per row. Each pass calculates a slightly different colour and draws a 1-pixel-tall, full-width rectangle. Together they form a smooth gradient.
What you'll see
Drawing 400 rectangles every frame is fine for 400 pixels of height. In a much larger game you might pre-render the gradient to a surface once and blit it each frame — but for these lessons the loop is perfectly fast enough.
Try It Yourself
13 minChange TOP and BOT in the worked example to make a night-sky gradient — try fading from (0, 0, 80) (dark blue) at the top to (0, 0, 0) (black) at the bottom.
Hint
TOP = (0, 0, 80) BOT = (0, 0, 0)
Draw five filled rectangles side by side, each 120×400 pixels wide (they fill a 600×400 window). Give each one a different named colour. Then add the RGB values as white text labels inside each rectangle.
Hint
SWATCHES = [ ("red", (255, 0, 0)), ("limegreen", (50, 205, 50)), ("deepskyblue",(0, 191, 255)), ("gold", (255, 215, 0)), ("violet", (238, 130, 238)), ] def draw(): for i, (name, rgb) in enumerate(SWATCHES): screen.draw.filled_rect(Rect((i * 120, 0), (120, 400)), rgb) screen.draw.text(name, center=(i * 120 + 60, 200), fontsize=14, color="white")
Mini-Challenge 🔥 · Buggy Rainbow
8 minNurul wrote a horizontal colour sweep but the screen is all black and there is a crash. Find and fix the bugs.
# nurul_rainbow.py — buggy
import pgzrun
WIDTH = 600
HEIGHT = 400
def draw():
for x in range(WIDTH):
fraction = x / WIDTH
r = 255 * fraction # missing int()
g = 0
b = 255 - (255 * fraction) # missing int()
screen.draw.filled_rect(Rect((x, 0), (1, HEIGHT)), (r, g, b))
pgzrun.go()It works if…
the window shows a smooth left-to-right sweep from blue on the left to red on the right
Show the fix
# nurul_rainbow.py — fixed import pgzrun WIDTH = 600 HEIGHT = 400 def draw(): for x in range(WIDTH): fraction = x / WIDTH r = int(255 * fraction) # bug 1: must wrap in int() g = 0 b = int(255 - (255 * fraction)) # bug 2: must wrap in int() screen.draw.filled_rect(Rect((x, 0), (1, HEIGHT)), (r, g, b)) pgzrun.go()
Both channel calculations produced floats. Pygame Zero requires integer RGB values — wrapping each with int() fixes the TypeError.
Recap
3 minColours in Pygame Zero can be written as named strings (e.g. "tomato") or as RGB tuples (r, g, b) where each channel is an integer from 0 to 255. To make a vertical gradient, loop through every row, calculate an interpolated colour using the row's fraction of the total height, and draw a 1-pixel-tall rectangle. Always use int() when computing channel values from floating-point arithmetic.
Vocabulary Card
- RGB
- Red-Green-Blue — the colour model used by screens. Each channel is an integer 0–255.
- named colour
- A string like
"skyblue"or"tomato"that Pygame Zero maps to a fixed RGB value. - gradient
- A smooth blend from one colour to another, made here by drawing many thin, slightly different coloured strips.
- interpolation
- Calculating in-between values — e.g. the colour 60% of the way between orange and purple.
Homework
4 minCreate a dawn scene. Use a vertical gradient for the sky (choose your own top and bottom colours to suggest early morning). Then draw a solid coloured circle near the horizon for the rising sun. Save as dawn.py and bring a screenshot.
Stretch. Add a horizontal ground rectangle at the bottom of the window in a dark green or brown colour.
Sample · dawn.py
# dawn.py — a dawn scene with gradient sky import pgzrun WIDTH = 600 HEIGHT = 400 TITLE = "Dawn Scene" TOP = (30, 20, 80) # deep indigo at the top BOT = (255, 180, 80) # warm amber at the horizon def draw(): for y in range(HEIGHT): fraction = y / HEIGHT r = int(TOP[0] + (BOT[0] - TOP[0]) * fraction) g = int(TOP[1] + (BOT[1] - TOP[1]) * fraction) b = int(TOP[2] + (BOT[2] - TOP[2]) * fraction) screen.draw.filled_rect(Rect((0, y), (WIDTH, 1)), (r, g, b)) screen.draw.filled_rect(Rect((0, 330), (600, 70)), (34, 80, 34)) # ground screen.draw.filled_circle((300, 330), 40, (255, 220, 50)) # sun pgzrun.go()
Your colour choices will differ. The important technique is the gradient loop plus drawing the sun circle on top of it.