Menu
CoddyTech

The Crate Hides the Gem

Part of the The Game Loop section of Coddy's Pygame journey. Lesson 18 of 35.

The crate is drawn before the gem, so the gem shows on top of it. For a crate the gem can hide under, draw the crate after the gem: what is drawn last covers what is already there.

Then a press on the crate must not reach the gem's test and catch a gem the player cannot see. Two if tests both run. With elif, the second runs only when the first was false, so only one of them takes the press:

if crate.collidepoint(event.pos):
    dragging = True
elif gem.collidepoint(event.pos):
    print("Got it!")

Test what is drawn on top first. A press on the crate then never reaches the gem behind it.

A darker edge makes a box look solid. Draw the same Rect again in a darker colour with a width, and only its outline is drawn, over the fill.

challenge icon

Challenge

Easy

Let the crate hide the gem, and keep a press on it from catching the gem.

  1. Move the crate's draw line to after the gem's outline, and below it draw crate again in (110, 70, 35) with width 3, as its edge.
  2. In the MOUSEBUTTONDOWN branch, change the gem's if to elif, below the crate's test.

Press Play, drag the crate onto the gem and click it: the gem stays hidden and no pink mark appears. Then Check.

Try it yourself

import random
import pygame

pygame.init()
screen = pygame.display.set_mode((480, 360))
pygame.display.set_caption("Gem Hunt")
clock = pygame.time.Clock()

gem = pygame.Rect(225, 165, 30, 30)
crate = pygame.Rect(40, 230, 60, 60)
dragging = False
score = 0

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.MOUSEBUTTONDOWN:
            if crate.collidepoint(event.pos):
                dragging = True
            if gem.collidepoint(event.pos):
                score += 1
                gem.x = random.randint(15, 435)
                gem.y = random.randint(55, 315)
        elif event.type == pygame.MOUSEBUTTONUP:
            dragging = False
        elif event.type == pygame.MOUSEMOTION and dragging:
            crate.move_ip(event.rel)

    screen.fill((30, 30, 46))
    pygame.draw.rect(screen, (150, 100, 50), crate)
    gem_points = [gem.midtop, gem.midright, gem.midbottom, gem.midleft]
    pygame.draw.polygon(screen, (80, 220, 255), gem_points)
    if gem.collidepoint(pygame.mouse.get_pos()):
        pygame.draw.rect(screen, (255, 196, 0), gem.inflate(10, 10), 2)
    for i in range(score):
        pygame.draw.rect(screen, (240, 110, 180), (10 + 10 * i, 14, 8, 8))
    mouse_x, mouse_y = pygame.mouse.get_pos()
    pygame.draw.circle(screen, (240, 240, 240), (mouse_x, mouse_y), 10, 2)
    pygame.display.flip()
    clock.tick(60)

pygame.quit()

All lessons in The Game Loop

Practice on your own: Pygame playground