Va chạm
Thuộc phần Luật chơi trong hành trình Pygame của Coddy. Bài học 27 trên 30.
Chạm vào chướng ngại vật sẽ kết thúc lượt chơi. pygame.sprite.spritecollideany(sprite, group) trả về sprite đầu tiên trong nhóm chạm vào sprite, hoặc None.
Mặc định, hàm này so sánh các hình chữ nhật. Hình ảnh có các góc trong suốt, đặc biệt là blob, nên hai hình chữ nhật có thể chồng lên nhau dù không có gì bạn nhìn thấy chạm vào nhau. Đối số thứ ba chọn phép kiểm tra chính xác hơn:
if pygame.sprite.spritecollideany(runner, obstacles, pygame.sprite.collide_mask):
state = "over"collide_mask so sánh các điểm ảnh được vẽ trong hình và bỏ qua những điểm ảnh trong suốt. Khi đó, va chạm sẽ đúng là một vụ va chạm mà người chơi có thể nhìn thấy.
Trạng thái hoạt động giống như trong Meteor Dodge: trò chơi chỉ cập nhật, nhân vật chỉ nhảy và chướng ngại vật mới chỉ xuất hiện khi trạng thái là "play". Màn hình kết thúc trò chơi sẽ hiển thị trò chơi đã đóng băng cùng một thông báo.
Thử thách
Trung bìnhKết thúc lượt chạy khi nhân vật chạy va vào chướng ngại vật.
- Thêm phông chữ
assets/fonts/pixel.ttfở cỡ 32 vàstate = "play". - Chỉ khi trạng thái là
"play": cho nhân vật nhảy, thêm chướng ngại vật, cập nhật nhân vật và các chướng ngại vật. - Một va chạm (
collide_mask) đặt trạng thái thành"over"; sau đó hiển thịGame overbằng màu(40, 50, 80), căn giữa tại (320, 140).
Nhấn Chơi rồi đứng yên: Game over sẽ hiển thị và mọi thứ dừng lại. Sau đó nhấn Kiểm tra.
Tự làm thử
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()
Tất cả bài học trong Luật chơi
Tự luyện tập: Playground Pygame