Menu
CoddyTech

Menabrak

Termasuk bagian Aturan Game dalam perjalanan Pygame di Coddy. Pelajaran 27 dari 29.

Menyentuh rintangan akan mengakhiri permainan. pygame.sprite.spritecollideany(sprite, group) mengembalikan sprite pertama dalam grup yang menyentuh sprite tersebut, atau None.

Secara default, fungsi ini membandingkan rect. Gambar-gambarnya memiliki sudut tembus pandang, terutama blob, jadi dua rect bisa saling tumpang tindih meskipun tidak ada bagian yang terlihat saling menyentuh. Argumen ketiga memilih pengujian yang lebih akurat:

if pygame.sprite.spritecollideany(runner, obstacles, pygame.sprite.collide_mask):
    state = "over"

collide_mask membandingkan piksel gambar yang terlihat dan mengabaikan bagian yang tembus pandang. Jadi, tabrakan hanya terjadi saat pemain bisa melihatnya.

State bekerja seperti di Meteor Dodge: pembaruan, lompatan, dan rintangan baru hanya terjadi saat nilainya "play", dan layar game over menampilkan permainan yang membeku dengan sebuah pesan.

challenge icon

Tantangan

Sedang
  1. Tambahkan font assets/fonts/pixel.ttf dengan ukuran 32, dan state = "play".
  2. Hanya saat state bernilai "play": lompat, tambahkan rintangan, perbarui runner dan rintangan.
  3. Saat runner menyentuh rintangan (collide_mask), atur state menjadi "over".
  4. Saat game berakhir, tampilkan Game over di (40, 50, 80) dengan posisi tengah di (320, 140).

Coba sendiri

import random
import pygame

pygame.init()
screen = pygame.display.set_mode((640, 320))
pygame.display.set_caption("Sky Runner")
clock = pygame.time.Clock()

SKY = (140, 200, 240)
GROUND = (90, 160, 80)
GROUND_Y = 260
GRAVITY = 1
SPAWN = pygame.USEREVENT + 1


class Runner(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.frames = [
            pygame.image.load("assets/images/player.png").convert_alpha(),
            pygame.image.load("assets/images/player_walk.png").convert_alpha(),
        ]
        self.image = self.frames[0]
        self.step = 0
        self.rect = self.image.get_rect(midbottom=(100, GROUND_Y))
        self.vy = 0

    def jump(self):
        if self.rect.bottom == GROUND_Y:
            self.vy = -16

    def update(self):
        self.vy += GRAVITY
        self.rect.y += self.vy
        if self.rect.bottom >= GROUND_Y:
            self.rect.bottom = GROUND_Y
            self.vy = 0
        if self.rect.bottom == GROUND_Y:
            self.step += 1
            self.image = self.frames[self.step // 8 % 2]
        else:
            self.image = self.frames[1]


class Obstacle(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = random.choice(obstacle_images)
        self.rect = self.image.get_rect(midbottom=(664, GROUND_Y))

    def update(self):
        self.rect.x -= speed
        if self.rect.right < 0:
            self.kill()


obstacle_images = [
    pygame.image.load("assets/images/spike_ball.png").convert_alpha(),
    pygame.image.load("assets/images/blob.png").convert_alpha(),
]
runner = Runner()
obstacles = pygame.sprite.Group()
speed = 6
pygame.time.set_timer(SPAWN, 1500)

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.KEYDOWN and event.key in (pygame.K_SPACE, pygame.K_UP):
            runner.jump()
        if event.type == SPAWN:
            obstacles.add(Obstacle())
            pygame.time.set_timer(SPAWN, random.randint(1000, 2000))

    runner.update()
    obstacles.update()

    screen.fill(SKY)
    pygame.draw.rect(screen, GROUND, (0, GROUND_Y, 640, 60))
    screen.blit(runner.image, runner.rect)
    obstacles.draw(screen)
    pygame.display.flip()
    clock.tick(60)

pygame.quit()

Semua pelajaran di Aturan Game

Latihan sendiri: Playground Pygame