Menu
CoddyTech

Un blob en patrouille

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

Deux blobs marchent vers la droite et continuent dans le vide. Un ennemi en patrouille marche d'avant en arrière : il fait demi-tour lorsqu'il heurte un mur ou atteint le bord de son sol. La classe Blob conserve sa direction, 1 vers la droite et -1 vers la gauche.

Après chaque pas, examine le point situé un pixel après le pied avant du blob, à la hauteur de ses pieds. Si aucun mur ne se trouve à cet endroit, le pas suivant le ferait avancer dans le vide :

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

any(...) vaut True lorsqu'au moins un mur satisfait le test. Un demi-tour annule le pas et inverse la direction. Le Rect du blob épouse son corps, mesure 30 sur 26, soit moins que l'image de 48 pixels, qui est dessinée avec son milieu inférieur aligné sur le milieu inférieur du Rect.

challenge icon

Défi

Difficile

Dans Blob.update, après l’étape :

  1. Définissez ahead sur self.rect.right lorsque vous vous déplacez vers la droite, sinon sur self.rect.left - 1.
  2. Vérifiez si le blob chevauche un mur et si un mur contient le point (ahead, self.rect.bottom).
  3. S’il a heurté un mur ou s’il n’y a pas de sol devant lui, annulez le déplacement et inversez self.direction.

Essayez vous-même

import pygame

TILE = 36
SPEED = 4
GRAVITY = 1
JUMP = -15
MAX_FALL = 12

LEVEL = [
    "................",
    "................",
    "................",
    "................",
    "..........####..",
    "................",
    "...####.........",
    "................",
    "#.P............#",
    "################",
]

pygame.init()
screen = pygame.display.set_mode((576, 360))
pygame.display.set_caption("Patrol")
clock = pygame.time.Clock()

background = pygame.image.load("assets/backgrounds/clouds.png").convert_alpha()
block_img = pygame.image.load("assets/images/block.png").convert_alpha()
player_img = pygame.image.load("assets/images/player.png").convert_alpha()
blob_img = pygame.image.load("assets/images/blob.png").convert_alpha()


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

    def update(self):
        self.rect.x += self.direction

walls = []
for row, line in enumerate(LEVEL):
    for col, char in enumerate(line):
        if char == "#":
            walls.append(pygame.Rect(col * TILE, row * TILE, TILE, TILE))
        elif char == "P":
            start = (col * TILE + TILE // 2, row * TILE + TILE)

blobs = pygame.sprite.Group(Blob((432, 144)), Blob((432, 324)))
player = player_img.get_rect(midbottom=start)
vel_y = 0
on_ground = False

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

    blobs.update()

    for y in range(0, 360, 72):
        for x in range(0, 576, 72):
            screen.blit(background, (x, y))
    for wall in walls:
        screen.blit(block_img, wall)
    for blob in blobs:
        screen.blit(blob.image, blob.image.get_rect(midbottom=blob.rect.midbottom))
    screen.blit(player_img, player)
    pygame.display.flip()
    clock.tick(60)

pygame.quit()
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Les mondes

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