Menu
CoddyTech

Blob yang Berpatroli

Termasuk bagian Dunia Game dalam perjalanan Pygame di Coddy. Pelajaran 24 dari 35.

Dua blob berjalan ke kanan lalu melangkah ke udara. Musuh yang berpatroli berjalan bolak-balik: musuh berbalik saat menabrak dinding atau mencapai ujung tanah yang dipijaknya. Class Blob menyimpan direction, yaitu 1 untuk kanan dan -1 untuk kiri.

Setelah setiap langkah, periksa titik yang berjarak satu piksel melewati kaki depan blob, setinggi kakinya. Jika tidak ada dinding yang menahan titik itu, langkah berikutnya akan membawanya ke udara:

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(...) bernilai True saat setidaknya satu dinding lolos dari pengujian. Saat berbalik, langkahnya dibatalkan dan arahnya dibalik. Rect blob pas dengan tubuhnya, berukuran 30 kali 26, lebih kecil daripada gambar berukuran 48 piksel. Gambar itu ditampilkan dengan titik tengah bawahnya sejajar dengan titik tengah bawah Rect.

challenge icon

Tantangan

Sulit

Di dalam Blob.update, setelah langkah berikut:

  1. Tetapkan ahead ke self.rect.right saat bergerak ke kanan, jika tidak, tetapkan ke self.rect.left - 1.
  2. Periksa apakah blob bertumpang tindih dengan dinding mana pun, dan apakah ada dinding yang memuat titik (ahead, self.rect.bottom).
  3. Jika blob menabrak dinding atau tidak ada tanah di depan, batalkan langkah tersebut dan balik arah self.direction.

Coba sendiri

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 iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Dunia Game

Latihan sendiri: Playground Pygame