Menu
CoddyTech

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 // 5

seconds // 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.

challenge icon

Görev

Orta
  1. reset() içinde start_time değerini pygame.time.get_ticks() olarak ayarla.
  2. play_frame() içinde, start_time üzerinden geçen seconds değerini ve speed = 3 + seconds // 5 ifadesini hesapla.
  3. Her kayayı 3 yerine speed kadar 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