An toàn sau khi trúng đòn
Thuộc phần Luật chơi trong hành trình Pygame của Coddy. Bài học 10 trên 30.
Trong phiên bản này, hãy đứng bên dưới một tảng đá. Tảng đá không còn nhảy ngược lên trên cùng khi va chạm, nó rơi xuyên qua người chơi và chạm vào người chơi liên tiếp trong nhiều khung hình. Mỗi khung hình như vậy làm mất một mạng, nên chỉ một tảng đá cũng kết thúc trò chơi.
Nhiều trò chơi cho bạn một khoảng thời gian ngắn an toàn sau khi bị trúng đòn. Để biết đã trôi qua bao lâu, hãy xem đồng hồ. pygame.time.get_ticks() là số mili giây tính từ lúc gọi pygame.init(). Hãy ghi nhớ thời điểm bị trúng đòn rồi lấy thời gian hiện tại trừ đi:
now = pygame.time.get_ticks()
if rock.colliderect(player) and now - hit_time > 1000:
hit_time = now
lives -= 1Đặt hit_time thành -2000 trong reset() để lần trúng đòn đầu tiên luôn được tính.
Hiển thị khoảng thời gian an toàn bằng cách nhấp nháy. get_ticks() // 100 % 2 có giá trị 0 trong một phần mười giây, sau đó là 1 rồi lại là 0, vì vậy chỉ vẽ người chơi khi giá trị này là 0 sẽ khiến người chơi nhấp nháy:
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)Thử thách
Trung bìnhĐể mỗi lần va chạm chỉ mất một mạng, không phải ba.
- Trong
reset(), đặthit_time = -2000(thêm biến này vào dòngglobal). - Mỗi lần va chạm chỉ làm mất một mạng nếu đã hơn 1000 ms kể từ
hit_time; sau đó đặthit_timethành thời điểm hiện tại. - Trong 1000 ms sau khi va chạm, chỉ vẽ người chơi khi
pygame.time.get_ticks() // 100 % 2 == 0.
Nhấn Chơi rồi để bị va chạm: một trái tim biến mất, người chơi nhấp nháy. 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)
def reset():
global player, rock, score, lives
player = pygame.Rect(220, 300, 40, 40)
rock = pygame.Rect(random.randint(0, 456), -24, 24, 24)
score = 0
lives = 3
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)
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
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())
rock.y += 4
if rock.top > 360:
rock.y = -24
rock.x = random.randint(0, 456)
score += 1
if rock.colliderect(player):
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 == 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