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()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/144881.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

KUKA机器人通过3点法设置工作台基坐标系的具体方法

KUKA机器人通过3点法设置工作台基坐标系的具体方法 具体方法和步骤可参考以下内容: 进入主菜单界面,依次选择“投入运行”—“测量”—基坐标,选择“3点法”, 在系统弹出的基坐标编辑界面,给基座标编号为3,命名为table1,然后单击“继续”按钮,进行下一步操作, 在弹出的…

300以内的开放耳机哪款好、300以内神级耳机推荐

开放式耳机基于不入耳、长久舒适佩戴的特点&#xff0c;在 2023 年迎来了增长爆发期。基于其开放式不入耳设计&#xff0c;佩戴时耳道会持续保持畅通状态&#xff0c;减少了对耳朵的压力&#xff0c;既能在通话或欣赏音乐时提供清晰的声音&#xff0c;又能让周围的环境声音透过…

win10,WSL的Ubuntu配python3.7手记

1.装linux 先在windows上安装WSL版本的Ubuntu Windows10系统安装Ubuntu子系统_哔哩哔哩_bilibili &#xff08;WSL2什么的一直没搞清楚&#xff09; 图形界面会出一些问题&#xff0c;注意勾选ccsm出的界面设置 win10安装Ubuntu16.04子系统&#xff0c;并开启桌面环境_win…

基于FPGA的图像坏点像素修复算法实现,包括tb测试文件和MATLAB辅助验证

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 vivado2019.2 matlab2022a 3.部分核心程序 timescale 1ns / 1ps // // Company: // Engineer: // // Create Date: 202…

华为智能企业远程办公安全解决方案(1)

华为智能企业远程办公安全解决方案&#xff08;1&#xff09; 课程地址方案背景需求分析企业远程办公业务概述企业远程办公安全风险分析企业远程办公环境搭建需求分析 方案设计组网架构设备选型方案亮点 课程地址 本方案相关课程资源已在华为O3社区发布&#xff0c;可按照以下…

CTF 入门指南:从零开始学习网络安全竞赛

文章目录 写在前面CTF 简介和背景CTF 赛题类型介绍CTF 技能和工具准备好书推荐 写作末尾 写在前面 CTF比赛是快速提升网络安全实战技能的重要途径&#xff0c;已成为各个行业选拔网络安全人才的通用方法。但是&#xff0c;本书作者在从事CTF培训的过程中&#xff0c;发现存在几…

mongodb Community 7 安装(linux)

链接&#xff1a;mongodb官网 链接&#xff1a;官方安装文档 一、安装 1.安装依赖 apt-get install gnupg curl2.安装public key cd /usr/localcurl -fsSL https://pgp.mongodb.com/server-7.0.asc | gpg -o /usr/share/keyrings/mongodb-server-7.0.gpg --dearmor3.把mon…

什么是Times New Roman 字体

如何评价 Times New Roman 字体&#xff1f;&#xff1a;https://www.zhihu.com/question/24614549?sortcreated 新罗马字体是Times New Roman字体&#xff0c;是Office Word默认自带的英文字体之一。 中英文字体 写作中&#xff0c;英文和数字的标准字体为 Times New Roma…

[杂谈]-ESP32中的无线通信协议

ESP32中的无线通信协议 文章目录 ESP32中的无线通信协议1、ESP32 无线通信协议简介2、Bluetooth Low Energy (BLE)3、**Bluetooth Classic**4、**ESP-NOW**5、Wi-Fi&#xff08;客户端-服务器通信协议&#xff09;6、MQTT7、**LoRa**8、**GSM/GPRS/LTE**9、总结 ESP32是一个基于…

【中秋节快乐】Matplotlib:3d绘图合集

目录 一、环境介绍 二、Matplotlib绘图&#xff08;3d&#xff09; 0. 设置中文字体 1. 3D线框图&#xff08;3D Wireframe Plot&#xff09; 2. 3D散点图&#xff08;3D Scatter Plot&#xff09; 3. 3D条形图&#xff08;3D Bar Plot&#xff09; 4. 3D曲面图&#xff0…

Unity中Shader通道ColorMask

文章目录 [TOC](文章目录) 前言一、ColorMask是用来干什么的二、怎么做到和 Unity UI 中的 Shader 一样根据UI层级自动适配Shader中模板测试值1、借鉴Unity官方的 UI Shader 前言 Unity中Shader通道ColorMask 一、ColorMask是用来干什么的 ColorMask RGB | A | 0 | R、G、B、…

【DTEmpower案例操作教程】智能数据挖掘

DTEmpower是由天洑软件自主研发的一款通用的智能数据建模软件&#xff0c;致力于帮助工程师及工科专业学生&#xff0c;利用工业领域中的仿真、试验、测量等各类数据进行挖掘分析&#xff0c;建立高质量的数据模型&#xff0c;实现快速设计评估、实时仿真预测、系统参数预警、设…

Unity实现设计模式——命令模式

Unity实现设计模式——命令模式 推荐一个Unity学习设计模式很好的GitHub地址&#xff1a;https://github.com/QianMo/Unity-Design-Pattern 有非常多的Star 一、介绍 命令模式使得请求的发送者与请求的执行者之间消除耦合&#xff0c;让对象之间的调用关系更加灵活。在命令模…

前端框架介绍

一、node.js 配置淘宝镜像源 npm config set registry https://registry.npm.taobao.org可以使用npm config list命令来确认镜像地址是否已成功更改。 如果需要将配置的镜像恢复为默认的npm官方源,可以执行以下命令: npm config delete registry二、vue 1、创建Vue项目 …

掌握 JavaScript 数组方法:了解如何操作和优化数组

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

最新AI创作系统源码ChatGPT源码+附详细搭建部署教程+AI绘画系统+支持国内AI提问模型

一、AI系统介绍 SparkAi创作系统是基于国外很火的ChatGPT进行开发的Ai智能问答系统。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署AI创作ChatGPT&#xff1f;小编这里写一个详细图文教程吧&am…

国密国际SSL双证书解决方案,满足企事业单位国产国密SSL证书要求

近年来&#xff0c;为了摆脱对国外技术和产品的依赖&#xff0c;建设安全的网络环境&#xff0c;以及加强我国对网络信息的安全可控能力&#xff0c;我国推出了国密算法。同时&#xff0c;为保护网络通信信息安全&#xff0c;更高级别的安全加密数字证书—国密SSL证书应运而生。…

Linux虚拟机无法联网

问题描述 Centos7&#xff0c;配置了静态IP后&#xff0c;无法联网 解决方式 虚拟机连接不上网络&#xff0c;解决办法_虚拟机连不上网络-CSDN博客 根据上面文章一步步做。 发现 在Windows的cmd中&#xff0c;可以ping通我的Linux虚拟机 但是&#xff0c;在虚拟机里 无法 …

微信、支付宝、百度、抖音开放平台第三方代小程序开发总结

大家好&#xff0c;我是小悟 小伙伴们都开启小长假了吧&#xff0c;值此中秋国庆双节之际&#xff0c;小悟祝所有的小伙伴们节日快乐。 支付宝社区很用心&#xff0c;还特意给寄了袋月饼&#xff0c;愿中秋节的圆月带给你身体健康&#xff0c;幸福团圆&#xff0c;国庆节的旗帜…

uni-app:js修改元素样式(宽度、外边距)

效果 代码 1、在<view>元素上添加一个ref属性&#xff0c;用于在JavaScript代码中获取对该元素的引用&#xff1a;<view ref"myView" id"mybox"></view> 2、获取元素引用 &#xff1a;const viewElement this.$refs.myView.$el; 3、修改…