Kademeli Artan Hız
Coddy'nin Pygame Journey'sinin Oyun Kuralları bölümünün bir parçası. Ders 15 / 29.
Hiç değişmeyen bir oyun sıkıcı hâle gelir, zor başlayan bir oyun da yeni oyuncuları kaybettirir. Yumuşak başlayıp oyuncu oyunda kaldıkça zorluğu artır.
Oyun başladıktan sonra geçen süre hızı belirler. reset() başlangıç zamanını hatırlar ve her karede hız buna göre hesaplanır:
seconds = (pygame.time.get_ticks() - start_time) // 1000
speed = 3 + seconds // 5seconds // 5 her beş saniyede 1 artar; böylece taşlar başlangıçta kare başına 3 piksel, beş saniye sonra 4, on saniye sonra 5 piksel düşer. Tam sayılı adımlar hızı tam sayı tutar; Rect buna ihtiyaç duyar: tam piksel değerleri saklar, bu yüzden rock.y += 3.5 yarım pikseli kaybettirir.
Enter ve R tuşlarının ikisi de reset() işlevini çağırır; böylece menü ne kadar süre görüntülenmiş olursa olsun, her oyunla birlikte saat yeniden başlar.
Görev
Ortareset()içindestart_timedeğerinipygame.time.get_ticks()olarak ayarla.play_frame()içinde,start_timeüzerinden geçensecondsdeğerini vespeed = 3 + seconds // 5ifadesini hesapla.- Her kayayı 3 yerine
speedkadar aşağı taşı.
Kendin dene
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()
Oyun Kuralları bölümündeki tüm dersler
Kendi başına pratik yap: Pygame playground