Login

Please fill in your details to login.





python space invaders

Build a classic game of Space Invaders using Python Turtle

image
Today, you are going to build a fully working Space Invaders game using Python 3. For this tutorial, you will be using Thonny, which is a fantastic environment for writing and running Python code. We will be using the built-in
turtle
module to draw the graphics. Make sure you read the introduction to each code block before you copy and paste it into the IDE.

image
Classic Space Invaders... but you can't play it here...

0
Get ready to code!

1
Open up Thonny
2
You should get a blank script editor and output window. If not, create a new file from the File menu.
3
Organise your workspace.

1
Setting up the Game Screen

Before we can draw any shapes or move any pieces, we need a blank canvas to work with. This step is designed to initialise the game window, set its size, give it a background colour, and title it. We also use a special command called
tracer(0)
. By default, the
turtle
module animates every single thing it draws. For a fast-paced game, this would look very jerky. By setting the tracer to zero, we turn off these automatic updates, allowing us to manually refresh the screen later on for perfectly smooth gameplay.

import turtle
import time
import math
wn = turtle.Screen()
wn.title("Space Invaders  -  The Computing Café")
wn.bgcolor("black")
wn.setup(width=600, height=600)
wn.tracer(0)

# Next: 2. Creating the Player


2
Creating the Player

Now we create the player's laser cannon. In the
turtle
module, every object on the screen is technically a "turtle", but we can change its shape to look like a triangle. We set its heading to point upwards and lift its "pen" up so that it doesn't draw a solid line as it moves into its starting position at the bottom centre of the screen.

player = turtle.Turtle()
player.speed(0)
player.shape("triangle")
player.color("blue")
player.setheading(90)
player.penup()
player.goto(0, -250)

# Next: 3. Creating the Player's Bullet


3
Creating the Player's Bullet

Next, we create the player's bullet. This starts as a small, yellow square. We will hide it and move it off-screen to begin with. We also create a variable called
bullet_state
to keep track of whether the bullet is "ready" to be fired or is currently moving ("fire"). This stops the player from being able to fire multiple bullets at once.

bullet = turtle.Turtle()
bullet.speed(0)
bullet.shape("square")
bullet.color("yellow")
bullet.shapesize(stretch_wid=0.5, stretch_len=0.5)
bullet.penup()
bullet.hideturtle()
bullet.goto(0, -400)
bullet_state = "ready"
bullet_speed = 20

# Next: 4. The Message Display


4
The Message Display

We want to tell the player how to control the game. To do this, we create another turtle object. However, we don't actually want to see this turtle at all - we only want to use it to write text onto the screen! We will hide the turtle shape, move it to the centre of the screen, and use it to display a starting instruction.

message = turtle.Turtle()
message.speed(0)
message.color("white")
message.penup()
message.hideturtle()
message.goto(0, 0)
message.write("Press Space to Fire", align="center", font=("Courier", 24, "normal"))

# Next: 5. Building a Fleet of Invaders


5
Building a Fleet of Invaders

A game of Space Invaders isn't complete without aliens to fight! Instead of writing the code for an invader 44 separate times, we use a programming technique called a "nested loop" (a loop inside a loop). The outer loop will run 4 times to create 4 rows. The inner loop will run 11 times to create 11 columns. As each invader is generated, it is coloured based on its row and added to an empty list so the computer can keep track of it later.

invaders = []
colours = ["red", "orange", "yellow", "green"]
invader_speed = 2
for y in range(4):
    for x in range(-5, 6):
        invader = turtle.Turtle()
        invader.speed(0)
        invader.shape("square")
        invader.color(colours[y])
        invader.penup()
        invader.goto(x * 50, 250 - (y * 30))
        invaders.append(invader)

# Next: 6. Adding Player Controls


6
Adding Player Controls

You need to be able to interact with the game! Here, we define three functions (blocks of reusable code). Two functions will move the player left and right by checking its current coordinate and adding or subtracting pixels. The third function will fire the bullet by changing its state from "ready" to "fire", only if it isn't already flying across the screen. Finally, we tell the computer screen to "listen" for keyboard inputs and link our functions to specific keys.

def player_right():
    x = player.xcor()
    if x < 240:
        x += 20
        player.setx(x)
def player_left():
    x = player.xcor()
    if x > -240:
        x -= 20
        player.setx(x)
def fire_bullet():
    global bullet_state
    if bullet_state == "ready":
        message.clear()
        bullet_state = "fire"
        x = player.xcor()
        y = player.ycor() + 10
        bullet.goto(x, y)
        bullet.showturtle()
wn.listen()
wn.onkeypress(player_right, "Right")
wn.onkeypress(player_left, "Left")
wn.onkeypress(fire_bullet, "space")

# Next: 7. The Main Game Loop & Invader Movement


7
The Main Game Loop & Invader Movement

This is the engine of your game. The
while True:
loop will run continuously forever. Inside this loop, we update the screen and add a tiny pause (
time.sleep
) so the game runs at a playable speed. The main logic moves the entire fleet of invaders sideways. We then check if any invader on the edge has touched the side of the screen. If one has, we move the entire fleet down and reverse their horizontal direction.

while True:
    wn.update()
    time.sleep(0.01)
    
    for invader in invaders:
        x = invader.xcor()
        x += invader_speed
        invader.setx(x)
    
    edge_hit = False
    for invader in invaders:
        if invader.xcor() > 280 or invader.xcor() < -280:
            edge_hit = True
            break
            
    if edge_hit:
        for invader in invaders:
            y = invader.ycor()
            y -= 10
            invader.sety(y)
        invader_speed *= -1

# Next: 8. Bullet and Invader Collisions


8
Bullet and Invader Collisions

Finally, we need to program the combat. The computer doesn't automatically know when two shapes touch; we have to tell it. We move the bullet up the screen if it's in the "fire" state, and check for collisions using the
distance()
function. Important: This code belongs inside the
while True:
loop. Make sure you indent it carefully in Thonny so it aligns with the code from Step 7!

    if bullet_state == "fire":
        y = bullet.ycor()
        y += bullet_speed
        bullet.sety(y)
        
    if bullet.ycor() > 290:
        bullet.hideturtle()
        bullet_state = "ready"
        
    for invader in invaders:
        if bullet_state == "fire" and bullet.distance(invader) < 20:
            bullet.hideturtle()
            bullet_state = "ready"
            bullet.goto(0, -400)
            invader.goto(0, 1000)
            invaders.remove(invader)
            break

# ...and we're done!


USE - MODIFY - CREATE

image
Once you have read the guidance on each part of the game (you did read the guidance, didn't you?) and carefully checked your indentation inside the main loop, click "Run" (green play button) in Thonny to test your game! Read Thonny's error messages closely to debug your code if things don't work the first time.

Watch carefully what happens. Can you clear the screen of all the invaders? What happens after the last one is gone?

USE - MODIFY - CREATE

image
Now that you have a working game, it is time to make it your own. Try finding the specific lines of code in your script in the challenges below and changing the values to see what happens.

1
A New Coat of Paint

Change the look of your game by altering the colours to match your own style.

Find the line that sets the background colour:
wn.bgcolor("black")
.
Try changing "black" to "navy" or "darkslategrey".
Locate the player and bullet colour settings:
player.color("blue")
and
bullet.color("yellow")
.
Pick your favourite colours and swap them in!

2
Resize the Player

Is the player cannon too big or too small? You can change its size easily.

Find the line:
player.shape("triangle")
.
Right after this line, add a new one:
player.shapesize(stretch_wid=2, stretch_len=1.5)
.
Modify the
stretch_wid
and
stretch_len
values to make the player cannon taller, wider, or smaller.

3
Alter the Speed

You can tweak how fast the game plays by changing the speed of the invaders, the bullet, and the player.

Look for
invader_speed = 2
and
bullet_speed = 20
near the top of your code.
Change these numbers to make the game easier or harder.
To make the player move faster, find
x += 20
and
x -= 20
in your player movement functions.
Increase
20
to
30
and test the difference in handling.

4
Invader Formation

You can easily add more rows of invaders by modifying the list of colours and the loop that generates them.

Find the list of colours:
colours = ["red", "orange", "yellow", "green"]
.
Add two more colours to the list, such as "purple" and "pink".
Directly below that, find the loop:
for y in range(4):
.
Change the
4
to a
6
so the loop builds six rows instead of four to accommodate your new colours.

5
Customise the Message

Make the game interface uniquely yours.

Locate the text written to the screen at the start:
message.write("Press Space to Fire", ...)
.
Change the string to something else, like "Let's Blast Some Aliens!".

USE - MODIFY - CREATE

image
Finished early? Your Space Invaders game works, but it is missing a few classic arcade features. Pick one or more of the challenges below to upgrade your project. You will need to think carefully about where in your existing code these new instructions belong.

1
Keep Score

Create a new turtle object to act as a scoreboard and place it at the top of the screen.
Create a score variable starting at 0.
Use the
turtle.write()
function to display it, and increase the score by 10 every time an invader is destroyed.
Remember to clear the old score before writing the new one!

2
Multiple Lives

Create a lives variable set to 3.
The game ends if the invaders reach the player. Modify your main loop to check the `ycor()` of the invaders.
If any invader gets too low (e.g., below -220), reset the game and subtract a life.
When lives reach 0, clear the screen and display a "Game Over" message.

3
Need for Speed

Make the game progressively harder as the player destroys invaders.
Add logic inside your collision loop that slightly increases the absolute value of
invader_speed
every time an invader is removed from the list.
This will make the remaining invaders move faster and faster!

4
Invaders Fire Back

Create an invader bullet turtle, similar to the player's bullet.
In your main loop, use Python's
random
module to randomly pick an active invader to fire a bullet downwards.
Add a collision check between the invader bullet and the player. If they hit, the player loses a life.

5
Add Sound Effects

Depending on your operating system, research how to import the
winsound
module for Windows or the
os
module for macOS/Linux.
Trigger a short 'pew' sound when the player fires, and a small 'boom' sound when an invader is hit.

image
Last modified: July 1st, 2026
The Computing Café works best in landscape mode.
Rotate your device.
Dismiss Warning