Python小游戲:外星人入侵!源碼奉上!!

首先看運(yùn)行之后的截圖

當(dāng)三艘飛船用光后,結(jié)束游戲
再次點(diǎn)擊“Play”按鈕,再次開(kāi)始
下面上代碼!
alien_invasion.py:
"""該游戲主程序,盡量做到最簡(jiǎn)單"""import pygamefrom settings import Settingsfrom ship import Shipfrom pygame.sprite import Groupfrom game_stats import GameStatsfrom button import Buttonfrom score_board import Scoreboardimport game_function as gfdef run_game():"""初始化背景設(shè)置"""pygame.init()""""創(chuàng)建一個(gè)Settings實(shí)例"""ai_settings=Settings()"""創(chuàng)建一個(gè)游戲窗口以及標(biāo)題"""screen=pygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height))pygame.display.set_caption('Alien Invasion')"""創(chuàng)建一艘飛船實(shí)例"""ship=Ship(ai_settings,screen)"""創(chuàng)建一個(gè)用于存儲(chǔ)子彈和外星人的編組"""bullets=Group()aliens=Group()"""創(chuàng)建外星人群"""gf.creat_fleet(ai_settings,screen,ship,aliens)"""創(chuàng)建存儲(chǔ)游戲統(tǒng)計(jì)信息的實(shí)例,并創(chuàng)建記分牌"""stats = GameStats(ai_settings)sb = Scoreboard(ai_settings,screen,stats)#創(chuàng)建play按鈕play_button = Button(ai_settings,screen,"Play")"""進(jìn)入主循環(huán)"""while True:""""監(jiān)視用戶(hù)的操作,鍵盤(pán)和鼠標(biāo)"""gf.check_events(ai_settings,screen,ship,aliens,bullets,stats,play_button,sb)if stats.game_active:"""更新飛船"""ship.update()"""更新子彈"""gf.update_bullet(ai_settings,screen,ship,aliens,bullets,stats,sb)"""更新外星人"""gf.update_aliens(ai_settings,screen,ship,aliens,stats,bullets,sb)"""刷新屏幕"""gf.update_screen(ai_settings,screen,ship,aliens,bullets,stats,play_button,sb)run_game()
如果把這個(gè)游戲比作一個(gè)人,那么上一段代碼是剛接觸這個(gè)人,他給你留下的第一印象,那么下面這段代碼可以說(shuō)是這個(gè)人的靈魂了
import sysimport pygamefrom random import randintfrom bullet import Bulletfrom alien import Alienfrom time import sleepdef fire_bullet(ai_settings,screen,ship,bullets,stats):"""開(kāi)火!"""#確保屏幕上的子彈數(shù)在限制范圍內(nèi)for i in range(int(stats.level/5) + 1):if len(bullets) < ai_settings.bullet_allowed:new_bullet=Bullet(ai_settings,screen,ship)bullets.add(new_bullet)def check_keydown(event,ai_settings,screen,ship,bullets,stats):"""檢查用戶(hù)按鍵是否按下以及執(zhí)行的任務(wù)"""if event.key == pygame.K_RIGHT:ship.moving_right=Trueelif event.key == pygame.K_LEFT:ship.moving_left=Trueelif event.key == pygame.K_UP:ship.moving_up=Trueelif event.key == pygame.K_DOWN:ship.moving_down=Trueelif event.key == pygame.K_SPACE:#發(fā)射一顆子彈,并且在限制范圍內(nèi)fire_bullet(ai_settings,screen,ship,bullets,stats)def check_keyup(event,ship):"""檢查用戶(hù)釋放按鍵"""if event.key == pygame.K_RIGHT:ship.moving_right=Falseelif event.key == pygame.K_LEFT:ship.moving_left=Falseelif event.key == pygame.K_UP:ship.moving_up=Falseelif event.key == pygame.K_DOWN:ship.moving_down=False????
def check_events(ai_settings,screen,ship,aliens,bullets,stats,play_button,sb):"""響應(yīng)鍵盤(pán)和鼠標(biāo)事件"""for event in pygame.event.get():if event.type == pygame.K_q:sys.exit()#如果一直按下右鍵或者左鍵,空格鍵,則向右或右移動(dòng)或者開(kāi)火elif event.type == pygame.KEYDOWN:check_keydown(event,ai_settings,screen,ship,bullets,stats)#釋放右鍵或左鍵,停止移動(dòng)elif event.type == pygame.KEYUP:check_keyup(event,ship)#點(diǎn)擊Play按鈕,開(kāi)始游戲elif event.type == pygame.MOUSEBUTTONDOWN:mouse_x,mouse_y = pygame.mouse.get_pos()check_play_button(ai_settings,screen,ship,aliens,bullets,stats,play_button,mouse_x,mouse_y,sb)def check_play_button(ai_settings,screen,ship,aliens,bullets,stats,play_button,mouse_x,mouse_y,sb):"""在玩家單擊Play按鈕時(shí)開(kāi)始游戲"""button_clicked = play_button.rect.collidepoint(mouse_x,mouse_y)if button_clicked and not stats.game_active:#重置游戲設(shè)置ai_settings.init_dynamic_settings()#隱藏光標(biāo)pygame.mouse.set_visible(False)#重置游戲統(tǒng)計(jì)信息stats.reset_stats()stats.game_active = True#重置記分牌圖像sb.prep_score()sb.prep_high_score(screen)sb.prep_level()sb.prep_ships(screen)#清空外星人和子彈列表aliens.empty()bullets.empty()#創(chuàng)建一群新的外星人,并讓飛船居中creat_fleet(ai_settings,screen,ship,aliens)ship.center_ship(ai_settings)def update_screen(ai_settings,screen,ship,aliens,bullets,stats,play_button,sb):"""每次循環(huán)都重繪屏幕"""screen.fill(ai_settings.bg_color)for bullet in bullets.sprites():bullet.draw_bullet()ship.blitme()aliens.draw(screen)sb.show_score()#如果游戲處于非活動(dòng)狀態(tài),繪制Play按鈕if not stats.game_active:play_button.draw_button()""""刷新屏幕,擦去舊屏幕,顯示新屏幕"""pygame.display.flip()
def update_bullet(ai_settings,screen,ship,aliens,bullets,stats,sb):"""更新子彈位置,并刪除已經(jīng)消失的子彈"""#更新子彈位置bullets.update()#刪除消失的子彈for bullet in bullets.copy():if bullet.rect.bottom<=0:bullets.remove(bullet)#檢查是否有子彈擊中外星人check_bullet_alien_colide(ai_settings,screen,ship,aliens,bullets,stats,sb)def get_number_aliens_x(ai_settings,alien_width):"""獲得水平方向上外星人個(gè)數(shù)"""available_space_x = ai_settings.screen_width-2 * alien_widthnumber_aliens_x = int(available_space_x/(2 * alien_width))return number_aliens_xdef get_space_rows(ai_settings,ship_height,alien_height):"""獲得垂直方向上外星人的行數(shù)"""available_space_y = (ai_settings.screen_height-(3 * alien_height)-ship_height)number_aliens_rows = int(available_space_y/(2 * alien_height))return number_aliens_rowsdef creat_alien(ai_settings,screen,aliens,alien_number,row_number):"""根據(jù)傳入的數(shù)據(jù)在某個(gè)位置創(chuàng)建一個(gè)外星人"""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 +20) + 2 * alien.rect.height * row_numberaliens.add(alien)def creat_random_alien_x(number_aliens_x,ai_settings,screen,aliens,row_number):"""在第一行隨機(jī)創(chuàng)建若干個(gè)外星人"""for i in range(2,number_aliens_x+2):random_number_x=randint(2,i)for alien_number in range(random_number_x - 1,random_number_x):creat_alien(ai_settings,screen,aliens,alien_number,row_number)?????????????????????
def creat_fleet(ai_settings,screen,ship,aliens):"""創(chuàng)建外星人群以及獲取屏幕上最大的行數(shù)和每行最多個(gè)數(shù)"""alien=Alien(ai_settings,screen)number_aliens_x = get_number_aliens_x(ai_settings,alien.rect.width)number_rows = get_space_rows(ai_settings,ship.rect.height,alien.rect.height)"""隨機(jī)創(chuàng)建行數(shù)"""for j in range(0,number_rows):random_number_y = randint(0,j)for row_number in range(random_number_y):creat_random_alien_x(number_aliens_x,ai_settings,screen,aliens,row_number)def check_fleet_edges(ai_settings,aliens):"""有外星人到達(dá)屏幕邊緣"""for alien in aliens.sprites():if alien.check_edges():change_fleet_direction(ai_settings,aliens)breakdef change_fleet_direction(ai_settings,aliens):"""將外星人下移,并改變它們的方向"""for alien in aliens.sprites():alien.rect.y += ai_settings.fleet_drop_speedai_settings.fleet_direction *= -1def update_aliens(ai_settings,screen,ship,aliens,stats,bullets,sb):"""檢測(cè)有外星人位于屏幕邊緣或者相撞或者外星人到達(dá)底部,更新外星人的位置"""check_fleet_edges(ai_settings,aliens)aliens.update()#檢測(cè)飛船與外星人的撞擊if pygame.sprite.spritecollideany(ship,aliens):ship_hit(ai_settings,screen,ship,aliens,stats,bullets,sb)#檢查是否有外星人到達(dá)屏幕底部check_aliens_bottom(ai_settings,screen,ship,aliens,stats,bullets,sb)def check_bullet_alien_colide(ai_settings,screen,ship,aliens,bullets,stats,sb):"""檢測(cè)子彈和外星人的碰撞"""collisions = pygame.sprite.groupcollide(bullets,aliens,True,True)#兩個(gè)True可使得子彈與外星人碰撞后消失,并返回一個(gè)字典#碰撞之后加分if collisions:for aliens in collisions.values():i = randint(0,10)if i>8:stats.score += (ai_settings.alien_points + 10) * len(aliens)sb.prep_score()else:stats.score += ai_settings.alien_points * len(aliens)sb.prep_score()#檢查是否刷新最高分check_high_score(stats,sb,screen)if len(aliens) == 0:#刪除現(xiàn)有的子彈,加快游戲速度,創(chuàng)建新的外星人ship.center_ship(ai_settings)bullets.empty()ai_settings.increase_speed()#提高等級(jí)stats.level += 1ai_settings.increase_bullet_size()sb.prep_level()creat_fleet(ai_settings,screen,ship,aliens)
def ship_hit(ai_settings,screen,ship,aliens,stats,bullets,sb):"""飛船與外星人相撞,生命減1,清除外星人和子彈列表并創(chuàng)建新的外星人,飛船放在屏幕底部中央位置"""if stats.ship_left > 0:stats.ship_left -= 1sb.prep_ships(screen)#清空外星人和子彈列表aliens.empty()bullets.empty()#新建一個(gè)飛船和外星人群creat_fleet(ai_settings,screen,ship,aliens)ship.center_ship(ai_settings)#暫停0.5秒sleep(0.5)else:ai_settings.bullet_width = 3stats.game_active = Falsepygame.mouse.set_visible(True)def check_aliens_bottom(ai_settings,screen,ship,aliens,stats,bullets,sb):"""檢查是否有外星人到達(dá)底部"""screen_rect = screen.get_rect()for alien in aliens.sprites():if alien.rect.bottom >= screen_rect.bottom:ship_hit(ai_settings,screen,ship,aliens,stats,bullets,sb)breakdef check_high_score(stats,sb,screen):"""檢查是否產(chǎn)生了新的最高分"""if stats.score > stats.high_score:stats.high_score = stats.scoresb.prep_high_score(screen)
后面的文件基本是作為分支吧,一些屬性還有一些初始化的數(shù)據(jù),都是為game_function文件提供資源的
settings.py:
class Settings():def __init__(self):"""設(shè)置長(zhǎng)度和寬度以及背景色屬性"""self.screen_width = 800self.screen_height = 700self.bg_color=(255,255,255)self.ship_limit = 2"""子彈設(shè)置"""self.bullet_width = 3self.bullet_height=15self.bullet_color=(60,60,60)self.bullet_allowed=8"""外星人移動(dòng)設(shè)置"""self.fleet_drop_speed = 10"""以什么樣的速度加快游戲節(jié)奏"""self.speed_up_scale = 1.1self.init_dynamic_settings()"""外星人點(diǎn)數(shù)的提高"""self.score_scale = 1.5"""子彈大小提高"""self.bullet_scale = 10def init_dynamic_settings(self):self.speed = 1.5self.bullet_speed = 3self.alien_speed = 0.2#fleet_direction為1表示向右移動(dòng),-1表示向左移動(dòng)self.fleet_direction = -1#計(jì)分self.alien_points = 10def increase_speed(self):"""提高速度設(shè)置和外星人點(diǎn)數(shù)設(shè)置"""self.speed *= self.speed_up_scaleself.bullet_speed *= self.speed_up_scaleself.alien_speed *= self.speed_up_scaleself.alien_points = int(self.alien_points * self.score_scale)def increase_bullet_size(self):??????????????self.bullet_width?+=?self.bullet_scale
ship.py:
import pygamefrom pygame.sprite import Spriteclass Ship(Sprite):def __init__(self,ai_settings,screen):"""初始化飛船并設(shè)置其初始位置"""super(Ship,self).__init__()self.screen=screen#加載飛船圖像并獲取其外接矩形self.image=pygame.image.load('images/ship.bmp')self.rect=self.image.get_rect()#獲取飛船的矩形self.screen_rect=screen.get_rect()#獲取屏幕矩形self.ai_settings=ai_settings#將每艘新飛船放在屏幕底部中央位置self.rect.centerx=self.screen_rect.centerxself.rect.centery=self.screen_rect.centeryself.rect.bottom=self.screen_rect.bottomself.center_x=float(self.rect.centerx)self.center_y=float(self.rect.centery)"""連續(xù)檢測(cè)按鍵,設(shè)置未按下右鍵為False"""self.moving_right=Falseself.moving_left=Falseself.moving_up=Falseself.moving_down=Falsedef update(self):"""如果連續(xù)按方向鍵,則一直移動(dòng),并且不超過(guò)邊界"""if self.moving_right and self.rect.right < self.screen_rect.right:self.center_x+=self.ai_settings.speed#使用兩個(gè)if,這樣玩家同時(shí)按下兩個(gè)鍵,#將先增大rect.centerx值,再降低,則飛船位置不變if self.moving_left and self.rect.left > 0:self.center_x-=self.ai_settings.speedif self.moving_up and self.rect.top > 0:self.center_y-=self.ai_settings.speedif self.moving_down and self.rect.bottom < self.screen_rect.bottom:self.center_y+=self.ai_settings.speedself.rect.centerx=self.center_xself.rect.centery=self.center_y"""在指定位置繪制飛船"""def blitme(self):self.screen.blit(self.image,self.rect)def center_ship(self,ai_settings):self.center_x = ai_settings.screen_width/2??????????????self.center_y?=?ai_settings.screen_height?-?28
alien.py:
import pygamefrom pygame.sprite import Spriteclass Alien(Sprite):def __init__(self,ai_settings,screen):super().__init__()"""初始化外星人并設(shè)置其初始位置"""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 check_edges(self):"""如果外星人碰到屏幕邊緣,則返回True"""screen_rect = self.screen.get_rect()if self.rect.right >= screen_rect.right:return Trueelif self.rect.left <= 0:return Truedef update(self):"""移動(dòng)外星人"""self.x += (self.ai_settings.alien_speed *(self.ai_settings.fleet_direction))self.rect.x=self.xdef blitme(self):"""在指定位置繪制飛船"""??????????????self.screen.blit(self.image,self.rect)
bullet.py:
import pygamefrom pygame.sprite import Spriteclass Bullet(Sprite):def __init__(self,ai_settings,screen,ship):#在飛船位置創(chuàng)建一個(gè)子彈對(duì)象super(Bullet,self).__init__()self.screen=screenself.rect=pygame.Rect(0,0,ai_settings.bullet_width,ai_settings.bullet_height)self.rect.centerx = ship.rect.centerxself.rect.top = ship.rect.topself.y=float(self.rect.y)self.color=ai_settings.bullet_colorself.speed=ai_settings.bullet_speeddef update(self):"""向上移動(dòng)子彈"""#更新子彈的小數(shù)值self.y -= self.speedself.rect.y=self.ydef draw_bullet(self):"""在屏幕上繪制子彈"""??????????????pygame.draw.rect(self.screen,self.color,self.rect)
button.py:
import pygame.fontclass Button():def __init__(self,ai_settings,screen,msg):"""初始化按鈕屬性"""self.screen = screenself.screen_rect = screen.get_rect()#設(shè)置按鈕大小以及其他屬性self.width,self.height = 200,50self.button_color = (0, 255, 0)self.text_color = (60,60,60)self.font = pygame.font.SysFont(None,48)#創(chuàng)建按鈕的rect對(duì)象,并使其居中self.rect = pygame.Rect(0, 0, self.width, self.height)self.rect.center = self.screen_rect.center#按鈕的標(biāo)簽只需要?jiǎng)?chuàng)建一次self.prep_msg(msg)def prep_msg(self,msg):"""將msg渲染為圖像,并使其在按鈕上居中"""self.msg_image = self.font.render(msg,True,self.text_color,self.button_color)self.msg_image_rect = self.msg_image.get_rect()self.msg_image_rect.center = self.rect.centerdef draw_button(self):#繪制一個(gè)用顏色填充的按鈕,再繪制文本self.screen.fill(self.button_color,self.rect)??????????????self.screen.blit(self.msg_image,self.msg_image_rect)
game_stats.py:
class GameStats():"""跟蹤游戲的統(tǒng)計(jì)信息"""def __init__(self,ai_settings):self.ai_settings = ai_settingsself.game_active = Falseself.reset_stats()#任何情況下都不能重置最高分self.high_score = 0def reset_stats(self):"""初始化在游戲運(yùn)行過(guò)程中可能變化的統(tǒng)計(jì)信息"""self.ship_left = self.ai_settings.ship_limitself.score = 0self.level = 1??????????????self.bullet_width?=?3
scord_board.py:
import pygame.fontfrom pygame.sprite import Groupfrom ship import Shipclass Scoreboard():"""顯示得分的類(lèi)"""def __init__(self,ai_settings,screen,stats):"""初始化顯示得分的屬性"""self.screen = screenself.screen_rect = screen.get_rect()self.ai_settings = ai_settingsself.stats = stats#顯示得分時(shí)的字體設(shè)置self.text_color = (30,30,30)self.font = pygame.font.SysFont(None,48)#準(zhǔn)備初始得分圖像以及當(dāng)前最高得分self.prep_score()self.prep_high_score(screen)self.prep_level()self.prep_ships(screen)def prep_score(self):"""將得分轉(zhuǎn)化為可渲染的圖像"""rounded_score = int(round(self.stats.score,-1))score_str ="Score:"+"{:,}".format(rounded_score)self.score_image = self.font.render(score_str,True,self.text_color,self.ai_settings.bg_color)#將得分放在屏幕右上角self.score_rect = self.score_image.get_rect()self.score_rect.right = self.screen_rect.right - 20self.score_rect.top = 20def prep_high_score(self,screen):"""將最高得分渲染為圖片"""high_score = int(round(self.stats.high_score,-1))high_score_str = "High Score:"+"{:,}".format(high_score)self.high_score_image = self.font.render(high_score_str,True,self.text_color,self.ai_settings.bg_color)"""將最高得分放在屏幕左上角"""self.high_score_rect = self.high_score_image.get_rect()self.high_score_rect.left = self.screen_rect.left + 20self.high_score_rect.top = 20def prep_level(self):"""將等級(jí)渲染為圖像"""self.level_image = self.font.render("Level:"+str(self.stats.level),True,self.text_color,self.ai_settings.bg_color)#將等級(jí)放在右下角self.level_rect = self.level_image.get_rect()self.level_rect.right = self.score_rect.rightself.level_rect.bottom = self.score_rect.bottom + 650def show_score(self):"""在屏幕上顯示得分,最高分,等級(jí)"""self.screen.blit(self.score_image,self.score_rect)self.screen.blit(self.high_score_image,self.high_score_rect)self.screen.blit(self.level_image,self.level_rect)#繪制剩余飛船self.ships.draw(self.screen)def prep_ships(self,screen):"""顯示剩余的飛機(jī)"""self.ships = Group()for ship_number in range(self.stats.ship_left + 1):ship =Ship(self.ai_settings,self.screen)ship.rect.x = 10 + ship_number * ship.rect.widthship.rect.y = self.screen_rect.top + 640?????????????????????self.ships.add(ship)
文章轉(zhuǎn)載:Python編程學(xué)習(xí)圈
(版權(quán)歸原作者所有,侵刪)

評(píng)論
圖片
表情
