Menu
CoddyTech

Satu sumbu setiap kali

Termasuk bagian Dunia Game dalam perjalanan Pygame di Coddy. Pelajaran 19 dari 35.

Kodemu untuk tabrakan menggerakkan dan membetulkan x, lalu menggerakkan dan membetulkan y. Kode awal ini menggerakkan keduanya lalu membetulkannya sekali. Jalankan dan berjalanlah ke kanan: pemain tersentak mundur di sepanjang lantai.

player.x += dx
vel_y = min(vel_y + GRAVITY, MAX_FALL)
player.y += vel_y
on_ground = False
for wall in walls:
    if player.colliderect(wall):
        if dx > 0:
            player.right = wall.left
        elif dx < 0:
            player.left = wall.right
        if vel_y > 0:
            player.bottom = wall.top
            on_ground = True
        elif vel_y < 0:
            player.top = wall.bottom
        vel_y = 0

Saat berdiri di tanah, gravitasi menggerakkan pemain 1 piksel ke bawah menembus tanah pada setiap frame. Jika bergerak ke kanan pada frame yang sama, pemain bertumpang tindih dengan tile tanah di bawahnya, dan kode tidak bisa mengetahui penyebabnya. Kode melihat dx > 0 lalu menempatkan sisi kanan pemain di sisi kiri tile itu: mundur, di sepanjang lantai.

Satu tumpang tindih, dua gerakan, tidak ada cara untuk mengetahui gerakan mana yang menyebabkannya. Dengan menggerakkan satu sumbu pada satu waktu, setiap tumpang tindih memiliki satu penyebab. Setelah gerakan x, pemain belum berada di dalam tanah, jadi hanya dinding sungguhan yang menghentikannya. Setelah gerakan y, tumpang tindih hanya bisa disebabkan oleh gerakan sepanjang sumbu y.

challenge icon

Tantangan

Sedang
  1. Pisahkan pergerakan: player.x += dx dan perulangan pada walls yang hanya memperbaiki x.
  2. Lalu gravitasi, player.y += vel_y, on_ground = False dan perulangan kedua yang hanya memperbaiki y.

Coba sendiri

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("One Axis at a Time")
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
    vel_y = min(vel_y + GRAVITY, MAX_FALL)
    player.y += vel_y
    on_ground = False
    for wall in walls:
        if player.colliderect(wall):
            if dx > 0:
                player.right = wall.left
            elif dx < 0:
                player.left = wall.right
            if vel_y > 0:
                player.bottom = wall.top
                on_ground = True
            elif vel_y < 0:
                player.top = wall.bottom
            vel_y = 0

    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()

Semua pelajaran di Dunia Game

Latihan sendiri: Playground Pygame