Tốc độ tăng dần
Thuộc phần Luật chơi trong hành trình Pygame của Coddy. Bài học 15 trên 30.
Trò chơi không bao giờ thay đổi sẽ trở nên nhàm chán, còn trò chơi bắt đầu quá khó sẽ khiến người chơi mới bỏ cuộc. Hãy bắt đầu nhẹ nhàng rồi tăng độ khó khi người chơi trụ càng lâu.
Thời gian từ lúc trò chơi bắt đầu quyết định tốc độ. reset() ghi nhớ thời điểm đó, và mỗi khung hình tính tốc độ dựa trên thời gian này:
seconds = (pygame.time.get_ticks() - start_time) // 1000
speed = 3 + seconds // 5seconds // 5 tăng thêm 1 sau mỗi năm giây, nên ban đầu đá rơi 3 pixel mỗi khung hình, sau năm giây là 4, sau mười giây là 5. Các bước tăng nguyên giúp tốc độ luôn là số nguyên, điều mà Rect cần: nó lưu số pixel nguyên, nên rock.y += 3.5 sẽ làm mất phần lẻ.
Enter và R đều gọi reset(), nên đồng hồ bắt đầu lại mỗi khi chơi ván mới, bất kể menu đã hiển thị bao lâu.
Thử thách
Trung bìnhKhi bạn trụ càng lâu, đá rơi càng nhanh.
- Trong
reset(), đặtstart_timethànhpygame.time.get_ticks(). - Trong
play_frame(), tính số giây đã trôi qua kể từstart_timevàspeed = 3 + seconds // 5. - Di chuyển từng tảng đá xuống một khoảng bằng
speedthay vì 3.
Nhấn Chơi: sau vài giây, đá sẽ rơi nhanh 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
player = pygame.Rect(220, 300, 40, 40)
rocks = []
score = 0
lives = 3
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))
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 rocks, lives, state
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())
kept = []
for rock in rocks:
rock.y += 3
if rock.colliderect(player):
lives -= 1
elif rock.top <= 360:
kept.append(rock)
rocks = kept
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":
reset()
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
Tự luyện tập: Playground Pygame