Menu
CoddyTech

Gökyüzü Koşucusu için Bir Menü

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

Sky Runner kuralları bu bölümden alır ve bir menüyle başlar. Yeni bir oyun için her şeyin başlangıç durumuna dönmesi gerekir; bu yüzden yeni bir koşucuyu, boş bir grubu, hızı ve skoru, ayrıca iki zamanlayıcıyı da yeniden başlatmayı reset() içine koy.

Boşluk tuşu artık her durum için bir tane olmak üzere iki iş yapıyor:

if state == "play":
    runner.jump()
elif state == "menu":
    reset()
    state = "play"

Menüde ortalanmış iki satır, oyun sonu ekranında ise üç satır gerekecek; bu yüzden küçük bir işlev, x 320 noktasında ortalanmış tek bir satır çizer:

def show(text, text_font, y):
    picture = text_font.render(text, True, INK)
    screen.blit(picture, picture.get_rect(center=(320, y)))

Skor bir oyuna aittir; bu yüzden menüde değil, yalnızca oyun başladıktan sonra göster.

challenge icon

Görev

Orta

Sky Runner için bir menü ekle.

  1. Runner, grup, speed, score ve her iki zamanlayıcı için reset() yaz; döngüden önce çağır ve state = "menu" ayarla.
  2. Menüde, big_font ile Sky Runner ve Press Space to start için show() kullan; skoru yalnızca menü dışında göster.
  3. Menüdeyken Space tuşuna basılması reset() işlevini çağırır ve state = "play" ayarlar.

“Oyna” düğmesine bas: Space tuşu bir koşuyu başlatır. Ardından “Kontrol et” düğmesine bas.

Kendin dene

import random
import pygame

pygame.init()
screen = pygame.display.set_mode((640, 320))
pygame.display.set_caption("Sky Runner")
clock = pygame.time.Clock()
font = pygame.font.Font("assets/fonts/pixel.ttf", 32)

SKY = (140, 200, 240)
GROUND = (90, 160, 80)
GROUND_Y = 260
GRAVITY = 1
SPAWN = pygame.USEREVENT + 1
POINT = pygame.USEREVENT + 2


class Runner(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.frames = [
            pygame.image.load("assets/images/player.png").convert_alpha(),
            pygame.image.load("assets/images/player_walk.png").convert_alpha(),
        ]
        self.image = self.frames[0]
        self.step = 0
        self.rect = self.image.get_rect(midbottom=(100, GROUND_Y))
        self.vy = 0

    def jump(self):
        if self.rect.bottom == GROUND_Y:
            self.vy = -16

    def update(self):
        self.vy += GRAVITY
        self.rect.y += self.vy
        if self.rect.bottom >= GROUND_Y:
            self.rect.bottom = GROUND_Y
            self.vy = 0
        if self.rect.bottom == GROUND_Y:
            self.step += 1
            self.image = self.frames[self.step // 8 % 2]
        else:
            self.image = self.frames[1]


class Obstacle(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = random.choice(obstacle_images)
        self.rect = self.image.get_rect(midbottom=(664, GROUND_Y))

    def update(self):
        self.rect.x -= speed
        if self.rect.right < 0:
            self.kill()


obstacle_images = [
    pygame.image.load("assets/images/spike_ball.png").convert_alpha(),
    pygame.image.load("assets/images/blob.png").convert_alpha(),
]
runner = Runner()
obstacles = pygame.sprite.Group()
speed = 6
pygame.time.set_timer(SPAWN, 1500)
pygame.time.set_timer(POINT, 100)
score = 0
state = "play"

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.KEYDOWN and event.key in (pygame.K_SPACE, pygame.K_UP):
            if state == "play":
                runner.jump()
        if event.type == SPAWN and state == "play":
            obstacles.add(Obstacle())
            pygame.time.set_timer(SPAWN, random.randint(1000, 2000))
        if event.type == POINT and state == "play":
            score += 1

    if state == "play":
        speed = min(14, 6 + score // 100)
        runner.update()
        obstacles.update()
        if pygame.sprite.spritecollideany(runner, obstacles, pygame.sprite.collide_mask):
            state = "over"

    screen.fill(SKY)
    pygame.draw.rect(screen, GROUND, (0, GROUND_Y, 640, 60))
    screen.blit(runner.image, runner.rect)
    obstacles.draw(screen)
    score_text = font.render(f"{score:05}", True, (40, 50, 80))
    screen.blit(score_text, score_text.get_rect(topright=(630, 10)))
    if state == "over":
        message = font.render("Game over", True, (40, 50, 80))
        screen.blit(message, message.get_rect(center=(320, 140)))
    pygame.display.flip()
    clock.tick(60)

pygame.quit()

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

Kendi başına pratik yap: Pygame playground