用pygame制作贪吃蛇游戏(详细)

案例导入

相信我们绝大多数的人都玩过贪吃蛇这款游戏
今天我们就用python制作这款游戏
但是首先我们想做它就得弄明白他的实现原理是什么

基本原理

首先我们要做的这款游戏界面是很low的,因为我们做的这款游戏算是最简单最入门的一款游戏
玩过这个游戏的人都很清楚,这个蛇在行走时的每一个格子都会移动到他前一个格子的位置,类似于这样一个一个跟随着往前走,最前面的那个格子是跟随着脑袋也就是蛇头往前走,头跟着你的控制器的方向走,这就实现了一个移动跟随
在这里插入图片描述
因为是贪吃蛇所以他要吃东西,当它的头部碰到了食物之后也就是头和食物重合了,他的尾部就会增加一格,这就是一个进食的过程 本人灵魂画师请不要介意
其实这就是这个游戏的核心思想,就干了这么两件事
在这里插入图片描述

所需工具

pygame 下载地址

实际操作

废话不多说,直接动手
第一步 导入模块
在这里插入图片描述
第二步 初始化框架
在这里插入图片描述
因为宽和高要经常用到,所以把它存在一个变量里面
在这里插入图片描述
在我们set_mode的同时会给我们创建一个window对象,我们就可以拿着window对象去显示了
set_caption设置标题
现在运行就会有个一闪而过的窗口
下面的们的代码会解决这个问题
我们代码最重要的部分 游戏循环
这个循环要一直循环下去,但是不能让他变成死循环
怎么解决这个问题呢,首先,这个游戏是可以结束的,结束的条件就是当用户点击退出或者是操作的蛇撞死的时候,这个循环就可以停了
所以我们可以设置一个变量quit=False,让他一直是false,循环应该结束的时候变成True
其次我们不能让这个循环一直不停的跑,我们要留出时间来去做一些游戏的渲染或者其他的一些工作,这些工作都是交给系统的,这里我们会用到pygame里面的time.Clock() 这个就是游戏的时间控制,比如把这个游戏调成多少帧
在这里插入图片描述
在这里插入图片描述
现在已经可以出现一个这样的窗口了

接下来我们还要处理游戏的一些事件和渲染
我们第一个要处理的事件就是游戏的退出
在这里插入图片描述
pygame.event.get()是获取到当前事件的队列
因为我们要处理这个队列的所有事件,
一般我们都会设置一个循环,就可以去处理内部一个一个的event

下面要做的就是渲染了,任何一个游戏都要有渲染的过程

pygame.draw.rect(window,)绘制工具,参数1要说明你要往哪画,参数2要说明你要画什么颜色的东西,参数三要说明你要画的范围,从哪开始到哪里结束
pygame.display.flip() #暂时把控制权交还给系统,让系统去做一些渲染操作
结果
显示结果如下:(不要在意它的颜色)
在这里插入图片描述
现在已经完成了框架初始化的操作
第三步 绘制场景
在这里插入图片描述可以把上面的场景看成一个相对较大的二维数组(学过numpy的同学应该很好理解)
类似于这样:0 0 0 0 0
0 2 1 1 0
0 0 0 1 1
1代表蛇 2代表食物 每个元素都有一个数据
现在我们需要把这个给体现出来:
在这里插入图片描述
先设置这个格子的行和列 行决定了它的纵向 列决定了它的左右位置 现在我们就得到了每个格子有多大 比如: 宽度=总宽度(width)/列(ROW)后面会有用
这里我弄一个Point对象,让每一个点是让行和列组成的
把点的行和列都保存起来 大致是这样一个功能

下面开始定义坐标:
在这里插入图片描述
在这里插入图片描述
先从蛇的头开始,蛇头其实就是一个point对象 我们让它的初始位置在正中间

然后再定义蛇的食物,因为蛇的食物是随机出现的,所以这里我们用到random模块
这里有个小细节,我们要生成食物并且不让食物生成在蛇的身体里面,我们可以定义一个函数去解决

下面开始下一步:
在这里插入图片描述
但是我们要计算坐标位置,在绘图中我们是不可以使用行和列的,我们获取到它的位置就要使用上下左右的间距,由此可以推算出左间距=clo*格子的width(可以画图仔细理解一波),上间距=row*格子的height
因为需要执行很多步画图操作 所以定义一个函数,这里其实是将方块涂色
下面我们就开始画蛇的部分:
在这里插入图片描述
下面是蛇的移动:
比如我们要朝左边,row不动,clo-=1 右边就是clo+=1 依次类推
我们可以先定义一个变量表示当前蛇移动的方向 再进行移动判断

在这里插入图片描述
在这里插入图片描述
这里还有一个小细节 就是当你在往左移动时,不能直接朝右边移动,朝上移动时,不能直接朝下,所以我们加了if判断
pygame.KEYDOWN 键盘摁下事件
event.key是每个键的编码,273->W 119->↑…

下面处理蛇的跟随移动:
在这里插入图片描述
我们可以吧坐标以元组的形式放入一个列表,每次移动头的位置会放对应的方向移动1格(吧原来的头插入到前面insert),并且尾部会消失pop(因为头往前移动了一格),其他不需要变动,只变动头和尾就可以
在这里插入图片描述
为了方便我们再给point对象添加一个方法 copy,在copy的过程中其实就是创建一个新的point,这样就可以复制他自己
在这里插入图片描述
但是如果蛇吃到食物之后,他是会增加一格的,所以我们这里判断一下,如果蛇头与食物重合,就说明蛇迟到了食物,没重合就说明没吃到这个食物,并且每次吃到这个食物,食物又会在随机位置出现

最后,我们要处理蛇撞到墙壁或者撞到自身之后游戏结束的操作,其实很简单,如果蛇头出现在了格子以外的地方或者蛇头与蛇的身体重合,就会视为游戏失败,随即会退出游戏

做到这里就告一段落了,其实这个游戏还有很多地方可以改进,比如添加一个计分系统、失败后出现重新开始按钮和开始时出现开始游戏按钮等等。。。如果有人需要的话我再后面会加以改进。

下面是源码

代码

import pygame
from sys import exit
import random


class Point():
    row = 0
    clo = 0

    def __init__(self, row, clo):
        self.row = row
        self.clo = clo

    def copy(self):
        return Point(row=self.row, clo=self.clo)


# 初始化
pygame.init()
width = 800
hight = 400

ROW = 30
CLO = 40

direct = 'left'
window = pygame.display.set_mode((width, hight))
pygame.display.set_caption('贪吃蛇游戏')

# 蛇头坐标定在中间
head = Point(row=int(ROW / 2), clo=int(CLO / 2))
# 初始化蛇身的元素数量
snake = [
    Point(row=head.row, clo=head.clo + 1),
    Point(row=head.row, clo=head.clo + 2),
    Point(row=head.row, clo=head.clo + 3)
]


# 生成食物并且不让食物生成在蛇的身体里面
def gen_food():
    while 1:
        position = Point(row=random.randint(0, ROW - 1), clo=random.randint(0, CLO - 1))
        is_coll = False
        if head.row == position.row and head.clo == position.clo:
            is_coll = True
        for body in snake:
            if body.row == position.row and body.clo == position.clo:
                is_coll = True
                break
        if not is_coll:
            break
    return position


# 定义坐标
# 蛇头颜色可以自定义
head_color = (0, 158, 128)
# 食物坐标
snakeFood = gen_food()
# 食物颜色
snakeFood_color = (255, 255, 0)

snake_color = (200, 147, 158)


# 需要执行很多步画图操作 所以定义一个函数
def rect(point, color):
    # 定位 画图需要left和top
    left = point.clo * width / CLO
    top = point.row * hight / ROW
    # 将方块涂色
    pygame.draw.rect(window, color, (left, top, width / CLO, hight / ROW))


quit = True
# 设置帧频率
clock = pygame.time.Clock()
while quit:
    # 处理帧频 锁帧
    clock.tick(30)
    # pygame.event.get()获取当前事件的队列 可以同时发生很多事件
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            quit = False
        elif event.type == pygame.KEYDOWN:
            # 这里小细节蛇不可以直接左右上下 要判断当前是在什么状态下前行
            if event.key == 273 or event.key == 119:
                if direct == 'left' or direct == 'right':
                    direct = 'top'
            if event.key == 274 or event.key == 115:
                if direct == 'left' or direct == 'right':
                    direct = 'bottom'
            if event.key == 276 or event.key == 97:
                if direct == 'top' or direct == 'bottom':
                    direct = 'left'
            if event.key == 275 or event.key == 100:
                if direct == 'top' or direct == 'bottom':
                    direct = 'right'
    # 吃东西
    eat = (head.row == snakeFood.row and head.clo == snakeFood.clo)

    # 处理蛇的身子
    # 1.把原来的头插入到snake的头上
    # 2.把最后一个snake删掉
    if eat:
        snakeFood = Point(row=random.randint(0, ROW - 1), clo=random.randint(0, CLO - 1))
    snake.insert(0, head.copy())
    if not eat:
        snake.pop()

    # 移动一下
    if direct == 'left':
        head.clo -= 1
    if direct == 'right':
        head.clo += 1
    if direct == 'top':
        head.row -= 1
    if direct == 'bottom':
        head.row += 1
    dead = False
    if head.clo < 0 or head.row < 0 or head.clo >= CLO or head.row >= ROW:
        dead = True
    for body in snake:
        if head.clo == body.clo and head.row == body.row:
            dead = True
            break
    if dead:
        print('Game Over')
        quit = False
    # 背景画图
    pygame.draw.rect(window, (245, 135, 155), (0, 0, width, hight))

    # 蛇头
    rect(head, head_color)
    # 绘制食物
    rect(snakeFood, snakeFood_color)
    # 绘制蛇的身子
    for body in snake:
        rect(body, snake_color)

    # 交还控制权
    pygame.display.flip()

希望此文章对你有所帮助,最后谢谢阅读

PS:pycharm背景图片
在这里插入图片描述

  • 82
    点赞
  • 361
    收藏
    觉得还不错? 一键收藏
  • 25
    评论
以下是使用PythonPygame制作的经典贪吃蛇游戏的示例代码: ```python import pygame import random # 初始化游戏 pygame.init() # 定义颜色 BLACK = (0, 0, 0) WHITE = (255, 255, 255) GREEN = (0, 255, 0) RED = (255, 0, 0) # 设置屏幕尺寸 screen_width = 800 screen_height = 600 screen = pygame.display.set_mode((screen_width, screen_height)) pygame.display.set_caption("贪吃蛇游戏") # 定义蛇的初始位置和大小 snake_block_size = 20 snake_speed = 15 font_style = pygame.font.SysFont(None, 50) score_font = pygame.font.SysFont(None, 35) def our_snake(snake_block_size, snake_list): for x in snake_list: pygame.draw.rect(screen, GREEN, [x[0], x[1], snake_block_size, snake_block_size]) def message(msg, color): mesg = font_style.render(msg, True, color) screen.blit(mesg, [screen_width / 6, screen_height / 3]) def game_loop(): game_over = False game_close = False # 初始化蛇的位置和移动方向 x1 = screen_width / 2 y1 = screen_height / 2 x1_change = 0 y1_change = 0 # 初始化蛇的身体 snake_List = [] Length_of_snake = 1 # 初始化食物的位置 foodx = round(random.randrange(0, screen_width - snake_block_size) / 20.0) * 20.0 foody = round(random.randrange(0, screen_height - snake_block_size) / 20.0) * 20.0 while not game_over: while game_close: screen.fill(BLACK) message("游戏结束!按Q退出或C重新开始", RED) pygame.display.update() for event in pygame.event.get(): if event.type == pygame.KEYDOWN: if event.key == pygame.K_q: game_over = True game_close = False if event.key == pygame.K_c: game_loop() 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: x1_change = -snake_block_size y1_change = 0 elif event.key == pygame.K_RIGHT: x1_change = snake_block_size y1_change = 0 elif event.key == pygame.K_UP: y1_change = -snake_block_size x1_change = 0 elif event.key == pygame.K_DOWN: y1_change = snake_block_size x1_change = 0 # 判断蛇是否撞墙 if x1 >= screen_width or x1 < 0 or y1 >= screen_height or y1 < 0: game_close = True x1 += x1_change y1 += y1_change screen.fill(BLACK) pygame.draw.rect(screen, RED, [foodx, foody, snake_block_size, snake_block_size]) snake_Head = [] snake_Head.append(x1) snake_Head.append(y1) snake_List.append(snake_Head) if len(snake_List) > Length_of_snake: del snake_List[0] for x in snake_List[:-1]: if x == snake_Head: game_close = True our_snake(snake_block_size, snake_List) pygame.display.update() # 判断蛇是否吃到食物 if x1 == foodx and y1 == foody: foodx = round(random.randrange(0, screen_width - snake_block_size) / 20.0) * 20.0 foody = round(random.randrange(0, screen_height - snake_block_size) / 20.0) * 20.0 Length_of_snake += 1 # 设置游戏速度 pygame.time.Clock().tick(snake_speed) pygame.quit() game_loop() ``` 你可以将以上代码保存为一个名为`snake_game.py`的文件,并在终端中运行该文件,即可开始游戏

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 25
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值