Menu
CoddyTech

موجات إضافية

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

موجة واحدة لا تكفي لصنع لعبة ممتعة. صِف الموجات على هيئة بيانات، بحيث يحتوي كل صف على صورة الموجة وعدد الأعداء وسرعتهم.

WAVES = [(red_image, 4, 1), (green_image, 5, 2)]

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)

تُعامل المجموعة الفارغة على أنها خطأ، لذا تكون not enemies صحيحة بمجرد اختفاء آخر عدو. لإضافة موجة جديدة، أضف صفًا آخر إلى القائمة.

challenge icon

التحدي

متوسط

أرسل الموجات واحدة تلو الأخرى.

  1. حمّل enemy_green.png وenemy_yellow.png، وأنشئ WAVES = [(red_image, 6, 2), (green_image, 8, 2), (yellow_image, 10, 3)].
  2. اجعل wave = 0 وأنشئ الموجة الأولى من WAVES[wave].
  3. عندما تكون enemies فارغة، انتقل إلى الموجة التالية وأنشئها إن وُجدت.
  4. ما دام wave < len(WAVES)، ارسم f"Wave {wave + 1}" بحيث يكون منتصفها العلوي عند (320, 10).

اضغط «العب» واجتز إحدى الموجات: تجلب Wave 2 معها 8 أعداء خضر. ثم اضغط «تحقق».

جرّب بنفسك

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

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

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