Menu
CoddyTech

Chạy và nhảy

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

Bây giờ, nhân vật thám hiểm di chuyển với đầy đủ cơ chế trọng lực, nhảy và va chạm với nền tảng. Mỗi khung hình, hãy di chuyển theo trục x và đẩy nhân vật ra khỏi tường, sau đó thêm trọng lực, di chuyển theo trục y rồi cho nhân vật tiếp đất hoặc va đầu vào vật cản, cuối cùng kiểm tra xem nhân vật có rơi khỏi hang không:

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

Phần nhảy nằm trong vòng lặp sự kiện: khi nhấn Space hoặc Up, một sự kiện KEYDOWN sẽ đặt vel_y = JUMP nếu on_ground đúng, còn sự kiện KEYUP sẽ giảm tốc độ đi lên nhanh xuống -4 để tạo cú nhảy ngắn.

Thêm các hằng số tốc độ ở đầu chương trình: SPEED = 4, GRAVITY = 1, JUMP = -15, MAX_FALL = 12. Với các con số này, cú nhảy cao khoảng 100 pixel: đủ để bước lên hai ô và vượt qua một hố rộng hai ô.

challenge icon

Thử thách

Trung bình

Khiến nhân vật thám hiểm chạy, nhảy và rơi.

  1. Thêm SPEED = 4, GRAVITY = 1, JUMP = -15 và MAX_FALL = 12 ở đầu chương trình, rồi thêm vel_y = 0 và on_ground = False trước vòng lặp.
  2. Thêm thao tác nhảy và nhảy ngắn vào các sự kiện.
  3. Sau các sự kiện, thêm đoạn code của khung hình như hình minh họa.

Nhấn Chơi rồi đi vào hố đầu tiên: bạn sẽ bắt đầu lại. Sau đó nhấn Kiểm tra.

Tự làm thử

import pygame

TILE = 36
WIDTH, HEIGHT = 576, 360

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

player = player_img.get_rect(midbottom=start)

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    for y in range(0, HEIGHT, 72):
        for x in range(0, WIDTH, 72):
            screen.blit(background, (x, y))
    for image, rect in tiles:
        screen.blit(image, rect)
    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