Stage 1: Build the Game Screen
Keep building in the workspace on the right.
This stage is part of the same Python Arcade project you started in Setup. Type each new code block into the Trinket rail and keep building on the last stage.
a game window, screen boundaries, and a player cannon
how coordinates name positions on the screen
a cannon sitting at the bottom of the playfield
The big idea
Before we draw anything, we need a map — a way to say "this thing is here." Python's Turtle library gives us one. The screen has a center point at (0, 0). X values move left and right. Y values move up and down.
Think of the screen like a sheet of graph paper with the middle marked. Every alien, every laser, and every cannon we build over the next nine stages will live somewhere on that paper.
A coordinate is just a pair of numbers — (x, y) — that says where something is. A Turtle is a thing the library draws for you; you tell it a coordinate, and it goes there.
(0, TOP)
│
│
(LEFT, 0)─────(0, 0)─────(RIGHT, 0)
│
│
(0, BOTTOM)
Today we will name the four edges (LEFT, RIGHT, TOP, BOTTOM) and a fifth one called FLOOR_LEVEL — the line the player cannon sits on. Once those names exist, every later stage gets to say "spawn at the TOP" instead of "spawn at y = 312." Names that mean something today become the vocabulary of the whole game.
Use the Trinket workspace on the right. If the setup test is still there, replace it with the Stage 1 code below.
Build it
Step 1 — Open the screen and name its edges
Every game needs a playfield before anything can happen on it. We create the screen first, then save its edges with names we will reuse for the rest of the course.
Why name them at all, instead of just typing the numbers later? Because LEFT tells the next reader which wall — -300 tells them nothing. Named numbers are the difference between code you can still read in nine stages and a pile of mystery values.
Start the current program with this:
Read the variable names
If `LEFT` is a negative number and `RIGHT` is a positive number, which one should the cannon use when it needs to stop at the left wall?
Check your thinking
It should compare against `LEFT`. The name tells you which side of the playfield it describes.
Write the screen setup
Type the setup block yourself. Say each variable name out loud before you type the value so it connects to the screen edge it represents.
Need a hint?
Use one assignment per edge: `LEFT`, `RIGHT`, `TOP`, `BOTTOM`, then give `FLOOR_LEVEL` its own fixed number.
main.py
Where it goes: Replace the setup smoke test with this new Stage 1 starter file. Keep the first line as line 1.
This starts the actual game file. Leave the first line at the top.
#!/bin/python3
import turtle
screen = turtle.Screen()
screen.bgcolor("black")
LEFT = -300
RIGHT = 300
TOP = 200
BOTTOM = -200
FLOOR_LEVEL = -150
turtle.done()
Run it. You should see a black game window appear. It is empty — that is fine. The four edge values are fixed on purpose so every student gets the same playfield in Trinket.
Step 2 — Drop a cannon at the floor
The cannon is the player. It needs a position before it can shoot, move, or take damage. We will create one Turtle, give it a color and a basic shape, and place it at FLOOR_LEVEL.
Now write the cannon setup above turtle.done():
Trace the cannon setup
turtle.Turtle()creates the object that will draw the cannon.penup()means moving it will not drag a line.setposition(0, FLOOR_LEVEL)puts it centered on the floor line.
main.py
Where it goes: Put this below the edge constants and above `turtle.done()`.
This creates the cannon Turtle before the program stops at `turtle.done()`.
cannon = turtle.Turtle()
cannon.penup()
cannon.color("white")
cannon.shape("square")
cannon.setposition(0, FLOOR_LEVEL)
Run the game again. You should see a white square near the bottom, centered left-to-right. Notice that the square is exactly at FLOOR_LEVEL — the name we picked in Step 1 is already doing real work.
Step 3 — Give it a cannon shape
A single square is not very cannon-looking. Instead of importing an image, we will stamp several squares into a simple ship shape. A stamp is a snapshot of the Turtle's current shape — once stamped, the Turtle can move on and the stamp stays behind.
We use one Turtle and stamp it five times rather than making five Turtles. Each Turtle is a little more work for the computer to track, and by Stage 5 we'll have dozens of lasers and aliens that each need their own — so we keep decoration cheap here to leave room for them later.
Now write the drawing function above turtle.done():
Predict the stamps
Before typing the function, point to the stamp() calls and predict which ones draw the base, body, and tip.
Need a hint?
Every `stamp()` leaves a copy of the current square. Every `setposition(...)` moves the same Turtle before the next stamp.
main.py
Where it goes: Put this function below the cannon setup and above the first `draw_cannon()` call.
Functions must be defined before you call them.
def draw_cannon():
cannon.clear()
cannon.shape("square")
x = cannon.xcor()
cannon.setposition(x - 20, FLOOR_LEVEL)
cannon.stamp()
cannon.setposition(x, FLOOR_LEVEL)
cannon.stamp()
cannon.setposition(x + 20, FLOOR_LEVEL)
cannon.stamp()
cannon.setposition(x, FLOOR_LEVEL + 20)
cannon.stamp()
cannon.setposition(x, FLOOR_LEVEL + 40)
cannon.stamp()
cannon.setposition(x, FLOOR_LEVEL)
cannon.hideturtle()
Then call it before turtle.done():
main.py
Where it goes: Put this one line below the `draw_cannon()` function and above `turtle.done()`.
This call runs the drawing function once.
draw_cannon()
Run it. Now your cannon has a base, a body, and a tip — a small stack of square stamps instead of one square.
Optional — Skin the square cannon with the ship sprite
Keep the square cannon code working first. Once it works, you can make the same player object look like the white pixel ship from the hero image.
If you uploaded player-ship.gif in Setup, add this block after screen.bgcolor("black") and before you create the cannon:
Use player-ship.gif only after the square cannon works. Upload it into Trinket with this exact filename.
main.py
Where it goes: Put this after `screen.bgcolor(...)` and before `cannon = turtle.Turtle()`.
Skip this if you are keeping the plain square cannon.
USE_PLAYER_SPRITE = True
try:
screen.addshape("player-ship.gif")
except:
USE_PLAYER_SPRITE = False
Then replace your draw_cannon() function with this version. It keeps the square fallback, but uses the uploaded ship sprite when Trinket can find it:
main.py
Where it goes: Replace the entire old `draw_cannon()` function with this version.
Do not keep two `draw_cannon()` functions. The second one would replace the first.
def draw_cannon():
cannon.clear()
x = cannon.xcor()
cannon.setposition(x, FLOOR_LEVEL)
if USE_PLAYER_SPRITE:
cannon.setheading(90)
cannon.shape("player-ship.gif")
cannon.showturtle()
return
cannon.shape("square")
cannon.setposition(x - 20, FLOOR_LEVEL)
cannon.stamp()
cannon.setposition(x, FLOOR_LEVEL)
cannon.stamp()
cannon.setposition(x + 20, FLOOR_LEVEL)
cannon.stamp()
cannon.setposition(x, FLOOR_LEVEL + 20)
cannon.stamp()
cannon.setposition(x, FLOOR_LEVEL + 40)
cannon.stamp()
cannon.setposition(x, FLOOR_LEVEL)
cannon.hideturtle()
Run it. If the GIF is uploaded correctly, the player looks like a white pixel ship pointed upward. The setheading(90) line matters in Trinket because a Turtle starts out facing right, and uploaded image shapes can follow that heading. If you see only one white square, Trinket did not load player-ship.gif; check that the sprite setup block is above cannon = turtle.Turtle() and that the uploaded filename is exactly player-ship.gif.
File order checkpoint
By the end of Stage 1, your main.py should be ordered like this:
#!/bin/python3andimport turtle- Screen setup and edge constants
- Optional sprite setup, if you are using
player-ship.gif - Cannon setup
draw_cannon()draw_cannon()call, thenturtle.done()
Understand it
The cannon you just built is still one Turtle that moved through several positions, leaving a stamp behind at each one. That is a design choice worth pausing on.
We could have used several separate Turtles — one for each stamped square — but every Turtle adds a little work for the computer to track. By the end of the course we will have lots of lasers and aliens that each need their own Turtle, so we keep "decoration" cheap and reuse one Turtle wherever we can.
Wrapping the stamping into a draw_cannon function also means we can call it again later, after the player moves. Calling cannon.clear() first wipes the old stamps so we do not pile up forty cannons on top of each other.
Try this
Try this
Three short experiments. Predict before you run, then test your guess.
Change FLOOR_LEVEL = -150 to FLOOR_LEVEL = -50. Where will the cannon end up? Decide before you run — then run it. Were you right?
Swap the cannon's shape("square") for shape("triangle") and run. Which one looks more like a cannon to you? Which one would a brand-new player understand faster?
Where else in this game will you need a position at the bottom of the screen? (Hint: when aliens reach the player, they have to know they got there.)
Test your stage
Stuck? Compare carefully
main.py
Where it goes: Compare this against your whole Stage 1 file from top to bottom. Do not paste it over later-stage work.
Use this only if your Stage 1 file will not run after you have checked the smaller tasks.
#!/bin/python3
import turtle
screen = turtle.Screen()
screen.bgcolor("black")
LEFT = -300
RIGHT = 300
TOP = 200
BOTTOM = -200
FLOOR_LEVEL = -150
cannon = turtle.Turtle()
cannon.penup()
cannon.color("white")
cannon.shape("square")
cannon.setposition(0, FLOOR_LEVEL)
def draw_cannon():
cannon.clear()
cannon.shape("square")
x = cannon.xcor()
cannon.setposition(x - 20, FLOOR_LEVEL)
cannon.stamp()
cannon.setposition(x, FLOOR_LEVEL)
cannon.stamp()
cannon.setposition(x + 20, FLOOR_LEVEL)
cannon.stamp()
cannon.setposition(x, FLOOR_LEVEL + 20)
cannon.stamp()
cannon.setposition(x, FLOOR_LEVEL + 40)
cannon.stamp()
cannon.setposition(x, FLOOR_LEVEL)
cannon.hideturtle()
draw_cannon()
turtle.done()
- The window opens with a black background.
- The cannon appears near the bottom of the screen.
- The cannon is centered left-to-right.
- Running the program twice does not pile up extra cannons.
- Optional sprite check: if
player-ship.gifis uploaded, the same player object renders as the white pixel ship. - Design check. Read your code out loud. Do
LEFT,RIGHT, andFLOOR_LEVELsound like real things, or like mystery numbers? - From memory. Without looking, write the line that places the cannon on the floor. Compare — did you use
cannon.setposition(0, FLOOR_LEVEL)?
If it breaks
- The window is blank.
draw_cannon()probably needs to be aboveturtle.done(). Theturtle.done()line is the "we are done setting up" signal — nothing after it runs. - The cannon is missing entirely. Check the spelling on
cannon.color("white"). Color names are case-sensitive in some setups, and a typo silently leaves the cannon invisible against the black background. - The cannon is way too high or way too low. Re-read
FLOOR_LEVEL = -150carefully. More negative numbers go lower. Less negative numbers go higher. - The cannon is one fat square, not a small stack of squares. The
cannon.setposition(...)calls between stamps need to actually run between the stamps. Read yourdraw_cannonfunction top-to-bottom and check the order. - The sprite skin does not show. The file must be uploaded to Trinket as exactly
player-ship.gif. If the filename is different,USE_PLAYER_SPRITEfalls back to the square cannon.
