Python Pygame 实现贪吃蛇游戏教程(上)

花开有时
花开有时
发布时间:2026-10-13 | 3人浏览过
原创

本文详解使用 Pygame 库从零构建贪吃蛇游戏的过程。内容涵盖游戏界面网格绘制、蛇头与豆子的随机位置生成、基于键盘事件的实时方向控制,以及利用时间戳实现蛇头匀速移动和身体跟随逻辑。通过分步代码解析,帮助开发者掌握 Pygame 基础绘图与游戏循环机制。

本文分享使用 Pygame 库开发贪吃蛇游戏的具体代码实现,供读者参考学习。

游戏界面网格绘制

1. 准备工作

首先初始化一个 400x400 像素的游戏窗口。为了直观展示游戏区域,我们在界面上绘制 40x40 像素的网格,即将窗口纵向和横向各分为 10 份。实现这一效果需要绘制 20 条线段,具体绘图代码如下。


for x in range(0,400,40):
 pygame.draw.line(screen,(255,255,255),(x,0),(x,400),1)
 for y in range(0,400,40):
 pygame.draw.line(screen,(255,255,255),(0,y),(400,y),1)

绘制网格后的界面效果如下图所示。

蛇头与豆子位置生成

2. 蛇头与豆子的位置设定

蛇头和豆子的初始位置可以通过 random 模块随机生成。


import random
snake_x = random.randint(0,9)*40+20
snake_y = random.randint(0,9)*40+20

使用 pygame.draw.circle 函数绘制一个圆形的蛇头。


yellow = 255,255,0
pygame.draw.circle(screen,yellow,[snake_x,snake_y],20,2)

豆子的绘制方法类似,但可以通过减小圆的半径并增加线宽,使其在视觉上呈现为实心圆点。


pygame.draw.circle(screen,yellow,[bean_x,bean_y],10,10)

此时游戏界面的显示效果如下。

上述功能的完整代码实现如下。


# -*- coding=utf-8 -*-
import random
import pygame
pygame.init()
screencaption = pygame.display.set_caption('first pygame')
screen = pygame.display.set_mode((400,400)) #设置400*400窗口

snake_x = random.randint(0,9)*40+20
snake_y = random.randint(0,9)*40+20

def get_bean_pos():
 return random.randint(0,9)*40+20,random.randint(0,9)*40+20

yellow = 255,255,0

bean_x,bean_y = get_bean_pos()

while True:
 for event in pygame.event.get():
  if event.type == pygame.QUIT:
  pygame.quit()
  exit()

 screen.fill((0,0,255)) # 将界面设置为蓝色

 for x in range(0,400,40):
 pygame.draw.line(screen,(255,255,255),(x,0),(x,400),1)
 for y in range(0,400,40):
 pygame.draw.line(screen,(255,255,255),(0,y),(400,y),1)

 pygame.draw.circle(screen,yellow,[snake_x,snake_y],20,2)
 pygame.draw.circle(screen,yellow,[bean_x,bean_y],10,10)
 pygame.display.update() # 必须调用update才能看到绘图显示

键盘输入与方向控制

3. 键盘控制蛇头移动

首先需要导入用于判断键盘事件的常量变量。


from pygame.locals import KEYDOWN,K_LEFT,K_RIGHT,K_UP,K_DOWN

在事件处理循环中增加对键盘按键的检测逻辑。


if event.type == KEYDOWN:
 if event.key == K_LEFT:
    if snake_x-40>0: snake_x-=40
   if event.key == K_RIGHT:
    if snake_x+40<400: snake_x+=40
   if event.key == K_UP:
    if snake_y-40>0: snake_y-=40
   if event.key == K_DOWN:
    if snake_y+40<400: snake_y+=40

运行程序后,即可通过键盘按键控制蛇头的移动方向。

蛇头匀速移动机制

4. 实现蛇头匀速移动

定义一个时间戳变量用于计算移动的时间间隔。


diff_ticks = 500 # 移动一次蛇头的事件,单位毫秒
ticks = pygame.time.get_ticks()
ticks += diff_ticks

在主游戏循环中判断时间是否到达设定间隔,若满足条件则触发蛇头移动到下一个网格位置。


if pygame.time.get_ticks() >= ticks:
  snake_x,snake_y = set_snake_next_pos(snake_x,snake_y)
  ticks += diff_ticks

set_snake_next_pos 函数的具体实现如下。


dire = random.randint(0,3) # 假设0、1、2、3分别代表方向左、右、上、下

def set_snake_next_pos(snake_x, snake_y):
 if dire == 0:
  if snake_x - 40 > 0:
   snake_x -= 40
 if dire == 1:
  if snake_x + 40 < 400:
   snake_x += 40
 if dire == 2:
  if snake_y - 40 > 0:
   snake_y -= 40
 if dire == 3:
  if snake_y + 40 < 400:
   snake_y += 40
 return snake_x,snake_y

此外,主循环中的键盘检测逻辑也需调整:按下按键时仅修改移动方向,而不立即移动蛇头,需等待时间间隔到达后由自动逻辑触发移动。修改后的判断代码如下。


if event.type == KEYDOWN:
    if event.key == K_LEFT:
     if dire!=0 and dire!=1 and snake_x - 40 > 0: # 和当前方向不是同方向或反方向并且可以左移
      dire = 0
    if event.key == K_RIGHT:
     if dire!=0 and dire!=1 and snake_x + 40 < 400: # 和当前方向不是同方向或反方向并且可以右移
      dire = 1
    if event.key == K_UP:
     if dire!=2 and dire!=3 and snake_y - 40 > 0: # 和当前方向不是同方向或反方向并且可以上移
      dire = 2
    if event.key == K_DOWN:
     if dire!=2 and dire!=3 and snake_y + 40 < 400: # 和当前方向不是同方向或反方向并且可以下移
      dire = 3

为避免蛇头初始位置紧贴墙壁导致立即碰撞,需对初始方向进行优化,使其朝向空白区域较多的一侧前进。相关代码如下。


#dire = random.randint(0,3) # 假设0、1、2、3分别代表方向左、右、上、下
if snake_x < 5:
 dire = 1 # 往右移动
else:
 dire = 0 # 往左移动

蛇身跟随逻辑实现

5. 增加蛇身逻辑

使用矩形表示蛇的身体。身体应位于蛇头后方一格,并根据蛇头的移动方向放置。若后方无空间,则向垂直方向的上方或下方延伸。身体初始位置的定义代码如下。


body_y = snake_y
if dire == 0: # 向左移动
 if snake_x + 40 < 400:
  body_x = snake_x + 40
 else: # 身体不能放右侧了,只能往上下方向放
  if snake_y > 200:
   body_x = snake_x
   body_y -= 40
  else:
   body_x = snake_x
   body_y += 40
else: # 向右移动
 if snake_x - 40 > 0:
  body_x = snake_x - 40
 else: # 身体不能放左侧了,只能往上下方向放
  if snake_y > 200:
   body_x = snake_x
   body_y -= 40
  else:
   body_x = snake_x
   body_y += 40

在主循环中增加对矩形蛇身的绘制代码。


pygame.draw.rect(screen,yellow,[body_x-20,body_y-20,40,40],5)

在每次更新蛇头位置前,先将身体的坐标更新为当前蛇头的坐标,再执行蛇头移动操作,从而实现身体跟随效果。


if pygame.time.get_ticks() >= ticks:
  body_x = snake_x
  body_y = snake_y
  snake_x,snake_y = set_snake_next_pos(snake_x,snake_y)
  ticks += diff_ticks

目前的运行效果图如下。

以下是目前的完整代码。关于吃豆判定和蛇身变长的逻辑将在下一章介绍。


# -*- coding=utf-8 -*-
import random
import pygame
from pygame.locals import KEYDOWN,K_LEFT,K_RIGHT,K_UP,K_DOWN
pygame.init()
screencaption = pygame.display.set_caption('first pygame')
screen = pygame.display.set_mode((400,400)) #设置400*400窗口

snake_x = random.randint(0,9)*40+20
snake_y = random.randint(0,9)*40+20

def get_bean_pos():
 return random.randint(0,9)*40+20,random.randint(0,9)*40+20

yellow = 255,255,0

bean_x,bean_y = get_bean_pos()

diff_ticks = 500 # 移动一次蛇头的事件,单位毫秒
ticks = pygame.time.get_ticks()
ticks += diff_ticks

#dire = random.randint(0,3) # 假设0、1、2、3分别代表方向左、右、上、下
if snake_x < 5:
 dire = 1 # 往右移动
else:
 dire = 0 # 往左移动

body_y = snake_y
if dire == 0: # 向左移动
 if snake_x + 40 < 400:
  body_x = snake_x + 40
 else: # 身体不能放右侧了,只能往上下方向放
  if snake_y > 200:
   body_x = snake_x
   body_y -= 40
  else:
   body_x = snake_x
   body_y += 40
else: # 向右移动
 if snake_x - 40 > 0:
  body_x = snake_x - 40
 else: # 身体不能放左侧了,只能往上下方向放
  if snake_y > 200:
   body_x = snake_x
   body_y -= 40
  else:
   body_x = snake_x
   body_y += 40

def set_snake_next_pos(snake_x, snake_y):
 if dire == 0:
  if snake_x - 40 > 0:
   snake_x -= 40
 if dire == 1:
  if snake_x + 40 < 400:
   snake_x += 40
 if dire == 2:
  if snake_y - 40 > 0:
   snake_y -= 40
 if dire == 3:
  if snake_y + 40 < 400:
   snake_y += 40
 return snake_x,snake_y

while True:
 for event in pygame.event.get():
   if event.type == pygame.QUIT:
    pygame.quit()
    exit()
   if event.type == KEYDOWN:
    if event.key == K_LEFT:
     if dire!=0 and dire!=1 and snake_x - 40 > 0: # 和当前方向不是同方向或反方向并且可以左移
      dire = 0
    if event.key == K_RIGHT:
     if dire!=0 and dire!=1 and snake_x + 40 < 400: # 和当前方向不是同方向或反方向并且可以右移
      dire = 1
    if event.key == K_UP:
     if dire!=2 and dire!=3 and snake_y - 40 > 0: # 和当前方向不是同方向或反方向并且可以上移
      dire = 2
    if event.key == K_DOWN:
     if dire!=2 and dire!=3 and snake_y + 40 < 400: # 和当前方向不是同方向或反方向并且可以下移
      dire = 3

 screen.fill((0,0,255)) # 将界面设置为蓝色

 for x in range(0,400,40):
  pygame.draw.line(screen,(255,255,255),(x,0),(x,400),1)
 for y in range(0,400,40):
  pygame.draw.line(screen,(255,255,255),(0,y),(400,y),1)

 pygame.draw.circle(screen,yellow,[snake_x,snake_y],20,2)
 pygame.draw.rect(screen,yellow,[body_x-20,body_y-20,40,40],5)

 pygame.draw.circle(screen,yellow,[bean_x,bean_y],10,10)

 pygame.display.update() # 必须调用update才能看到绘图显示

 if pygame.time.get_ticks() >= ticks:
  body_x = snake_x
  body_y = snake_y
  snake_x,snake_y = set_snake_next_pos(snake_x,snake_y)
  ticks += diff_ticks

以上就是本文的全部内容,希望对大家学习 Python 游戏开发有所帮助,欢迎继续支持本站。

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表