当前位置: 首页 > news >正文

Python游戏编程:用Python打造经典贪吃蛇小游戏

贪吃蛇作为一款极其经典且广受欢迎的小游戏,是早期 Windows 电脑和功能手机(特别是诺基亚手机)流行度极高的小游戏,是当时功能手机时代最具代表性的游戏之一。
在这里插入图片描述

贪吃蛇游戏分析

控制蛇的移动:通过上下左右键,控制一条蛇在游戏区域中移动,最初蛇很短,通常由 1 个方块组成。

吃到食物增长:游戏区域中会随机出现食物(例如一个方块),当蛇头触碰到食物时,代表蛇吃到了食物,蛇身体会增长一节,同时得 1 分。

避免越界或碰撞:游戏中需要避免蛇头撞到游戏区域的边界,或者蛇头碰到自己的身体。

策略性移动:随着游戏的进行蛇身增长,需要巧妙地操控蛇的路径,既要吃到食物,又要避免越界碰撞,这变得越来越具挑战性和趣味性。

游戏分数和结束:游戏过程中,需要记录当前得分(即:蛇吃到食物的数量),游戏结束,展示总得分和重新开始游戏或者退出。

在这里插入图片描述

游戏进行中界面

准备:安装 pygame 工具包

贪吃蛇游戏依赖pygame这个强大的 Python 游戏工具包:

pip install pygame   

代码:设置基础参数

基础参数包括屏幕大小、中文字体、背景颜色、字体颜色、蛇的颜色、食物的颜色、蛇的大小和蛇游动速度等。中文simsun.ttf字体文件在源代码目录,请一起下载到本地:

import random   import pygame      # 初始化   pygame.init()      # 设置窗口和初始化   SCREEN_WIDTH = 640   SCREEN_HEIGHT = 480   SCREEN = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))      # 设置窗口标题   pygame.display.set_caption('老牛同学:贪吃蛇')      # 游戏屏幕字体   SCORE_FONT = pygame.font.Font('./fonts/simsun.ttf', 25)   RESULT_FONT = pygame.font.Font('./fonts/simsun.ttf', 25)      # 颜色设置   BLACK = (0, 0, 0)  # 黑色(屏幕的颜色)   WHITE = (255, 255, 255)  # 白色(分数的颜色)   GREEN = (0, 255, 0)  # 绿色(蛇的颜色)   RED = (255, 0, 0)  # 红色(食物的颜色,游戏结束字体的颜色)      # 蛇区块大小(正方形)和游动速度   SNAKE_BLOCK = 10   SNAKE_SPEED = 8   

代码:绘制游戏进行中的得分

游戏进行中,得分默认在窗口左上角展示:

def draw_score(score):       """绘制当前分数"""       score_text = SCORE_FONT.render("总分数:" + str(score), True, WHITE)       #SCREEN.blit(score_text, [20, 20])  # 左上角   

也可以设置为顶部居中展示,如下代码:

def draw_score(score):       """绘制当前分数"""       score_text = SCORE_FONT.render("总分数:" + str(score), True, WHITE)       score_rect = score_text.get_rect(center=(SCREEN_WIDTH // 2, 20))       SCREEN.blit(score_text, score_rect)   

代码:绘制游戏进行中蛇的身体

游戏进行中,蛇的身体其实就是一些方块的位置,蛇的数据结构为一个 list 列表,列表的元素是 x 和 y 坐标 list 列表,即[[x1,y1],[x2,y2],[x3,y3]...]数据存储形式,蛇尾是第 1 个元素,蛇头是在最后 1 个元素。

def draw_snake(snake_list):       """绘制蛇的身体,由于都是方块,所以绘制过程无需区分蛇头和蛇身等"""       for x in snake_list:           pygame.draw.rect(SCREEN, GREEN, [x[0], x[1], SNAKE_BLOCK, SNAKE_BLOCK])   

问题:蛇尾在第 1 个元素,而蛇头在最后 1 个元素,为什么要这么设计?

答案:从后面代码可以看出,蛇在游动的过程中,蛇新的坐标是用的append到列表,然后删除列表的第 1 个元素。当然完全可以通过insert的方式反过来设计。

代码:计算食物的随机坐标

我们使用random函数随机计算食物的坐标,同时需要注意,避免食物越界:

def food_position():       """随机计算食物坐标"""       x_food = round(random.randrange(0, SCREEN_WIDTH - SNAKE_BLOCK, SNAKE_BLOCK))       y_food = round(random.randrange(0, SCREEN_HEIGHT - SNAKE_BLOCK, SNAKE_BLOCK))       return x_food, y_food   

代码:绘制游戏结束分数和提示

我们在屏幕正中央分别展示 3 行提示文本:游戏结束、总得分和继续游戏提示。文本正中央展示和总得分类似:

def draw_result(snake_length):  """绘制游戏结果"""  # 在屏幕中央显示文本  game_over_text = RESULT_FONT.render('游戏结束', True, RED)  game_over_rect = game_over_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 - 50))  SCREEN.blit(game_over_text, game_over_rect)  # 显示最终得分文本  final_score_text = RESULT_FONT.render(f'总得分: {snake_length - 1}', True, RED)  final_score_rect = final_score_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2))  SCREEN.blit(final_score_text, final_score_rect)  # 显示重新开始游戏的提示文本  restart_text = RESULT_FONT.render('按`Q`退出游戏,按`C`重新开始游戏', True, RED)  restart_rect = restart_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 + 50))  SCREEN.blit(restart_text, restart_rect)  

代码:游戏主循环设置

主循环游戏把以上功能函数缝合起来,同时包括控制代码:

  1. game_close参数控制单局游戏是否结束,game_over参数控制整个游戏是否结束

  2. 上下左右按键:上下按键控制蛇Y轴(上减少、下增加),左右按键控制蛇X轴(左减少、右增加)

  3. 蛇触墙检测:蛇头坐标x1,y1是否在整个屏幕之内

  4. 蛇触蛇身检测:蛇头坐标是否在蛇身体的任意坐标相同

  5. 蛇吃到食物检测:蛇头坐标是否和食物坐标相同,如果相同则重新设置食物位置,同时蛇身长加 1 个方块

def game_loop():  """游戏主循环函数"""  game_over = False  # 退出游戏  game_close = False  # 单次游戏结束  # 初始化蛇的坐标和坐标增量  x1 = SCREEN_WIDTH / 2  y1 = SCREEN_HEIGHT / 2  x1_change = 0  y1_change = 0  # 蛇的身体列表,初始长度为1  snake_list = []  snake_length = 1  # 随机生成食物的位置  x_food, y_food = food_position()  while not game_over:  # 如果游戏结束但未选择退出或重玩,则进入此循环  while game_close:  # 清空屏幕,准备下一轮绘制  SCREEN.fill(BLACK)  draw_result(snake_length)  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:  # 左:X坐标减少1个区块,Y坐标不变  x1_change = -1  y1_change = 0  elif event.key == pygame.K_RIGHT:  # 右:X坐标增加1个区块,Y坐标不变  x1_change = 1  y1_change = 0  elif event.key == pygame.K_UP:  # 上:X坐标不变,Y坐标减少1个区块  x1_change = 0  y1_change = -1  elif event.key == pygame.K_DOWN:  # 下:X坐标不变,Y坐标增加1个区块  x1_change = 0  y1_change = 1  # 退出游戏  if game_over:  break  # 检测蛇是否触墙  if x1 >= SCREEN_WIDTH or x1 < 0 or y1 >= SCREEN_HEIGHT or y1 < 0:  game_close = True  # 更新蛇的位置  x1 += x1_change * SNAKE_BLOCK  y1 += y1_change * SNAKE_BLOCK  # 清空屏幕,准备下一轮绘制  SCREEN.fill(BLACK)  # 画食物  pygame.draw.rect(SCREEN, RED, [x_food, y_food, SNAKE_BLOCK, SNAKE_BLOCK])  # 新的蛇头位置,同时删除最后蛇尾区块,以保持蛇的总长度不变  snake_head = [x1, y1]  snake_list.append(snake_head)  if len(snake_list) > snake_length:  del snake_list[0]  # 删除蛇尾  # 检查蛇头是否碰到蛇的身体  for x in snake_list[:-1]:  if x == snake_head:  game_close = True  # 绘制蛇  draw_snake(snake_list)  # 绘制得分  draw_score(snake_length - 1)  # 刷新屏幕  pygame.display.update()  # 检查蛇头是否碰到食物,若碰到则增加长度并重新生成食物  if x1 == x_food and y1 == y_food:  x_food, y_food = food_position()  snake_length += 1  # 控制游戏帧率  clock = pygame.time.Clock()  clock.tick(SNAKE_SPEED)  # 游戏结束时清理pygame环境  pygame.quit()  quit()  

最后:启动游戏主循环

启动游戏,进入主循环,通过上下左右按键控制蛇身游动:

# 开始游戏  
if __name__ == '__main__':  game_loop()  

最后,我们游戏界面大概像这样:

在这里插入图片描述

游戏进行中界面

单局游戏结束的界面:

在这里插入图片描述

游戏结束界面

禅定: 我们可以继续进一步优化这个程序:

  1. 每次吃到食物、单局游戏结束增加音效

  2. 增加难度:长按上下左右按键,加速蛇游动的速度

  3. 记住每轮游戏分数,进行分数排名(本地记录,或者联网)


关于Python技术储备

学好 Python 不论是就业还是做副业赚钱都不错,但要学会 Python 还是要有一个学习规划。最后大家分享一份全套的 Python 学习资料,给那些想学习 Python 的小伙伴们一点帮助!

在这里插入图片描述

👉Python学习路线汇总👈

Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。

在这里插入图片描述

👉Python必备开发工具👈

在这里插入图片描述

👉Python学习视频合集👈

观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。

在这里插入图片描述

👉实战案例👈

光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。

在这里插入图片描述

👉Python副业兼职路线&方法👈

学好 Python 不论是就业还是做副业赚钱都不错,但要学会兼职接单还是要有一个学习规划。

在这里插入图片描述

👉 这份完整版的Python全套学习资料已经上传,朋友们如果需要可以扫描下方二维码免费领取

在这里插入图片描述

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Kafka:浅谈对Kafka的认识
  • C#基础(5)交错数组*
  • Python | Leetcode Python题解之第390题消除游戏
  • IDEA加载工程报错Error Loading Project: Cannot load module demo.iml解决
  • 【Rust光年纪】Rust 机器人学库全景:功能、安装与API概览
  • 多个线程如何轮流输出1到100
  • GPU池化赋能智能制造
  • 原型模式prototype
  • C++ | Leetcode C++题解之第390题消除游戏
  • 专项练习-数据库SQL-177题(下)
  • cmake命令交叉编译opencv
  • linux高级学习9
  • NAT技术+代理服务器+内网穿透
  • (一)十分简易快速 自己训练样本 opencv级联haar分类器 车牌识别
  • ASP.Net Core 因集成WebSocket导致Swagger UI显示错误
  • CSS进阶篇--用CSS开启硬件加速来提高网站性能
  • java8 Stream Pipelines 浅析
  • Joomla 2.x, 3.x useful code cheatsheet
  • Linux gpio口使用方法
  • 动态魔术使用DBMS_SQL
  • 多线程事务回滚
  • 个人博客开发系列:评论功能之GitHub账号OAuth授权
  • 前端面试之CSS3新特性
  • 与 ConTeXt MkIV 官方文档的接驳
  • 自定义函数
  • ​3ds Max插件CG MAGIC图形板块为您提升线条效率!
  • #我与Java虚拟机的故事#连载14:挑战高薪面试必看
  • $forceUpdate()函数
  • $jQuery 重写Alert样式方法
  • (4)事件处理——(6)给.ready()回调函数传递一个参数(Passing an argument to the .ready() callback)...
  • (6)设计一个TimeMap
  • (BAT向)Java岗常问高频面试汇总:MyBatis 微服务 Spring 分布式 MySQL等(1)
  • (JSP)EL——优化登录界面,获取对象,获取数据
  • (多级缓存)缓存同步
  • (删)Java线程同步实现一:synchronzied和wait()/notify()
  • (原創) 如何動態建立二維陣列(多維陣列)? (.NET) (C#)
  • *p++,*(p++),*++p,(*p)++区别?
  • .Net 6.0 处理跨域的方式
  • .net CHARTING图表控件下载地址
  • .net core 外观者设计模式 实现,多种支付选择
  • .net 设置默认首页
  • .Net(C#)自定义WinForm控件之小结篇
  • .net8.0与halcon编程环境构建
  • .NET8使用VS2022打包Docker镜像
  • .NETCORE 开发登录接口MFA谷歌多因子身份验证
  • .Net的DataSet直接与SQL2005交互
  • .Net实现SCrypt Hash加密
  • .NET学习教程二——.net基础定义+VS常用设置
  • @FeignClient 调用另一个服务的test环境,实际上却调用了另一个环境testone的接口,这其中牵扯到k8s容器外容器内的问题,注册到eureka上的是容器外的旧版本...
  • [18] Opencv_CUDA应用之 基于颜色的对象检测与跟踪
  • [20190401]关于semtimedop函数调用.txt
  • [Android]创建TabBar
  • [Android]使用Android打包Unity工程
  • [BZOJ] 2006: [NOI2010]超级钢琴
  • [C# 开发技巧]如何使不符合要求的元素等于离它最近的一个元素