Opencv项目实战:17 贪吃蛇游戏

news2025/9/12 16:25:09

目录

0、项目介绍

1、效果展示

2、项目搭建

3、项目代码展示与讲解

4、项目资源

5、项目总结


0、项目介绍

这次是一个有意思的计算机视觉游戏——贪吃蛇,我们以食指为蛇头,不断的移动我们的手指,当吃到甜甜圈的时候,蛇身增长,当食指停止或触碰蛇身时,游戏结束。点击'r'将重新开始游戏。

1、效果展示

制作成GIF图片的效果有点卡,实际的效果还是很好的。

2、项目搭建

————17 Gluttonous snake

        ——Donut.png

        ——snake.py

3、项目代码展示与讲解

#snake.py

import math
import random
import cvzone
import cv2
import numpy as np
from cvzone.HandTrackingModule import HandDetector

cap = cv2.VideoCapture(0)
cap.set(3, 1280)
cap.set(4, 720)

detector = HandDetector(detectionCon=0.8, maxHands=1)


class SnakeGameClass:
    def __init__(self, pathFood):
        self.points = []  # 蛇的所有点
        self.lengths = []  # 每个点之间的距离
        self.currentLength = 0  # 蛇的总长度
        self.allowedLength = 150  # 总共允许长度
        self.previousHead = 0, 0  # 起点

        self.imgFood = cv2.imread(pathFood, cv2.IMREAD_UNCHANGED)  # 读取甜甜圈的位置路径
        self.hFood, self.wFood, _ = self.imgFood.shape  # 得到甜甜圈图像的长、宽
        self.foodPoint = 0, 0  # 初始化甜甜圈的位置

        self.randomFoodLocation()  # 随机分布甜甜圈的位置   

        self.score = 0  # 吃得甜甜圈的分数
        self.gameOver = False # gameover

    def randomFoodLocation(self):
        self.foodPoint = random.randint(100, 1000), random.randint(100, 600)

    def update(self, imgMain, currentHead):

        if self.gameOver:
            cvzone.putTextRect(imgMain, "Game Over", [300, 400],
                               scale=7, thickness=5, offset=20)
            cvzone.putTextRect(imgMain, f'Your Score: {self.score}', [300, 550],
                               scale=7, thickness=5, offset=20)
        else:
            px, py = self.previousHead
            cx, cy = currentHead

            self.points.append([cx, cy])
            distance = math.hypot(cx - px, cy - py)
            self.lengths.append(distance)
            self.currentLength += distance
            self.previousHead = cx, cy

            # Length Reduction
            if self.currentLength > self.allowedLength:
                for i, length in enumerate(self.lengths):
                    self.currentLength -= length
                    self.lengths.pop(i)
                    self.points.pop(i)
                    if self.currentLength < self.allowedLength:
                        break

            # Check if snake ate the Food
            rx, ry = self.foodPoint
            if rx - self.wFood // 2 < cx < rx + self.wFood // 2 and \
                    ry - self.hFood // 2 < cy < ry + self.hFood // 2:
                self.randomFoodLocation()
                self.allowedLength += 50
                self.score += 1
                print(self.score)

            # Draw Snake
            if self.points:
                for i, point in enumerate(self.points):
                    if i != 0:
                        cv2.line(imgMain, self.points[i - 1], self.points[i], (0, 0, 255), 20)
                cv2.circle(imgMain, self.points[-1], 20, (0, 255, 0), cv2.FILLED)

            # Add Food
            imgMain = cvzone.overlayPNG(imgMain, self.imgFood,
                                        (rx - self.wFood // 2, ry - self.hFood // 2))

            cvzone.putTextRect(imgMain, f'Score: {self.score}', [50, 80],
                               scale=3, thickness=3, offset=10)

            # Check for Collision
            pts = np.array(self.points[:-2], np.int32)
            pts = pts.reshape((-1, 1, 2))
            cv2.polylines(imgMain, [pts], False, (0, 255, 0), 3)
            minDist = cv2.pointPolygonTest(pts, (cx, cy), True)

            if -1 <= minDist <= 1:
                print("Hit")
                self.gameOver = True
                self.points = []  # all points of the snake
                self.lengths = []  # distance between each point
                self.currentLength = 0  # total length of the snake
                self.allowedLength = 150  # total allowed Length
                self.previousHead = 0, 0  # previous head point
                self.randomFoodLocation()

        return imgMain


game = SnakeGameClass("Donut.png")

while True:
    success, img = cap.read()
    img = cv2.flip(img, 1)
    hands, img = detector.findHands(img, flipType=False)

    if hands:
        lmList = hands[0]['lmList']
        pointIndex = lmList[8][0:2]
        img = game.update(img, pointIndex)
    cv2.imshow("Image", img)
    key = cv2.waitKey(1)
    if key == ord('r'):

        game.gameOver = False

    elif key==27:break

首先,打开摄像头的窗口得比较的大,不仅为了方便测试,而且窗口小了也会影响我们的手势识别,然后建立SnakeGameClass类,其下的变量名用途请查看注释。

其中,先看while True里面,cv2.flip函数是用窗口画面翻转的,输入一个正值,便会绕y轴翻转,这样能够保证窗口画面中的动作与我们的想法相同,接下来获得我们的手指landmark,即是获得目前蛇的头部landmark,之后完成我们的游戏更新部分。

其次,来看randomFoodLocation()函数,可以用于随机生成甜甜圈所在位置,我们为边缘留了些位置,避免手势识别失误和容易出界的问题。此时它并不具备更新位置的能力(只是生成了一个随机数位置),我们用update函数来完成主要的功能。我们想要实现的一个效果是游戏结束时,我需要得到一个提示,你不能再继续下去了,就如上面的GIF图片中,当我手势被识别时,会有一个提示(用putTextRcet完成),否则就会进行正常的游戏操作。

正常的游戏操作,我希望有这几个方面,甜甜圈覆盖窗口画面实现更新、蛇头与蛇身相撞就会gameover、手势一旦识别必须不停移动、吃掉一个甜甜圈增长一节蛇身等。

  • Length Reduction:

        一旦蛇的总长度超过了我们允许的长度,我们就需要对其进行缩减,这里使用了enumerate函数对列表进行了迭代,返回了一个索引和值,方便减去对应的距离。

  • Check if snake ate the Food:

        只要蛇头进入了甜甜圈的范围内,即可认为是吃到了甜甜圈,接下来就可以完成食物位置的更新,蛇身的加长,score得分。

  • Draw Snake:

        画蛇的初始态。

  • Add Food:

        在窗口画面中覆盖上甜甜圈,可以使用cvzone.overlayPNG函数。

  • Check for Collision:

        [pts]为多边形曲线阵列,在这里我们将会绘制一个多边形,并用cv2.pointPolygonTest来返回除最后两个点外与蛇头最近的距离,因为有tickness的原因,所以我们无需纠结于minDist一定小于等于0。

4、项目资源

GitHub:17 Gluttonous snake

5、项目总结

最近本来在准备期末考试的,所以很久没写博客了,但由于疫情原因提前返乡回家了,这学期的考试要得等到明年啦。想要添加按钮、声音、毒药这些的,没有精力搞了,有兴趣的大家可以试试。

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

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

相关文章

浅谈字节码增强技术系列2-Asm与Cglib

作者&#xff1a;董子龙 前言 记得那是2022年秋天的第一场雨&#xff0c;比2021年来的稍晚一些&#xff0c;在那个秋雨朦胧的下午&#xff0c;正在工位上奋笔疾书的我突然听到了前面波哥对着手机听筒说出来的"温柔"的话语&#xff1a;说说你了解的spring-aop。话音…

基于Vision Transformers的文档理解简介

文档理解是从pdf、图像和Word文档中提取关键信息的技术。这篇文章的目标是提供一个文档理解模型的概述。 文档理解算法使用编码器-解码器结构分析文档内容&#xff0c;该管道结合了计算机视觉(CV)和自然语言处理(NLP)方法。管道的CV部分将文档作为输入图像进行分析&#xff0c…

对数据库索引的理解以及索引在MySQL中的数据结构

引言 索引在本质上相当于书的目录&#xff0c;通过目录就可以快速的找到某个章节对应的位置。索引的效果&#xff0c;就是加快了查找的速度。日常进行数据库的操作&#xff0c;一般地都是进行增删查改&#xff0c;而在很多场景中&#xff0c;进行查找的概率要比增删改大很多。…

搭建Flutter Web开发调试环境

Setting up the Framework/Engine development environment背景搭建 framework 开发环境修改调试 framework 源码运行 framework 测试用例同步更新 framework 源码搭建 engine 开发环境准备 depot_tools部署 engine 源码编译 engine 源码修改调试 engine 源码指定 --local-engi…

​极氪汽车被曝拟美股上市:最高募资10亿 李书福接连收获IPO

雷递网 雷建平 12月13日极氪汽车日前被曝出已“秘密递交申请”&#xff0c;准备在美股上市&#xff0c;此次拟募资10亿美元&#xff0c;估值可能高达100亿美元。有分析认为&#xff0c;极氪汽车秘密递交招股书&#xff0c;是为尽可能向其他竞争对手隐藏招股书细节&#xff0c;以…

十二、对象继承深入、call_apply、※圣杯模式、※构造函数和闭包、※企业模块化

十二、对象继承深入、call_apply、※圣杯模式、※构造函数和闭包、※企业模块化 对象继承深入 原型链继承 原型链定义 ​ 对象沿着__proto__在原型上寻找属性形成一种链条式的继承关系&#xff0c;这种继承关系就叫做原型链。 例如&#xff1a; Professor.prototype {na…

Linux(二)vim编辑器,gcc,库

vim 简介 vi是“visual interface”的简称。 类似于Windows下的记事本。 vim可以视为vi的高级版本 按下vimtutor进入帮助文档&#xff0c;以下内容在其中都有 vim的三种模式 Vi有三种基本工作模式&#xff1a;命令模式、文本输入模式、末行模式 基本操作 命令模式下的操作…

迷宫--dfs解法以及迷宫问题要不要回溯

文章目录题意题解思路&#xff1a;问题&#xff1a; 迷宫问题dfs要不要回溯&#xff1f;题意 一天Extense在森林里探险的时候不小心走入了一个迷宫&#xff0c;迷宫可以看成是由 n∗n 的格点组成&#xff0c;每个格点只有2种状态&#xff0c;.和#&#xff0c;前者表示可以通行…

装载问题 ——分支限界法(Java)

装载问题 ——分支限界法&#xff08;Java&#xff09; 文章目录装载问题 ——分支限界法&#xff08;Java&#xff09;1、 问题描述2、算法设计3、算法的改进4、程序代码5、参考资料1、 问题描述 有一批共n个集装箱要装上2艘载重量分别为C1和C2的轮船&#xff0c;其中集 装箱…

数图互通高校房产管理——教职工住宅方案

数图互通房产管理系统在这方面做得比较全面&#xff1b; 1、住房管理 1.1 住房档案 住房模块的管理主要是针对学校的承租住宅和已售住宅的管理&#xff0c;用于登记已售住宅的产权人信息&#xff0c;记录承租住宅的租赁起止日期、月租金等基本信息。 支持住房的坐落信息、楼栋…

Cas:146368-11-8(水溶)|Sulfo CY5-羧酸|Cyanine5 Carboxylic Acidic acid

Cas:146368-11-8(水溶)|Sulfo CY5-羧酸|Cyanine5 Carboxylic Acidic acid Sulfo CY5-羧酸这种分子可以被认为是非活性染料&#xff0c;用于控制样品和仪器校准。为了与胺和蛋白质标记偶联&#xff0c; 中文名&#xff1a;Sulfo CY5-羧酸 英文名&#xff1a;Cyanine5 Carboxy…

rate-limit 一款 java 开源渐进式分布式限流框架使用介绍

项目简介 rate-limit 是一个为 java 设计的渐进式限流工具。 目的是为了深入学习和使用限流&#xff0c;后续将会持续迭代。 特性 渐进式实现 支持独立于 spring 使用 支持整合 spring 支持整合 spring-boot 内置多种限流策略 快速开始 需求 jdk 1.7 maven 3.x mav…

ARM S5PV210 时钟系统与时钟体系框图

前言 This chapter describes the clock management unit (CMU) supported by S5PV210. The system controller (SYSCON) manages CMU and power management unit (PMU) in S5PV210. 本章介绍 S5PV210 支持的时钟管理单元&#xff08;CMU&#xff09;。系统控制器&#xff08…

【软考】系统集成项目管理工程师(十一)项目人力资源管理

一、项目人力资源管理概述二、激励理论1. 马斯洛需求层次理论2. 赫茨伯格的双因素理论3. X 理论/ Y 理论4. 期望理论三、人力资源管理子过程1. 规划人力资源管理2. 组建项目团队3. 建设项目团队4. 管理项目团队一、项目人力资源管理概述 在了解人力资源管理之前,我们先来认识…

从局部到全局:语义相似度的测地线距离

©PaperWeekly 原创 作者 | 苏剑林单位 | 追一科技研究方向 | NLP、神经网络前段时间在最近的一篇论文《Unsupervised Opinion Summarization Using Approximate Geodesics》[1] 中学到了一个新的概念&#xff0c;叫做“测地线距离&#xff08;Geodesic Distance&#xff…

.net开发安卓入门 - Service (服务)

.net开发安卓入门 - Service Android Service 概述Service VS Thread &#xff08;服务和线程之间进行选择&#xff09;前台服务代码启动前台服务方法运行效果后台服务代码启动代码绑定服务AIDL同系列文章推荐Android Service 概述 移动应用不像桌面应用。 桌面具有大量资源&a…

基于51单片机的正弦波发生器设计

程序运行图&#xff1a; 仿真原理图&#xff1a; 部分程序&#xff1a; #include <reg52.h> //接口定义 sbit DA P1^1; sbit CK P1^2; sbit CS P1^4; //10bit取样&#xff0c;1024点正弦查表数据 unsigned int code sine_dot[1024] { 0x200,0x203,0x206,0x209,…

可视化编排的数据集成和分发开源框架Nifi轻松入门-上

文章目录概述定义dataflow面临挑战特性核心概念架构高级概述安装部署常见处理器入门示例概述 定义 Nifi 官网地址 https://nifi.apache.org/ Nifi 官网文档 https://nifi.apache.org/docs.html Nifi GitHub源码地址 https://github.com/apache/nifi Apache NiFi是一个易于使用…

NetInside助力IT提高业务性能管理能力(二)

​​需求简介 某外高桥公司的OA系统是其重要的业务系统&#xff0c;OA系统负责人表示&#xff0c;部分用户反馈&#xff0c;访问OA系统时比较慢。需要通过分析系统看一下实际情况。 本次分析重点针对OA系统性能进行分析&#xff0c;以供安全取证、性能分析、网络质量监测以及…

关于推特隐私设置的一些小窍门

大家在使用推特进行引流的时候&#xff0c;在使用的时候难免会遇到一些功能模糊不清&#xff0c;这里twitter群推王给大家总结了一些偏门功能应该如何去设置&#xff0c;让你使用起来更加得心应手。 一、推特怎么设置自动放声音 1、首先打开推特APP并登陆。 2、其次在推特主…