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

pygame - 贪吃蛇小游戏

蛇每吃掉一个身体块,蛇身就增加一个长度。为了统一计算,界面的尺寸和游戏元素的位置都是身体块长度的倍数
1. 上下左右方向键(或者ASDW键)控制蛇的移动方向
2. 空格键暂停和继续蛇的身体图片文件,复制到项目的asset\img目录下

import sys
import pygame
from pygame import Rect, font
import random# control panel contains the controllers and score
ControlPanelColor = (100, 100, 100)
# game panel is the main area for gaming
GamePanelColor = (0, 0, 0)
SnakeSize = 30
MaxWidthBlock = 15
MaxHeightBlock = 10
ControlPanelHeightBlock = 2
SnakeStartX = MaxWidthBlock // 2
SnakeStartY = MaxHeightBlock // 2
ControlPanelHeight = ControlPanelHeightBlock * SnakeSize
GamePanelWidth = MaxWidthBlock * SnakeSize
GamePanelHeight = MaxHeightBlock * SnakeSize
ControlPanelRect = Rect((0, 0), (GamePanelWidth, ControlPanelHeight))
GamePanelRect = Rect((0, ControlPanelHeight), (GamePanelWidth, GamePanelHeight - ControlPanelHeight))
Tick = 20
Tick_Snake_Move = 10
# two buttons to increase and decrease the game speed
minus_btn_rect = None
plus_btn_rect = None
# score
score_value = 0# the SnakeBody
class SnakeBody:def __init__(self, x, y, direction, ishead=False, istail=False):'''身体块,蛇身是由多个身体块组成,头和尾也是图案不同的身体块:param x: 身体块坐标x:param y: 身体块坐标y:param direction: 身体块显示的方向:param ishead: 是否头身体块:param istail:是否尾身体块'''self.__x = xself.__y = yself.__ishead = isheadself.__istail = istailself.__direction = directionname = Noneif self.__ishead:name = "head.png"elif self.__istail:name = "tail.png"else:name = "body.png"angle = 0match direction:case pygame.K_UP:angle = 0case pygame.K_DOWN:angle = 180case pygame.K_LEFT:angle = 90case pygame.K_RIGHT:angle = -90img = pygame.image.load(f"asset/img/{name}")img = pygame.transform.rotate(img, angle)self.image = pygame.transform.scale(img, (SnakeSize, SnakeSize))def get_rect(self):return Rect((self.__x, self.__y), (SnakeSize, SnakeSize))def move(self, x, y):self.__x = self.__x + xself.__y = self.__y + ydef set_direction(self, direction):if self.__direction == direction:returnself.__direction = directionname = Noneif self.__ishead:name = "head.png"elif self.__istail:name = "tail.png"else:name = "body.png"angle = 0match direction:case pygame.K_UP:angle = 0case pygame.K_DOWN:angle = 180case pygame.K_LEFT:angle = 90case pygame.K_RIGHT:angle = -90img = pygame.image.load(f"asset/img/{name}")img = pygame.transform.rotate(img, angle)self.image = pygame.transform.scale(img, (SnakeSize, SnakeSize))def get_direction(self):return self.__directionclass Snake:bodys = []new_body = None__new_direction = pygame.K_UP__tick_movement = 0__tick_create_body = 0__stop = False__is_paused = Falsedef __init__(self):self.bodys.insert(0, SnakeBody(SnakeSize * SnakeStartX, SnakeSize * SnakeStartY, pygame.K_UP, True, False))self.bodys.insert(1,SnakeBody(SnakeSize * SnakeStartX, SnakeSize * (SnakeStartY + 1), pygame.K_UP, False, False))self.bodys.insert(2,SnakeBody(SnakeSize * SnakeStartX, SnakeSize * (SnakeStartY + 2), pygame.K_UP, False, True))def set_direction(self, direction):# do not set inverse directionif ((self.bodys[0].get_direction() == pygame.K_UP and direction != pygame.K_DOWN) or(self.bodys[0].get_direction() == pygame.K_DOWN and direction != pygame.K_UP) or(self.bodys[0].get_direction() == pygame.K_LEFT and direction != pygame.K_RIGHT) or(self.bodys[0].get_direction() == pygame.K_RIGHT and direction != pygame.K_LEFT)):self.__new_direction = directiondef move(self):if self.__stop:returnif self.__is_paused:returnself.__tick_movement += 1if self.__tick_movement <= Tick_Snake_Move:returnself.__tick_movement = 0length = len(self.bodys)head = self.bodys[0]oldheadpos = head.get_rect()oldheaddirection = head.get_direction()# update head direction and movehead.set_direction(self.__new_direction)match self.__new_direction:case pygame.K_UP:head.move(0, -SnakeSize)case pygame.K_DOWN:head.move(0, SnakeSize)case pygame.K_LEFT:head.move(-SnakeSize, 0)case pygame.K_RIGHT:head.move(SnakeSize, 0)if ((self.new_body is not None) and(head.get_rect().x == self.new_body.get_rect().x and head.get_rect().y == self.new_body.get_rect().y)):# as head move, the old head position is empty,# add the new body at the second positionself.new_body.set_direction(head.get_direction())offsetx = oldheadpos.x - self.new_body.get_rect().xoffsety = oldheadpos.y - self.new_body.get_rect().yself.new_body.move(offsetx, offsety)self.bodys.insert(1, self.new_body)self.new_body = Noneglobal score_valuescore_value += 1else:# as head move, the old head position is empty,# move the second-to-last body to the second bodysecond2lastbody = self.bodys[length - 2]second2lastpos = second2lastbody.get_rect()second2lastdirection = second2lastbody.get_direction()offsetx = oldheadpos.x - second2lastpos.xoffsety = oldheadpos.y - second2lastpos.ysecond2lastbody.set_direction(oldheaddirection)second2lastbody.move(offsetx, offsety)self.bodys.remove(second2lastbody)self.bodys.insert(1, second2lastbody)# move tail to the direction of the second-to-last bodytailbody = self.bodys[length - 1]tailbody.set_direction(second2lastdirection)offsetx = second2lastpos.x - tailbody.get_rect().xoffsety = second2lastpos.y - tailbody.get_rect().ytailbody.move(offsetx, offsety)def stop(self):self.__stop = Truedef create_body(self):self.__tick_create_body += 1if self.__tick_create_body <= 30:returnif self.is_paused():returnself.__tick_create_body = 0if self.new_body is not None:returnx, y = 0, 0while True:isspare = Trueintx = random.randint(0, MaxWidthBlock - 1)inty = random.randint(ControlPanelHeightBlock, MaxHeightBlock - 1)x = intx * SnakeSizey = inty * SnakeSizefor b in self.bodys:rect = b.get_rect()if rect.x == x and rect.y == y:isspare = Falsebreakif isspare:breakprint(f"create body block at {intx}, {inty}")self.new_body = SnakeBody(x, y, pygame.K_UP, False, False)def is_collided(self):iscollided = Falsehead = self.bodys[0]headrect = self.bodys[0].get_rect()# boundary collisionif headrect.x <= (0 - SnakeSize) or headrect.x >= GamePanelWidth or \headrect.y <= (ControlPanelHeight - SnakeSize) or headrect.y >= (ControlPanelHeight + GamePanelHeight):iscollided = True# body collisionelse:if head.get_direction() == pygame.K_LEFT:passfor b in self.bodys[1:len(self.bodys)]:if head.get_rect().colliderect(b.get_rect()):iscollided = Truebreakreturn iscollideddef pause(self):self.__is_paused = not self.__is_pauseddef is_paused(self):return self.__is_pauseddef display_result():final_text1 = "Game Over"final_surf = pygame.font.SysFont("Arial", SnakeSize * 2).render(final_text1, 1, (242, 3, 36))  # 设置颜色screen.blit(final_surf, [screen.get_width() / 2 - final_surf.get_width() / 2,screen.get_height() / 2 - final_surf.get_height() / 2])  # 设置显示位置def display_paused():paused_text = "Paused"paused_surf = pygame.font.SysFont("Arial", SnakeSize * 2).render(paused_text, 1, (242, 3, 36))screen.blit(paused_surf, [screen.get_width() / 2 - paused_surf.get_width() / 2,screen.get_height() / 2 - paused_surf.get_height() / 2])def display_control_panel():global minus_btn_rect, plus_btn_rectcolor = (242, 3, 36)speed_text = "Speed"speed_surf = pygame.font.SysFont("Arial", SnakeSize).render(speed_text, 1, "blue")  # 设置颜色speed_rect = speed_surf.get_rect()speed_rect.x, speed_rect.y = 0, 0screen.blit(speed_surf, speed_rect)offsetx = speed_rect.x + speed_rect.width + 10text_minus = "-"minus_btn = pygame.font.SysFont("Arial", SnakeSize).render(text_minus, 1, color)  # 设置颜色minus_btn_rect = minus_btn.get_rect()minus_btn_rect.x, minus_btn_rect.y = offsetx, 0screen.blit(minus_btn, minus_btn_rect)offsetx = minus_btn_rect.x + minus_btn_rect.width + 10text_speed_value = str(Tick - Tick_Snake_Move)speed_value_surf = pygame.font.SysFont("Arial", SnakeSize).render(text_speed_value, 1, color)  # 设置颜色speed_value_rect = speed_value_surf.get_rect()speed_value_rect.x, speed_value_rect.y = offsetx, 0screen.blit(speed_value_surf, speed_value_rect)offsetx = speed_value_rect.x + speed_value_rect.width + 10text_plus = "+"plus_btn = pygame.font.SysFont("Arial", SnakeSize).render(text_plus, 1, color)  # 设置颜色plus_btn_rect = plus_btn.get_rect()plus_btn_rect.x, plus_btn_rect.y = offsetx, 0screen.blit(plus_btn, plus_btn_rect)score_value_text = str(score_value)score_value_surf = pygame.font.SysFont("Arial", SnakeSize).render(score_value_text, 1, color)  # 设置颜色score_value_rect = score_value_surf.get_rect()score_value_rect.x = GamePanelWidth - score_value_rect.widthscore_value_rect.y = 0screen.blit(score_value_surf, score_value_rect)score_text = "Score"score_surf = pygame.font.SysFont("Arial", SnakeSize).render(score_text, 1, "blue")  # 设置颜色score_rect = score_surf.get_rect()score_rect.x = score_value_rect.x - score_rect.width - 10score_rect.y = 0screen.blit(score_surf, score_rect)def check_click(position):global Tick_Snake_Moveif minus_btn_rect == None or plus_btn_rect == None:returnx, y = position[0], position[1]minus_btn_x, minus_btn_y = minus_btn_rect.x, minus_btn_rect.yplus_btn_x, plus_btn_y = plus_btn_rect.x, plus_btn_rect.yif minus_btn_x < x < minus_btn_x + minus_btn_rect.width and \minus_btn_y < y < minus_btn_y + minus_btn_rect.height:Tick_Snake_Move += 1elif plus_btn_x < x < plus_btn_x + plus_btn_rect.width and \plus_btn_y < y < plus_btn_y + plus_btn_rect.height:Tick_Snake_Move -= 1pygame.init()
pygame.font.init()  # 初始化字体
screen = pygame.display.set_mode((GamePanelWidth, ControlPanelHeight + GamePanelHeight))
clock = pygame.time.Clock()
snake = Snake()screen.fill(ControlPanelColor, ControlPanelRect)while True:clock.tick(20)for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()sys.exit()elif event.type == pygame.KEYDOWN:if event.key == pygame.K_LEFT or event.key == pygame.K_a:snake.set_direction(pygame.K_LEFT)elif event.key == pygame.K_RIGHT or event.key == pygame.K_d:snake.set_direction(pygame.K_RIGHT)elif event.key == pygame.K_UP or event.key == pygame.K_w:snake.set_direction(pygame.K_UP)elif event.key == pygame.K_DOWN or event.key == pygame.K_s:snake.set_direction(pygame.K_DOWN)elif event.key == pygame.K_SPACE:snake.pause()if pygame.mouse.get_pressed()[0]:check_click(pygame.mouse.get_pos())screen.fill(GamePanelColor, (0, ControlPanelHeight, GamePanelWidth, ControlPanelHeight + GamePanelHeight))snake.move()for body in snake.bodys:screen.blit(body.image, body.get_rect())# collision detectionif snake.is_collided():snake.stop()display_result()else:# new bodysnake.create_body()if snake.new_body is not None:screen.blit(snake.new_body.image, snake.new_body.get_rect())screen.fill(ControlPanelColor, (0, 0, GamePanelWidth, ControlPanelHeight))display_control_panel()if snake.is_paused():display_paused()pygame.display.flip()

相关文章:

pygame - 贪吃蛇小游戏

蛇每吃掉一个身体块&#xff0c;蛇身就增加一个长度。为了统一计算&#xff0c;界面的尺寸和游戏元素的位置都是身体块长度的倍数 1. 上下左右方向键&#xff08;或者ASDW键&#xff09;控制蛇的移动方向 2. 空格键暂停和继续蛇的身体图片文件&#xff0c;复制到项目的asset\im…...

基于 QT 实现 Task Timer,高效利用时间

一、开发环境 Ubuntu 20.04 QT6.0 二、新建 Qt Wigets Application 这里的基类选择 Wigets&#xff0c; pro 配置文件添加 sql 模块&#xff0c;需要用到 sqlite&#xff0c; QT sql 三、添加数据库连接头文件 // connection.h #ifndef CONNECTION_H #define CONNECTION_…...

图像处理与计算机视觉--第五章-图像分割-霍夫变换

文章目录 1.霍夫变换(Hough Transform)原理介绍2.霍夫变换(Hough Transform)算法流程3.霍夫变换(Hough Transform)算法代码4.霍夫变换(Hough Transform)算法效果 1.霍夫变换(Hough Transform)原理介绍 Hough Transform是一种常用的计算机视觉图形检验方法&#xff0c;霍夫变换一…...

linux下文件操作命令

title: linux下文件操作命令 createTime: 2020-10-29 18:05:52 updateTime: 2020-10-29 18:05:52 categories: linux tags: Linux下文件操作命令 tar命令 使用tar命令一般打包分为两种*.tar ,*.tar.gz 相信大家也使用过tar -zcvf test.tar test/tar -zcvf test.tar.gz test/…...

Golang语法、技巧和窍门

Golang简介 命令式语言静态类型语法标记类似于C&#xff08;但括号较少且没有分号&#xff09;&#xff0c;结构类似Oberon-2编译为本机代码&#xff08;没有JVM&#xff09;没有类&#xff0c;但有带有方法的结构接口没有实现继承。不过有type嵌入。函数是一等公民函数可以返…...

Grander因果检验(格兰杰)原理+操作+解释

笔记来源&#xff1a; 1.【传送门】 2.【传送门】 前沿原理介绍 Grander因果检验是一种分析时间序列数据因果关系的方法。 基本思想在于&#xff0c;在控制Y的滞后项 (过去值) 的情况下&#xff0c;如果X的滞后项仍然有助于解释Y的当期值的变动&#xff0c;则认为 X对 Y产生…...

Python-Flask:编写自动化连接demo脚本:v1.0.0

主函数&#xff1a; # _*_ Coding : UTF-8 _*_ # Time : 13:14 # Author : YYZ # File : Flask # Project : Python_Project_爬虫 import jsonfrom flask import Flask,request,jsonify import sshapi Flask(__name__)# methods: 指定请求方式 接口解析参数host host_info[…...

kafka客户端应用参数详解

一、基本客户端收发消息 Kafka提供了非常简单的客户端API。只需要引入一个Maven依赖即可&#xff1a; <dependency><groupId>org.apache.kafka</groupId><artifactId>kafka_2.13</artifactId><version>3.4.0</version></depend…...

Apache Doris 行列转换可以这样玩

行列转换在做报表分析时还是经常会遇到的&#xff0c;今天就说一下如何实现行列转换吧。 行列转换就是如下图所示两种展示形式的互相转换 1. 行转列 我们来看一个简单的例子&#xff0c;我们要把下面这个表的数据&#xff0c;转换成图二的样式 image-20230914151818953.png …...

【Qt图形视图框架】自定义QGraphicsItem和QGraphicsView,实现鼠标(移动、缩放)及键盘事件、右键事件

自定义QGraphicsItem和QGraphicsView 说明示例myitem.hmyitem.cppmyview.hmyview.cpp调用main.cpp 效果 说明 在使用Qt的图形视图框架实现功能时&#xff0c;一般会在其基础上进行自定义功能实现。 如&#xff1a;滚轮对场景的缩放&#xff0c;鼠标拖动场景中的项&#xff0c;…...

C语言结构体指针学习

结构体变量存放内存中&#xff0c;也有起始地址&#xff0c;定义一个变量来存放这个地址&#xff0c;那这个变量就是结构体指针&#xff1b; typedef struct mydata{int a1;int a2;int a3; }mydata;void CJgtzzView::OnDraw(CDC* pDC) {CJgtzzDoc* pDoc GetDocument();ASSERT…...

华为云云耀云服务器L实例评测|部署在线轻量级备忘录 memos

华为云云耀云服务器L实例评测&#xff5c;部署在线轻量级备忘录 memos 一、云耀云服务器L实例介绍1.1 云服务器介绍1.2 产品优势1.3 应用场景1.4 支持镜像 二、云耀云服务器L实例配置2.1 重置密码2.2 服务器连接2.3 安全组配置 三、部署 memos3.1 memos介绍3.2 Docker 环境搭建…...

详解Avast Driver Updater:电脑驱动更新工具的利器还是多余的软件?

亲爱的读者朋友们&#xff0c;你是不是经常为电脑的驱动问题而烦恼&#xff1f;如果是的话&#xff0c;你可能会对这款软件——Avast Driver Updater 电脑驱动更新工具感兴趣。但在你决定尝试之前&#xff0c;不妨先和我一起深入探讨一下它的优点、缺点以及它适用的使用场景。 …...

大数据Flink(九十五):DML:Window TopN

文章目录 DML:Window TopN DML:Window TopN Window TopN 定义(支持 Streaming):Window TopN 是一种特殊的 TopN,它的返回结果是每一个窗口内的 N 个最小值或者最大值。 应用场景...

使用OKHttpClient访问网络

使用OKHttpClient前要引入依赖&#xff1a; 在build.gradle(Moduel :app)中添加 implementation com.squareup.okhttp3:okhttp:3.14.1 implementation com.squareup.okhttp3:logging-interceptor:3.14.1 implementation com.squareup.okio:okio:1.6.0 1. GET&#xff08;同步…...

maui 开发AMD CPU踩的坑。

刚换的 amd R7735HS 笔记本&#xff0c;8核16线程&#xff0c;32GB内存。性能得实强悍 。 当需要发布iOS版本时发现&#xff0c;我没有macos &#xff0c;那就安装个vmware 吧。看了一下Apple 要求以后的发布的APP需要以xcode14.3或以后版本开发的版本&#xff0c;但xcode14.3…...

宝塔反代openai官方API接口详细教程,502 Bad Gateway问题解决

一、前言 宝塔反代openai官方API接口详细教程&#xff0c;实现国内使用ChatGPT502 Bad Gateway问题解决&#xff0c; 此方法最简单快捷&#xff0c;没有复杂步骤&#xff0c;不容易出错&#xff0c;即最简单&#xff0c;零代码、零部署的方法。 二、实现前提 一台海外VPS服务…...

【leetocde】128. 最长连续序列

给定一个未排序的整数数组 nums &#xff0c;找出数字连续的最长序列&#xff08;不要求序列元素在原数组中连续&#xff09;的长度。 请你设计并实现时间复杂度为 O(n) 的算法解决此问题。 示例 1&#xff1a; 输入&#xff1a;nums [100,4,200,1,3,2] 输出&#xff1a;4 …...

【Vue3】动态 class 类

如果你想在 Vue.js 中动态设置元素的 class 类名&#xff0c;你可以使用以下两种主要方式&#xff1a; 绑定一个动态的 class 对象&#xff1a;你可以使用 v-bind 或简写的 : 来绑定一个包含类名的对象&#xff0c;其中类名的键是类名字符串&#xff0c;值是一个布尔值或计算属…...

【Redis】redis基本数据类型详解(String、List、Hash、Set、ZSet)

目录 RedisString(字符串)List(列表)Hash(字典)Set(集合)ZSet(有序集合) Redis Redis有5种基本的数据结构&#xff0c;分别为&#xff1a;string&#xff08;字符串&#xff09;、list&#xff08;列表&#xff09;、set&#xff08;集合&#xff09;、hash&#xff08;哈希&a…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

【Oracle APEX开发小技巧12】

有如下需求&#xff1a; 有一个问题反馈页面&#xff0c;要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据&#xff0c;方便管理员及时处理反馈。 我的方法&#xff1a;直接将逻辑写在SQL中&#xff0c;这样可以直接在页面展示 完整代码&#xff1a; SELECTSF.FE…...

工业安全零事故的智能守护者:一体化AI智能安防平台

前言&#xff1a; 通过AI视觉技术&#xff0c;为船厂提供全面的安全监控解决方案&#xff0c;涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面&#xff0c;能够实现对应负责人反馈机制&#xff0c;并最终实现数据的统计报表。提升船厂…...

【网络安全产品大调研系列】2. 体验漏洞扫描

前言 2023 年漏洞扫描服务市场规模预计为 3.06&#xff08;十亿美元&#xff09;。漏洞扫描服务市场行业预计将从 2024 年的 3.48&#xff08;十亿美元&#xff09;增长到 2032 年的 9.54&#xff08;十亿美元&#xff09;。预测期内漏洞扫描服务市场 CAGR&#xff08;增长率&…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路

进入2025年以来&#xff0c;尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断&#xff0c;但全球市场热度依然高涨&#xff0c;入局者持续增加。 以国内市场为例&#xff0c;天眼查专业版数据显示&#xff0c;截至5月底&#xff0c;我国现存在业、存续状态的机器人相关企…...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法&#xff1a;原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件&#xff0c;如包含恶意代码、敏感数据或欺诈内容的文档&#xff0c;在企业协同办公环境中&#xff08;如Teams、Google Workspace&#xff09;尤为重要。结合大模型技术&…...

html-<abbr> 缩写或首字母缩略词

定义与作用 <abbr> 标签用于表示缩写或首字母缩略词&#xff0c;它可以帮助用户更好地理解缩写的含义&#xff0c;尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时&#xff0c;会显示一个提示框。 示例&#x…...

算法岗面试经验分享-大模型篇

文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer &#xff08;1&#xff09;资源 论文&a…...

LLMs 系列实操科普(1)

写在前面&#xff1a; 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容&#xff0c;原视频时长 ~130 分钟&#xff0c;以实操演示主流的一些 LLMs 的使用&#xff0c;由于涉及到实操&#xff0c;实际上并不适合以文字整理&#xff0c;但还是决定尽量整理一份笔…...

PostgreSQL——环境搭建

一、Linux # 安装 PostgreSQL 15 仓库 sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-$(rpm -E %{rhel})-x86_64/pgdg-redhat-repo-latest.noarch.rpm# 安装之前先确认是否已经存在PostgreSQL rpm -qa | grep postgres# 如果存在&#xff0…...