الموجات والنصر
جزء من قسم الكائنات والصور في رحلة 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!. الموجة الرابعة هي عنصر إضافي في القائمة.
التحدي
متوسط- حمّل
enemy_green.pngوenemy_yellow.png، وأنشئ القائمةWAVESالمذكورة أعلاه. - اجعل
wave = 0وابدأ الموجة الأولى منWAVES. - عندما تكون
enemiesفارغة، انتقل إلى الموجة التالية وابدأها إن وُجدت. - حدّث فقط ما دام
lives > 0 and wave < len(WAVES). - أثناء اللعب، اعرض
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()
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس الكائنات والصور
4الكائنات الرسومية والمجموعات
صنف Spriteالمجموعاتالإزالة باستخدام kill()الالتقاط باستخدام spritecollideمجموعة ضد مجموعة7دورية النجوم
سفينة الدوريةأطلق أشعة الليزر2دوّر واقلب وغيّر الحجم
التدوير حول المركزوجّهها في اتجاه الطيرانغيّر حجم الصورةدوّر انطلاقًا من الصورة الأصلية5تصادمات مثالية على مستوى البكسل
المستطيلات تبدو غير منصفةالأقنعةكائنات Sprite مثالية على مستوى البكسلمناطق التصادم الدائرية6التحريك باستخدام أوراق الرسوم المتحركة
قصّ ورقة الرسوم المتحركةعداد الإطاراتالتحريك باستخدام الوقتانفجار لمرة واحدةتدرّب بنفسك: Playground لـ Pygame