Pintu Terkunci
Termasuk bagian Dunia Game dalam perjalanan Pygame di Coddy. Pelajaran 34 dari 35.
Sebuah pintu menutup terowongan di dekat ujung gua, dan sebuah kunci tergeletak di lantai di depannya. Pintu itu terdiri dari dua tile D. Tambahkan Rect pintu itu ke walls, agar kode tabrakan menghentikan pemain, dan ke tiles dengan door_img, agar pintu itu digambar. Simpan juga pintu itu dalam list doors.
Tile K adalah kuncinya, berupa satu Rect bernama key. Saat pemain menyentuhnya, nilai has_key = True akan ditetapkan. Setelah itu, kunci digambar di bilah atas, bukan di lantai.
Pemain yang terdorong hingga menempel pada pintu menyentuhnya, tetapi tidak tumpang tindih dengannya, jadi lakukan pemeriksaan menggunakan Rect yang 4 piksel lebih lebar di setiap sisi:
if has_key and doors and player.inflate(8, 0).colliderect(doors[0]):
for door in doors:
walls.remove(door)
tiles = [(image, rect) for image, rect in tiles if rect not in doors]
doors = []Pintu dihapus dari kedua list, sehingga tidak lagi menjadi penghalang atau digambar. Pemahaman list membuat tiles baru yang berisi setiap pasangan dengan Rect yang bukan pintu.
Tantangan
Sulit- Muat
key.pngdandoor.pngke dalamkey_imgdandoor_img; buatdoors = []danhas_key = False. - Dalam perulangan peta: untuk
K,key = rect; untukD, tambahkan Rect kewallsdandoors, serta(door_img, rect)ketiles. - Setiap frame, setelah blob: menyentuh
keymenetapkanhas_key = True; jika memiliki kunci, menyentuh pintu akan menghapus semua pintu seperti yang ditunjukkan. - Gambar kunci pada koordinat x-nya dikurangi
camera_xsaathas_keybernilai False, dan pada(130, 8)setelah nilainya True.
Coba sendiri
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()
font = pygame.font.Font("assets/fonts/pixel.ttf", 24)
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")
coin_img = load("coin.png")
spikes_img = load("spikes.png")
heart_img = load("heart.png")
heart_empty_img = load("heart_empty.png")
blob_img = load("blob.png")
blob_walk_img = load("blob_walk.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] == "#"
class Blob(pygame.sprite.Sprite):
def __init__(self, midbottom):
super().__init__()
self.frames = [blob_img, blob_walk_img]
self.image = blob_img
self.rect = pygame.Rect(0, 0, 30, 26)
self.rect.midbottom = midbottom
self.direction = 1
self.timer = 0
def update(self):
self.timer += 1
self.image = self.frames[self.timer // 10 % 2]
self.rect.x += self.direction
if self.direction > 0:
ahead = self.rect.right
else:
ahead = self.rect.left - 1
hit_wall = any(self.rect.colliderect(wall) for wall in walls)
ground_ahead = any(wall.collidepoint(ahead, self.rect.bottom) for wall in walls)
if hit_wall or not ground_ahead:
self.rect.x -= self.direction
self.direction = -self.direction
walls = []
tiles = []
coins = []
spikes = []
blobs = pygame.sprite.Group()
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
elif char == "C":
coins.append(rect)
elif char == "^":
spikes.append(pygame.Rect(rect.x, rect.y + 18, TILE, 18))
elif char == "E":
blobs.add(Blob(rect.midbottom))
level_width = len(LEVEL[0]) * TILE
player = player_img.get_rect(midbottom=start)
vel_y = 0
on_ground = False
camera_x = 0
coins_collected = 0
lives = 3
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
hurt = False
if player.top > HEIGHT:
hurt = True
for coin in coins[:]:
if player.colliderect(coin):
coins.remove(coin)
coins_collected += 1
for spike in spikes:
if player.colliderect(spike):
hurt = True
blobs.update()
for blob in blobs:
if player.colliderect(blob.rect):
if vel_y > 0 and player.bottom < blob.rect.centery:
blob.kill()
vel_y = -8
else:
hurt = True
if hurt:
lives -= 1
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))
for coin in coins:
screen.blit(coin_img, (coin.x - camera_x, coin.y))
for spike in spikes:
screen.blit(spikes_img, (spike.x - camera_x, spike.y - 18))
for blob in blobs:
spot = blob.image.get_rect(midbottom=(blob.rect.centerx - camera_x, blob.rect.bottom))
screen.blit(blob.image, spot)
screen.blit(player_img, (player.x - camera_x, player.y))
for i in range(3):
if i < lives:
screen.blit(heart_img, (10 + i * 40, 8))
else:
screen.blit(heart_empty_img, (10 + i * 40, 8))
text = font.render(f"Coins: {coins_collected}", True, (255, 255, 255))
screen.blit(text, text.get_rect(topright=(WIDTH - 12, 14)))
pygame.display.flip()
clock.tick(60)
pygame.quit()
Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.
Semua pelajaran di Dunia Game
1Peta dari Teks
Level dalam TeksBaris dan KolomHuruf yang Memiliki MaknaTempat Pemain MemulaiSatu Layar Setiap Kali4Tabrakan dengan Platform
Dinding kiri dan kananMendarat di platformMembentur kepalaJatuh keluar dari levelSatu sumbu setiap kali7Gua Berlumut
Bangun GuaBerlari dan MelompatLatihan sendiri: Playground Pygame