貪吃蛇(三)

上一期,我們基本上完成了我們的貪吃蛇游戲。但是任然存在一些小問題:

  1. 游戲一打開,我們的小蛇就開始跑了,沒有任何的提示,而且游戲結束之后,窗口就被直接關閉了,很不友好。

  2. 游戲沒有評分,沒有等級什么的,用戶不知道自己到底在什么水平上。

好的,本期我們就來解決這兩個問題。

原先我們的設計是:無論用戶是按關閉按鈕還是小蛇死亡,我們都置running=False,也就是游戲退出,而不是游戲結束。這明顯是不合理的,我們只有在用戶按關閉按鈕的時候才應該退出,而再其他情況下應該使本局游戲結束,但用戶仍然可以開始下一局。這里我們引入另外一個變量game_is_over,用于標注本局游戲結束。

在本局游戲結束之后,如果用戶需要重新開始新一局游戲,我們可以重新初始化游戲中用到的用于存儲游戲狀態的數據,從而開始新的一局游戲。 為了方便,我們可以將初始化用戶狀態變量的語句用一個函數封裝起來,再將這邊變量及函數用一個GameStatus類封裝起來,這樣可以使我們的游戲代碼更加清晰,更容易重構。

為了方便,我們提示用戶按任意鍵可以開始游戲。

GameStatus

首先,我們將原先定義為全局變量的狀態,放在一個類GameStatus里面,再定義一個實例用于保存當前狀態

class GameStatus():
    def __init__(self):
        self.reset_game_status()

    # 重置所有的狀態為初始態
    def reset_game_status(self):
        self.food_pos = generate_food()
        self.direction = D_LEFT
        self.game_is_over = True
        self.running = True
        self.hardness = HARD_LEVEL[0]

        # 每次小蛇身體加長的時候,我們就將身體的位置加到列表末尾
        self.snake_body = [(int(GRID_WIDTH_NUM / 2) * CUBE_WIDTH,
                            int(GRID_HEIGHT_NUM / 2) * CUBE_WIDTH)]

# 定義一個類的實例,用于保存當前游戲狀態
status = GameStatus()

這樣的話,我們原先用的到一些狀態,比如running/direction 等等,只要在變量面前加上 [status.] 就好了也就是 status.running/status.direction 是不是很簡單~~

開始、結束界面

改完狀態類之后,我們還需要繪制兩個界面,一個開始界面,一個結束界面。開始界面我么顯示“歡樂貪吃蛇“,”按任意鍵開始游戲“。結束界面,我們顯示”你掛了“。OK,我們開始吧!

文字輸出

由于要在屏幕上輸出文字,我么需要指定字體,所以首先我們獲取一個字體(這里我已經提前把字體放到了font目錄下面):

font_name = os.path.join(base_folder, 'font/font.ttc')
font = pygame.font.Font(font_name, size)

定義好字體之后我們需要把我們需要顯示的文字用我們選定的字體“寫”出來,這個寫出來的字呢,我們可以將它放到屏幕的任何地方哦~,就像之前我們導入的圖片一樣,只需要指定一個位置,我們就可以將圖片復制過去

text_surface = font.render(text, True, color)

上面那行代碼中,text是我們需要顯示的文字。

結下來我們需要獲取我們文字所在的矩形,并且將矩形的中心,設置到我們想要的位置,當然你也可以選擇其他對齊的方式,大家可以參考pygame的文檔。最后就是將其畫到屏幕上了,所用到的函數和我們畫圖片時的一樣,也是blit,ok,看一下我們的函數

def show_text(surf, text, size, x, y, color=WHITE):
    font_name = os.path.join(base_folder, 'font/font.ttc')
    font = pygame.font.Font(font_name, size)
    text_surface = font.render(text, True, color)
    text_rect = text_surface.get_rect()
    text_rect.midtop = (x, y)
    surf.blit(text_surface, text_rect)

接下來,歡迎界面就簡單多了

def show_welcome(screen):
    show_text(screen, u'歡樂貪吃蛇', 30, WIDTH / 2, HEIGHT / 2)
    show_text(screen, u'按任意鍵開始游戲', 20, WIDTH / 2, HEIGHT / 2 + 50)

結束界面,只需要打印幾個字,并加一下延遲

show_text(screen, u'你掛了', 30, WIDTH / 2, HEIGHT / 2)
          pygame.display.update()
          pygame.time.delay(2000)

好了,各個部件都已經完成了,我們來修改一下游戲邏輯,在檢測到有按鈕按下時,我們需要判斷一下游戲是否還沒有開始,如果沒有開始我們就需要,將游戲狀態置為開始。并且游戲沒有開始的時候,我們不需要更新屏幕

for event in pygame.event.get():
    if event.type == pygame.QUIT:
        status.running = False
    elif event.type == pygame.KEYDOWN:      # 如果有按鍵被按下了
        # 如果本局游戲已經結束(或者沒有開始),那么按任意鍵開始游戲
        if status.game_is_over:
            # 重置游戲狀態
            status.reset_game_status()
            status.game_is_over = False
            break

# ................................................................................

if status.game_is_over:
    show_welcome(screen)
    pygame.display.update()

    如果游戲還沒有開始,接下來的操作就沒有必要進行了
    continue

大功告成!!

我們開一下效果~


game_start.png

評分

現在我們來解決下一個問題 --- 評分

我們在屏幕右端添加一個寬為200px的區域用于展示分數和當前我們的 level

SCREEN_WIDTH = WIDTH + 200

然后更改一下我們的畫布

# 設置畫布
screen = pygame.display.set_mode((SCREEN_WIDTH, HEIGHT))

這樣我們的屏幕就變寬了~

我們在GameStatus類中添加一個score字段用于存儲當前的得分,每次小蛇吃到一個事物我們就加點分數

class GameStatus():
    def __init__(self):
        self.reset_game_status()

    # 重置所有的狀態為初始態
    def reset_game_status(self):
        # ...
        self.score = 0

然后再定義一個展示分數的函數

def show_scores(screen, status):
    show_text(screen, u'級別: {}'.format(status.hardness), CUBE_WIDTH,
        WIDTH + CUBE_WIDTH * 3, CUBE_WIDTH * 4)

    show_text(screen, u'得分: {}'.format(status.score), CUBE_WIDTH,
        WIDTH + CUBE_WIDTH * 3, CUBE_WIDTH * 6)

OK!現在來修改一下我們主函數

# 如果吃到了食物我們就產生一個新的食物
if got_food:
    status.score += status.hardness

# 每次刷新屏幕前加上刷新分數的函數調用
show_scores(screen, status)

好的~ 我們看一下最終效果~


snake-v2.png

我們的貪吃蛇又進一步完善了~

完整的代碼可以去我的 github 看,點擊這里進入GitHub。
如果這篇文章對您有幫助,贊賞一下吧~

您的支持是我繼續創作的動力~~~

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,118評論 25 708
  • 發現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,202評論 4 61
  • Ubuntu的發音 Ubuntu,源于非洲祖魯人和科薩人的語言,發作 oo-boon-too 的音。了解發音是有意...
    螢火蟲de夢閱讀 99,529評論 9 467
  • 轉眼間,大二下學期就要開始了,目標就是好好學習,省錢,回想上學期的生活,整個一慘不忍睹,那我就從幾個方面講吧。(...
    crystallkw閱讀 279評論 0 0
  • 291028~魏鴻超 2017/7/29 連續總結第168天 思考內容: 即將在上海進入博物館照明項目領域,改領域...
    a0001911cc5a閱讀 246評論 0 1