Menu
CoddyTech

Trouve la clé

Fait partie de la section Les mondes du Journey Pygame de Coddy. Leçon 34 sur 36.

Une clé repose sur le sol de la grotte et, à l’étape suivante, elle ouvre une porte. La case K représente la clé : un Rect nommé key, lu dans la boucle de la carte comme le point de départ P.

La toucher définit has_key = True, une seule fois :

if not has_key and player.colliderect(key):
    has_key = True

La clé fait partie du niveau jusque-là, elle est donc dessinée à travers la caméra. Une fois ramassée, elle appartient au joueur et se déplace donc vers la barre supérieure, à côté des cœurs, dessinée sans la caméra :

if not has_key:
    screen.blit(key_img, (key.x - camera_x, key.y))
# après les cœurs
if has_key:
    screen.blit(key_img, (130, 8))
challenge icon

Défi

Moyen

Place une clé dans la grotte.

  1. Charge key.png dans key_img et définis has_key = False.
  2. Dans la boucle de la carte, un K définit key = rect.
  3. Après les blobs, toucher key définit has_key = True.
  4. Affiche la clé à (key.x - camera_x, key.y) tant que has_key est faux, puis à (130, 8).

Appuie sur « Jouer » et marche jusqu’à la clé : elle se déplace vers la barre supérieure. Puis clique sur « Vérifier ».

Essayez vous-même

import pygame

TILE = 36
WIDTH, HEIGHT = 576, 360
SPEED = 4
GRAVITY = 1
JUMP = -15
MAX_FALL = 12

LEVEL = [
    "................................................................",
    "................................................................",
    "................................................................",
    "................................................................",
    "#..............................................................#",
    "#....................C.........................#####...........#",
    "#......CC...C................CC.....CC.........#####.....CC....#",
    "#....................#.........................D...............#",
    "#.P.........#...E....#...^.......K......E......D.C....^......F.#",
    "#######..####################..##########################..#####",
]

pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Moss Caves")
clock = pygame.time.Clock()
font = pygame.font.Font("assets/fonts/pixel.ttf", 24)


def load(name):
    return pygame.image.load("assets/images/" + name).convert_alpha()


background = pygame.image.load("assets/backgrounds/forest.png").convert_alpha()
grass_img = load("grass.png")
grass_left_img = load("grass_left.png")
grass_right_img = load("grass_right.png")
dirt_img = load("dirt.png")
player_img = load("player.png")
coin_img = load("coin.png")
spikes_img = load("spikes.png")
heart_img = load("heart.png")
heart_empty_img = load("heart_empty.png")
blob_img = load("blob.png")
blob_walk_img = load("blob_walk.png")


def solid(row, col):
    if row < 0 or row >= len(LEVEL) or col < 0 or col >= len(LEVEL[0]):
        return False
    return LEVEL[row][col] == "#"


class Blob(pygame.sprite.Sprite):
    def __init__(self, midbottom):
        super().__init__()
        self.frames = [blob_img, blob_walk_img]
        self.image = blob_img
        self.rect = pygame.Rect(0, 0, 30, 26)
        self.rect.midbottom = midbottom
        self.direction = 1
        self.timer = 0

    def update(self):
        self.timer += 1
        self.image = self.frames[self.timer // 10 % 2]
        self.rect.x += self.direction
        if self.direction > 0:
            ahead = self.rect.right
        else:
            ahead = self.rect.left - 1
        hit_wall = any(self.rect.colliderect(wall) for wall in walls)
        ground_ahead = any(wall.collidepoint(ahead, self.rect.bottom) for wall in walls)
        if hit_wall or not ground_ahead:
            self.rect.x -= self.direction
            self.direction = -self.direction


walls = []
tiles = []
coins = []
spikes = []
blobs = pygame.sprite.Group()
for row, line in enumerate(LEVEL):
    for col, char in enumerate(line):
        rect = pygame.Rect(col * TILE, row * TILE, TILE, TILE)
        if char == "#":
            if solid(row - 1, col):
                image = dirt_img
            elif not solid(row, col - 1) and solid(row, col + 1):
                image = grass_left_img
            elif solid(row, col - 1) and not solid(row, col + 1):
                image = grass_right_img
            else:
                image = grass_img
            walls.append(rect)
            tiles.append((image, rect))
        elif char == "P":
            start = rect.midbottom
        elif char == "C":
            coins.append(rect)
        elif char == "^":
            spikes.append(pygame.Rect(rect.x, rect.y + 18, TILE, 18))
        elif char == "E":
            blobs.add(Blob(rect.midbottom))

level_width = len(LEVEL[0]) * TILE
player = player_img.get_rect(midbottom=start)
vel_y = 0
on_ground = False
camera_x = 0
coins_collected = 0
lives = 3

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN and event.key in (pygame.K_SPACE, pygame.K_UP):
            if on_ground:
                vel_y = JUMP
        elif event.type == pygame.KEYUP and event.key in (pygame.K_SPACE, pygame.K_UP):
            if vel_y < -4:
                vel_y = -4

    keys = pygame.key.get_pressed()
    dx = 0
    if keys[pygame.K_LEFT]:
        dx -= SPEED
    if keys[pygame.K_RIGHT]:
        dx += SPEED

    player.x += dx
    for wall in walls:
        if player.colliderect(wall):
            if dx > 0:
                player.right = wall.left
            elif dx < 0:
                player.left = wall.right

    vel_y = min(vel_y + GRAVITY, MAX_FALL)
    player.y += vel_y
    on_ground = False
    for wall in walls:
        if player.colliderect(wall):
            if vel_y > 0:
                player.bottom = wall.top
                on_ground = True
            elif vel_y < 0:
                player.top = wall.bottom
            vel_y = 0

    hurt = False
    if player.top > HEIGHT:
        hurt = True

    for coin in coins[:]:
        if player.colliderect(coin):
            coins.remove(coin)
            coins_collected += 1
    for spike in spikes:
        if player.colliderect(spike):
            hurt = True

    blobs.update()
    for blob in blobs:
        if player.colliderect(blob.rect):
            if vel_y > 0 and player.bottom < blob.rect.centery:
                blob.kill()
                vel_y = -8
            else:
                hurt = True

    if hurt:
        lives -= 1
        player.midbottom = start
        vel_y = 0

    camera_x = player.centerx - WIDTH // 2
    camera_x = max(0, min(camera_x, level_width - WIDTH))

    shift = camera_x // 3 % 72
    for y in range(0, HEIGHT, 72):
        for x in range(-shift, WIDTH, 72):
            screen.blit(background, (x, y))
    for image, rect in tiles:
        screen.blit(image, (rect.x - camera_x, rect.y))
    for coin in coins:
        screen.blit(coin_img, (coin.x - camera_x, coin.y))
    for spike in spikes:
        screen.blit(spikes_img, (spike.x - camera_x, spike.y - 18))
    for blob in blobs:
        spot = blob.image.get_rect(midbottom=(blob.rect.centerx - camera_x, blob.rect.bottom))
        screen.blit(blob.image, spot)
    screen.blit(player_img, (player.x - camera_x, player.y))
    for i in range(3):
        if i < lives:
            screen.blit(heart_img, (10 + i * 40, 8))
        else:
            screen.blit(heart_empty_img, (10 + i * 40, 8))
    text = font.render(f"Coins: {coins_collected}", True, (255, 255, 255))
    screen.blit(text, text.get_rect(topright=(WIDTH - 12, 14)))
    pygame.display.flip()
    clock.tick(60)

pygame.quit()

Toutes les leçons de Les mondes

Entraînez-vous par vous-même : Playground Pygame