Menu
CoddyTech

Gem Hunt

Part of the The Game Loop section of Coddy's Pygame journey. Lesson 17 of 32.

Now the crate becomes the game. Each gem appears under the crate: drag the crate off and click the gem, and the crate moves onto the next one. A round lasts 30 seconds.

Put the crate on the gem by giving it the gem's centre: crate.center = gem.center. Do it before the loop and each time a new gem appears.

Count the time in frames. At 60 frames a second, 30 seconds is 1800 frames:

time_left = 1800

while running:
    # events
    if time_left > 0:
        time_left -= 1

When time_left reaches 0, the game stops taking clicks and drags, and the score row shows the result. Add and time_left > 0 to the MOUSEBUTTONDOWN and MOUSEMOTION tests.

A bar at the top shows the time left. Its width is the share of the round still to go: 480 * time_left // 1800 is 480 at the start, 240 halfway and 0 at the end.

challenge icon

Challenge

Medium
  1. After making the crate, set crate.center = gem.center. Do the same after a collected gem gets its new place.
  2. Before the loop, set time_left = 1800. In the loop, after the events, take 1 from it while it is above 0.
  3. Handle MOUSEBUTTONDOWN and MOUSEMOTION only while time_left > 0.
  4. After the score row, draw the time bar: green (120, 200, 120) at (0, 0, 480 * time_left // 1800, 6).

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
            elif 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))
    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)
    pygame.draw.rect(screen, (150, 100, 50), crate)
    pygame.draw.rect(screen, (110, 70, 35), crate, 3)
    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()
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in The Game Loop

Practice on your own: Pygame playground