新手向——pygame實現貪喫蛇小遊戲
豬頭圖片由一隻可愛的靈魂畫家提供
貪喫蛇主要邏輯是蛇的頭部帶動身體移動,所以移動操作時,只需要更新頭部的位置信息,而蛇身的每一塊位置則更替爲前一塊的位置。使用列表存儲蛇(蛇的頭部和身體塊分別由一對座標表示),列表的第一個元素即爲蛇頭,對於每一次移動,採用生成新的位置座標插入到列表的首位充當新的頭部,並將列表的最後一個元素丟棄,實現蛇身每一塊的前移。完整代碼如下:
源碼文件: https://download.csdn.net/download/qq_36947570/12348761.
詳細註釋源碼
import pygame
import sys
import random
#定義用來表示移動方向的常量(Python中並沒有提供定義常量的保留字)
UP = 'move_up'
DOWN = 'move_down'
LEFT = 'move_left'
RIGHT = 'move_right'
#初始化pygame 關於init()函數相關信息見https://blog.csdn.net/Enderman_xiaohei/article/details/88655432
pygame.init()
#加載頭部,身體和食物的圖片
image_head = pygame.image.load("src/head.png")
image_body = pygame.image.load("src/body.png")
image_food = pygame.image.load("src/food.png")
#設置格子單位,後面的移動操作都是以此最單位進行
unit = image_body.get_width()
#設置遊戲窗體尺寸
frame_size = width, height = 40,20
#生成遊戲窗口
screen = pygame.display.set_mode((frame_size[0]*unit, frame_size[1]*unit))
#設置窗體標題
pygame.display.set_caption("貪喫豬")
#設置遊戲圖標
pygame.display.set_icon(image_head)
#加載字體
font_score = pygame.font.Font("src/font.ttf",24)
font_start = pygame.font.Font("C:/Windows/Fonts/HGCY_CNKI.TTF",48)
#用於設置遊戲畫面刷新幀數
clock = pygame.time.Clock()
#食物生成函數,需要傳入蛇
def gen(snack):
while True:
#隨機生成食物的座標
x = random.randrange(1, frame_size[0] - 1) * unit
y = random.randrange(1, frame_size[1] - 1) * unit
#用來標誌生成的食物是否於蛇重疊
repeat = False
for each in snack:
#判斷是否重疊,如果重疊就將repeat標識設置爲True,重新生成食物
if x == each[0] and y == each[1]:
repeat = True
#不重疊就返回食物座標
if not repeat:
return [x, y]
#移動函數,需要傳入移動方向和蛇
def move(direction,snack):
newhead = []
#聲明unit是全局變量
global unit
#生成新的頭部
newhead.append(snack[0][0])
newhead.append(snack[0][1])
#根據傳入的方向設置新頭部的移動
if direction == UP:
newhead[1] -= unit
elif direction == DOWN:
newhead[1] += unit
elif direction == RIGHT:
newhead[0] += unit
elif direction == LEFT:
newhead[0] -= unit
#將新的頭部插到列表的首位,並移除snake列表的最後一個元素,實現蛇的整體移動
#移動的本質時頭部帶動身體,每一塊身體移動到前一塊身體的位置
snack.insert(0,newhead)
snack.pop()
#返回移動過的蛇
return snack
#遊戲開始界面,隨便寫的,可以忽略
def gamestart():
global unit,frame_size
speed_start = [1, 1]
speed_exit = [1, 1]
text_start = font_start.render("開始遊戲", True, (255, 0, 0))
text_start_rect = text_start.get_rect()
text_exit = font_start.render("退出遊戲", True, (255, 0, 0))
text_exit_rect = text_exit.get_rect()
text_exit_rect.left = frame_size[0]*unit - text_exit_rect.width
while True:
for event in pygame.event.get():
#設置退出
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.pos[0] > text_start_rect.left \
and event.pos[0] < text_start_rect.right \
and event.pos[1] > text_start_rect.top \
and event.pos[1] < text_start_rect.bottom:
return True
elif event.pos[0] > text_exit_rect.left \
and event.pos[0] < text_exit_rect.right \
and event.pos[1] > text_exit_rect.top \
and event.pos[1] < text_exit_rect.bottom:
pygame.quit()
sys.exit()
text_start_rect = text_start_rect.move(speed_start[0], speed_start[1])
text_exit_rect = text_exit_rect.move(speed_exit[0], speed_exit[1])
if text_start_rect.left < 0 or text_start_rect.right > frame_size[0] * unit:
speed_start[0] = - speed_start[0]
if text_start_rect.top < 0 or text_start_rect.bottom > frame_size[1] * unit:
speed_start[1] = - speed_start[1]
if text_exit_rect.left < 0 or text_exit_rect.right > frame_size[0] * unit:
speed_exit[0] = - speed_exit[0]
if text_exit_rect.top < 0 or text_exit_rect.bottom > frame_size[1] * unit:
speed_exit[1] = - speed_exit[1]
screen.fill((255, 255, 255))
screen.blit(text_start, text_start_rect)
screen.blit(text_exit,text_exit_rect)
pygame.display.update()
clock.tick(300)
#遊戲主體函數
def maingame():
global unit
# 遊戲開始時生成蛇的頭部(遊戲中的頭部,身體和食物均以座標元組(x,y)表示
head = [5 * unit, 5 * unit]
# 使用列表來表示整條蛇,遊戲開始時只有頭部和兩節身體
snack = [head, [4 * unit, 5 * unit], [3 * unit, 5 * unit]]
#用於檢測頭部是否觸碰身體
collision = False
# 設置蛇默認的移動方向
direction = RIGHT
# 用於判斷畫面中是否已經存在食物,如果不存在(被喫掉)就重新生成食物
food_exist = False
# 用來保存食物的位置
food_site = (0, 0)
# 用於控制移動頻率
delay = 0
while True:
for event in pygame.event.get():
#設置退出
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
#設置按鈕操作監聽
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
#按下上建如果當前方向不是向下,則設置方向向上,並移動一次
if direction != DOWN:
direction = UP
#重置delay,防止移動後立即再次移動
delay = 0
snack = move(direction, snack)
elif event.key == pygame.K_DOWN:
if direction != UP:
direction = DOWN
delay = 0
snack = move(direction, snack)
elif event.key == pygame.K_RIGHT:
if direction != LEFT:
direction = RIGHT
delay = 0
snack = move(direction, snack)
elif event.key == pygame.K_LEFT:
if direction != RIGHT:
direction = LEFT
delay = 0
snack = move(direction, snack)
#當不存在食物時,創建食物
if not food_exist:
food_site = gen(snack)
food_exist = not food_exist
#填充窗體背景爲白色
screen.fill((255, 255, 255))
delay = (delay + 1) % 90
#如果頭部和食物座標相同,代表食物被喫,重新生成食物,身體加一
if snack[0][0] == food_site[0] and snack[0][1] == food_site[1]:
food_exist = False
#在身體的第一塊設置新的身體,便於檢測頭部與身體的碰撞
snack.append(snack[1])
#畫面沒刷新30此執行一次移動
if not delay%30:
snack = move(direction, snack)
#繪製得分,得分爲snack的長度減3
text = font_score.render("Your Score: {}".format(len(snack)-3), True, (255, 0, 0))
screen.blit(text,(30,30))
#繪製蛇
for each in snack:
screen.blit(image_body, (each[0], each[1]))
#重新繪製頭部
screen.blit(image_head,(snack[0][0], snack[0][1]))
#繪製食物
screen.blit(image_food,(food_site[0],food_site[1]))
#檢測頭部是否與身體碰撞
for each in snack[1:]:
if each[0] == snack[0][0] and each[1] == snack[0][1]:
collision = True
#如果頭部碰牆,則遊戲結束,繪製遊戲結束畫面
if snack[0][0] < 0 or snack[0][1] < 0 \
or snack[0][0] + unit > frame_size[0]*unit \
or snack[0][1] + unit > frame_size[1]*unit\
or collision:
screen.fill((255,255,255))
text_again = font_start.render("GameOver", True, (255, 0, 0))
screen.blit(text_again, (450, 100))
text_score = font_score.render("Your Score: {}".format(len(snack)-3), True, (255, 0, 0))
screen.blit(text_score, (510, 200))
text_again = font_start.render("重新開始", True, (255, 0, 0))
screen.blit(text_again, (480, 300))
text_exit = font_start.render("退出遊戲", True, (255, 0, 0))
screen.blit(text_exit, (480, 400))
pygame.display.update()
while True:
for event in pygame.event.get():
# 設置退出
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN:
#點擊重新開始
if event.pos[0] > 480\
and event.pos[0] < 480 + text_again.get_rect().width\
and event.pos[1] > 300\
and event.pos[1] < 300 + text_again.get_rect().height:
return True
#點擊退出遊戲
elif event.pos[0] > 480\
and event.pos[0] < 480 + text_exit.get_rect().width\
and event.pos[1] > 400\
and event.pos[1] < 400 + text_exit.get_rect().height:
pygame.quit()
sys.exit()
#設置刷新幀率
clock.tick(50)
#更新畫面
pygame.display.update()
if __name__ == '__main__':
#控制界面顯示
Start = False
while True:
if Start:
Start = maingame()
else:
Start = gamestart()
遊戲界面