基于pygame的射击小游戏制作(三)让外星人动起来
在本篇文章中,將學(xué)習(xí)如何創(chuàng)建一群外星人,如何使用嵌套循環(huán)來(lái)創(chuàng)建元素網(wǎng)格,如何移動(dòng)外星人
1、編程思路
1.1 創(chuàng)建外星人
創(chuàng)建Alien.py 文件,該文件配置與Ship.py類似,每個(gè)外星人最初都出現(xiàn)在屏幕左上角。修改update_screen()里的形參,傳遞一個(gè)外星人實(shí)例,并在該函數(shù)中調(diào)用方法blitme,就可以讓外星人出現(xiàn)在屏幕上。代碼較多不一一贅述,具體源碼附加在文章最后。
2.2 創(chuàng)建一群外星人
首先在alien——invasion.py中創(chuàng)建一個(gè)空編組aliens,用與存儲(chǔ)全部外星人,在調(diào)用game_functions.py里的函數(shù)來(lái)創(chuàng)建外星人群。接下來(lái)編寫函數(shù)create_fleet(),并將ai_settings、對(duì)象screen和空編組aliens傳遞給它。
def create_alien(ai_settings, screen, aliens, alien_number , row_number):"""創(chuàng)建一個(gè)外星人并將其放在當(dāng)前行"""alien = Alien(ai_settings, screen)alien_width = alien.rect.widthalien.x = alien_width + 2 * alien_width * alien_numberalien.rect.x = alien.xalien.rect.y = alien.rect.height + 2 * alien.rect.height * row_numberaliens.add(alien)create_fleet()函數(shù)主要是計(jì)算一行可以放置多少個(gè)外星人,用int()確保出現(xiàn)的外星人數(shù)量是整數(shù)。在for循環(huán)中,創(chuàng)建一個(gè)新的外星人,并通過(guò)設(shè)置x坐標(biāo)將其加入當(dāng)前行,將每個(gè)外星人都往右推一個(gè)外星人的寬度,將外星人寬度乘于2得到每個(gè)外星人占據(jù)的空間。就可以得到當(dāng)前外星人在當(dāng)前行的位置。最后吧新創(chuàng)建的外星人添加到編組aliens中。
def create_fleet(ai_settings, screen,ship , aliens):"""創(chuàng)建外星人群"""#創(chuàng)建一個(gè)外星人,并計(jì)算一行可以容納多少個(gè)外星人#外星人間距為外星人寬度alien = Alien(ai_settings, screen)number_aliens_x = get_number_aliens_x(ai_settings, alien.rect.width)number_rows = get_number_rows(ai_settings, ship.rect.height,alien.rect.height)#創(chuàng)建外星人群for row_number in range(number_rows):for alien_number in range(number_aliens_x):#創(chuàng)建第一個(gè)外星人并加入當(dāng)前行create_alien(ai_settings, screen, aliens,alien_number, row_number)添加多行外星人與添加一行外星人類似。需要計(jì)算出屏幕可以容納多少行,并循環(huán)相應(yīng)的次數(shù)。計(jì)算公式如:將屏幕高度減去第一行外星人的上邊距(外星人高度)、飛船的高度以及最初外星人群與飛船的距離(外星人高度的兩倍)。將可用垂直空間除以外星人高度的兩倍留出空白區(qū)域,給玩家擊殺的時(shí)間。
def get_number_rows(ai_settings, ship_height, alien_height):"""計(jì)算屏幕可以容納多少行外星人"""available_space_y = (ai_settings.screen_height -(3 * alien_height) - ship_height)number_rows = int(available_space_y / (2 * alien_height))return number_rowsdef get_number_aliens_x(ai_settings, alien_width):"""計(jì)算每行可容納多少個(gè)外星人"""available_space_x = ai_settings.screen_width - 2 * alien_widthnumber_aliens_x = int(available_space_x / (2 * alien_width))return number_aliens_xdef create_alien(ai_settings, screen, aliens, alien_number , row_number):"""創(chuàng)建一個(gè)外星人并將其放在當(dāng)前行"""alien = Alien(ai_settings, screen)alien_width = alien.rect.widthalien.x = alien_width + 2 * alien_width * alien_numberalien.rect.x = alien.xalien.rect.y = alien.rect.height + 2 * alien.rect.height * row_numberaliens.add(alien)1.3讓外星人移動(dòng)
我們讓外星人群在屏幕上向右移動(dòng),撞到屏幕邊緣后下移一定的距離,再沿相反的方向移動(dòng)。外星人將不斷地移動(dòng),直到所有外星人都被消滅。
在setting.py中添加一個(gè)控制外星人速度的設(shè)置
然后在alien.py中添加update()來(lái)控制外星人移動(dòng)。每次更新外星人位置時(shí),外星人向右移動(dòng)。
def update(self):"""向右移動(dòng)外星人"""self.x += (self.ai_settings.alien_speed_factor* self.ai_settings.fleet_direction)self.rect.x = self.x我們需要外星人移動(dòng)到桌面邊緣時(shí)再向反方向移動(dòng)并往下移動(dòng)一行。在setting.py中設(shè)置移動(dòng)速度,fleet_direction為1表示向右移,為-1表示向左移。編寫if-elif語(yǔ)句來(lái)檢查外星人群的移動(dòng)方向。鑒于只有兩個(gè)可能的方向,我們使用值1和-1來(lái)表示它們,并在外星人群改變方向時(shí)在這兩個(gè)值之間切換。
#外星人設(shè)置self.alien_speed_factor = 3self.fleet_drop_speed = 10#+1右移,-1左移self.fleet_direction = 11.4 檢查外星人碰到屏幕邊緣
通過(guò)check_edges()來(lái)檢查外星人碰到屏幕邊緣,如果外星人的rect的right屬性大于或等于屏幕的rect的right屬性,就說(shuō)明外星人位于屏幕右邊緣。如果外星人的rect的left屬性小于或等于0,就說(shuō)明外星人位于屏幕左邊緣。
有外星人到達(dá)屏幕邊緣時(shí),需要將整群外星人下移,并改變它們的移動(dòng)方向。編寫check_fleet_edges()函數(shù),對(duì)其中的每個(gè)外星人調(diào)用check_edges()。如果check_edges()返回True,說(shuō)明該外星人位于屏幕邊緣,需要改變其移動(dòng)方向。change_fleet_direction()用來(lái)使外星人下移,下移的量也可以自己設(shè)置。
二、源代碼
alien.py
import pygame from pygame.sprite import Sprite class Alien(Sprite):"""表示單個(gè)外星人的類"""def __init__(self, ai_settings, screen):"""初始化外星人并設(shè)置其初始位置"""super(Alien, self).__init__()self.screen = screenself.ai_settings = ai_settings#加載外星人圖像,設(shè)置其rect屬性self.image = pygame.image.load('images/alien.bmp')self.rect = self.image.get_rect()#每個(gè)外星人最初都在屏幕左上角附近self.rect.x = self.rect.widthself.rect.y = self.rect.height#存儲(chǔ)外星人的準(zhǔn)確位置self.x = float(self.rect.x)def blitme(self):"""在指定位置繪制外星人"""self.screen.blit(self.image, self.rect)def update(self):"""向右移動(dòng)外星人"""self.x += (self.ai_settings.alien_speed_factor* self.ai_settings.fleet_direction)self.rect.x = self.xdef check_edges(self):"""如果外星人位于屏幕邊緣,就返回True"""screen_rect = self.screen.get_rect()if self.rect.right >= screen_rect.right:return Trueelif self.rect.left <= 0:return Truealien_invation.py
import sys #退出游戲 import pygame #包含開發(fā)所需功能 from settings import Settings from ship import Ship from alien import Alien import game_functions as gf from pygame.sprite import Group from game_stats import GameStates def run_game():# 初始化背景設(shè)置pygame.init()ai_settings = Settings()# 創(chuàng)建游戲窗口screen = pygame.display.set_mode((ai_settings.screen_width, ai_settings.screen_height))pygame.display.set_caption("Alien Invasion")"""創(chuàng)建一艘飛船"""ship = Ship(ai_settings, screen)"""創(chuàng)建一個(gè)外星人"""alien = Alien(ai_settings, screen)"""創(chuàng)建一個(gè)用于存儲(chǔ)子彈的編組"""bullets = Group()aliens = Group()#創(chuàng)建外星人群gf.create_fleet(ai_settings,screen, ship, aliens)"""設(shè)置背景色"""bg_color = (230,230,230)"""存儲(chǔ)游戲統(tǒng)計(jì)信息"""stats = GameStates(ai_settings)"""游戲主循環(huán)"""while True:"""監(jiān)視鍵鼠事件"""gf.check_events(ai_settings, screen, ship, bullets)if stats.game_active:ship.update()#print(len(bullets))gf.update_bullets(ai_settings, screen, ship, aliens, bullets)gf.update_aliens(ai_settings, stats, screen, ship, aliens, bullets)gf.update_screen(ai_settings, screen, ship, aliens, bullets)run_game()game_functions.py
import sys import pygame from bullet import Bullet from alien import Alien from time import sleepdef check_events(ai_settings, screen, ship, bullets):#鍵鼠響應(yīng)for event in pygame.event.get():if event.type == pygame.QUIT:sys.exit()elif event.type == pygame.KEYDOWN:check_keydown_events(event, ai_settings, screen, ship, bullets)elif event.type == pygame.KEYUP:check_keyup_events(event, ship) def check_keydown_events(event, ai_settings, screen, ship, bullets):"""響應(yīng)按鍵"""if event.key == pygame.K_RIGHT:# 向右移動(dòng)飛船ship.moving_right = Trueelif event.key == pygame.K_LEFT:ship.moving_left = Trueelif event.key == pygame.K_SPACE:fire_bullet(ai_settings, screen, ship, bullets)elif event.key == pygame.K_q:sys.exit()def check_keyup_events(event, ship):if event.key == pygame.K_RIGHT:ship.moving_right = Falseelif event.key == pygame.K_LEFT:ship.moving_left = Falsedef update_screen(ai_settings, screen, ship, aliens, bullets):#更新屏幕圖像# 每次循環(huán)時(shí)都重繪屏幕screen.fill(ai_settings.bg_color)#在飛船和外星人后面重繪所有子彈for bullets in bullets.sprites():bullets.draw_bullet()ship.blitme()aliens.draw(screen)# 讓最近繪制的屏幕可見pygame.display.flip() # 不斷更新屏幕def check_bullet_alien_collisions(ai_settings, screen,ship, aliens, bullets):#檢查是否有子彈擊中了外星人#若擊中,刪除相應(yīng)的子彈和外星人collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)if len(aliens) == 0:#刪除現(xiàn)有的子彈并新建一群外星人bullets.empty()create_fleet(ai_settings, screen, ship, aliens)def update_bullets(ai_settings, screen, ship, aliens, bullets):"""更新子彈的位置,刪除已消失的子彈"""#更新子彈位置bullets.update()# 刪除已經(jīng)消失的子彈for bullet in bullets.copy():if bullet.rect.bottom <= 0:bullets.remove(bullet)check_bullet_alien_collisions(ai_settings, screen,ship, aliens, bullets)def fire_bullet(ai_settings, screen, ship, bullets):"""如果還沒(méi)有達(dá)到限制,就發(fā)射一顆子彈"""# 創(chuàng)建一顆子彈,并將其加入到編組bulletsif len(bullets) < ai_settings.bullets_allowed:new_bullet = Bullet(ai_settings, screen, ship)bullets.add(new_bullet)def create_fleet(ai_settings, screen,ship , aliens):"""創(chuàng)建外星人群"""#創(chuàng)建一個(gè)外星人,并計(jì)算一行可以容納多少個(gè)外星人#外星人間距為外星人寬度alien = Alien(ai_settings, screen)number_aliens_x = get_number_aliens_x(ai_settings, alien.rect.width)number_rows = get_number_rows(ai_settings, ship.rect.height,alien.rect.height)#創(chuàng)建外星人群for row_number in range(number_rows):for alien_number in range(number_aliens_x):#創(chuàng)建第一個(gè)外星人并加入當(dāng)前行create_alien(ai_settings, screen, aliens,alien_number, row_number)def get_number_aliens_x(ai_settings, alien_width):"""計(jì)算每行可容納多少個(gè)外星人"""available_space_x = ai_settings.screen_width - 2 * alien_widthnumber_aliens_x = int(available_space_x / (2 * alien_width))return number_aliens_xdef create_alien(ai_settings, screen, aliens, alien_number , row_number):"""創(chuàng)建一個(gè)外星人并將其放在當(dāng)前行"""alien = Alien(ai_settings, screen)alien_width = alien.rect.widthalien.x = alien_width + 2 * alien_width * alien_numberalien.rect.x = alien.xalien.rect.y = alien.rect.height + 2 * alien.rect.height * row_numberaliens.add(alien)def get_number_rows(ai_settings, ship_height, alien_height):"""計(jì)算屏幕可以容納多少行外星人"""available_space_y = (ai_settings.screen_height -(3 * alien_height) - ship_height)number_rows = int(available_space_y / (2 * alien_height))return number_rowsdef check_fleet_edges(ai_settings, aliens):"""外星人到達(dá)邊緣時(shí)采取相應(yīng)的措施"""for alien in aliens.sprites():if alien.check_edges():change_fleet_direction(ai_settings, aliens)breakdef change_fleet_direction(ai_setting, aliens):"""將整群外星人下移,并改變他們的方向"""for alien in aliens.sprites():alien.rect.y += ai_setting.fleet_drop_speedai_setting.fleet_direction *= -1def update_aliens(ai_settings, stats, screen, ship, aliens, bullets):"""檢查是否有外星人位于屏幕邊緣,并更新整群外星人的位置"""check_fleet_edges(ai_settings, aliens)aliens.update()#檢測(cè)外星人和飛船之間的碰撞if pygame.sprite.spritecollideany(ship, aliens):ship_hit(ai_settings, stats, screen, ship, aliens, bullets)""""檢查是否到達(dá)地端"""check_aliens_bottom(ai_settings, stats, screen, ship,aliens, bullets)def ship_hit(ai_settings, stats, screen, ship, aliens, bullets):"""響應(yīng)被外星人撞到的飛船"""if stats.ships_left > 0:#將ships_left減1stats.ships_left -= 1#清空外星人列表和子彈列表aliens.empty()bullets.empty()#創(chuàng)建新的外星人create_fleet(ai_settings, screen, ship, aliens)ship.center_ship()#暫停sleep(0.5)else:stats.game_active = Falsedef check_aliens_bottom(ai_settings, stats, screen, ship, aliens, bullets):"""檢查是否有外星人到達(dá)"""screen_rect = screen.get_rect()for alien in aliens.sprites():if alien.rect.bottom >= screen_rect.bottom:#像飛船被撞到一樣進(jìn)行處理ship_hit(ai_settings, stats, screen, ship, aliens, bullets)breaksetting.py
class Settings():#用于存儲(chǔ)該項(xiàng)目設(shè)置的所有的類def __init__(self):#初始化設(shè)置#屏幕設(shè)置self.screen_width = 1200self.screen_height = 800self.bg_color = (230,230,230)#飛船設(shè)置self.ship_speed_factor = 1.5self.ship_limit = 1#子彈設(shè)置self.bullet_speed_factor = 1self.bullet_width = 3self.bullet_height = 15self.bullet_color = (60,60,60)self.bullets_allowed = 3#外星人設(shè)置self.alien_speed_factor = 3self.fleet_drop_speed = 10#+1右移,-1左移self.fleet_direction = 1ship.py
import pygame class Ship():def __init__(self, ai_settings, screen):"""初始化飛船并設(shè)置其初始位置"""self.screen = screenself.ai_settings = ai_settings"""加在飛船圖像并獲取其外接矩形"""self.image = pygame.image.load('images/ship.bmp')self.rect = self.image.get_rect()self.screen_rect = screen.get_rect()"""將每艘新飛船放在屏幕底部中央"""self.rect.centerx = self.screen_rect.centerxself.rect.bottom = self.screen_rect.bottom"""在飛船的屬性center中存儲(chǔ)最小數(shù)值"""self.center = float(self.rect.centerx)"""#移動(dòng)標(biāo)志"""self.moving_right = Falseself.moving_left = Falsedef update(self):"""根據(jù)移動(dòng)標(biāo)志調(diào)整飛船的位置"""#更新飛船的center值,而不是rectif self.moving_right and self.rect.right < self.screen_rect.right:self.center += self.ai_settings.ship_speed_factorif self.moving_left and self.rect.left > 0:self.center -= self.ai_settings.ship_speed_factor#根據(jù)self.center更新rect對(duì)象self.rect.centerx = self.centerdef blitme(self):"""在指定位置繪制飛船"""self.screen.blit(self.image, self.rect)def center_ship(self):"""讓飛船在屏幕上居中"""self.center = self.screen_rect.centerx三、實(shí)現(xiàn)效果
總結(jié)
以上是生活随笔為你收集整理的基于pygame的射击小游戏制作(三)让外星人动起来的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: JAVA分布式篇1——Linux
- 下一篇: 分页插件PageHelper的使用方法