pygame學習日記——貪喫豬(蛇)

新手向——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()




遊戲界面
## 生成一個適合你的列表

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章