使用Python的pygame库实现贪吃蛇小游戏


1. 前言

应某人要求,把非常难看的贪吃蛇发到博客上,界面如下(非常难看):

1

2

2. 源码

import pygame
import sys
import random
import pygame.freetype

# 初始化
pygame.init()
pygame.mixer.init()

# 基本颜色
WHITE = 255, 255, 255
BLACK = 0, 0, 0
RED = 255, 0, 0
YELLOW = 255, 255, 0
GREEN = 0, 255, 0

# 果实参数
BlueFlower = pygame.image.load("blue-flower.png")
FireFlower = pygame.image.load("fire-flower.png")
PinkFlower = pygame.image.load("pink-flower.png")
Flower = pygame.image.load("flower.png")
IceFlower = pygame.image.load("ice-flower.png")
BlueFlower = pygame.transform.scale(BlueFlower, (20, 20))
FireFlower = pygame.transform.scale(FireFlower, (20, 20))
PinkFlower = pygame.transform.scale(PinkFlower, (20, 20))
Flower = pygame.transform.scale(Flower, (20, 20))
IceFlower = pygame.transform.scale(IceFlower, (20, 20))
FoodType = [BlueFlower, FireFlower, PinkFlower, Flower, IceFlower]

# 基本窗口及图形
size = width, height = 1000, 700
startX = 0
startY = 100
PAUSE = pygame.image.load("pause.png")
CONTINUE = pygame.image.load("continue.png")
PAUSE_AFTER = pygame.image.load("pause-after.png")
GAMEOVER = pygame.image.load("game-over.png")
ICON = pygame.image.load("icon.png")
RETURN = pygame.image.load("return.png")
PAUSE = pygame.transform.scale(PAUSE, (100, 100))
CONTINUE = pygame.transform.scale(CONTINUE, (100, 100))
PAUSE_AFTER = pygame.transform.scale(PAUSE_AFTER, (400, 200))
GAMEOVER = pygame.transform.scale(GAMEOVER, (100, 100))
RETURN = pygame.transform.scale(RETURN, (100, 100))
BackGround = BLACK  # 背景为黑色
SimKai = pygame.freetype.Font("simkai.ttf")
MUSIC = "music.mp3"
P_C_Position = pygame.Rect(0, 0, 100, 100)
GameoverPosition = pygame.Rect(100, 0, 100, 100)
PausePosition = pygame.Rect(300, 300, 400, 200)

# 蛇及食物基本信息
SnakePosition = [200, 300]  # 蛇头位置
SnakeBodys = [[200, 300], [180, 300], [160, 300]]  # 蛇身位置
FoodPositions = [[400, 400, 1]]  # 果实位置,0表示该果实为FoodType[0],即BlueFlower
SnakeColor = GREEN
global Speed, EatNumber, Direction, ChangeDirection

# 初始化窗口
screen = pygame.display.set_mode(size)
screen.fill(BackGround)
pygame.display.set_caption("欢迎来到贪吃蛇大作战!")
pygame.display.set_icon(ICON)
pygame.mixer.music.load(MUSIC)
pygame.mixer.music.play(-1)


# 游戏开始
def GameBegain():
    global Speed, EatNumber, Direction, ChangeDirection
    Speed = 2
    EatNumber = 1
    Direction = "right"
    ChangeDirection = Direction

    screen.fill(BackGround)
    SnakePosition.clear()
    SnakePosition.insert(0, 300)
    SnakePosition.insert(0, 200)

    SnakeBodys.clear()
    SnakeBodys.insert(0, [160, 300])
    SnakeBodys.insert(0, [180, 300])
    SnakeBodys.insert(0, [200, 300])

    FoodPositions.clear()
    FoodPositions.insert(0, [400, 400, 1])
    TipsSet()
    SnakeMove()
    FoodDisplay()
    Pause()


# 菜单栏设置
def TipsSet():
    screen.blit(GAMEOVER, GameoverPosition)
    SimKaiRect1 = SimKai.render_to(screen, (210, 10), "点击空格键继续/暂停", fgcolor=RED, size=25)
    SimKaiRect2 = SimKai.render_to(screen, (210, 50), "点击暂停键继续/暂停", fgcolor=RED, size=25)
    SimKaiRect3 = SimKai.render_to(screen, (450, 30), "当前得分:", fgcolor=RED, size=50)
    SimKaiRect4 = SimKai.render_to(screen, (700, 30), str(len(SnakeBodys)), fgcolor=RED, size=60)
    LineRect1 = pygame.draw.line(screen, WHITE, (0, 100), (1000, 100), 5)
    pygame.display.update()


# display 蛇的位置
def SnakeMove():
    for body in SnakeBodys:
        pygame.draw.rect(screen, SnakeColor, pygame.Rect(body[0], body[1], 20, 20))


# display 果实位置
def FoodDisplay():
    for food in FoodPositions:
        position = pygame.Rect(food[0], food[1], 20, 20)
        num = food[2]
        screen.blit(FoodType[num], position)


# 游戏结束
def GameOver():
    pygame.draw.rect(screen, YELLOW, pygame.Rect(300, 300, 400, 300))
    SimKaiRect5 = SimKai.render_to(screen, (360, 350), "最终得分:", fgcolor=RED, size=50)
    SimKaiRect6 = SimKai.render_to(screen, (600, 350), str(len(SnakeBodys)), fgcolor=RED, size=60)
    screen.blit(RETURN, (360, 420))
    screen.blit(GAMEOVER, (520, 420))
    pygame.display.flip()

    while True:
        event = pygame.event.poll()
        if event.type == pygame.MOUSEBUTTONDOWN:
            x, y = event.pos
            if 360 < x < 460 and 420 < y < 520:
                GameBegain()  # 重新开始
                break
            elif 520 < x < 620 and 420 < y < 520:
                sys.exit()  # 退出游戏
        elif event.type == pygame.QUIT:
            sys.exit()


# 继续游戏
def Continue():
    screen.fill(BackGround)
    screen.blit(PAUSE, P_C_Position)
    TipsSet()
    SnakeMove()
    FoodDisplay()
    pygame.display.flip()


# 游戏暂停
def Pause():
    screen.blit(PAUSE_AFTER, PausePosition)
    screen.blit(CONTINUE, P_C_Position)
    pygame.display.flip()
    while True:
        event = pygame.event.poll()
        if event.type == pygame.QUIT:  # 退出游戏
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE:  # 重新开始
                break
            elif event.key == pygame.K_ESCAPE:  # ESC键
                sys.exit()
        elif event.type == pygame.MOUSEBUTTONDOWN:  # 重新开始
            x, y = event.pos
            if 1 < x < 99 and 1 < y < 99:
                break
    Continue()


# 增加食物
def AddFood(num):
    while num > 0:
        addType = int(random.randrange(0, 100)) % 5
        addX = int(random.randrange(0, 50))
        addY = int(random.randrange(0, 30))
        position = [addX * 20, addY * 20 + 100, addType]
        occupied = 0
        for food in FoodPositions:
            if food[0] == position[0] and food[1] == position[1]:
                occupied = 1
                break
        for body in SnakeBodys:
            if body[0] == position[0] and body[1] == position[1]:
                occupied = 1
                break
            elif occupied == 1:
                break
        if occupied == 0:
            FoodPositions.insert(0, list(position))
            num -= 1


# main函数
def main():
    time_clock = pygame.time.Clock()

    GameBegain()

    # 开始游戏
    global Speed, EatNumber, Direction, ChangeDirection
    while True:

        # 事件处理
        for event in pygame.event.get():
            if event.type == pygame.QUIT:  # 退出游戏
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:  # ESC
                    sys.exit()
                elif event.key == pygame.K_SPACE:  # 暂停
                    Pause()
                elif event.key == pygame.K_UP:  # change direction
                    ChangeDirection = "up"
                elif event.key == pygame.K_DOWN:  # change direction
                    ChangeDirection = "down"
                elif event.key == pygame.K_LEFT:  # change direction
                    ChangeDirection = "left"
                elif event.key == pygame.K_RIGHT:  # change direction
                    ChangeDirection = "right"
            elif event.type == pygame.MOUSEBUTTONDOWN:
                x, y = event.pos
                if 101 < x < 199 and 1 < y < 99:  # 暂停
                    GameOver()
                elif 1 < x < 99 and 1 < y < 99:  # 终止
                    Pause()

        # 防止蛇头反向
        if ChangeDirection == "right" and not Direction == "left":
            Direction = ChangeDirection
        if ChangeDirection == "left" and not Direction == "right":
            Direction = ChangeDirection
        if ChangeDirection == "up" and not Direction == "down":
            Direction = ChangeDirection
        if ChangeDirection == "down" and not Direction == "up":
            Direction = ChangeDirection

        # 根据方向移动蛇头
        if Direction == "right":
            SnakePosition[0] += 20
        if Direction == "left":
            SnakePosition[0] -= 20
        if Direction == "up":
            SnakePosition[1] -= 20
        if Direction == "down":
            SnakePosition[1] += 20

        # 增加蛇的长度
        SnakeBodys.insert(0, list(SnakePosition))

        # 判断是否吃到果实
        for food in FoodPositions:
            if food[0] == SnakePosition[0] and food[1] == SnakePosition[1]:
                FoodPositions.remove(food)
                EatNumber += 1
                break
        else:
            SnakeBodys.pop()

        # 生成食物
        FoodRange = int(random.randrange(0, 100)) % 3 + 50
        if len(FoodPositions) < FoodRange:
            addNum = int(random.randrange(0, 100)) % 3 + 2
            AddFood(addNum)

        # 更改食物位置
        if EatNumber % 10 == 0:
            EatNumber = 1
            replaceNum = int(random.randrange(0, 100)) % 3 + 2
            AddFood(replaceNum)
            while replaceNum > 0:
                FoodPositions.pop()
                replaceNum -= 1
            Speed += len(SnakeBodys) / 5 * 0.3  # 设置递增速度

        # 碰到身体结束游戏
        num = 0
        for body in SnakeBodys[1:]:
            num += 1
            if body[0] == SnakePosition[0] and body[1] == SnakePosition[1]:
                GameOver()

        # 碰到边界结束游戏
        if SnakePosition[0] < startX or SnakePosition[0] >= width or \
                SnakePosition[1] < startY or SnakePosition[1] >= height:
            GameOver()

        # 显示游戏过程
        Continue()
        # 控制游戏速度
        time_clock.tick(Speed)


# 入口函数
if __name__ == "__main__":
    main()

3.附件

由于还没搞好下载文件的功能,使用的花朵图片、icon、按键、音乐等自行P图,或联系我直接获取。


文章作者: 易安
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 易安 !
评论
  目录