Chông nhọn và trái tim
Thuộc phần Thế giới trò chơi trong hành trình Pygame của Coddy. Bài học 32 trên 36.
Trò chơi cần có hiểm nguy. Nhà thám hiểm có 3 mạng, được biểu thị bằng trái tim. Mỗi lần chạm gai hoặc rơi khỏi hang đều mất một mạng.
Gai chỉ chiếm nửa dưới của ô, nên Rect của chúng là nửa dưới: pygame.Rect(rect.x, rect.y + 18, TILE, 18). Vẽ hình ảnh cao hơn 18 pixel, ngay tại góc ô.
Nhiều mối nguy gây ra cùng một việc: lấy đi một mạng và đưa nhà thám hiểm trở lại điểm xuất phát. Dùng chung một cờ cho chúng và tạo một khối lệnh xử lý cờ đó:
hurt = False
if player.top > HEIGHT:
hurt = True
for spike in spikes:
if player.colliderect(spike):
hurt = True
# sau đó
if hurt:
lives -= 1
player.midbottom = start
vel_y = 0Ba trái tim nằm thành một hàng ở góc trên bên trái: trái tim đầy ứng với mỗi mạng còn lại, trái tim rỗng ứng với mỗi mạng đã mất.
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))Thử thách
Trung bìnhKhi chạm gai hoặc rơi xuống hố, người chơi mất một mạng.
- Tải ba hình ảnh được hiển thị; tạo
spikes = []vàlives = 3. Mỗi^thêm một Rect ở nửa dưới. - Khi rơi xuống hoặc chạm gai, đặt
hurt = True; thêm khốiif hurt:sau phần xử lý xu. - Vẽ gai tại
(spike.x - camera_x, spike.y - 18)và vẽ các trái tim.
Nhấn Chơi và chạm vào gai: bạn sẽ mất một trái tim. Sau đó nhấn Kiểm tra.
Tự làm thử
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")
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 = []
coins = []
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)
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
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
if player.top > HEIGHT:
player.midbottom = start
vel_y = 0
for coin in coins[:]:
if player.colliderect(coin):
coins.remove(coin)
coins_collected += 1
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))
screen.blit(player_img, (player.x - camera_x, player.y))
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()
Tất cả bài học trong Thế giới trò chơi
1Bản đồ dạng văn bản
Một màn chơi bằng văn bảnHàng và cộtCác chữ cái mang ý nghĩaNơi người chơi bắt đầuTừng màn hình một4Va chạm với các bệ
Tường bên trái và bên phảiTiếp đất trên các bệĐụng đầuRơi khỏi màn chơiTừng trục một7Hang động rêu
Xây dựng hang độngChạy và nhảyTự luyện tập: Playground Pygame