Build Asteroids using Python and Pygame

Lesson 6 of 7

Collisions, Score, and Game Over

With bullets and asteroids both on screen, it's time to make them actually interact: destroy asteroids you shoot, and end the game if one hits your ship.

Distance-based collision detection

import math

def distance(a, b):
    return math.hypot(a.x - b.x, a.y - b.y)

For circular objects (ships, asteroids, bullets all drawn as circles/triangles with a radius), you don't need pixel-perfect collision, just check whether the distance between two centers is less than the sum of their radii:

def circles_collide(a, b):
    return distance(a, b) < (a.radius + b.radius)

Bullets destroying asteroids

score = 0

for bullet in bullets:
    for asteroid in asteroids:
        if distance(bullet, asteroid) < asteroid.size:
            bullet.life = 0        # mark the bullet dead so it gets filtered out
            asteroid.hit = True    # mark this asteroid for removal
            score += 100

asteroids = [a for a in asteroids if not getattr(a, 'hit', False)]
bullets = [b for b in bullets if not b.is_dead()]

Rather than removing items from asteroids/bullets in the middle of the nested loop (which corrupts the loop you're iterating over), the pattern is the same as the bullet-cleanup from the last lesson: mark things as "should be removed" first, then filter both lists once, after the collision checks are done.

Ending the game

game_over = False

for asteroid in asteroids:
    if circles_collide(player, asteroid):
        game_over = True

if game_over:
    font = pygame.font.SysFont(None, 64)
    text = font.render("GAME OVER", True, (255, 60, 60))
    screen.blit(text, (250, 260))

pygame.font.SysFont(None, 64) loads the operating system's default font at size 64, .render(text, antialias, color) turns a string into a drawable Surface, and screen.blit(surface, position) is how you draw any image or rendered text onto the screen, it's the same function you'd use to draw a sprite image.

WARNING

Once game_over is True, this snippet still keeps calling player.update()/asteroid.update() every frame unless you guard those calls too, remember to stop updating gameplay (but keep the event loop and drawing running) once the game has ended, otherwise the ship and asteroids keep moving invisibly under your "GAME OVER" text.

📝 Collisions & Game Over Quiz

Passing score: 70%
  1. 1.What does screen.blit(surface, position) do?

  2. 2.Two circular objects are considered colliding when the distance between their centers is less than the sum of their radii.

  3. 3.math.____(dx, dy) computes the straight-line distance between two points from their x and y differences.