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