Choque
Parte de la sección Reglas del juego del Journey de Pygame de Coddy. Lección 27 de 29.
Tocar un obstáculo termina la partida. pygame.sprite.spritecollideany(sprite, group) devuelve el primer sprite del grupo que toca al sprite, o None.
De forma predeterminada, compara los rectángulos. Las imágenes tienen las esquinas transparentes, sobre todo la masa, así que dos rectángulos pueden superponerse aunque nada de lo que ves se toque. Un tercer argumento elige una prueba más justa:
if pygame.sprite.spritecollideany(runner, obstacles, pygame.sprite.collide_mask):
state = "over"collide_mask compara los píxeles dibujados de las imágenes e ignora los transparentes. Así, un choque es algo que el jugador puede ver.
El estado funciona igual que en Meteor Dodge: la actualización, los saltos y los nuevos obstáculos ocurren solo mientras está en "play", y la pantalla de fin de partida dibuja el juego congelado con un mensaje.
Desafío
Intermedio- Añade una fuente,
assets/fonts/pixel.ttfde tamaño 32, ystate = "play". - Solo mientras el estado sea
"play": salta, añade obstáculos, actualiza al corredor y los obstáculos. - Cuando el corredor toque un obstáculo (
collide_mask), establece el estado en"over". - Cuando termine el juego, muestra
Game overen(40, 50, 80)centrado en (320, 140).
Pruébalo tú mismo
import random
import pygame
pygame.init()
screen = pygame.display.set_mode((640, 320))
pygame.display.set_caption("Sky Runner")
clock = pygame.time.Clock()
SKY = (140, 200, 240)
GROUND = (90, 160, 80)
GROUND_Y = 260
GRAVITY = 1
SPAWN = pygame.USEREVENT + 1
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)
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):
runner.jump()
if event.type == SPAWN:
obstacles.add(Obstacle())
pygame.time.set_timer(SPAWN, random.randint(1000, 2000))
runner.update()
obstacles.update()
screen.fill(SKY)
pygame.draw.rect(screen, GROUND, (0, GROUND_Y, 640, 60))
screen.blit(runner.image, runner.rect)
obstacles.draw(screen)
pygame.display.flip()
clock.tick(60)
pygame.quit()
Todas las lecciones de Reglas del juego
Practica por tu cuenta: Playground de Pygame