Menü und Bestpunktzahl
Teil des Abschnitts Spielregeln der Pygame-Journey von Coddy. Lektion 29 von 29.
Sky Runner bezieht die Regeln aus diesem Abschnitt: ein Menü, ein neues Spiel per Tastendruck und der beste Punktestand.
reset() erstellt einen neuen Läufer und eine leere Gruppe, setzt den Punktestand und die Geschwindigkeit zurück und startet beide Timer neu. Das Spiel beginnt mit "menu", und best wird einmal außerhalb von reset() festgelegt.
Die Leertaste erfüllt jetzt drei Aufgaben, eine pro Zustand:
if state == "play":
runner.jump()
elif state == "menu":
reset()
state = "play"
elif pygame.time.get_ticks() - over_time > 500:
reset()
state = "play"Die Leertaste ist die Sprungtaste, deshalb drücken Spieler sie oft genau im Moment eines Zusammenstoßes. Ohne Wartezeit würde das Spiel neu starten, bevor sie das Ergebnis sehen. Speichere den Zeitpunkt des Zusammenstoßes in over_time und akzeptiere die Leertaste auf dem Game-Over-Bildschirm erst 500 ms später.
Eine kleine Funktion show(text, text_font, y) zeichnet eine Zeile zentriert bei x 320, da sowohl das Menü als auch der Game-Over-Bildschirm fünf Zeilen benötigen.
Aufgabe
Schwer- Schreibe
reset()für den Runner, die Gruppe,speed,scoreund beide Timer; rufe die Funktion vor der Schleife auf und setzestate = "menu",best = 0undover_time = 0. - Zeige im Menü
Sky Runner(Größe 48) undPress Space to startan; die Leertaste oder die Pfeiltaste nach oben startet ein Spiel. - Aktualisiere bei einem Zusammenstoß
bestund setzeover_time. - Zeige auf dem Game-over-Bildschirm
Game over,Best: 00120(fünf Ziffern) undPress Space to play againan; die Leertaste startet ein neues Spiel, aber erst 500 ms nach dem Zusammenstoß. - Zeige den Punktestand nur während des Spiels und auf dem Game-over-Bildschirm an.
Probier es selbst
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()
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Spielregeln
3Timer und Wellen
Sicher nach einem TrefferEin Timer-EreignisAlle 800 ms ein FelsbrockenWachsende WellenCountdown bis zum Start6Himmelsläufer
Der LäuferSpringenÜbe selbstständig: Pygame-Playground