Menu
CoddyTech

Thu thập xu

Thuộc phần Thế giới trò chơi trong hành trình Pygame của Coddy. Bài học 31 trên 36.

Tiền xu cho nhà thám hiểm một thứ để theo đuổi: một vài đồng treo trên các hố, nơi chạm tới chúng là một việc mạo hiểm.

Đọc mỗi C thành một danh sách Rect, bao gồm toàn bộ ô, vì coin.png có viền trống riêng. Khi người chơi chạm vào một đồng xu, hãy xóa nó khỏi danh sách và đếm số xu:

for coin in coins[:]:
    if player.colliderect(coin):
        coins.remove(coin)
        coins_collected += 1

coins[:] là bản sao của danh sách. Xóa phần tử khỏi danh sách trong khi vòng lặp duyệt qua danh sách sẽ làm các phần tử dịch chuyển bên dưới vòng lặp và khiến vòng lặp bỏ qua một phần tử; duyệt qua bản sao sẽ tránh được điều đó.

Hiển thị số xu ở góc trên bên phải. Số xu thuộc về cửa sổ, không thuộc màn chơi, nên hãy vẽ số đó mà không dùng camera:

font = pygame.font.Font("assets/fonts/pixel.ttf", 24)
# trong vòng lặp
text = font.render(f"Coins: {coins_collected}", True, (255, 255, 255))
screen.blit(text, text.get_rect(topright=(WIDTH - 12, 14)))
challenge icon

Thử thách

Trung bình

Thêm xu để thu thập.

  1. Nạp coin.png vào coin_img; tạo font (assets/fonts/pixel.ttf, kích thước 24), coins = [] và coins_collected = 0.
  2. Mỗi C thêm Rect của ô vào coins.
  3. Sau khi di chuyển, xóa từng đồng xu chạm vào và tăng coins_collected thêm 1.
  4. Vẽ các đồng xu qua camera và hiển thị Coins: 0 ở góc trên bên phải như hình.

Nhấn Chơi rồi nhặt một đồng xu: số đếm sẽ tăng. Sau đó nhấn Kiểm tra.

Tự làm thử

import pygame

TILE = 36
WIDTH, HEIGHT = 576, 360
SPEED = 4
GRAVITY = 1
JUMP = -15
MAX_FALL = 12

LEVEL = [
    "................................................................",
    "................................................................",
    "................................................................",
    "................................................................",
    "#..............................................................#",
    "#....................C.........................#####...........#",
    "#......CC...C................CC.....CC.........#####.....CC....#",
    "#....................#.........................D...............#",
    "#.P.........#...E....#...^.......K......E......D.C....^......F.#",
    "#######..####################..##########################..#####",
]

pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Moss Caves")
clock = pygame.time.Clock()


def load(name):
    return pygame.image.load("assets/images/" + name).convert_alpha()


background = pygame.image.load("assets/backgrounds/forest.png").convert_alpha()
grass_img = load("grass.png")
grass_left_img = load("grass_left.png")
grass_right_img = load("grass_right.png")
dirt_img = load("dirt.png")
player_img = load("player.png")


def solid(row, col):
    if row < 0 or row >= len(LEVEL) or col < 0 or col >= len(LEVEL[0]):
        return False
    return LEVEL[row][col] == "#"


walls = []
tiles = []
for row, line in enumerate(LEVEL):
    for col, char in enumerate(line):
        rect = pygame.Rect(col * TILE, row * TILE, TILE, TILE)
        if char == "#":
            if solid(row - 1, col):
                image = dirt_img
            elif not solid(row, col - 1) and solid(row, col + 1):
                image = grass_left_img
            elif solid(row, col - 1) and not solid(row, col + 1):
                image = grass_right_img
            else:
                image = grass_img
            walls.append(rect)
            tiles.append((image, rect))
        elif char == "P":
            start = rect.midbottom

level_width = len(LEVEL[0]) * TILE
player = player_img.get_rect(midbottom=start)
vel_y = 0
on_ground = False
camera_x = 0

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

    if player.top > HEIGHT:
        player.midbottom = start
        vel_y = 0

    camera_x = player.centerx - WIDTH // 2
    camera_x = max(0, min(camera_x, level_width - WIDTH))

    shift = camera_x // 3 % 72
    for y in range(0, HEIGHT, 72):
        for x in range(-shift, WIDTH, 72):
            screen.blit(background, (x, y))
    for image, rect in tiles:
        screen.blit(image, (rect.x - camera_x, rect.y))
    screen.blit(player_img, (player.x - camera_x, player.y))
    pygame.display.flip()
    clock.tick(60)

pygame.quit()

Tất cả bài học trong Thế giới trò chơi

Tự luyện tập: Playground Pygame