Menu
CoddyTech

Bir Zamanlayıcı Olayı

Coddy'nin Pygame Journey'sinin Oyun Kuralları bölümünün bir parçası. Ders 11 / 29.

Geçip giden her kaya için bir puan vermek, bekleyerek puan kazanmayı ödüllendirir. Hayatta kaldığın her saniye için bir puan vermek daha adildir. pygame, oyunun için her saniye kendi etkinliğini gönderebilir.

Etkinlik türleri sayılardır. pygame.USEREVENT, pygame'in senin için boş bıraktığı ilk türdür; bu nedenle kendi türünü bundan türet:

POINT = pygame.USEREVENT + 1
...
pygame.time.set_timer(POINT, 1000)

Bundan sonra diğer etkinliklerle birlikte her 1000 ms'de bir POINT etkinliği gelir ve bunu bir tuş basışı gibi işlersin:

if event.type == POINT and state == "play":
    score += 1

Zamanlayıcı menüde ve oyun bitti ekranında da çalışmaya devam eder, bu yüzden durumu kontrol et. set_timer'ı yeniden çağırmak zamanlayıcıyı baştan başlatır; bu nedenle reset() içine koyulur: her yeni oyun, ilk puanını almak için tam bir saniye bekler.

challenge icon

Görev

Orta
  1. Renklerden sonra POINT = pygame.USEREVENT + 1 ekle.
  2. reset() içinde, her 1000 ms'de bir POINT gönderen bir zamanlayıcı başlat.
  3. Oyun sırasında bir POINT olayı gerçekleştiğinde skoru 1 artır.
  4. Aşağı düşüp geçen kayalar artık puan kazandırmaz.

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)


def reset():
    global player, rock, score, lives, hit_time
    player = pygame.Rect(220, 300, 40, 40)
    rock = pygame.Rect(random.randint(0, 456), -24, 24, 24)
    score = 0
    lives = 3
    hit_time = -2000


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)
    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
    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
    now = pygame.time.get_ticks()
    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 == 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()
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Oyun Kuralları bölümündeki tüm dersler

Kendi başına pratik yap: Pygame playground