Menu
CoddyTech

Injak atau Terkena

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

Menyentuh blob seharusnya berdampak dalam dua cara. Mendarat di atasnya akan mengalahkan blob. Berjalan menabraknya akan melukai pemain.

Perbedaannya terletak pada cara pemain tiba. Pemain datang dari atas jika sedang jatuh, vel_y > 0, dan kakinya masih berada di atas bagian tengah blob:

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:
            player.midbottom = start
            vel_y = 0

blob.kill() menghapus sprite dari grup, sehingga sprite itu tidak lagi diperbarui atau digambar. vel_y = -8 menghasilkan pantulan kecil, yang memberi tahu pemain bahwa serangan injak berhasil dan memungkinkan mereka melanjutkannya dengan melompat. Selain itu, pemain terkena serangan dari samping atau bawah, lalu kembali ke awal, seperti setelah terjatuh.

Lakukan perulangan pada grup untuk memeriksa setiap blob. kill() di dalam perulangan aman digunakan di sini, karena perulangan berjalan pada sprite dalam grup sebagaimana keadaannya saat perulangan dimulai.

challenge icon

Tantangan

Sedang
  1. Setelah blob bergerak, lakukan perulangan pada blobs.
  2. Saat pemain bertabrakan dengan Rect milik blob: jika vel_y > 0 dan player.bottom < blob.rect.centery, panggil blob.kill() dan atur vel_y = -8.
  3. Jika tidak, atur player.midbottom = start dan vel_y = 0.

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("Stomp")
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
        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 = []
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()

Semua pelajaran di Dunia Game

Latihan sendiri: Playground Pygame