遊戲結束 - LanKuDot/MLGame GitHub Wiki

遊戲的最後一個功能就是在蛇撞到牆或是自己的時候結束遊戲。

判斷遊戲結束

在場景中判斷如果蛇撞到自己或是牆,那就讓遊戲結束。在 gamecore.pyScene 類別中的 update() 最後面加入判斷遊戲結束的程式碼:

class Scene:
    ...

    def update(self, action):
        ...

        if (not Scene.area_rect.collidepoint(self._snake.head_pos) or
            self._snake.is_body_pos(self._snake.head_pos)):
            return "GAME_OVER"
        else:
            return "GAME_ALIVE"

第一個會讓遊戲結束的情況是蛇撞到牆。利用檢查蛇頭的位置有沒有超出場景範圍來判定這樣的情況。檢查一個位置有沒有超出範圍可以透過比較座標來檢查,例如:self._snake.head_pos[0] < 0(超出左邊界)、self._snake.head_pos[0] >= Scene.area_rect.width(超出右邊界)等。而這邊則是利用 pygame.Rect.collidepoint() 來檢查一個點有沒有在該 rect 中,只要蛇頭的位置沒有在 area_rect 這個 rect 中,代表蛇頭在場景範圍之外,那就是撞牆了。

第二個情況則是蛇頭撞到蛇身。這種情況可以直接檢查蛇頭的位置有沒有等於任一蛇身的位置來判定。

如果上述兩條件任一達成的話,就代表遊戲結束,回傳 "GAME_OVER" 來通知遊戲要結束了,否則就回傳 "GAME_ALIVE"

更新遊戲主程式

snake.py 中接收場景的判定結果後,也要做對應的處理:

if __name__ == "__main__":
    ...
    while running:
        ...
        # Update the scene
        game_status = scene.update(action)

        if game_status == "GAME_OVER":
            break
        ...

如果場景更新後回傳 "GAME_OVER",就跳出執行迴圈,直接結束程式。

到這邊可以執行遊戲看看成果。

重新開始遊戲

在遊戲結束後,如果直接重新開始遊戲,就可以不用一直重新啟動程式。

在重新開始遊戲時,要重新設置場景回初始狀態。在 gamecore.pyScene 類別中加入 reset()

class Scene:
    ...

    def reset(self):
        self._snake = Snake()
        self._random_food_pos()
        self._draw_group.empty()
        self._draw_group.add(self._snake.head, *self._snake.body, self._food)

這裡直接建立一個新的蛇物件出來,如此一來蛇的位置就會是剛開始的樣子,而舊的蛇物件會因為 python 的垃圾回收機制被清除。另外也可以在蛇類別中加入可以重設蛇狀態的函式,再去呼叫該函式。在新的蛇物件建立後,才重新決定食物的位置,因為食物要避開蛇的位置。最後呼叫 pygame.sprite.Group.empty() 清除被放在 _draw_group 裡的遊戲物件(裡面有舊的蛇物件),再重新把新的蛇物件與食物加回去。

更新遊戲主程式

再回到 snake.py。在遊戲結束時,去呼叫剛剛建立的 reset() 函式,而不是直接離開執行迴圈:

        if game_status == "GAME_OVER":
            scene.reset()

執行遊戲

Imgur