Trova la chiave
Fa parte della sezione Mondi del percorso Pygame di Coddy. Lezione 34 di 36.
Una chiave giace sul pavimento della caverna e, nel passaggio successivo, apre una porta. La tessera K è la chiave: un Rect chiamato key, letto nel ciclo della mappa come la posizione iniziale P.
Toccandola, si imposta has_key = True, una sola volta:
if not has_key and player.colliderect(key):
has_key = TrueFino a quel momento la chiave fa parte del livello, quindi viene disegnata attraverso la telecamera. Una volta raccolta, appartiene al giocatore, quindi si sposta nella barra superiore, accanto ai cuori, e viene disegnata senza la telecamera:
if not has_key:
screen.blit(key_img, (key.x - camera_x, key.y))
# dopo i cuori
if has_key:
screen.blit(key_img, (130, 8))Sfida
MedioMetti una chiave nella caverna.
- Carica
key.pnginkey_imge impostahas_key = False. - Nel ciclo della mappa, una
Kimpostakey = rect. - Dopo i blob, toccare
keyimpostahas_key = True. - Disegna la chiave in
(key.x - camera_x, key.y)finchéhas_keyè falso, poi in(130, 8).
Premi «Gioca» e raggiungi la chiave: si sposta nella barra superiore. Poi premi «Verifica».
Provalo tu
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()
Tutte le lezioni di Mondi
1Mappe dal testo
Un livello in testoRighe e colonneLettere con significatoDove inizia il giocatoreUna schermata alla volta4Collisioni con le piattaforme
Muri a sinistra e a destraAtterrare sulle piattaformeBattere la testaCadere fuori dal livelloUn asse alla volta5Una telecamera a scorrimento
Un offset della telecameraSegui il giocatoreMantieni la telecamera all'internoParallasseEsercitati da solo: Playground Pygame