今天利用python開發一款童年小遊戲:貪喫蛇
1.首先導入必備的包,這裏就出現了本次項目的一個bug就是from pygame.locals import * 始終無法調用,導致一些pygame中的常亮調用出現標紅,最後在常亮之前加上pygame.才得已解決,目前仍不明爲何調用不到?
import pygame
import sys # py解析器
from pygame.locals import *
import random
import copy
2.定義遊戲界面的基本顏色
redColor = pygame.Color(255, 0, 0)
whiteColor = pygame.Color(255, 255, 255)
blackColor = pygame.Color(0, 0, 0)
3.定義遊戲的結束函數,當運行過程中滿足某些情況時調用該函數結束遊戲
def gameOver():
pygame.quit()
sys.exit()
4.初始化遊戲的一些變量,首先初始化pygame,這是必要的操作,然後定義遊戲的fps速率,定義遊戲窗口的大小,之後解釋貪喫蛇的原始位置也就是蛇頭,定義了蛇的身子列表,定義了目標方塊的位置以及判斷方塊是否被喫掉的標記,最後定義了貪喫蛇的移動方向,這裏先初始設置向右移動。
def main():
# 初始化pygame
pygame.init()
# 控制遊戲速度
fpsClock = pygame.time.Clock()
# 定義一個窗口
playSurface = pygame.display.set_mode((640, 480))
pygame.display.set_caption('貪喫蛇')
# 初始化變量
# 貪喫是初始位置
snakePosition = [100, 100]
# 貪喫蛇長度
snakeBody = [[100, 100], [80, 100], [60, 100]]
# 目標方塊位置
targetPosition = [300, 300]
# 定義標記,判斷是否喫掉
targetflag = 1
# 初始化方向,往右
direction = 'right'
# 改變方向變量
changeDirection = direction
4.1 pygame中的事件,放到一個實時循環當中處理,使得控制檯實時的監視用戶的操作,加以改變遊戲的進程。就是計算機實時的監視用戶對鍵盤的操作,用以改變蛇是移動方向
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
changeDirection = 'right'
if event.key == pygame.K_LEFT:
changeDirection = 'left'
if event.key == pygame.K_UP:
changeDirection = 'up'
if event.key == pygame.K_DOWN:
changeDirection = 'down'
4.2 這裏的判斷意義在於當蛇再向左或向右移動時,是不可能立馬做出反方向的移動的,必須先向上或向下移動之後,纔可以反方向水平移動,這裏的判斷就是將上下左右的反向移動全部禁用掉,使得反向移動無效
if changeDirection == 'left' and not direction == 'right':
direction = changeDirection
if changeDirection == 'right' and not direction == 'left':
direction = changeDirection
if changeDirection == 'up' and not direction == 'down':
direction = changeDirection
if changeDirection == 'down' and not direction == 'up':
direction = changeDirection
4.3 根據方向移動蛇頭,這裏的操作是將蛇頭按照上一步的移動方向進行位置的遞增
if direction =='right':
snakePosition[0] += 20
if direction =='left':
snakePosition[0] -= 20
if direction =='up':
snakePosition[1] -= 20
if direction =='down':
snakePosition[1] += 20
4.4 增加蛇的長度,將新蛇頭添加到body列表的首位,然後利用判斷語句,如果喫到方塊即新蛇頭的位置與目標方塊的位置相同,就將方塊的標記改爲0,證明場上已經沒有方塊了,系統將隨機生成新的方塊,這樣蛇的長度就增加了一個單位,實現喫方塊蛇變長的邏輯,然後如果蛇的這次移動沒有喫到方塊,就將body的末位pop()刪掉,蛇的長度依舊沒有變化,實現了蛇的移動
snakeBody.insert(0,list(snakePosition))
# 判斷喫方塊
if snakePosition[0] == targetPosition[0] and snakePosition[1] == targetPosition[1]:
targetflag = 0
else:
snakeBody.pop()
4.5 及時補充目標方塊,系統判斷到目前的小方塊已經被蛇喫掉,標記爲0,就使用random.randrange在移動範圍內產生隨機數,經過計算產生新的方塊
if targetflag == 0:
x = random.randrange(1, 32)
y = random.randrange(1, 24)
targetPosition = [int(x*20), int(y*20)]
targetflag = 1
4.6 繪製遊戲界面,這裏再次遇到了Rect無法調用的問題,最後使用 pygame.Rect才使程序不報錯
playSurface.fill(blackColor)
for position in snakeBody:
pygame.draw.rect(playSurface, whiteColor, pygame.Rect(position[0], position[1], 20, 20))
pygame.draw.rect(playSurface, redColor, pygame.Rect(targetPosition[0], targetPosition[1], 20, 20))
4.7 遊戲結束判定,最開始僅僅利用邊界限制,當蛇頭超出上下左右的邊界框時遊戲結束,我再測試時發現普通遊戲中蛇頭如果撞到自己的身體也會使得遊戲結束,因此對代碼進行了修改使蛇頭撞到自己的身體時結束遊戲,在這裏我最先使用的是直接對body進行判斷,如果蛇頭在body.pop[0]內則說明蛇撞到了自己,結果發現pop會使蛇缺失紫的身體,於是改用賦值語句新建了一個bodyB來存儲預判斷,結果發現就像之前幾天學習的copy一樣如果有多級的列表多級列表中保存的依舊是原始body的地址,於是想到了剛學的deepcopy只會複製取值,而不會關聯地址,於是最終實現了蛇頭撞到自身判斷結束遊戲這個功能
pygame.display.flip()
snakeB = copy.deepcopy(snakeBody)
snakeB.pop(0)
print(snakeB)
if snakePosition[0] > 620 or snakePosition[0] < 0:
gameOver()
if snakePosition[1] >460 or snakePosition[1] <0:
gameOver()
elif snakePosition in snakeB:
gameOver()
4.8 控制遊戲速度
fpsClock.tick(5)
5.運行遊戲開始
if __name__ == '__main__':
main()