Menu
CoddyTech

Đụng đầu

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

Nhảy từ dưới lên một bệ, nhân vật đi xuyên qua bệ rồi đáp xuống phía trên. Bệ vững chắc sẽ chặn đầu nhân vật. Khi đi lên, vel_y là số âm, vậy nên hãy thêm trường hợp còn lại vào vòng lặp dọc:

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

Đầu nhân vật chạm đáy của bức tường, và tốc độ trở thành 0 trong cả hai trường hợp. Sau khi va vào bệ, trọng lực lập tức khiến nhân vật rơi xuống. Nếu không có vel_y = 0, nhân vật sẽ tiếp tục cố đi lên và mắc kẹt bên dưới bệ cho đến khi trọng lực triệt tiêu cú nhảy.

Dấu của vel_y cho biết nhân vật đi từ phía nào, giống như dx với các bức tường: khi rơi, nhân vật va vào mặt trên của tường; khi đi lên, nhân vật va vào mặt dưới.

challenge icon

Thử thách

Dễ

Dừng cú nhảy khi đầu va vào bệ.

  1. Trong vòng lặp xử lý va chạm theo chiều dọc, thêm trường hợp vel_y < 0: player.top = wall.bottom.
  2. Đặt vel_y = 0 sau cả hai trường hợp để cú va đầu làm nhân vật ngừng bay lên.

Nhấn Chơi rồi nhảy: đầu nhân vật dừng lại bên dưới bệ phía trên. Sau đó nhấn Kiểm tra.

Tự làm thử

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("Head Bump")
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()

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)

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
                vel_y = 0
                on_ground = True

    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)
    screen.blit(player_img, player)
    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