成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

Python學(xué)習(xí)之路12-外星人

chemzqm / 3095人閱讀

摘要:現(xiàn)在開始創(chuàng)建多行外星人。小結(jié)本篇講述了如何在游戲中添加大量相同的元素如何用嵌套循環(huán)來創(chuàng)建元素網(wǎng)格如何控制對象在屏幕上移動的方向以及響應(yīng)事件如何檢測和響應(yīng)元素碰撞如何在游戲中跟蹤統(tǒng)計信息如何使用標志來判斷游戲是否結(jié)束。

《Python編程:從入門到實踐》筆記。
本章主要是對上一篇的繼續(xù),添加“外星人”,“外星人”與飛船的交互。
1. 回顧項目

開發(fā)較大的項目時,進入每個開發(fā)階段前回顧一下開發(fā)計劃,搞清楚接下來要通過代碼實現(xiàn)哪些功能至關(guān)重要。本篇將設(shè)計一下內(nèi)容:

研究即有代碼,確定實現(xiàn)新功能前是否需要重構(gòu)代碼

在屏幕左上角添加一個外星人,并指定合適的邊距

根據(jù)第一個外星人的邊距和屏幕尺寸計算屏幕上可容納多少個外星人。編寫一個循環(huán)來填滿屏幕的上半部分

讓外星艦隊向兩邊和下方移動,直到外星人被全部擊落,或有外星人撞到飛船,或有外星人抵達屏幕底部。如果所有外星人都被擊落,再創(chuàng)建一批外星人。如果有外星人撞到飛船或到達屏幕底部,則銷毀飛船并再創(chuàng)建一群外星人。

限制玩家可用的飛機數(shù),消耗完則游戲結(jié)束

希望各位上一篇的代碼沒有刪掉。在開始新的代碼前,我們先在前面的check_keydown_events()函數(shù)中添加“通過快捷鍵Q結(jié)束游戲”的代碼:

def check_keydown_event(event, ship, ai_settings, screen, bullets):
    -- snip --
    elif event.key == pygame.K_q:
        sys.exit()
2. 創(chuàng)建外星人

首先我們需要編寫一個外星人Alien類。新建alien.py模塊,在其中加入如下代碼:

import pygame
from pygame.sprite import Sprite

class Alien(Sprite):
    """表示單個外星人的類"""
    def __init__(self, ai_settings, screen):
        """初始化外星人并設(shè)置其起始位置"""
        super(Alien, self).__init__()
        self.screen = screen
        self.ai_settings = ai_settings

        # 加載外星人圖像,并設(shè)置其rect屬性
        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)

它和Bullet類一樣繼承自Sprite類。現(xiàn)在開始創(chuàng)建多行外星人。

2.1 修改game_functions.py模塊

首先在game_functions.py模塊中添加create_fleet()函數(shù)用于創(chuàng)建外星艦隊:

def create_fleet(ai_settings, screen, ship, aliens):
    """創(chuàng)建外星艦隊"""
    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)

    # 嵌套循環(huán)創(chuàng)建外星艦隊
    for row_number in range(number_rows):
        for alien_number in range(number_aliens_x):
            # 創(chuàng)建外星人并將其加入艦隊
            create_alien(ai_settings, screen, aliens, alien_number, row_number)

然后我們依次補充下面三個函數(shù)(注意各個函數(shù)的參數(shù)),這三個函數(shù)也位于game_functions.py中:

get_number_aliens_x(): 計算一行能放多少個外星人

def get_number_aliens_x(ai_settings, alien_width):
    """計算每行可容納多少個外星人"""
    # 左右兩側(cè)留出一個外星人的寬度
    available_space_x = ai_settings.screen_width - 2 * alien_width
    # 列間距為一個外星人寬度
    number_aliens_x = int(available_space_x / (2 * alien_width))
    return number_aliens_x

get_number_rows(): 計算能放多少行外星人

def get_number_rows(ai_settings, ship_height, alien_height):
    """計算屏幕可容納多少行外星人"""
    # 可用高度 = 窗口高度 - 上方一個外星人高度 - 下方一個飛船高度 - 兩個外星人高度作為緩沖空間
    available_space_y = (ai_settings.screen_height - 3 * alien_height - ship_height)
    # 行距為一個外星人高度
    number_rows = int(available_space_y / (2 * alien_height))
    return number_rows

create_alien(): 創(chuàng)建外星人

def create_alien(ai_settings, screen, aliens, alien_number, row_number):
    """創(chuàng)建一個外星人并將其放在當前行"""
    alien = Alien(ai_settings, screen)
    # 下面就是根據(jù)上面的公式計算每一個外星人在窗口中的位置(這是左上角的坐標)
    alien.x = alien.rect.width * (1 + 2 * alien_number)
    alien.rect.x = alien.x
    alien.rect.y = alien.rect.height * (1 + 2 * row_number)
    aliens.add(alien)

現(xiàn)在我們還需要修改update_screen()函數(shù):

def update_screen(ai_settings, screen, ship, bullets, aliens):
    -- snip --
    # 繪制外星人,放在繪制子彈的代碼后面,讓外星人的圖像覆蓋掉子彈的圖像
    aliens.draw(screen)
    -- snip --

注意,該函數(shù)增加了一個參數(shù)aliens,這是個Group對象,所以代碼中的draw()方法也跟前一篇中的bullets.update()方法一樣,一行代碼更新所有對象。

2.2 修改alien_invasion.py模塊

在主程序中添加創(chuàng)建外星人的代碼:

def run_game():
    -- snip --
    gf.create_fleet(ai_settings, screen, ship, aliens)

    while True:
        -- snip --
        # 比之前代碼多傳入了一個aliens參數(shù)
        gf.update_screen(ai_settings, screen, ship, bullets, aliens)
        
-- snip --

現(xiàn)在我們執(zhí)行程序?qū)玫饺缦陆Y(jié)果:

3. 讓外星艦隊動起來

我們將讓外星艦隊在窗體中向右移動,撞到屏幕邊緣后下以一定距離下降,再沿反方向移動,直到外星人被消滅,或外星人撞上飛船,或有外星人到達窗體底部。

3.1 補充settings.py模塊
class Settings:
    def __init__(self):
        -- snip --
        self.fleet_drop_speed = 10
        # 外星艦隊方向標志:1向右,-1向左
        # 也可以用如left, right之類的標志,但這樣會很麻煩
        self.fleet_direction = 1
3.2 修改alien.py模塊

我們需要在Alien類中添加兩個方法,一個用于檢測窗體邊緣,一個用于更新Alien對象:

class Alien(Sprite):
    -- snip --
    def check_edges(self):
        """如果外星人位于屏幕邊緣則返回True"""
        screen_rect = self.screen.get_rect()
        return self.rect.right >= screen_rect.right or self.rect.left <= 0

    def update(self):
        """向右移動外星人"""
        # 以后這樣的方式會用的很多
        self.x += self.ai_settings.alien_speed_factor * self.ai_settings.fleet_direction
        self.rect.x = self.x

如果使用文本值來控制方向,那就需要添加if-else語句來檢測艦隊移動方向。鑒于只有兩個可能的方向,這里使用-11來表示,這樣更容易改變外星人對象的坐標。

3.3 修改game_functions.py模塊

首先,我們在該模塊中添加一個更新外星艦隊的函數(shù)update_aliens()

def update_aliens(ai_settings, aliens):
    """檢查是否有外星人位于屏幕邊緣,并更新外星艦隊中所有外星人的位置"""
    check_fleet_edges(ai_settings, aliens)
    aliens.update()  # “一鍵更新”

check_fleet_edges()函數(shù)用于檢測艦隊是否碰到了窗體邊緣,代碼如下:

def check_fleet_edges(ai_settings, aliens):
    """有外星人到達邊緣時采取相應(yīng)的措施"""
    # 檢測艦隊中每一個外星人是否碰到了窗體邊緣
    for alien in aliens.sprites():
        if alien.check_edges():
            change_fleet_direction(ai_settings, aliens)
            break

change_fleet_direction()函數(shù)用于改變艦隊的移動方向,以及讓艦隊向下移動,代碼如下:

def change_fleet_direction(ai_settings, aliens):
    """將外星艦隊下移,并改變它們的方向"""
    for alien in aliens.sprites():
        alien.rect.y += ai_settings.fleet_drop_speed
    ai_settings.fleet_direction *= -1

上面三個函數(shù)就是在game_functions.py中的所有變動。

3.4 修改alien_invasion.py模塊

在該模塊中我們只需要在while循環(huán)中添加一行代碼:

# 開始游戲的主循環(huán)
    while True:
        gf.check_events(ai_settings, screen, ship, bullets)
        ship.update()
        gf.update_bullets(bullets)
        # 添加對外星艦隊的修改
        gf.update_aliens(ai_settings, aliens)
        gf.update_screen(ai_settings, screen, ship, bullets, aliens)

最后運行主程序,得到如下效果:

截了一張靜態(tài)圖,實際是動態(tài)的。

4. 擊殺外星人

對于當前的程序,如果發(fā)射子彈,子彈將穿過外星人,而不是擊殺,下面我們繼續(xù)完善該項目,使其能擊殺外星人。而要實現(xiàn)這一點,關(guān)鍵就是要檢測到子彈圖像與外星人圖像是否重疊,重疊了則表示擊中。

4.1 修改game_functions.py

為何檢測子彈與衛(wèi)星人的碰撞,我們需要修改update_bullets()函數(shù),這里我們增加了update_bullets()的參數(shù),還調(diào)用了一個新函數(shù):

def update_bullets(bullets, aliens, ship, screen, ai_settings):
    -- snip --
    check_bullet_alien_collisions(ai_settings, screen, ship, aliens, bullets)

函數(shù)check_bullet_alien_collisions()用于檢測子彈與外星人的碰撞,當外星人被消滅光時,清空現(xiàn)有子彈,并生成新的外星艦隊,它的代碼如下:

def check_bullet_alien_collisions(ai_settings, screen, ship, aliens, bullets):
    """檢測是否有子彈擊中了外星人,如果有,就刪除相應(yīng)的子彈和外星人"""
    # 下一篇中我們將用該變量實現(xiàn)分數(shù)統(tǒng)計
    collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)
    
    #如果外星人被消滅光,則生成新的外星人艦隊
    if len(aliens) == 0:
        # 刪除現(xiàn)有的子彈并創(chuàng)建新的艦隊
        bullets.empty()
        create_fleet(ai_settings, screen, ship, aliens)

sprite.groupcollide()方法用于檢測對象之間的碰撞,它將bullets中的每個子彈的rectaliens中的每個外星人的rect進行比較,并返回一個字典。該字典以第一個參數(shù)中的對象為鍵,以第二個參數(shù)中的鍵為值,在這里,以bullets中發(fā)生了碰撞的bullet為鍵,它的值為與之碰撞的alien(不是aliens)!第三個參數(shù)表示是否刪除第一個參數(shù)中發(fā)生了碰撞的對象,而四個參數(shù)表示是否刪除第二個參數(shù)中發(fā)生了碰撞的對象。

4.2 修改alien_invasion.py

只需要修改調(diào)用update_bullets()函數(shù)的那行代碼即可,增加幾個參數(shù):

gf.update_bullets(bullets, aliens, ship, screen, ai_settings)

基礎(chǔ)功能基本完成。

4.3 測試技巧補充

對于上述代碼,我們可能需要測試當消滅完外星人后,新的艦隊是否能被正確創(chuàng)建等,如果我們以現(xiàn)在游戲的設(shè)定,即子彈速度為1,子彈寬度為3,那測試起來將會很痛苦。此時,我們可以修改修改游戲的參數(shù),比如將子彈寬度修改為300,子彈速度修改為3,這樣就相當于對游戲進行了快進,此時代碼的運行效果如下:

不過最后記得將參數(shù)修改回去。

5. 結(jié)束游戲

接下來我們實現(xiàn)外星人碰到飛船,外星人抵達窗體底部,飛船數(shù)用光導(dǎo)致游戲結(jié)束的代碼。

5.1 創(chuàng)建GameStats類

首先我們創(chuàng)建一個用于存儲游戲信息的GameStats類,存放在game_stats.py文件中:

class GameStats:
    """跟蹤游戲的統(tǒng)計信息"""
    def __init__(self, ai_settings):
        """初始化統(tǒng)計信息"""
        # 用于控制游戲啟動與否
        self.game_active = True
        self.ai_settings = ai_settings
        self.reset_stats()

    def reset_stats(self):
        """初始化在游戲運行期間可能變化的統(tǒng)計信息"""
        # 重置飛船數(shù)
        self.ships_left = self.ai_settings.ship_limit
5.2 修改settings.py

從上述代碼可以看出,我們需要在settings.py中添加一項表示“飛船數(shù)”的信息:

class Settings:
    def __init__(self):
        """初始化游戲的設(shè)置"""
        # 屏幕設(shè)置
        -- snip --
        # 設(shè)置飛船數(shù)量限制
        self.ship_limit = 3
        -- snip --
5.3 響應(yīng)飛船與外星人的碰撞,修改game_functions.py

我們在更新每個外星人的位置后立即檢測外星人和飛船之間的碰撞,隨后再檢查外星人是否到達了窗體底部。修改update_aliens()函數(shù),使用sprite中的spritecollideany()方法來檢測碰撞:將第二參數(shù)中的每一個元素與第一個參數(shù)比較,檢測是否碰撞,返回第二個參數(shù)中第一個發(fā)生碰撞的對象,如果沒有發(fā)生碰撞則返回None:

# 增加了參數(shù)和碰撞檢測
def update_aliens(ai_settings, aliens, ship, screen, bullets, stats):
    -- snip --
    # 檢測外星人和飛船之間的碰撞
    if pygame.sprite.spritecollideany(ship, aliens):
        ship_hit(ai_settings, stats, screen, ship, aliens, bullets)

    check_aliens_bottom(ai_settings, stats, screen, ship, aliens, bullets)

為此我們需要增加兩個函數(shù):

ship_hit():當外星人與飛船發(fā)生碰撞時,調(diào)用次函數(shù)

-- snip --
from time import sleep

def ship_hit(ai_settings, stats, screen, ship, aliens, bullets):
    """響應(yīng)被外星人撞到的飛船"""
    # 將ship_left減1
    if stats.ships_left > 0:
        stats.ships_left -= 1

        # 清空外星人列表和子彈列表
        aliens.empty()
        bullets.empty()

        # 創(chuàng)建一群新的外星人,并將飛船恢復(fù)到初始位置
        create_fleet(ai_settings, screen, ship, aliens)
        ship.center_ship()

        # 暫停
        sleep(0.5)
    else:
        stats.game_active = False

從上面的代碼還可以看出,我們還需要在Ship類中添加一個center_ship()方法:

def center_ship(self):
    """讓飛船在屏幕上居中"""
    self.center = self.screen_rect.centerx

check_aliens_bottom(): 當飛船到達窗體底部時調(diào)用次函數(shù)

def check_aliens_bottom(ai_settings, stats, screen, ship, aliens, bullets):
    """檢測是否有外星人到達了屏幕底部"""
    screen_rect = screen.get_rect()
    for alien in aliens.sprites():
        if alien.rect.bottom >= screen_rect.bottom:
            # 和飛船被碰撞是的代碼沒啥區(qū)別,故調(diào)用同一個函數(shù)
            ship_hit(ai_settings, stats, screen, ship, aliens, bullets)
            break
5.4 修改主程序alien_invasion.py

修改游戲的循環(huán)部分:

# 開始游戲的主循環(huán)
while True:
    gf.check_events(ai_settings, screen, ship, bullets)
    
    # 決定程序運行時該執(zhí)行的部分
    if stats.game_active:
        ship.update()
        gf.update_bullets(bullets, aliens, ship, screen, ai_settings)
        gf.update_aliens(ai_settings, aliens, ship, screen, bullets, stats)

    gf.update_screen(ai_settings, screen, ship, bullets, aliens)

在主循環(huán)中,任何情況下都需要調(diào)用check_events(),即使游戲處于非活動狀態(tài);還需要不斷更新屏幕,以便在等待玩家是否選擇重新開始游戲時能夠修改屏幕;其他函數(shù)僅在游戲處于活動狀態(tài)時太需要調(diào)用。

6. 小結(jié)

本篇講述了:

如何在游戲中添加大量相同的元素;

如何用嵌套循環(huán)來創(chuàng)建元素網(wǎng)格;

如何控制對象在屏幕上移動的方向以及響應(yīng)事件;

如何檢測和響應(yīng)元素碰撞;

如何在游戲中跟蹤統(tǒng)計信息;

如何使用標志game_active來判斷游戲是否結(jié)束。

下一篇中,同時也是本項目的最后一篇,我們將:

添加一個Play按鈕讓玩家能夠開始游戲,以及游戲結(jié)束后再開始;

每當玩家消滅一群外星人后,加快游戲節(jié)奏;

添加一個分數(shù)系統(tǒng)。


迎大家關(guān)注我的微信公眾號"代碼港" & 個人網(wǎng)站 www.vpointer.net ~

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/41789.html

相關(guān)文章

  • Python學(xué)習(xí)之路5-字典

    摘要:本章主要介紹字典的概念,基本操作以及一些進階操作。使用字典在中,字典是一系列鍵值對。中用花括號來表示字典。代碼定義空字典的語法結(jié)果如果要修改字典中的值,只需通過鍵名訪問就行。 《Python編程:從入門到實踐》筆記。本章主要介紹字典的概念,基本操作以及一些進階操作。 1. 使用字典(Dict) 在Python中,字典是一系列鍵值對。每個鍵都與一個值相關(guān)聯(lián),用鍵來訪問值。Python中用...

    NicolasHe 評論0 收藏0
  • Python學(xué)習(xí)之路11-武裝飛船

    摘要:和標志,用于表示飛船是否正在移動,用于實現(xiàn)飛船在不松開按鍵下連續(xù)移動。重寫了函數(shù),用于繪制飛船模塊該模塊主要是集中處理游戲中發(fā)生的各種事件。函數(shù)用于監(jiān)聽游戲的事件,比如,它表示游戲推出事件和分別表示鍵盤按下與松開事件。 《Python編程:從入門到實踐》筆記。本章主要學(xué)習(xí)如何使用pygame編寫一個簡單的小飛機打外星人的游戲,由于本人對用python寫游戲并不是特別感興趣,所以主要是看...

    李昌杰 評論0 收藏0
  • Python學(xué)習(xí)之路13-記分

    摘要:之所以這里要添加這四行代碼,其實是為了當你重新開始也就是第二次及以后點擊按鈕游戲時,計分板能正確顯示。當?shù)谝贿\行游戲時,沒有這四行也能正確顯示計分板。 《Python編程:從入門到實踐》筆記。本篇是Python小游戲《外星人入侵》的最后一篇。 1. 前言 本篇我們將結(jié)束Pygame小游戲《外星人入侵》的開發(fā)。在本篇中,我們將添加如下內(nèi)容: 添加一個Play按鈕,用于根據(jù)需要啟動游戲以...

    tommego 評論0 收藏0
  • 云棲大會上有哪些亮點值得關(guān)注?

    摘要:年云棲大會在杭州舉行,據(jù)主辦方介紹本次云棲大會吸引了五萬多人參會,但是在密集的會議中又有哪些亮點值得關(guān)注領(lǐng)導(dǎo)致辭很無聊每次重要的大會,都離不開一些政府要員們的參與,但是在高新技術(shù)的互聯(lián)網(wǎng),云計算,大數(shù)據(jù)領(lǐng)域真心不敢恭維,除了讓整個會議前半場 2016年云棲大會在杭州舉行,據(jù)主辦方介紹本次云棲大會吸引了五萬多人參會,但是在密集的會議中又有哪些亮點值得關(guān)注?領(lǐng)導(dǎo)致辭很無聊每次重要的大會,都離不開...

    Lavender 評論0 收藏0
  • 我家貓老喜歡和我躲貓貓,我用Python趕忙寫了個貓臉檢測器。在哪里都逃不出我的手心。

    摘要:前言喵星人真的是要統(tǒng)治世界了。完整的代碼如下所示效果如下我們選擇這位顏值高的喵星人代碼測試效果要測試代碼,只需使用您選擇的工具運行它。 ?前言 ? ? ?喵星人真的是要統(tǒng)治世界了。?不然為什么OpenCV自帶的檢測器中除了人臉檢測、行人檢測 這些意料之中就應(yīng)該存在的檢測器之外,還悄悄多出了貓...

    crossoverJie 評論0 收藏0

發(fā)表評論

0條評論

chemzqm

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<