一、项目效果展示。
二、游戏规则介绍
通过以上画面我们可以发现我们需要用手掌去击打屏幕中的小球来获得得分,我们用手靠进小球到达一定的距离内小球就会改变颜色,然后我们将手掌远离小球,小球又会恢复原来的颜色,并且我们会获得一分。
规则很简单,那么接下来我们就去实现它!
注意:本小游戏所有环境配置都会给出,无需其他复杂操作代码也简单,只要按照步骤来一定可以自己运行在PC端。
三、游戏环境介绍安装
首先python的版本此处选择为3.7.7(其余版本相差不大的都可)
然后,我们所需要下载的环境如下所示,你可以将其存为txt格式直接在终端输入(具体格式如下图):
pip install -r environment.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
absl-py==1.2.0
attrs==22.1.0
cvzone==1.5.6
cycler==0.11.0
fonttools==4.37.4
kiwisolver==1.4.4
matplotlib==3.5.3
mediapipe==0.8.9.1
numpy==1.21.6
opencv-contrib-python==4.6.0.66
opencv-python==4.6.0.66
opencv-python-headless==4.6.0.66
packaging==21.3
Pillow==9.2.0
protobuf==3.19.1
pyparsing==3.0.9
python-dateutil==2.8.2
six==1.16.0
speech==0.5.2
typing_extensions==4.4.0
保存格式如下:
完成以上安装后,就可以开始编写我们的代码了!
四、代码编写。
1、 导入所需库。
此处我们用到了cv2、cvzone和一些其他基本模块。
import random
import time
import cv2
from cvzone.HandTrackingModule import HandDetector
import math
import numpy as np
import cvzone
from winsound import Beep
2、计算距离。
此处我们设置了摄像头返回画面的大小,并且通过numpy计算了我们手距离摄像头的一个距离。
cap = cv2.VideoCapture(0)
cap.set(3, 1280)
cap.set(4, 720)
#hand detector
detector = HandDetector(detectionCon=0.8, maxHands=1)
#find function
#x is the raw distance y is the value in cm
x = [300, 245, 200, 170, 145, 130, 112, 103, 93, 87, 80, 75, 70, 67, 62, 59, 57]
y = [20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100]
Ax^2 + Bx + C
coff = np.polyfit(x, y, 2)
3、主要游戏代码。
此处设定了游戏中需要使用到的一些参数,并且通过手部信息和球的信息来判断我们的游戏进程,此外还设置了分数计数器和时间计数器来测试我们的游戏能力,可以自己调节游戏时间。
此处以20s为例我给出我自己认为的排行:
socre:10~20 菜鸡
score:20~30 黑铁
score:30~50 白银
score:50~70 钻石
score:70~100 王者
score:1000+ 你改代码了!
#game variables
cx, cy = 250, 250
color = (255, 0, 255)
counter = 0
score = 0
timeStart = time.time()
totalTime = 30
#loop
while True:
success, img = cap.read()
img = cv2.flip(img, 1)
if time.time()-timeStart < totalTime:
hands = detector.findHands(img, draw=False)
if hands:
lmList = hands[0]['lmList']
x, y, w, h = hands[0]['bbox']
x1, y1 = lmList[5][:2]
x2, y2 = lmList[17][:2]
distance = math.sqrt((y2-y1)**2 + (x2-x1)**2)
A, B, C = coff
distanceCM = A*distance**2 + B*distance + C
#判断距离并判断矩阵框中是否有button
if distanceCM < 40 and x< cx< x+w and y < cy <y+h: counter="1" else: color="(255," 0, 255) cv2.rectangle(img, (x,y), (x+w, y+h), (255, 255), 3) cvzone.puttextrect(img, f'{int(distancecm)} cm', (x, y)) if counter: +="1" 255, 0) 3: cx="random.randint(100," 1100) cy="random.randint(100," 600) score beep(100, 50) #draw button cv2.circle(img, (cx,cy), 30, color, cv2.filled) (cx, cy), 10, 20, 2) (50, 50, 50), #game hud f'time: {int(totaltime-(time.time()-timestart))}', (1000,75),scale="3," offset="20)" f'score: {str(score).zfill(2)}', (60, 75), scale="3," 'game over', (400, 400), thickness="7)" f'your score: {score}', (450, 500), f'press r to restart', (460, 575), cv2.imshow('img', img) k="cv2.waitKey(1)" ord('r'): timestart="time.time()" elif 27: break< code></y+h:>
五、完整代码如下。
import random
import time
import cv2
from cvzone.HandTrackingModule import HandDetector
import math
import numpy as np
import cvzone
from winsound import Beep
cap = cv2.VideoCapture(0)
cap.set(3, 1280)
cap.set(4, 720)
#hand detector
detector = HandDetector(detectionCon=0.8, maxHands=1)
#find function
#x is the raw distance y is the value in cm
x = [300, 245, 200, 170, 145, 130, 112, 103, 93, 87, 80, 75, 70, 67, 62, 59, 57]
y = [20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100]
Ax^2 + Bx + C
coff = np.polyfit(x, y, 2)
#game variables
cx, cy = 250, 250
color = (255, 0, 255)
counter = 0
score = 0
timeStart = time.time()
totalTime = 30
#loop
while True:
success, img = cap.read()
img = cv2.flip(img, 1)
if time.time()-timeStart < totalTime:
hands = detector.findHands(img, draw=False)
if hands:
lmList = hands[0]['lmList']
x, y, w, h = hands[0]['bbox']
x1, y1 = lmList[5][:2]
x2, y2 = lmList[17][:2]
distance = math.sqrt((y2-y1)**2 + (x2-x1)**2)
A, B, C = coff
distanceCM = A*distance**2 + B*distance + C
#判断距离并判断矩阵框中是否有button
if distanceCM < 40 and x< cx< x+w and y < cy <y+h: counter="1" else: color="(255," 0, 255) cv2.rectangle(img, (x,y), (x+w, y+h), (255, 255), 3) cvzone.puttextrect(img, f'{int(distancecm)} cm', (x, y)) if counter: +="1" 255, 0) 3: cx="random.randint(100," 1100) cy="random.randint(100," 600) score beep(100, 50) #draw button cv2.circle(img, (cx,cy), 30, color, cv2.filled) (cx, cy), 10, 20, 2) (50, 50, 50), #game hud f'time: {int(totaltime-(time.time()-timestart))}', (1000,75),scale="3," offset="20)" f'score: {str(score).zfill(2)}', (60, 75), scale="3," 'game over', (400, 400), thickness="7)" f'your score: {score}', (450, 500), f'press r to restart', (460, 575), cv2.imshow('img', img) k="cv2.waitKey(1)" ord('r'): timestart="time.time()" elif 27: break< code></y+h:>
六、问题总结。
以上就是opencv的一个趣味小游戏,如果能成功运行麻烦点个👍。
当然如果你遇到环境问题或者其他问题,可以在评论中留言,我会帮助你完成此趣味小游戏,一起学习进步!
Original: https://blog.csdn.net/qq_58535145/article/details/127297344
Author: 醉翁之意不在酒~
Title: OpenCV-趣味小游戏-手掌击球
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/719593/
转载文章受原作者版权保护。转载请注明原作者出处!