Menu
CoddyTech

الموجات والنصر

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

الجزء الأخير: موجات أكثر، تزداد صعوبة كل واحدة منها، وطريقة للفوز. صِف الموجات على شكل بيانات، عنصر واحد لكل موجة: صورتها، وعدد الأعداء، وسرعتهم.

WAVES = [(red_image, 6, 2), (green_image, 8, 2), (yellow_image, 10, 3)]

wave هو فهرس الموجة التي يجري لعبها. ابدأ الأولى باستخدام image, count, speed = WAVES[wave]، الذي يفكك العنصر إلى ثلاثة أسماء، ثم استخدم spawn_wave(image, count, speed). عندما تكون enemies فارغة، تكون الموجة قد اكتملت:

if not enemies:
    wave += 1
    if wave < len(WAVES):
        image, count, speed = WAVES[wave]
        spawn_wave(image, count, speed)

عندما يصل wave إلى len(WAVES)، تكون كل الموجات قد انتهت: يفوز اللاعب. أوقِف اللعبة عندئذٍ أيضًا، باستخدام if lives > 0 and wave < len(WAVES):، واعرض You win!. الموجة الرابعة هي عنصر إضافي في القائمة.

challenge icon

التحدي

متوسط
  1. حمّل enemy_green.png وenemy_yellow.png، وأنشئ القائمة WAVES المذكورة أعلاه.
  2. اجعل wave = 0 وابدأ الموجة الأولى من WAVES.
  3. عندما تكون enemies فارغة، انتقل إلى الموجة التالية وابدأها إن وُجدت.
  4. حدّث فقط ما دام lives > 0 and wave < len(WAVES).
  5. أثناء اللعب، اعرض Wave وwave + 1 بحيث يكون موضع أعلى منتصفهما عند (320, 10). بعد الموجة الأخيرة، اعرض You win! في المنتصف عند (320, 240)، ما لم تنتهِ اللعبة.

جرّب بنفسك

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))
        self.mask = pygame.mask.from_surface(self.image)

    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
lives = 3
spawn_wave(red_image, 6, 2)

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

    if lives > 0:
        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()
                lives -= 1
        hits = pygame.sprite.groupcollide(enemies, lasers, True, True, pygame.sprite.collide_mask)
        for enemy in hits:
            score += 10
            explosions.add(Explosion(enemy.rect.center))
        crashes = pygame.sprite.spritecollide(player, enemies, True, pygame.sprite.collide_mask)
        for enemy in crashes:
            lives -= 1
            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))
    lives_text = font.render(f"Lives: {max(lives, 0)}", True, (240, 240, 240))
    screen.blit(lives_text, lives_text.get_rect(topright=(630, 10)))
    if lives <= 0:
        message = font.render("Game over", True, (240, 240, 240))
        screen.blit(message, message.get_rect(center=(320, 240)))
    pygame.display.flip()
    clock.tick(60)

pygame.quit()
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

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

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