Các đợt ngày càng lớn
Thuộc phần Luật chơi trong hành trình Pygame của Coddy. Bài học 13 trên 30.
Nhiều trò chơi được chia thành các đợt: một nhóm kẻ địch, một khoảng lặng ngắn khi kẻ cuối cùng biến mất, rồi đến một nhóm lớn hơn. Cách này cho người chơi biết trò chơi đang khó hơn và giúp họ có chút thời gian nghỉ.
Hai con số điều khiển việc này: wave, đợt bạn đang chơi, và to_spawn, số tảng đá trong đợt này vẫn còn cần rơi xuống. Bộ đếm thời gian tạo vật thể chỉ thả một tảng đá khi to_spawn lớn hơn 0:
if event.type == SPAWN and state == "play" and to_spawn > 0:
rocks.append(pygame.Rect(random.randint(0, 456), -24, 24, 24))
to_spawn -= 1Đợt kết thúc khi không còn tảng đá nào cần rơi xuống và cũng không còn tảng đá nào đang rơi. Đợt tiếp theo bắt đầu với nhiều hơn một tảng đá:
if to_spawn == 0 and not rocks:
wave += 1
to_spawn = wave + 2not rocks là đúng khi danh sách trống. Đợt 1 thả 3 tảng đá, đợt 2 thả 4 tảng đá, đợt 3 thả 5 tảng đá.
Thử thách
KhóĐưa đá ra theo từng đợt ngày càng lớn.
reset()đặtwave = 1vàto_spawn = 3.SPAWNchỉ thả đá khito_spawnlớn hơn 0, rồi giảm giá trị này xuống.- Trong
play_frame(), khito_spawnbằng 0 vàrockstrống, tăngwavethêm 1; đặtto_spawn = wave + 2. - Hiển thị
Wave 1,Wave 2... bằngmidtop=(240, 10).
Nhấn Chơi: đợt 2 bắt đầu sau khi có ba hòn đá. Sau đó nhấn Kiểm tra.
Tự làm thử
import random
import pygame
pygame.init()
screen = pygame.display.set_mode((480, 360))
pygame.display.set_caption("Meteor Dodge")
clock = pygame.time.Clock()
heart = pygame.image.load("assets/images/heart.png").convert_alpha()
heart_empty = pygame.image.load("assets/images/heart_empty.png").convert_alpha()
font = pygame.font.Font("assets/fonts/pixel.ttf", 24)
big_font = pygame.font.Font("assets/fonts/pixel.ttf", 48)
WHITE = (240, 240, 240)
PLATE = (60, 60, 90)
POINT = pygame.USEREVENT + 1
SPAWN = pygame.USEREVENT + 2
def reset():
global player, rocks, score, lives, hit_time
player = pygame.Rect(220, 300, 40, 40)
rocks = []
score = 0
lives = 3
hit_time = -2000
pygame.time.set_timer(POINT, 1000)
pygame.time.set_timer(SPAWN, 800)
def draw_menu():
screen.fill((30, 30, 46))
title = big_font.render("Meteor Dodge", True, WHITE)
title_rect = title.get_rect(center=(240, 140))
pygame.draw.rect(screen, PLATE, title_rect.inflate(24, 12))
screen.blit(title, title_rect)
hint = font.render("Press Enter to play", True, WHITE)
screen.blit(hint, hint.get_rect(center=(240, 200)))
def draw_game():
screen.fill((30, 30, 46))
safe = pygame.time.get_ticks() - hit_time < 1000
if not safe or pygame.time.get_ticks() // 100 % 2 == 0:
pygame.draw.rect(screen, (255, 196, 0), player)
for rock in rocks:
pygame.draw.rect(screen, (235, 80, 80), rock)
score_text = font.render(f"{score:05}", True, WHITE)
score_rect = score_text.get_rect(topright=(470, 10))
pygame.draw.rect(screen, PLATE, score_rect.inflate(12, 8))
screen.blit(score_text, score_rect)
for i in range(3):
if i < lives:
screen.blit(heart, (10 + i * 40, 10))
else:
screen.blit(heart_empty, (10 + i * 40, 10))
def play_frame():
global score, lives, state, hit_time, rocks
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
player.x -= 6
if keys[pygame.K_RIGHT]:
player.x += 6
player.clamp_ip(screen.get_rect())
for rock in rocks:
rock.y += 4
rocks = [rock for rock in rocks if rock.top <= 360]
now = pygame.time.get_ticks()
for rock in rocks:
if rock.colliderect(player) and now - hit_time > 1000:
hit_time = now
lives -= 1
if lives == 0:
state = "over"
draw_game()
def draw_over():
draw_game()
message = big_font.render("Game over", True, WHITE)
screen.blit(message, message.get_rect(center=(240, 160)))
hint = font.render("Press R to play again", True, WHITE)
screen.blit(hint, hint.get_rect(center=(240, 200)))
reset()
state = "menu"
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == POINT and state == "play":
score += 1
if event.type == SPAWN and state == "play":
rocks.append(pygame.Rect(random.randint(0, 456), -24, 24, 24))
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RETURN and state == "menu":
state = "play"
elif event.key == pygame.K_r and state == "over":
reset()
state = "play"
if state == "menu":
draw_menu()
elif state == "play":
play_frame()
else:
draw_over()
pygame.display.flip()
clock.tick(60)
pygame.quit()
Tất cả bài học trong Luật chơi
3Bộ hẹn giờ và các đợt
An toàn sau khi trúng đònSự kiện hẹn giờMột tảng đá sau mỗi 800 msCác đợt ngày càng lớnĐếm ngược đến lúc bắt đầuTự luyện tập: Playground Pygame