Python使用pygame写的贪吃蛇详解

使用python实现的贪吃蛇小游戏,只实现了基础功能

代码

import pygame #python中流行游戏开发库,提供图像处理等功能
import random #python标准库,随机生成数,随机生成食物位置

#初始化模块
pygame.init()

# 颜色
white = (255, 255, 255)
yellow = (255, 255, 102)
black = (0, 0, 0)
red = (213, 50, 80)
green = (0, 255, 0)
blue = (50, 153, 213)

# 定义显示屏幕大小
dis_width = 800  #宽度800像素
dis_height = 600 #高度600像素

#创建游戏窗口和题目
dis = pygame.display.set_mode((dis_width, dis_height))
pygame.display.set_caption('贪吃蛇小游戏')

#提供了一个方法控制帧率
clock = pygame.time.Clock()

#蛇被绘制成10×10的像素块
snake_block = 10

#游戏中字体设置
font_style = pygame.font.SysFont(None, 80, bold=False)
score_font = pygame.font.SysFont(None, 25)

def your_score(score):
    #显示当前分数
    value = score_font.render("Score: " + str(score), True, yellow) #将分数储存在value中
    dis.blit(value, [10, 10])                                       #绘制在离图像左上10×10的位置

def our_snake(snake_block, snake_list):
    #绘制蛇
    for x in snake_list:
        pygame.draw.rect(dis, black, [x[0], x[1], snake_block, snake_block])    #绘制每节蛇的位置
'''
#使用这段代码不能够将\n显示分行
def message(msg, color):        #传入文本和颜色
    #居中显示信息
    mesg = font_style.render(msg, True, color)  #True表示抗锯齿
    text_rect = mesg.get_rect(center=(dis_width / 2, dis_height / 2))  # 获取居中位置
    dis.blit(mesg, text_rect)
'''

def message(msg, color):        
    # 分割消息为多行并居中显示
    lines = msg.split('\n')  # 使用换行符分割消息
    line_height = font_style.get_height()  # 获取单行文本的高度
    total_height = line_height * len(lines)  # 计算所有行的总高度
    start_y = (dis_height - total_height) // 2  # 计算开始绘制的位置,使其垂直居中

    # 循环绘制每一行
    for i, line in enumerate(lines):
        mesg = font_style.render(line, True, color)  # 渲染每行文本
        text_rect = mesg.get_rect(center=(dis_width / 2, start_y + i * line_height))  # 获取每行的矩形区域并居中
        dis.blit(mesg, text_rect)  # 绘制消息


def gameLoop():
    #游戏主循环
    game_over = False

    #初始位置
    x1 = dis_width / 2
    y1 = dis_height / 2

    #控制运动方向,初始不移动
    x1_change = 0
    y1_change = 0

    snake_list = []     #储存蛇的位置
    Length_of_snake = 1 #蛇的长度

    #定义食物随机位置
    foodx = round(random.randrange(0, dis_width - snake_block)/10) * 10.0 
    foody = round(random.randrange(0, dis_height - snake_block)/10) * 10.0

    #游戏循环
    while not game_over:

        for event in pygame.event.get():
            #用户点击了×就停止
            if event.type == pygame.QUIT:
                game_over = True
            #检测用户按下的键
            if event.type == pygame.KEYDOWN:
                # 防止掉头
                if event.key == pygame.K_LEFT and x1_change == 0:
                    x1_change = -snake_block
                    y1_change = 0
                elif event.key == pygame.K_RIGHT and x1_change == 0:
                    x1_change = snake_block
                    y1_change = 0
                elif event.key == pygame.K_UP and y1_change == 0:
                    y1_change = -snake_block
                    x1_change = 0
                elif event.key == pygame.K_DOWN and y1_change == 0:
                    y1_change = snake_block
                    x1_change = 0
                
                '''
                # WASD 键对应的控制,加入WASD控制会明显感觉到运行变慢,有延迟
                elif event.key == pygame.K_a and x1_change == 0:  # A: 向左
                    x1_change = -snake_block
                    y1_change = 0
                elif event.key == pygame.K_d and x1_change == 0:  # D: 向右
                    x1_change = snake_block
                    y1_change = 0
                elif event.key == pygame.K_w and y1_change == 0:  # W: 向上
                    y1_change = -snake_block
                    x1_change = 0
                elif event.key == pygame.K_s and y1_change == 0:  # S: 向下
                    y1_change = snake_block
                    x1_change = 0
                '''
        # 判断是否撞墙,位置超出边界就撞墙
        if x1 >= dis_width or x1 < 0 or y1 >= dis_height or y1 < 0:
            game_over = True

        #更新位置
        x1 += x1_change
        y1 += y1_change
        dis.fill(blue)  #填充屏幕
        pygame.draw.rect(dis, green, [foodx, foody, snake_block, snake_block])  #绘制食物,矩形
        snake_head = [x1, y1]
        snake_list.append(snake_head)
        if len(snake_list) > Length_of_snake:
            del snake_list[0]

        # 判断是否撞到自己
        for block in snake_list[:-1]:
            if block == snake_head:
                game_over = True

        our_snake(snake_block, snake_list)
        your_score(Length_of_snake - 1)
        pygame.display.update()

        # 判断是否吃到食物
        if x1 == foodx and y1 == foody:
            foodx = round(random.randrange(0, dis_width - snake_block)/10) * 10.0
            foody = round(random.randrange(0, dis_height - snake_block)/10) * 10.0
            Length_of_snake += 1

        #蛇的帧率,或者说蛇移动的速度,随着Length_of_snake越大,速度越快
        clock.tick(10 + (Length_of_snake // 5))

    # 游戏结束
    #dis.fill(blue)
    message("Game Over!\nYour Score=" + str(Length_of_snake-1), yellow)
    pygame.display.update()
    pygame.time.delay(2000)  # 显示2秒退出
    pygame.quit()

gameLoop()

运行需要pygame库

pip3 install pygame

可以打包成exe

pip install pyinstaller
pyinstaller --onefile --windowed snake_game.py

pygame函数

使用的pygame部分函数

  • 创建窗口:screen = pygame.display.set_mode((800, 600)) # 800x600窗口
  • 设置窗口标题:pygame.display.set_caption("My Game")
  • 更新窗口:pygame.display.update()
  • 检测输入,如鼠标键盘等:
#点×退出
for event in pygame.event.get():
    if event.type == pygame.QUIT:
        pygame.quit()

#键盘
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
    # 左箭头键被按下

#鼠标
x, y = pygame.mouse.get_pos()

#鼠标键
left, middle, right = pygame.mouse.get_pressed()
if left:
    # 鼠标左键被按下...
  • 图形绘制:
pygame.draw.rect(screen, (255, 0, 0), (100, 100, 50, 50))  # rect红色矩形
pygame.draw.circle(screen, (0, 255, 0), (400, 300), 50)  # circle绿色圆形
pygame.draw.line(screen, (0, 0, 255), (100, 100), (200, 200), 5)  # line蓝色线条
pygame.draw.polygon(screen, (255, 255, 0), [(100, 100), (200, 50), (300, 100)])  # 黄色三角形,polygon是多边形
  • 图像加载:image = pygame.image.load("image.png")
  • 图像放置:screen.blit(image, (x, y)) # 在指定位置绘制图像
  • 帧率:clock = pygame.time.Clock() clock.tick(60) # 设置帧率为60
  • 字体文字:
#字体样式,大小
font = pygame.font.SysFont("Arial", 30)
#字体内容,抗锯齿,颜色
text_surface = font.render("Hello, World!", True, (255, 255, 255))
#输出,位置
screen.blit(text_surface, (100, 100))