Menu
CoddyTech

Trois vies

Fait partie de la section Sprites et images du Journey Pygame de Coddy. Leçon 35 sur 36.

Maintenant, il est possible de perdre la partie. Le vaisseau a trois vies. Un ennemi en fait perdre une lorsqu’il dépasse le bas de l’écran, et une autre lorsqu’il percute le vaisseau :

crashes = pygame.sprite.spritecollide(player, enemies, True, pygame.sprite.collide_mask)
for enemy in crashes:
    lives -= 1
    explosions.add(Explosion(enemy.rect.center))

Le vaisseau a aussi besoin de son propre self.mask. Dans la boucle qui élimine les ennemis qui dépassent le bas de l’écran, faites également perdre une vie.

Lorsque lives atteint 0, la partie s’arrête : placez toute la partie de mise à jour, de player.update() jusqu’aux collisions, sous if lives > 0:, et affichez Game over au centre. Laissez explosions.update() en dehors de cette condition, afin que la dernière explosion puisse quand même se terminer.

Deux ennemis pourraient faire perdre les deux dernières vies pendant la même image, ce qui laisserait lives à -1. Affichez max(lives, 0), le plus grand des deux nombres, afin que le compteur ne descende jamais en dessous de 0.

challenge icon

Défi

Moyen
  1. Définis lives = 3 et ajoute un self.mask à Player.
  2. Un ennemi qui dépasse le bas de l’écran fait perdre une vie. Un ennemi qui touche le vaisseau, détecté avec collide_mask, est éliminé, fait perdre une vie et explose.
  3. Place la partie mise à jour sous if lives > 0:.
  4. Affiche Lives: et max(lives, 0) avec leur coin supérieur droit en (630, 10), et Game over au centre de (320, 240) lorsque lives <= 0.

Essayez vous-même

import random
import pygame

pygame.init()
screen = pygame.display.set_mode((640, 480))
pygame.display.set_caption("Star Patrol")
clock = pygame.time.Clock()
font = pygame.font.Font(None, 32)

ship_image = pygame.image.load("assets/images/ship.png").convert_alpha()
laser_image = pygame.image.load("assets/images/laser.png").convert_alpha()
red_image = pygame.image.load("assets/images/enemy_red.png").convert_alpha()
explosion_frames = []
for number in range(1, 5):
    explosion_frames.append(pygame.image.load(f"assets/images/explosion_{number}.png").convert_alpha())


class Player(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = ship_image
        self.rect = self.image.get_rect(midbottom=(320, 470))

    def update(self):
        keys = pygame.key.get_pressed()
        if keys[pygame.K_LEFT]:
            self.rect.x -= 6
        if keys[pygame.K_RIGHT]:
            self.rect.x += 6
        self.rect.clamp_ip(screen.get_rect())


class Laser(pygame.sprite.Sprite):
    def __init__(self, x, y):
        super().__init__()
        self.image = laser_image
        self.rect = self.image.get_rect(midbottom=(x, y))
        self.mask = pygame.mask.from_surface(self.image)

    def update(self):
        self.rect.y -= 10
        if self.rect.bottom < 0:
            self.kill()


class Enemy(pygame.sprite.Sprite):
    def __init__(self, image, x, y, speed):
        super().__init__()
        self.image = image
        self.rect = self.image.get_rect(center=(x, y))
        self.mask = pygame.mask.from_surface(self.image)
        self.speed = speed

    def update(self):
        self.rect.y += self.speed


class Explosion(pygame.sprite.Sprite):
    def __init__(self, center):
        super().__init__()
        self.index = 0
        self.timer = 0
        self.image = explosion_frames[0]
        self.rect = self.image.get_rect(center=center)

    def update(self):
        self.timer += 1
        if self.timer == 5:
            self.timer = 0
            self.index += 1
            if self.index == len(explosion_frames):
                self.kill()
            else:
                self.image = explosion_frames[self.index]


def spawn_wave(image, count, speed):
    for i in range(count):
        x = random.randint(40, 600)
        enemies.add(Enemy(image, x, -40 - i * 120, speed))


player = Player()
lasers = pygame.sprite.Group()
enemies = pygame.sprite.Group()
explosions = pygame.sprite.Group()
last_shot = 0
score = 0
spawn_wave(red_image, 6, 2)

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    player.update()
    keys = pygame.key.get_pressed()
    now = pygame.time.get_ticks()
    if keys[pygame.K_SPACE] and now - last_shot >= 250:
        lasers.add(Laser(player.rect.centerx, player.rect.top))
        last_shot = now
    lasers.update()
    enemies.update()
    for enemy in enemies:
        if enemy.rect.top > 480:
            enemy.kill()
    hits = pygame.sprite.groupcollide(enemies, lasers, True, True, pygame.sprite.collide_mask)
    for enemy in hits:
        score += 10
        explosions.add(Explosion(enemy.rect.center))
    explosions.update()

    screen.fill((12, 14, 30))
    enemies.draw(screen)
    lasers.draw(screen)
    screen.blit(player.image, player.rect)
    explosions.draw(screen)
    score_text = font.render(f"Score: {score}", True, (240, 240, 240))
    screen.blit(score_text, (10, 10))
    pygame.display.flip()
    clock.tick(60)

pygame.quit()

Toutes les leçons de Sprites et images

Entraînez-vous par vous-même : Playground Pygame