Menu
CoddyTech

ثلاث حيوات

جزء من قسم الكائنات والصور في رحلة Pygame على Coddy. الدرس 35 من 36.

أصبح من الممكن الآن خسارة اللعبة. للسفينة ثلاث أرواح. يخسر اللاعب حياةً عندما يتجاوز عدوٌّ أسفل الشاشة، ويخسر حياةً أخرى عندما يصطدم العدو بالسفينة:

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

تحتاج السفينة أيضًا إلى self.mask. وفي الحلقة التي تقضي على الأعداء الذين يتجاوزون أسفل الشاشة، أنقص حياةً أيضًا.

عندما تصل قيمة lives إلى 0، تتوقف اللعبة: ضع جزء التحديث بأكمله، من player.update() حتى التصادمات، تحت if lives > 0:، واعرض Game over في المنتصف. اترك explosions.update() خارج هذا الشرط، لكي يستمر الانفجار الأخير حتى نهايته.

قد يخصم عدوّان آخر حياتين في الإطار نفسه، فتصبح قيمة lives -1. اعرض max(lives, 0)، أي الأكبر من العددين، حتى لا يعرض العداد أبدًا قيمةً أقل من 0.

challenge icon

التحدي

متوسط
  1. اجعل lives = 3 وأضف إلى Player قناعًا self.mask.
  2. العدو الذي يتجاوز أسفل الشاشة يخصم حياة. يُقتل العدو الذي يلامس السفينة، ويُختبر ذلك باستخدام collide_mask، ويخصم حياة وينفجر.
  3. ضع جزء التحديث ضمن if lives > 0:.
  4. اعرض Lives: وmax(lives, 0) بحيث تكون الزاوية العلوية اليمنى عند (630, 10)، واعرض Game over في المنتصف عند (320, 240) بمجرد أن تصبح lives <= 0.

جرّب بنفسك

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()

جميع دروس الكائنات والصور

تدرّب بنفسك: Playground لـ Pygame