در این بخش بازی مهاجمان فضایی را به پایان می بریم. این بازی از مفاهیم شی گرایی استفاده می کند و از این نظر با بازی های پیشین متفاوت است.
اگر بازی را اجرا کنیم می بینیم که سفینه در جای مناسبی قرار ندارد. برای تغییر جای مانع در فایل main.py داریم:
self.create_obstacle(40,480)
def create_obstacle(self,x_start,y_start):
for row_index,row in enumerate(self.shape):
for col_index,col in enumerate(row):
if col =='x':
x=x_start + col_index*self.block_size
y=y_start + row_index*self.block_size
block=obstacle.Block(self.block_size,(241,79,80),x,y)
self.blocks.add(block)
اگر بازی را دوباره اجرا کنیم تصویر زیر را خواهیم دید:

برای ایجاد مانع های گوناگون تغییرهای زیر را فایل main.py اعمال می کنیم:
# obstacle setup
self.shape=obstacle.shape
self.block_size=6
self.blocks=pygame.sprite.Group()
self.create_multiple_obstacles(0,480,0,100,200)
def create_obstacle(self,x_start,y_start,offset_x):
for row_index,row in enumerate(self.shape):
for col_index,col in enumerate(row):
if col =='x':
x=x_start + col_index*self.block_size + offset_x
y=y_start + row_index*self.block_size
block=obstacle.Block(self.block_size,(241,79,80),x,y)
self.blocks.add(block)
def create_multiple_obstacles(self,x_start,y_start,*offset):
for offset_x in offset:
self.create_obstacle(x_start,y_start,offset_x)
اگر بازی را دوباره اجرا کنیم تغییر زیر را خواهیم داشت:

با نگاه به تصویر بالا متوجه خواهیم شد که مانع سمت چپ از پنجره فاصله ای ندارد. برای ایجاد فاصله میان مانع ها تغییر زیر را در کد اعمال می کنیم:
self.create_multiple_obstacles(0,100,200,x_start=0,y_start=480)
def create_obstacle(self,x_start,y_start,offset_x):
for row_index,row in enumerate(self.shape):
for col_index,col in enumerate(row):
if col =='x':
x=x_start + col_index*self.block_size + offset_x
y=y_start + row_index*self.block_size
block=obstacle.Block(self.block_size,(241,79,80),x,y)
self.blocks.add(block)
def create_multiple_obstacles(self,*offset,x_start,y_start,):
for offset_x in offset:
self.create_obstacle(x_start,y_start,offset_x)
سپس داریم:
self.obstacle_amount=4 self.obstacle_x_positions= [num * (WIDTH / self.obstacle_amount) for num in range(self.obstacle_amount)] self.create_multiple_obstacles(*self.obstacle_x_positions,x_start=0,y_start=480)
و برای ایجاد فاصله از چپ داریم:
self.create_multiple_obstacles(*self.obstacle_x_positions,x_start=WIDTH / 15 ,y_start=480)
کد فایل main.py تا این لحظه:
import pygame,sys
from player import Player
import obstacle
class Game:
def __init__(self):
player_sprite=Player((WIDTH/2,HEIGHT),WIDTH,5)
self.player=pygame.sprite.GroupSingle(player_sprite)
# obstacle setup
self.shape=obstacle.shape
self.block_size=6
self.blocks=pygame.sprite.Group()
self.obstacle_amount=4
self.obstacle_x_positions= [num * (WIDTH / self.obstacle_amount) for num in range(self.obstacle_amount)]
self.create_multiple_obstacles(*self.obstacle_x_positions,x_start=WIDTH / 15 ,y_start=480)
def create_obstacle(self,x_start,y_start,offset_x):
for row_index,row in enumerate(self.shape):
for col_index,col in enumerate(row):
if col =='x':
x= x_start + col_index*self.block_size + offset_x
y= y_start + row_index*self.block_size
block=obstacle.Block(self.block_size,(241,79,80),x,y)
self.blocks.add(block)
def create_multiple_obstacles(self,*offset,x_start,y_start,):
for offset_x in offset:
self.create_obstacle(x_start,y_start,offset_x)
def run(self):
self.player.draw(SCREEN)
self.player.sprite.lasers.draw(SCREEN)
self.player.update()
self.blocks.draw(SCREEN)
if __name__ == "__main__":
pygame.init()
WIDTH=600
HEIGHT=600
SCREEN=pygame.display.set_mode((WIDTH,HEIGHT))
Clock=pygame.time.Clock()
game=Game()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
SCREEN.fill((30,30,30))
game.run()
pygame.display.flip()
Clock.tick(60)
یک فایل جدید به نام alien.py در پوشه code می سازیم:
import pygame
class Alien(pygame.sprite.Sprite):
def __init__(self,color,x,y):
super().__init__()
file_path=r'C:/Users/Rahmani/Desktop/space_invaders/graphics/' + color + '.png'
self.image=pygame.image.load(file_path).convert_alpha()
self.rect=self.image.get_rect(topleft=(x,y))
سپس در فایل main داریم:
import pygame,sys,os
from player import Player
import obstacle
from alien import Alien
class Game:
def __init__(self):
# player setup
player_sprite=Player((WIDTH/2,HEIGHT),WIDTH,5)
self.player=pygame.sprite.GroupSingle(player_sprite)
# obstacle setup
self.shape=obstacle.shape
self.block_size=6
self.blocks=pygame.sprite.Group()
self.obstacle_amount=4
self.obstacle_x_positions= [num * (WIDTH / self.obstacle_amount) for num in range(self.obstacle_amount)]
self.create_multiple_obstacles(*self.obstacle_x_positions,x_start=WIDTH / 15 ,y_start=480)
# Alien setup
self.aliens=pygame.sprite.Group()
self.alien_setup(rows=6,cols=8)
def create_obstacle(self,x_start,y_start,offset_x):
for row_index,row in enumerate(self.shape):
for col_index,col in enumerate(row):
if col =='x':
x=x_start + col_index*self.block_size + offset_x
y=y_start + row_index*self.block_size
block=obstacle.Block(self.block_size,(241,79,80),x,y)
self.blocks.add(block)
def create_multiple_obstacles(self,*offset,x_start,y_start,):
for offset_x in offset:
self.create_obstacle(x_start,y_start,offset_x)
def alien_setup(self,rows,cols):
for row_index,row in enumerate(range(rows)):
for col_index,col in enumerate(range(cols)):
x= col_index
y= row_index
alien_sprite=Alien('red',x,y)
self.aliens.add(alien_sprite)
def run(self):
self.player.update()
self.player.sprite.lasers.draw(SCREEN)
self.player.draw(SCREEN)
self.blocks.draw(SCREEN)
self.aliens.draw(SCREEN)
if __name__ == "__main__":
pygame.init()
WIDTH=600
HEIGHT=600
SCREEN=pygame.display.set_mode((WIDTH,HEIGHT))
Clock=pygame.time.Clock()
game=Game()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
SCREEN.fill((30,30,30))
game.run()
pygame.display.flip()
Clock.tick(60)
بیگانگان در شش سطر و هشت ستون خواهند بود:
# Alien setup self.aliens=pygame.sprite.Group() self.alien_setup(rows=6,cols=8)
تابع alien_setup برای رسم بیگانگان به کار می رود:
def alien_setup(self,rows,cols):
for row_index,row in enumerate(range(rows)):
for col_index,col in enumerate(range(cols)):
x= col_index
y= row_index
alien_sprite=Alien('red',x,y)
self.aliens.add(alien_sprite)
فعلا بیگانه قرمز رنگ را نمایش می دهیم.اگر بازی را اجرا کنیم نتیجه زیر را خواهیم دید:

تغییر زیر را در متد alien_setup در فایل main.py می دهیم تا همه بیگانگان نشان داده شوند و در جای مناسب قرار گیرند:
def alien_setup(self,rows,cols,x_distance=60,y_distance=48,x_offset=70,y_offset=100):
for row_index,row in enumerate(range(rows)):
for col_index,col in enumerate(range(cols)):
x= col_index * x_distance + x_offset
y= row_index * y_distance + y_offset
self.aliens.add(alien_sprite)
با اجرای کد بالا همه بیگانگان نمایش داده می شوند:

برای نمایش بیگانگان با رنگ های گوناگون کد زیر را به فایل alien.py می افزاییم:
import pygame
class Alien(pygame.sprite.Sprite):
def __init__(self,color,x,y):
super().__init__()
file_path = r'C:/Users/Rahmani/Desktop/space_invaders/graphics/' + color + '.png'
self.image = pygame.image.load(file_path).convert_alpha()
self.rect = self.image.get_rect(topleft = (x,y))
if color == 'red': self.value = 100
elif color == 'green': self.value = 200
else: self.value = 300
سپس در فایل main.py داریم:
def alien_setup(self,rows,cols,x_distance=60,y_distance=48,x_offset=70,y_offset=100):
for row_index,row in enumerate(range(rows)):
for col_index,col in enumerate(range(cols)):
x= col_index * x_distance + x_offset
y= row_index * y_distance + y_offset
if row_index == 0 : alien_sprite=Alien('yellow',x,y)
elif 1 <= row_index <= 2: alien_sprite = Alien('green',x,y)
else: alien_sprite=Alien('red',x,y)
self.aliens.add(alien_sprite)
اگر بازی را اجرا کنیم بیگانگان را با رنگ های گوناگون خواهیم دید:

سپس متد update را به فایل alien.py می افزاییم:
def update(self,direction):
self.rect.x += direction
سپس کد زیر را به main.py اضافه می کنیم:
# Alien setup self.aliens=pygame.sprite.Group() self.alien_setup(rows=6,cols=8) self.alien_direction = 1
سپس در متد run داریم :
def run(self):
self.player.update()
self.aliens.update(self.alien_direction)
برای حرکت بیگانگان به چپ و راست داریم متد alien_position_checker را به main.py اضافه می کنیم:
def alien_position_checker(self):
all_aliens=self.aliens.sprites()
for alien in all_aliens:
if alien.rect.right >= WIDTH:
self.alien_direction = -1
elif alien.rect.left <= 0:
self.alien_direction = 1
برای حرکت بیگانگان به پایین متد alien_move_down را به main.py اضافه می کنیم:
def alien_position_checker(self):
all_aliens=self.aliens.sprites()
for alien in all_aliens:
if alien.rect.right >= WIDTH:
self.alien_direction = -1
self.alien_move_down(2)
elif alien.rect.left <= 0:
self.alien_direction = 1
self.alien_move_down(2)
def alien_move_down(self,distance):
if self.aliens:
for alien in self.aliens.sprites():
alien.rect.y += distance
ابتدا ماژول random را وارد main.py می کنیم:
from random import choice, randint
سپس Laser را وارد main.py می کنیم:
from laser import Laser
سپس خط زیر را اضافه می کنیم:
# Alien setup self.aliens=pygame.sprite.Group() self.alien_lasers=pygame.sprite.Group() self.alien_setup(rows=6,cols=8) self.alien_direction = 1
سپس متد alien_shoot را می سازیم:
def alien_shoot(self):
if self.aliens.sprites():
random_alien=choice(self.aliens.sprites())
laser_sprite=Laser(random_alien.rect.center,6,HEIGHT)
self.alien_lasers.add(laser_sprite)
سپس باید لیزرها را نمایش بدهیم:
def run(self):
self.player.update()
self.aliens.update(self.alien_direction)
self.alien_position_checker()
self.alien_shoot()
self.alien_lasers.update()
self.player.sprite.lasers.draw(SCREEN)
self.player.draw(SCREEN)
self.blocks.draw(SCREEN)
self.aliens.draw(SCREEN)
self.alien_lasers.draw(SCREEN)
اگر بازی را اجرا کنیم بیگانگان بی امان تیر شلیک خواهند کرد.برای درست کردن این مشکل باید از زمان سنج(timer) استفاده کنیم:
if __name__ == "__main__":
pygame.init()
WIDTH=600
HEIGHT=600
SCREEN=pygame.display.set_mode((WIDTH,HEIGHT))
Clock=pygame.time.Clock()
game=Game()
ALIENLASER=pygame.USEREVENT + 1
pygame.time.set_timer(ALIENLASER, 800)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == ALIENLASER:
game.alien_shoot()
SCREEN.fill((30,30,30))
game.run()
pygame.display.flip()
Clock.tick(60)
سپس متد alien_shoot در متد run را comment می کنیم:
# self.alien_shoot() self.alien_lasers.update()
برای افزودن بیگانگان بیش تر در فایل alien.py داریم:
class Extra(pygame.sprite.Sprite):
def __init__(self,side,screen_width):
super().__init__()
self.image=pygame.image.load(r'C:/Users/Rahmani/Desktop/space_invaders/graphics/extra.png').convert_alpha()
if side == 'right':
x = screen_width + 50
self.speed = -3
else:
x = -50
self.speed = 3
self.rect= self.image.get_rect(topleft = (x,80))
def update(self):
self.rect.x += self.speed
سپس در فایل main.py داریم:
from alien import Alien,Extra
سپس داریم:
# Alien setup self.aliens=pygame.sprite.Group() self.alien_lasers=pygame.sprite.Group() self.alien_setup(rows=6,cols=8) self.alien_direction = 1 # extra setup self.extra=pygame.sprite.GroupSingle() self.extra_spawn_time=randint(400,800)
سپس متد زیر را برای بیگانه آبی رنگ داریم:
def extra_alien_timer(self):
self.extra_spawn_time -= 1
if self.extra_spawn_time <= 0:
self.extra.add(Extra(choice(['right','left']),WIDTH))
self.extra_spawn_time=randint(400,800)
پس از آن داریم:
# self.alien_shoot() self.alien_lasers.update() self.extra_alien_timer()
سپس نوبت نمایش آن است:
def run(self):
self.player.update()
self.aliens.update(self.alien_direction)
self.alien_position_checker()
# self.alien_shoot()
self.alien_lasers.update()
self.extra_alien_timer()
self.extra.update()
self.player.sprite.lasers.draw(SCREEN)
self.player.draw(SCREEN)
self.blocks.draw(SCREEN)
self.aliens.draw(SCREEN)
self.alien_lasers.draw(SCREEN)
self.extra.draw(SCREEN)
اگر بازی را اجرا کنیم بیگانه آبی رنگ را خواهیم دید:

برای بررسی برخورد تیر بازیکن به مانع ها در فایل main.py داریم:
def collision_checks(self):
#player lasers
if self.player.sprite.lasers:
for laser in self.player.sprite.lasers:
# obstacle collisions
if pygame.sprite.spritecollide(laser, self.blocks,True):
laser.kill()
سپس باید این متد را فراخوانی کنیم:
# self.alien_shoot() self.alien_lasers.update() self.extra_alien_timer() self.extra.update() self.collision_checks()
برای برخورد تیر بازیکن به بیگانگان داریم:
def collision_checks(self):
#player lasers
if self.player.sprite.lasers:
for laser in self.player.sprite.lasers:
# obstacle collisions
if pygame.sprite.spritecollide(laser, self.blocks,True):
laser.kill()
# alien collisions
if pygame.sprite.spritecollide(laser, self.aliens,True):
laser.kill()
برای برخورد تیر بازیکن به سفینه بیگانه داریم:
# extra collisions
if pygame.sprite.spritecollide(laser, self.extra,True):
laser.kill()
برای برخورد تیر بیگانه به بازیکن کد زیر را داریم:
#alien lasers
if self.alien_lasers:
for laser in self.alien_lasers:
# obstacle collisions
if pygame.sprite.spritecollide(laser, self.blocks,True):
laser.kill()
if pygame.sprite.spritecollide(laser, self.player,False):
laser.kill()
print("dead")
می خواهیم وقتی صف بیگانگان به سفینه ما می رسد بازی پایان یابد.پس داریم:
#aliens
if self.aliens:
for alien in self.aliens:
pygame.sprite.spritecollide(alien, self.blocks,True)
if pygame.sprite.spritecollide(alien, self.player,False):
sys.exit()
برای پیاده سازی سیستم تندرستی کد زیر را به تابع __init__ در فایل main.py می افزاییم:
def __init__(self):
# player setup
player_sprite=Player((WIDTH/2,HEIGHT),WIDTH,5)
self.player=pygame.sprite.GroupSingle(player_sprite)
# health and score setup
self.lives = 3
self.live_surf = pygame.image.load(r'C:/Users/Rahmani/Desktop/space_invaders/graphics/player.png').convert_alpha()
self.live_x_start_pos = WIDTH - (self.live_surf.get_size()[0] * 2 + 20)
سپس برای نمایش سیستم سلامتی داریم:
def display_lives(self):
for live in range(self.lives - 1):
x = self.live_x_start_pos + (live * (self.live_surf.get_size()[0] + 10))
SCREEN.blit(self.live_surf,(x,8))
برای نمایش نهایی باید تابع بالا را فراخوانی کنیم:
def run(self):
self.player.update()
self.aliens.update(self.alien_direction)
self.alien_position_checker()
# self.alien_shoot()
self.alien_lasers.update()
self.extra_alien_timer()
self.extra.update()
self.collision_checks()
self.display_lives()
می خواهیم با هر برخورد تیر به سفینه یکی از جان های بازیکن کم شود پس داریم:
#alien lasers
if self.alien_lasers:
for laser in self.alien_lasers:
# obstacle collisions
if pygame.sprite.spritecollide(laser, self.blocks,True):
laser.kill()
if pygame.sprite.spritecollide(laser, self.player,False):
laser.kill()
if self.lives <= 0:
pygame.quit()
sys.exit()
برای نشان دادن امتیاز کد زیر را به متد __init__ می افزاییم:
self.score = 0 self.font = pygame.font.Font(r'C:/Users/Rahmani/Desktop/space_invaders/font/Pixeled.ttf', 20)
برای نمایش سیستم امتیاز داریم:
def display_score(self):
score_surf = self.font.render(f'score : {self.score}', False, 'white')
score_rect=score_surf.get_rect(topleft=(10,-10))
SCREEN.blit(score_surf,score_rect)
برای نمایش امتیاز تغییرهای زیر را در متد run انجام می دهیم:
def run(self):
self.player.update()
self.aliens.update(self.alien_direction)
self.alien_position_checker()
# self.alien_shoot()
self.alien_lasers.update()
self.extra_alien_timer()
self.extra.update()
self.collision_checks()
self.player.sprite.lasers.draw(SCREEN)
self.player.draw(SCREEN)
self.blocks.draw(SCREEN)
self.aliens.draw(SCREEN)
self.alien_lasers.draw(SCREEN)
self.extra.draw(SCREEN)
self.display_lives()
self.display_score()
می خواهیم برای زدن هر بیگانه با یک رنگ خاص یک امتیاز ویژه را قرار بدهیم. برای این کار در درفایل alien.py داریم:
def __init__(self,color,x,y):
super().__init__()
file_path=r'C:/Users/Rahmani/Desktop/space_invaders/graphics/' + color + '.png'
self.image=pygame.image.load(file_path).convert_alpha()
self.rect=self.image.get_rect(topleft=(x,y))
if color == 'red' : self.value = 100
elif color == 'green' : self.value = 200
else: self.value = 300
سپس در فایل main.py در متد check_collision داریم:
def collision_checks(self):
#player lasers
if self.player.sprite.lasers:
for laser in self.player.sprite.lasers:
# obstacle collisions
if pygame.sprite.spritecollide(laser, self.blocks,True):
laser.kill()
# alien collisions
aliens_hit=pygame.sprite.spritecollide(laser, self.aliens,True)
if aliens_hit:
for alien in aliens_hit:
self.score += alien.value
laser.kill()
# extra collisions
if pygame.sprite.spritecollide(laser, self.extra,True):
self.score += 500
laser.kill()
کلاس CRT رادر فایل main.py می سازیم:
class CRT:
def __init__(self):
self.tv = pygame.image.load(r'C:/Users/Rahmani/Desktop/space_invaders/graphics/tv.png').convert_alpha()
def draw(self):
SCREEN.blit(self.tv,(0,0))
برای نمایش تصویر تلویزیون داریم:
crt=CRT()
ALIENLASER=pygame.USEREVENT + 1
pygame.time.set_timer(ALIENLASER, 800)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == ALIENLASER:
game.alien_shoot()
SCREEN.fill((30,30,30))
game.run()
crt.draw()
اگر بازی را اجرا کنیم تصویر تلویزیون دارای مشکل خواهد بود.برای حل این مشکل داریم:
class CRT:
def __init__(self):
self.tv = pygame.image.load(r'C:/Users/Rahmani/Desktop/space_invaders/graphics/tv.png').convert_alpha()
self.tv = pygame.transform.scale(self.tv,(WIDTH, HEIGHT))
def draw(self):
self.tv.set_alpha(randint(75,90))
SCREEN.blit(self.tv,(0,0))
برای ایجاد خطوط crt در پنجره بازی داریم:
class CRT:
def __init__(self):
self.tv = pygame.image.load(r'C:/Users/Rahmani/Desktop/space_invaders/graphics/tv.png').convert_alpha()
self.tv = pygame.transform.scale(self.tv,(WIDTH, HEIGHT))
def create_crt_lines(self):
line_height = 3
line_amount = int(HEIGHT / line_height)
for line in range(line_amount):
y_pos = line * line_height
pygame.draw.line(self.tv,'black',(0,y_pos),(WIDTH,y_pos),1)
def draw(self):
self.tv.set_alpha(randint(25,90))
self.create_crt_lines()
SCREEN.blit(self.tv,(0,0))
کد زیر را به متد __init__ در فایل main می افزاییم:
# audio music = pygame.mixer.Sound(r'C:/Users/Rahmani/Desktop/space_invaders/audio/music.wav') music.set_volume(0.2) music.play(loops = -1)
سپس داریم:
# Audio music = pygame.mixer.Sound(r'C:/Users/Rahmani/Desktop/space_invaders/audio/music.wav') music.set_volume(0.2) music.play(loops = -1) self.laser_sound = pygame.mixer.Sound(r'C:/Users/Rahmani/Desktop/space_invaders/audio/laser.wav') self.laser_sound.set_volume(0.5) self.explosion_sound = pygame.mixer.Sound(r'C:/Users/Rahmani/Desktop/space_invaders/audio/explosion.wav') self.explosion_sound.set_volume(0.3)
در ادامه داریم:
# alien collisions
aliens_hit = pygame.sprite.spritecollide(laser,self.aliens,True)
if aliens_hit:
for alien in aliens_hit:
self.score += alien.value
laser.kill()
self.explosion_sound.play()
اگر همه بیگانگان در صفحه نابود شوند باید پیام پیروزی نمایش داده شود:
def victory_message(self):
if not self.aliens.sprites():
victory_surf = self.font.render('You won',False,'white')
victory_rect = victory_surf.get_rect(center = (screen_width / 2, screen_height / 2))
screen.blit(victory_surf,victory_rect)
تصویر نهایی بازی به شکل زیر خواهد شد:

کد کامل بازی را می توانید از نشانی دانلود کنید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.