Her Seferinde Tek Eksen
Coddy'nin Pygame Journey'sinin Dünyalar bölümünün bir parçası. Ders 19 / 35.
Çarpışma kodunuz önce x'i hareket ettirip düzeltir, sonra y'yi hareket ettirip düzeltir. Bu başlangıç kodu ikisini de hareket ettirip yalnızca bir kez düzeltir. Çalıştırın ve sağa yürüyün: oyuncu zemin boyunca geriye doğru sıçrar.
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 = 0Zeminde dururken yer çekimi, her karede oyuncuyu zeminin içine doğru 1 piksel aşağı taşır. Aynı karede sağa hareket ederken oyuncu altındaki zemin karosuyla çakışır ve kod bunun nedenini anlayamaz. dx > 0 olduğunu görür ve oyuncunun sağ tarafını o karonun sol tarafına yerleştirir: geriye doğru, zemin boyunca.
Tek bir çakışma, iki hareket; hangisinin buna neden olduğunu anlamanın yolu yok. Her seferinde tek bir eksende hareket edildiğinde, her çakışmanın tek bir nedeni olur. x hareketinden sonra oyuncu henüz zeminin içine girmemiştir, dolayısıyla onu yalnızca gerçek duvarlar durdurur. y hareketinden sonra ise çakışma yalnızca y eksenindeki hareketten kaynaklanabilir.
Görev
Orta- Hareketi böl:
player.x += dxve yalnızca x'i düzelten,wallsüzerinde bir döngü. - Ardından yerçekimi,
player.y += vel_y,on_ground = Falseve yalnızca y'yi düzelten ikinci bir döngü.
Kendin dene
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()
Dünyalar bölümündeki tüm dersler
1Metinden Haritalar
Metinde Bir SeviyeSatırlar ve SütunlarAnlam Taşıyan HarflerOyuncunun Başladığı YerHer Seferinde Bir Ekran4Platform Çarpışmaları
Sağ ve Sol DuvarlarPlatformlara İnişBaşını ÇarpSeviyenin Dışına DüşmekHer Seferinde Tek Eksen3Yerçekimi ve Zıplama
Yerçekimiyle DüşmeYerden ZıplamaKısa SıçrayışlarEn Yüksek Düşme HızıZıplama Tamponu6Devriye Gezen Düşmanlar
Devriye Gezen Bir BlobÜzerine Bas ya da Darbe AlYürüme DöngüsüHaritadaki DüşmanlarKendi başına pratik yap: Pygame playground