در این بخش بازی مهاجمان فضایی را به پایان می بریم. این بازی از مفاهیم شی گرایی استفاده می کند و از این نظر با بازی های پیشین متفاوت است.
اگر بازی را اجرا کنیم می بینیم که سفینه در جای مناسبی قرار ندارد. برای تغییر جای مانع در فایل 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)
تصویر نهایی بازی به شکل زیر خواهد شد:
کد کامل بازی را می توانید از نشانی دانلود کنید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.