目錄
0 引言
1 環境
2 需求分析
3 程式碼實現
4 後記
0 引言
前幾天,星球有人提到貪吃蛇,一下子就勾起了我的興趣,畢竟在那個Nokia稱霸的年代,這款遊戲可是經典中的經典啊!而用Python(蛇)玩Snake(貪吃蛇),那再合適不過了???
先通過下面這個效果圖來感受下吧!
1 環境
作業系統:Windows
Python版本:3.7.3
2 需求分析
我們先來回顧下貪吃蛇中的遊戲元素及遊戲規則。
首先呢,需要有貪吃蛇、有食物;需要能控制貪吃蛇來上下移動獲取食物;貪吃蛇在吃取食物後,自身長度增加,同時食物消失並隨機生成新的食物;如果貪吃蛇觸碰到四周牆壁或是觸碰到自己身體時,則遊戲結束。
遊戲規則就是這麼簡單,接下來我們藉助一個第三方庫pygame來實現它。
Pygame是一個利用SDL庫的遊戲庫, 是一組用來開發遊戲軟體的 Python 程式模組。
SDL(Simple DirectMedia Layer)是一個跨平臺庫,支援訪問計算機多媒體硬體(聲音、視訊、輸入等),SDL非常強大,但美中不足的是它是基於 C 語言的。
PyGame是 SDL 庫的 Python 包裝器(wrapper),Pygame 在SDL庫的基礎上提供了各種介面,從而使用使用者能夠使用python語言建立各種各樣的遊戲或多媒體程式。
它的安裝方法很簡單,如下:
pip install pygame
想要了解更多pygame功能的朋友也可以查閱官方的文件。
3 程式碼實現
首先匯入我們要用到的模組,除了第三方庫pygame外,我們還會用到一些Python內建的模組如sys、random、time等,一併匯入即可。
import pygame, sys, random, time
# 從pygame模組匯入常用的函式和常量
from pygame.locals import *
3.1 一些全域性引數的初始化
接下來,我們需要宣告一些全域性引數。如初始化pygame、定義遊戲視窗的大小、視窗的標題、定義全域性的顏色變數等資訊。
# 初始化Pygame庫
pygame.init()
# 初始化一個遊戲介面視窗
DISPLAY = pygame.display.set_mode((640, 480))
# 設定遊戲視窗的標題
pygame.display.set_caption('人人都是Pythonista - Snake')
# 定義一個變數來控制遊戲速度
FPSCLOCK = pygame.time.Clock()
# 初始化遊戲介面內使用的字型
BASICFONT = pygame.font.SysFont("SIMYOU.TTF", 80)
# 定義顏色變數
BLACK = pygame.Color(0, 0, 0)
WHITE = pygame.Color(255, 255, 255)
RED = pygame.Color(255, 0, 0)
GREY = pygame.Color(150, 150, 150)
3.2 初始化貪吃蛇及食物
遊戲中需要有貪吃蛇及食物,我們給定一個初始值。我們將整個介面看成許多20*20的小方塊,每個小方塊代表一個標準小格子,貪吃蛇的長度就可以用幾個標準小格子表示。我們將貪吃蛇身體用列表的形式儲存,方便之後的刪減。
'''初始化貪吃蛇及食物'''
# 貪吃蛇的的初始位置
snake_Head = [100,100]
# 初始化貪吃蛇的長度 (注:這裡以20*20為一個標準小格子)
snake_Body = [[80,100],[60,100],[40,100]]
# 指定蛇初始前進的方向,向右
direction = "right"
# 給定第一枚食物的位置
food_Position = [300,300]
# 食物標記:0代表食物已被吃掉;1代表未被吃掉。
food_flag = 1
3.3 實現貪吃蛇的上下左右移動
我們需要控制貪吃蛇的上下左右的移動,這裡通過監聽鍵盤輸入來實現。利用鍵盤中的上下左右鍵或WASD鍵來控制貪吃蛇的運動。
# 檢測按鍵等Pygame事件
for event in pygame.event.get():
if event.type == QUIT:
# 接收到退出事件後,退出程式
pygame.quit()
sys.exit()
# 判斷鍵盤事件,用 方向鍵 或 wsad 來表示上下左右
elif event.type == KEYDOWN:
if (event.key == K_UP or event.key == K_w) and direction != DOWN:
direction = UP
if (event.key == K_DOWN or event.key == K_s) and direction != UP:
direction = DOWN
if (event.key == K_LEFT or event.key == K_a) and direction != RIGHT:
direction = LEFT
if (event.key == K_RIGHT or event.key == K_d) and direction != LEFT:
direction = RIGHT
接下來就是將蛇前進方向按照鍵盤的輸入進行轉彎操作,並將蛇的頭部當前的位置加入到蛇身的列表中。
# 根據鍵盤的輸入,改變蛇的頭部,進行轉彎操作
if direction == LEFT:
snake_Head[0] -= 20
if direction == RIGHT:
snake_Head[0] += 20
if direction == UP:
snake_Head[1] -= 20
if direction == DOWN:
snake_Head[1] += 20
# 將蛇的頭部當前的位置加入到蛇身的列表中
snake_Body.insert(0, list(snake_Head))
3.4 判斷是否吃到食物
如果蛇頭與食物的位置重合,則判定吃到食物,將食物數量清零;而沒吃到食物的話,蛇身就會跟著蛇頭運動,蛇身的最後一節將被踢出列表。
# 判斷是否吃掉食物
if snake_Head[0]==food_Position[0] and snake_Head[1]==food_Position[1]:
food_flag = 0
else:
snake_Body.pop()
3.5 重新生成食物
當遊戲介面中的食物數量為0時,需要重新生成食物。利用random函式來生成隨機位置
# 生成新的食物
if food_flag == 0:
# 隨機生成x, y
x = random.randrange(1,32)
y = random.randrange(1,24)
food_Position = [int(x*20),int(y*20)]
food_flag = 1
3.6 繪製貪吃蛇、食物、分數等資訊
定義貪吃蛇的繪製函式
# 繪製貪吃蛇
def drawSnake(snake_Body):
for i in snake_Body:
pygame.draw.rect(DISPLAY, WHITE, Rect(i[0], i[1], 20, 20))
定義食物的繪製函式
# 繪製食物的位置
def drawFood(food_Position):
pygame.draw.rect(DISPLAY, RED, Rect(food_Position[0], food_Position[1], 20, 20))
定義分數的繪製函式
# 列印出當前得分
def drawScore(score):
# 設定分數的顯示顏色
score_Surf = BASICFONT.render('%s' %(score), True, GREY)
# 設定分數的位置
score_Rect = score_Surf.get_rect()
score_Rect.midtop = (320, 240)
# 繫結以上設定到控制程式碼
DISPLAY.blit(score_Surf, score_Rect)
這些都定義好之後,我們需要在遊戲主邏輯中呼叫它們,並重新整理Pygame的顯示層,貪吃蛇與食物的每一次移動,都會進行重新整理顯示層的操作來顯示。最後我們可以設定一個速度值來合理控制遊戲執行的速度。
DISPLAY.fill(BLACK)
# 畫出貪吃蛇
drawSnake(snake_Body)
# 畫出食物的位置
drawFood(food_Position)
# 列印出玩家的分數
drawScore(len(snake_Body) - 3)
# 重新整理Pygame的顯示層,貪吃蛇與食物的每一次移動,都會進行重新整理顯示層的操作來顯示。
pygame.display.flip()
# 控制遊戲速度
FPSCLOCK.tick(7)
3.7 定義遊戲結束的畫面並判斷遊戲是否結束
定義函式,用於展示遊戲結束的畫面並退出程式
# 遊戲結束並退出
def GameOver():
# 設定GameOver的顯示顏色
GameOver_Surf = BASICFONT.render('Game Over!', True, GREY)
# 設定GameOver的位置
GameOver_Rect = GameOver_Surf.get_rect()
GameOver_Rect.midtop = (320, 10)
# 繫結以上設定到控制程式碼
DISPLAY.blit(GameOver_Surf, GameOver_Rect)
pygame.display.flip()
# 等待3秒
time.sleep(3)
# 退出遊戲
pygame.quit()
# 退出程式
sys.exit()
在遊戲主邏輯中加入判斷,遊戲是否結束
'''遊戲結束的判斷'''
# 貪吃蛇觸碰到邊界
if snake_Head[0]<0 or snake_Head[0]>620:
GameOver()
if snake_Head[1]<0 or snake_Head[1]>460:
GameOver()
# 貪吃蛇觸碰到自己
for i in snake_Body[1:]:
if snake_Head[0]==i[0] and snake_Head[1]==i[1]:
GameOver()
4 後記
本文利用Pygame模組實現了最簡單的貪吃蛇版本。當然還有很多需要優化的地方,比如隨機生成食物時如何避免出現在貪吃蛇的自身上、通過貪吃蛇的長度來自動控制遊戲速度等等。更高階一點的有如何通過AI自動玩貪吃蛇、貪吃蛇的雙人對戰等,期待大家利用Python可以把貪吃蛇玩出一個新的高度!???
公眾號「Python專欄」後臺回覆關鍵字「貪吃蛇」獲取本文全套完整程式碼!