OpenCV进阶(3)基于OpenCV的贪吃蛇游戏
在这篇文章中,我们将使用Python和OpenCV创建贪吃蛇游戏。
1.贪吃蛇游戏
在贪吃蛇游戏中,我们使用箭头键控制数字蛇。
一个苹果随机出现在屏幕上,我们的目标是移动蛇,让它吃苹果。蛇在吃了苹果后会变大,我们的目标是让蛇尽可能长。
然而,如果蛇撞到墙或撞到自己,游戏就结束了。
2.用OpenCV实现贪吃蛇游戏
代码展示
import cv2
import numpy as np
from random import randint
from random import choiceclass SnakePart:def __init__(self, front, x, y):self.front = frontself.x = xself.y = ydef move(self):# 跟随它前面的部分移动self.x = self.front.xself.y = self.front.yclass Head:def __init__(self, direction, x, y):self.direction = directionself.x = xself.y = ydef move(self):# 检查它当前的方向,并相应地移动if self.direction == 0:self.x += 1elif self.direction == 1:self.y += 1elif self.direction == 2:self.x -= 1elif self.direction == 3:self.y -= 1def display():# 创建空白图像board = np.zeros([BOARD_SIZE, BOARD_SIZE, 3])# 把蛇涂成绿色for part in snake:board[part.y, part.x] = [0, 255, 0]# 把苹果涂成红色board[appley, applex] = [0, 0, 255]# 显示屏cv2.imshow("Snake Game", np.uint8(board.repeat(CELL_SIZE, 0).repeat(CELL_SIZE, 1)))key = cv2.waitKey(int(1000/SPEED))# 返回按下的键。如果没有按下键,则为-1。 return keydef win_focus():# 全屏打开图像,然后返回正常窗口cv2.namedWindow("Snake Game", cv2.WINDOW_AUTOSIZE);board = np.zeros([BOARD_SIZE * CELL_SIZE, BOARD_SIZE * CELL_SIZE, 3])cv2.imshow("Snake Game", board);cv2.setWindowProperty("Snake Game", cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN);cv2.waitKey(2000)cv2.setWindowProperty("Snake Game", cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_AUTOSIZE)if __name__ == '__main__' : # 棋盘游戏中每个单元格的大小CELL_SIZE = 20# 游戏中沿宽度排列的单元数BOARD_SIZE = 45# 改变速度使游戏进行得更快SPEED = 12# 吃过苹果后,蛇会按生长单位生长GROWTH = 3# 变量跟踪苹果是否被吃eaten = True# 变量来检查游戏是否应该退出quit = False# 变量跟踪增长。grow = 0# 存储蛇的数组snake = []#蛇的头从棋盘的中心开始。head = Head(0, int((BOARD_SIZE - 1)/2), int((BOARD_SIZE - 1)/2))snake.append(head)# 通过打印说明开始游戏print('w = top, a = left, s = down, d = right')# 让窗口聚焦的丑把戏win_focus()while True:# 检查苹果是否被吃掉,并生成一个新的if eaten:# 列出所有可能的地点s = list(range(0, BOARD_SIZE ** 2))# 删除属于蛇的一部分的cellfor part in snake:s.remove(part.x * BOARD_SIZE + part.y)# 从剩余的cell中随机挑选一个 a = choice(s)applex = int(a/BOARD_SIZE)appley = a % BOARD_SIZEeaten = False# 制作并展示显示屏key = display()# 获取按下的键并相应地移动# 8和27是删除键和退出键# 方向键在OpenCV中很棘手。所以我们使用#键'w', 'a','s','d'表示移动。# w = top, a = left, s = down, d = rightif key == 8 or key == 27:breakelif key == ord("d") :head.direction = 0elif key == ord("s") :head.direction = 1elif key == ord("a") :head.direction = 2elif key == ord("w") :head.direction = 3# 移动snakefor part in snake[::-1]:part.move() # 碰撞规则if head.x < 0 or head.x > BOARD_SIZE - 1 or head.y < 0 or head.y > BOARD_SIZE - 1:breakfor part in snake[1:]:if head.x == part.x and head.y == part.y:quit = Truebreakif quit:break# 蛇在多帧中逐渐生长 if grow > 0:snake.append(SnakePart(snake[-1], subx, suby))grow -= 1# 当蛇吃苹果的时候,蛇就会长出来if applex == head.x and appley == head.y:subx = snake[-1].xsuby = snake[-1].yeaten = Truegrow += GROWTH
代码解析
首先,我们将导入一些库用于显示和生成苹果的随机位置。
import cv2
import numpy as np
from random import randint
from random import choice
让我们制作几个类来代表游戏。
- 1.
SnakePart
:这代表了蛇的身体(不包括头部)。 - 2.
Head
:这个类代表蛇头
SnakePart
类有x和y坐标,以及对它前面的另一个SnakePart
或Head
的引用。
class SnakePart:def __init__(self, front, x, y):self.front = frontself.x = xself.y = ydef move(self):# Moves by following the part in front of itself.x = self.front.xself.y = self.front.y
move()
方法只是复制前面部件的位置。
Head
类也有x和y。此外,它还有一个指定移动方向的direction
变量。
class Head:def __init__(self, direction, x, y):self.direction = directionself.x = xself.y = ydef move(self):# 检查它当前的方向,并相应地移动if self.direction == 0:self.x += 1elif self.direction == 1:self.y += 1elif self.direction == 2:self.x -= 1elif self.direction == 3:self.y -= 1
现在,让我们转到主函数,看看游戏是如何实现的。我们首先定义几个有用的常量。
CELL_SIZE
指定显示屏上每个单元格的宽度,以像素为单位。
BOARD_SIZE
沿显示屏宽度的单元格数。在我们的示例中,CELL_SIZE
是20,BOARD_SIZE
是45。因此,显示器的大小是20 x 45 = 900
像素。
SPEED
决定了蛇的快慢。如果游戏对你来说太快,请使用较小的数字。
GROWTH
是指蛇吃了一个苹果后生长的单位数。
if __name__ == '__main__' : # Size of each cell in the board gameCELL_SIZE = 20# Number of cells along the width in the gameBOARD_SIZE = 45# Change SPEED to make the game go fasterSPEED = 12# After eating an apple the snake grows by GROWTH unitsGROWTH = 3
接下来,我们定义一些以后会派上用场的变量。
# Variable to track if apple is eaten
eaten = True
# Variable to check if the game should quit
quit = False
# Variable to track growth.
grow = 0
现在,让我们创建一个空数组来存储head 和 snakeparts.。
# Array for storing snake
snake = []
#snake's head starts at the center of the board.
head = Head(0, int((BOARD_SIZE - 1)/2), int((BOARD_SIZE - 1)/2))
snake.append(head)
在进入程序的主while循环之前,让我们先看看显示当前游戏的display()函数。
在下面的代码中,我们执行以下操作。
- 我们首先创建一个显示屏,并将其填充为零(黑色),
- 我们将蛇所占据的单元格涂成绿色。
- 我们把被苹果占据的单元格涂成红色。
- 如果键盘上有一个键被按下,返回该键的id。
def display():# Create a blank imageboard = np.zeros([BOARD_SIZE * CELL_SIZE, BOARD_SIZE * CELL_SIZE, 3])# Color the snake greenfor part in snake:x = part.x * CELL_SIZEy = part.y * CELL_SIZEboard[y:y + CELL_SIZE, x:x + CELL_SIZE] = [0, 255, 0]# Color the apple red x = applex * CELL_SIZEy = appley * CELL_SIZEboard[y:y + CELL_SIZE, x:x + CELL_SIZE] = [0, 0, 255]# Display boardcv2.imshow("Snake Game", np.uint8(board))key = cv2.waitKey(int(1000/SPEED))# Return the key pressed. It is -1 if no key is pressed. return key
我们几乎准备好进入游戏的主要while循环了。在此之前,我们先打印一些说明。
# Start the game by printing instructions
print('w = top, a = left, s = down, d = right')
# Ugly trick to bring the window in focus
win_focus()
您将注意到一个函数win_focus()
。取决于OpenCV在你的系统上使用的窗口方法,当你运行这个游戏时,显示窗口可能不在焦点中。为了解决这一问题,我们使用了这种丑陋的方法来聚焦游戏窗口,这样用户就不必点击窗口。
在下面的代码中,我们执行以下操作
- 我们打开一个窗口
- 显示游戏窗口
- 将窗口设置为全屏。这使窗口成为焦点。
- 我们将窗口调整回正常大小。
def win_focus():# Ugly trick to get the window in focus.# Opens an image in fullscreen and then back to normal windowcv2.namedWindow("Snake Game", cv2.WINDOW_AUTOSIZE);board = np.zeros([BOARD_SIZE * CELL_SIZE, BOARD_SIZE * CELL_SIZE, 3])cv2.imshow("Snake Game", board);cv2.setWindowProperty("Snake Game", cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN);cv2.waitKey(2000)cv2.setWindowProperty("Snake Game", cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_AUTOSIZE)
如果遇到任何故障,可以在主函数中注释掉win_focus()
。
对于代码的主要部分,我们将使用一个while循环,其中每次迭代都是蛇的一次移动。在下面的循环中,我们完成两件事:
- 检查苹果是否被吃了。
- 如果是,生成一个新的苹果。在生成苹果的时候,我们确保它的位置不与蛇重叠。
while True:# Checks if the apple is eaten and generates a new oneif eaten:# Create a list of all possible locationss = list(range(0, BOARD_SIZE ** 2))# Delete cells that are part of the snakefor part in snake:s.remove(part.x * BOARD_SIZE + part.y)# Randomly pick from one of the remaining cells a = choice(s)applex = int(a/BOARD_SIZE)appley = a % BOARD_SIZEeaten = False
接下来,我们显示显示屏,并查找键盘输入。
if/elif
语句检查是否按下了‘w’、‘a’、’、‘d’、escape 或 delete 键
。根据键盘输入,蛇改变方向或停止程序。
# Makes and displays the board
key = display()# Gets key presses and moves accordingly
# 8 and 27 are delete and escape keys
# Arrow keys are tricky in OpenCV. So we use
# keys 'w', 'a','s','d' for movement.
# w = top, a = left, s = down, d = rightif key == 8 or key == 27:break
elif key == ord("d") :head.direction = 0
elif key == ord("s") :head.direction = 1
elif key == ord("a") :head.direction = 2
elif key == ord("w") :head.direction = 3
根据键盘输入,我们移动蛇。您可能还记得,SnakePart
的move
方法只是在它前面复制蛇部分的位置。
# Moving the snake
for part in snake[::-1]:part.move()
接下来,我们实现碰撞检查。下面的代码实现了两个规则:
- 如果蛇的头移出显示屏,游戏就结束了。
- 如果蛇的头部与蛇的身体发生碰撞,游戏就结束了。
# Collision rulesif head.x < 0 or head.x > BOARD_SIZE - 1 or head.y < 0 or head.y > BOARD_SIZE - 1:breakfor part in snake[1:]:if head.x == part.x and head.y == part.y:quit = Truebreakif quit:break
最后,我们制定了蛇吃苹果生长的规则。当苹果被吃掉的时候,生长变量的增量GROWTH是不变的,蛇每帧生长一个单元格,直到它完全长大。
# The snake grows gradually over multiple frames if grow > 0:snake.append(SnakePart(snake[-1], subx, suby))grow -= 1# Grows the snake when it eats an appleif applex == head.x and appley == head.y:subx = snake[-1].xsuby = snake[-1].yeaten = Truegrow += GROWTH
参考目录
https://learnopencv.com/snake-game-with-opencv-python/
OpenCV进阶(3)基于OpenCV的贪吃蛇游戏相关推荐
- python贪吃蛇设计目标_基于 pygame 设计贪吃蛇游戏
基于 pygame 设计贪吃蛇游戏 贪吃蛇游戏通过玩家控制蛇移动,不断吃到食物增长,直到碰到蛇身或边界游戏结束.其运行效果如下所示: 游戏开始时,先导入可能需要用到的包. import time im ...
- 基于React的贪吃蛇游戏的设计与实现
代码地址如下: http://www.demodashi.com/demo/11818.html 贪吃蛇小游戏(第二版) 一年半前层用react写过贪吃蛇小游戏https://github.com/c ...
- 基于HTML5的贪吃蛇游戏的设计与实现
基于HTML5的贪吃蛇游戏的设计与实现 功能要求: 贪吃蛇游戏是一款经典的单机休闲游戏,玩家通过上下左右按键控制蛇头的移动方向使其向指定方向前进,并吃掉随机位置上产生食物来获得分数.每吃掉一次食物,贪 ...
- Linux下基于SDL库贪吃蛇游戏
Linux下基于SDL库贪吃蛇游戏 SDL(Simple DirectMediaLayer)是一套开放源代码的跨平台多媒体开发库,使用C语言写成.SDL提供了数种控制图像.声音.输出入的函数,让开 ...
- 基于EasyX的贪吃蛇游戏
基于EasyX的贪吃蛇游戏 一.预备知识 二.游戏逻辑 1.贪吃蛇元素 2.贪吃蛇规则 三.游戏设计 1.地图设计 2.移动设计 3.速度设计 4.整体设计 一.预备知识 1.使用EasyX必须要知道 ...
- 基于单片机的贪吃蛇游戏设计_前端入门,基于html,css,javascript的贪吃蛇游戏
源代码: 贪吃蛇 .box1{ font-size: 15px; float:left; display: block; margin-right: 150px; } .box2{ font-size ...
- 基于单片机的贪吃蛇游戏
绪论 1.1 研究背景与意义 随着社会的发展,人们生活的步调日益加快,越来越多的人加入了全球化的世界. 人们不再拘泥于--,J,块天地,加班,出差成了现代人不可避免的公务.而此时一款可以 随时随地娱乐 ...
- 基于linux的贪吃蛇游戏设计_贪吃蛇还能这么玩?绝对是你从未体验过的全新版本(上)...
上个月 Gitee 宣布推出「Python 贪吃蛇魔改大赛」的活动,受到了众多开发者们的欢迎.半个多月后,我们收到了共计 42 个参赛作品,有的作品创意无限,有的作品视觉效果极佳,看看下面的作品一览, ...
- 基于java的贪吃蛇游戏
贪吃蛇的游戏开发 实验内容: 1)实现贪吃蛇游戏基本功能,屏幕上随机出现一个"食物",称为豆子,上下左右 控制"蛇"的移动,吃到"豆子"以后 ...
- 基于MFC的贪吃蛇游戏
一.软件说明 贪吃蛇游戏是一款有趣的益智游戏,可以锻炼大脑的反映能力,在游戏中娱乐和放松自己.该贪吃蛇采用传统的游戏规则,实现蛇的移动.进食.增长以及死亡过程,并统计所得分数.最初蛇只有3节,每吃一个 ...
最新文章
- sql 2008数据库日志清理(转)
- Android 程序打包及签名
- iis 跨域_织梦会员登录二级域名不能跨域
- stateless_Spring Stateless State Security第3部分:JWT +社会认证
- 第三十七期:刷脸支付叫好不叫座,为啥消费者和商家都不愿用先进科技?
- 坑爹的水题之“元芳你怎么看”
- 理解ASP.NET中的三层结构
- Bezier曲线扫盲
- 138. Copy List with Random Pointer
- 解决requests.text乱码问题content.decode()
- 设置jupyter notebook软件的字体样式
- vue 实现图片预览
- axure rp8.1 注册码
- 微课录制神器,新手老师必备录屏软件!
- 检测应用位于后台,并弹出手势解锁,解锁成功进入主界面
- linux各个版本简介 (未完待续)
- android 耳机数据传输,智能手机耳机电路工作原理
- 【爬虫】python爬虫从入门到放弃
- 详解动态规划01背包问题--JavaScript实现
- 江南百景图显示服务器错误,江南百景图通讯失败请保持网络畅通并重试
热门文章
- Android 简单的计算器实现
- lpv4的地址格式由多少个字节组成_2020年智慧树艺术品拍卖第八单元章节测试答案...
- 中国移动云能力中心校招面试总结(三面)
- linux软件安装之详解apt、yum、dnf 和 pkg包安装
- Ubuntu20.04 安装HPC_SDK加速库
- 管道-过滤器软件架构
- 乔布斯05年斯坦福大学毕业典礼上的演讲
- 乔布斯在斯坦福大学的演讲视频
- 毕业设计英文文献java_计算机专业毕业设计论文外文文献中英文翻译——java对象...
- 不念过往,不畏将来——告别曾经