飛船大戰(zhàn)UFO

ShipVSUFO

由python寫的一個(gè)小游戲拗引,飛船大戰(zhàn)外星人又谋。實(shí)現(xiàn)了能夠闖關(guān)打分?jǐn)?shù)的經(jīng)典飛機(jī)射擊游戲。玩法是玩家需要將ufo全部擊落个扰,獲得更多的分?jǐn)?shù),否則將會(huì)被逼近的ufo撞擊而被迫結(jié)束游戲葱色。

一递宅,分析

  1. 對(duì)象
    飛船(ship),UFO(Alien)冬筒, 子彈(bullet)恐锣, 顯示分?jǐn)?shù)與關(guān)卡的面板(scoreboard)茅主, 用于開始游戲的按鈕(button)舞痰。
  2. 功能
    基本參數(shù)設(shè)置(settings),游戲狀況(game_status)诀姚,主函數(shù)(alien_invasion)以及主函數(shù)的函數(shù)(game_function)

二响牛,編碼實(shí)現(xiàn)

  1. 主函數(shù)(alien_invasion)
import sys
import pygame
from settings import Settings
from ship import Ship
from pygame.sprite import Group
import game_functions as gf
from alien import Alien
from game_status import GameStatus
from button import Button
from scoreboard import Scoreboard
def run_game():
        pygame.init() ###初始化
        ai_settings = Settings() ###設(shè)置類
        screen = pygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height))  ###屏幕顯示
        ship = Ship(ai_settings,screen) ###飛船
        pygame.display.set_caption("飛船大戰(zhàn)UFO") ###標(biāo)題
        play_button = Button(ai_settings,screen,"Start Game") ###開始按鈕
        bullets = Group() ###子彈組
        aliens = Group() ###外星人組
        gf.create_fleet(ai_settings,ship,screen,aliens) ##創(chuàng)建外星人艦隊(duì)
        status = GameStatus(ai_settings) ###游戲狀態(tài)
        sb = Scoreboard(ai_settings,screen,status) ###分?jǐn)?shù)板顯示分?jǐn)?shù)與關(guān)卡
        while True:
                gf.check_events(ai_settings,screen,ship,bullets,status,play_button,aliens)###事件監(jiān)聽
                if status.game_active:  ###若是游戲中
                        ship.update() ###飛船狀態(tài)更新
                        gf.update_bullet(ai_settings,ship,screen,aliens,bullets,sb,status)### 子彈狀態(tài)更新
                        gf.update_aliens(ai_settings,status,screen,ship,aliens,bullets)### 外星人更新
                gf.update_screen(ai_settings,screen,ship,bullets,aliens,play_button,status,sb) ###屏幕更新重繪
                
run_game()

  1. 主函數(shù)中抽離的函數(shù)game_function:
import sys
import pygame
from bullet import Bullet
from alien import Alien
from time import sleep
def check_keydown_events(event,ai_settings,screen,ship,bullets):###監(jiān)測(cè)按鈕按下
    if event.key == pygame.K_RIGHT:
        ship.moving_right = True
    elif event.key == pygame.K_LEFT:
        ship.moving_left = True
    elif event.key == pygame.K_UP:
        ship.moving_up = True
    elif event.key == pygame.K_DOWN:
        ship.moving_down = True
    elif event.key == pygame.K_SPACE:
        new_bullet = Bullet(ai_settings,screen,ship)
        bullets.add(new_bullet)
    elif event.key == pygame.K_z:
        sys.exit()
    elif event.key == pygame.K_q:
        ai_settings.bullet_width = 1000
    elif event.key == pygame.K_w:
        ai_settings.alien_speed_factor = 1
    elif event.key == pygame.K_e:
        ai_settings.alien_points = 500
def check_keyup_events(event,ai_settings,screen,ship,bullets):###監(jiān)測(cè)按鈕松開
    if event.key == pygame.K_RIGHT:
        ship.moving_right = False
    elif event.key == pygame.K_LEFT:
        ship.moving_left = False    
    elif event.key == pygame.K_UP:
        ship.moving_up = False
    elif event.key == pygame.K_DOWN:
        ship.moving_down = False
def check_events(ai_settings,screen,ship,bullets,status,play_button,aliens):###監(jiān)聽各種事件
    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,ai_settings,screen,ship,bullets)
        elif event.type == pygame.MOUSEBUTTONDOWN:
            mouse_x,mouse_y = pygame.mouse.get_pos()
            check_play_button(status,play_button,mouse_x,mouse_y,aliens,bullets,ship,ai_settings,screen)
def check_play_button(status,play_button,mouse_x,mouse_y,aliens,bullets,ship,ai_settings,screen):###監(jiān)聽開始按鍵
    if play_button.rect.collidepoint(mouse_x,mouse_y) and not status.game_active:
        ai_settings.initialize_dynamic_settings()
        pygame.mouse.set_visible(False)
        status.reset_status()
        status.game_active = True
        status.level = 1
        status.score = 0
        aliens.empty()
        bullets.empty()
        create_fleet(ai_settings,ship,screen,aliens)
        ship.center_ship()   
def update_screen(ai_settings,screen,ship,bullets,aliens,play_button,status,sb):###屏幕的一切重繪,保證動(dòng)態(tài)性
    screen.fill(ai_settings.bg_color)
    for bullet in bullets.sprites():
        bullet.draw_bullet()
    ship.blitme()
    sb.show_score()
    sb.show_level()
    aliens.draw(screen)
    if not status.game_active:
        play_button.draw_button()
    pygame.display.flip() ###重繪顯示
def update_bullet(ai_settings,ship,screen,aliens,bullets,sb,status): ###
        bullets.update()
        for bullet in bullets.copy():
            if bullet.rect.bottom <= 0:###子彈到頭了赫段,就刪掉
                bullets.remove(bullet)
        check_bullet_alien_collisions(ai_settings,ship,screen,aliens,bullets,sb,status)
def check_bullet_alien_collisions(ai_settings,ship,screen,aliens,bullets,sb,status):###監(jiān)聽子彈與UFO碰撞
    collisions = pygame.sprite.groupcollide(bullets,aliens,True,True)
    if collisions:###發(fā)生碰撞呀打,一起消失
        for aliens in collisions.values():                
            status.score += ai_settings.alien_points*len(aliens)
            sb.prep_score()
    if len(aliens)==0:###外星人為空,就重置游戲糯笙,并升級(jí)難度
        bullets.empty()
        ai_settings.increase_speed()
        status.level += 1
        sb.prep_level()
        create_fleet(ai_settings,ship,screen,aliens)
def get_number_aliens_x(ai_settings,alien_width):###根據(jù)屏幕計(jì)算外星人數(shù)量
    available_space_x = ai_settings.screen_width-2 * alien_width
    number_aliens_x = int(available_space_x / (2 * alien_width))
    return number_aliens_x
def create_alien(ai_settings,screen,aliens,alien_number,row_number):###創(chuàng)建外星人贬丛,初始化參數(shù),并添加至艦隊(duì)
    alien = Alien(ai_settings,screen)
    alien_width = alien.rect.width
    alien.x = alien_width + 2*alien_width*alien_number
    alien.rect.x = alien.x
    alien.rect.y = alien.rect.height + 2*alien.rect.height*row_number
    aliens.add(alien)
def create_fleet(ai_settings,ship,screen,aliens):###創(chuàng)建艦隊(duì)
    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)
    for row_number in range(number_rows):
        for alien_number in range(number_aliens_x):
            create_alien(ai_settings,screen,aliens,alien_number,row_number)
def update_aliens(ai_settings,status,screen,ship,aliens,bullets):
    check_fleet_edges(ai_settings, aliens)
    aliens.update()
    if pygame.sprite.spritecollideany(ship,aliens):
        ship_hit(ai_settings,status,screen,ship,aliens,bullets)
    check_aliens_bottom(ai_settings,status,screen,ship,aliens,bullets)
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_rows
def check_fleet_edges(ai_settings,aliens):
    for alien in aliens.sprites():###監(jiān)測(cè)艦隊(duì)是否移動(dòng)到屏幕的邊境
        if alien.check_edges():
            change_fleet_direction(ai_settings,aliens)
            break
def change_fleet_direction(ai_settings,aliens):###改變艦隊(duì)方向
    for alien in aliens.sprites():
        alien.rect.y += ai_settings.fleet_drop_speed
    ai_settings.fleet_direction *= -1
def ship_hit(ai_settings,status,screen,ship,aliens,bullets):###飛船被撞擊后
    if status.ships_left > 1:###生命還有
        status.ships_left -= 1
        aliens.empty()
        bullets.empty()

        create_fleet(ai_settings,ship,screen,aliens)
        ship.center_ship()
        sleep(0.5)
    else: ###沒有生命了
        status.game_active = False 
        pygame.mouse.set_visible(True)
def check_aliens_bottom(ai_settings,status,screen,ship,aliens,bullets): ##監(jiān)聽外星UFO是否突破防線
    screen_rect = screen.get_rect()
    for alien in aliens.sprites():
        if alien.rect.bottom >= screen_rect.bottom:###到達(dá)底部
            ship_hit(ai_settings,status,screen,ship,aliens,bullets)
            break
  1. 飛船類:
import pygame
class Ship():

    def __init__(self,ai_settings,screen):###初始化
        self.screen = screen
        self.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.centerx ###中心x與屏幕中心x一致
        self.rect.bottom = self.screen_rect.bottom ### 底下與屏幕底下一致
        ### 移動(dòng)狀態(tài)
        self.moving_right = False 
        self.moving_left = False
        self.moving_up = False
        self.moving_down = False
        ### 飛船坐標(biāo)
        self.center = float(self.rect.centerx)
        self.centery = float(self.rect.centery)
    def blitme(self):
        ###重繪
        self.screen.blit(self.image,self.rect)
    def update(self): ###坐標(biāo)范圍的判定给涕,不能讓飛船跳到外面去
        if self.moving_right and self.rect.right < self.screen_rect.right:
            self.center += self.ai_settings.ship_speed_factor
        elif self.moving_left and self.rect.left > 0:
            self.center -= self.ai_settings.ship_speed_factor
        elif self.moving_up and self.rect.top > 0:
            self.centery -= self.ai_settings.ship_speed_factor
        elif self.moving_down and self.rect.bottom < self.screen_rect.bottom:
            self.centery += self.ai_settings.ship_speed_factor
        self.rect.centerx = self.center
        self.rect.centery = self.centery
    def center_ship(self): ###讓飛船回到初始之地
        self.center = self.screen_rect.centerx
        self.centery = self.screen_rect.bottom - 1/2*(self.rect.bottom-self.rect.top)

  1. 外星人類:
import pygame
from pygame.sprite import Sprite
class Alien(Sprite):
    def __init__(self,ai_settings,screen): ###初始化外星人的各個(gè)參數(shù)
        super(Alien,self).__init__()
        self.screen = screen
        self.ai_settings = ai_settings
        self.image = pygame.image.load('images/alien.bmp')
        self.rect = self.image.get_rect()
        self.rect.x = self.rect.width
        self.rect.y = self.rect.height
        self.x = float(self.rect.x)
    def blitme(self):###屏幕繪制外星人模型
        self.screen.blit(self.image,self.rect)
    def update(self): ###更新UFO
        self.x += self.ai_settings.alien_speed_factor*self.ai_settings.fleet_direction
        self.rect.x = self.x
    def check_edges(self):###檢查是否超出屏幕
        screen_rect = self.screen.get_rect()
        if self.rect.right >= screen_rect.right:
            return True
        elif self.rect.left <= 0:
            return True
        return False
    

  1. 子彈類
import pygame
from pygame.sprite import Sprite

class Bullet(Sprite):
    def __init__(self,ai_settings,screen,ship):### 初始化
        super(Bullet,self).__init__()
        self.screen = screen
        self.rect = pygame.Rect(0,0,ai_settings.bullet_width,ai_settings.bullet_height)
        self.rect.centerx = ship.rect.centerx
        self.rect.top = ship.rect.top
        self.y = float(self.rect.y)
        self.color = ai_settings.bullet_color
        self.speed_factor = ai_settings.bullet_speed_factor
    def update(self):###射出后豺憔,不斷讓縱坐標(biāo)減少
        self.y -= self.speed_factor
        self.rect.y = self.y
    def draw_bullet(self):###繪制子彈
        pygame.draw.rect(self.screen,self.color,self.rect)


  1. 分?jǐn)?shù)板類
import pygame.font
class Scoreboard():
    def __init__(self, ai_settings, screen, stats):###分?jǐn)?shù)板初始化
        self.screen = screen
        self.screen_rect = screen.get_rect()
        self.ai_settings = ai_settings
        self.stats = stats
        self.text_color = (30, 30, 30)
        self.font = pygame.font.SysFont(None, 48)
        self.prep_score()
        self.prep_level()
    def prep_score(self):###分?jǐn)?shù)顯示的模型,位置初始化
        score_str = str(self.stats.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 - 20
        self.score_rect.top = 20
    def show_score(self):###顯示分?jǐn)?shù)
        self.screen.blit(self.score_image, self.score_rect)
    def prep_level(self):###關(guān)卡顯示模型够庙,位置初始化
        level_str = str(self.stats.level)
        self.level_image = self.font.render(level_str,True,self.text_color,self.ai_settings.bg_color)
        self.level_rect = self.level_image.get_rect()
        self.level_rect.top = self.score_rect.top
        self.level_rect.centerx = self.screen_rect.centerx
    def show_level(self):###顯示關(guān)卡
        self.screen.blit(self.level_image,self.level_rect)
  1. 游戲狀態(tài)類
class GameStatus():
    def __init__(self, ai_settings):###游戲狀態(tài)初始化
        self.ai_settings = ai_settings
        self.reset_status()
        self.game_active = False
    def reset_status(self):###重置游戲后恭应,分?jǐn)?shù)與關(guān)卡清零
        self.ships_left = self.ai_settings.ship_limit
        self.score = 0
        self.level = 1
  1. 游戲設(shè)置類
class Settings():
    def __init__(self):
        # 屏幕設(shè)置
        self.screen_width = 1200
        self.screen_height = 800
        self.bg_color = (230, 230, 230)
        # 飛船設(shè)置
        self.ship_limit = 1
        # 子彈設(shè)置 3
        self.bullet_width = 3
        self.bullet_height = 15
        self.bullet_color = 60, 60, 60
        # 外星人設(shè)置
        self.fleet_drop_speed = 10

        self.speedup_scale = 2
        self.initialize_dynamic_settings()
    def initialize_dynamic_settings(self):
        self.ship_speed_factor = 1.5
        self.bullet_speed_factor = 3
        self.alien_speed_factor = 1
        # fleet_direction為1表示向右;為-1表示向左
        self.fleet_direction = 1
        self.alien_points = 50
    def increase_speed(self): #速度增加
        self.ship_speed_factor *= self.speedup_scale
        self.bullet_speed_factor *= self.speedup_scale
        self.alien_speed_factor *= self.speedup_scale

  1. 按鈕類
import pygame.font
class Button():
    def __init__(self,ai_settings,screen,msg):###開始按鈕初始化
        self.screen = screen
        self.screen_rect = screen.get_rect()

        self.width,self.height = 200,50
        self.button_color = (66,66,66)
        self.text_color = (255,255,255)
        self.font = pygame.font.SysFont(None,48)
        self.rect = pygame.Rect(0,0,self.width,self.height)
        self.rect.center = self.screen_rect.center

        self.pre_msg(msg)
    def pre_msg(self,msg): ###輸入內(nèi)容
        self.msg_img = self.font.render(msg,True,self.text_color,self.button_color)
        self.msg_img_rect = self.msg_img.get_rect()
        self.msg_img_rect.center = self.rect.center
    def draw_button(self):###繪制
        self.screen.fill(self.button_color,self.rect)
        self.screen.blit(self.msg_img,self.msg_img_rect)

三耘眨,展示

  1. 點(diǎn)擊Start Game開始游戲昼榛,最上方中間的是關(guān)卡,右邊是分?jǐn)?shù)


    start.png
  2. 射擊時(shí)剔难,子彈擊中UFO就一起出局


    shoot.png
  3. 飛船撞上UFO失敗


    fail.png

四胆屿,總代碼地址

https://github.com/Teskinfly/ShipVSUFO

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末奥喻,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子莺掠,更是在濱河造成了極大的恐慌衫嵌,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件彻秆,死亡現(xiàn)場(chǎng)離奇詭異楔绞,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)唇兑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門酒朵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人扎附,你說我怎么就攤上這事蔫耽。” “怎么了留夜?”我有些...
    開封第一講書人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵匙铡,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我碍粥,道長(zhǎng)鳖眼,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任嚼摩,我火速辦了婚禮钦讳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘枕面。我一直安慰自己愿卒,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開白布潮秘。 她就那樣靜靜地躺著琼开,像睡著了一般。 火紅的嫁衣襯著肌膚如雪枕荞。 梳的紋絲不亂的頭發(fā)上柜候,一...
    開封第一講書人閱讀 51,554評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音买猖,去河邊找鬼改橘。 笑死,一個(gè)胖子當(dāng)著我的面吹牛玉控,可吹牛的內(nèi)容都是我干的飞主。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼碌识!你這毒婦竟也來了碾篡?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤筏餐,失蹤者是張志新(化名)和其女友劉穎开泽,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體魁瞪,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡穆律,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了导俘。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片峦耘。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖旅薄,靈堂內(nèi)的尸體忽然破棺而出辅髓,到底是詐尸還是另有隱情,我是刑警寧澤少梁,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布洛口,位于F島的核電站,受9級(jí)特大地震影響凯沪,放射性物質(zhì)發(fā)生泄漏第焰。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一著洼、第九天 我趴在偏房一處隱蔽的房頂上張望樟遣。 院中可真熱鬧而叼,春花似錦身笤、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至脱篙,卻和暖如春娇钱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背绊困。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工文搂, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人秤朗。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓煤蹭,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子硝皂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355