一、项目效果演示
QQ录屏20240122164409
二、游戏玩法介绍
本项目为娱乐项目非原创,主要玩法即通过电脑摄像头检测手部信息,来实现挡板的移动控制,可以一人或者2人参与游戏,调节代码可以控制球飞行速度。
注意:本小游戏所有环境配置都会给出,无需其他复杂操作代码也简单,只要按照步骤来一定可以自己运行在PC端。
三、游戏所需python环境介绍和安装
首先python的版本此处选择为3.7.7(其余版本相差不大的都可)
然后,我们所需要下载的环境如下所示,你可以将其存为txt格式直接在终端输入(具体格式如下):
pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
absl-py==2.1.0 attrs==23.2.0 cvzone==1.6.1 cycler==0.11.0 flatbuffers==23.5.26 fonttools==4.38.0 importlib-metadata==6.7.0 kiwisolver==1.4.5 matplotlib==3.5.3 mediapipe==0.9.0.1 numpy==1.21.6 opencv-contrib-python==4.9.0.80 opencv-python==4.9.0.80 packaging==23.2 Pillow==9.5.0 protobuf==3.20.3 pyparsing==3.1.1 python-dateutil==2.8.2 six==1.16.0 typing_extensions==4.7.1 zipp==3.15.0
四、代码编写和介绍
1、导入所需库和加载图像信息
- import cv2
- import cvzone
- from cvzone.HandTrackingModule import HandDetector
- import numpy as np
-
- cap = cv2.VideoCapture(0)
- cap.set(3, 1280)
- cap.set(4, 720)
-
- # Importing all images
- imgBackground = cv2.imread("Resources/Background.png")
- imgGameOver = cv2.imread("Resources/gameOver.png")
- imgBall = cv2.imread("Resources/Ball.png", cv2.IMREAD_UNCHANGED)
- imgBat1 = cv2.imread("Resources/bat1.png", cv2.IMREAD_UNCHANGED)
- imgBat2 = cv2.imread("Resources/bat2.png", cv2.IMREAD_UNCHANGED)
2、捕捉手部信息并计算小球运动数据
speedX:调节小球X轴运动速度
speedY:调节小球Y轴运动速度
ballPos:调节小球初始位置
- # Hand Detector
- detector = HandDetector(detectionCon=0.8, maxHands=2)
-
- # Variables
- ballPos = [100, 100]
- speedX = 15
- speedY = 15
- gameOver = False
- score = [0, 0]
-
- while True:
- _, img = cap.read()
- img = cv2.flip(img, 1)
- imgRaw = img.copy()
-
- # Find the hand and its landmarks
- hands, img = detector.findHands(img, flipType=False) # with draw
-
- # Overlaying the background image
- img = cv2.addWeighted(img, 0.2, imgBackground, 0.8, 0)
-
- # Check for hands
- if hands:
- for hand in hands:
- x, y, w, h = hand['bbox']
- h1, w1, _ = imgBat1.shape
- y1 = y - h1 // 2
- y1 = np.clip(y1, 20, 415)
-
- if hand['type'] == "Left":
- img = cvzone.overlayPNG(img, imgBat1, (59, y1))
- if 59 < ballPos[0] < 59 + w1 and y1 < ballPos[1] < y1 + h1:
- speedX = -speedX
- ballPos[0] += 30
- score[0] += 1
-
- if hand['type'] == "Right":
- img = cvzone.overlayPNG(img, imgBat2, (1195, y1))
- if 1195 - 50 < ballPos[0] < 1195 and y1 < ballPos[1] < y1 + h1:
- speedX = -speedX
- ballPos[0] -= 30
- score[1] += 1
-
- # Game Over
- if ballPos[0] < 40 or ballPos[0] > 1200:
- gameOver = True
-
- if gameOver:
- img = imgGameOver
- cv2.putText(img, str(score[1] + score[0]).zfill(2), (585, 360), cv2.FONT_HERSHEY_COMPLEX,
- 2.5, (200, 0, 200), 5)
-
- # If the game is not over, move the ball
- else:
-
- # Move the Ball
- if ballPos[1] >= 500 or ballPos[1] <= 10:
- speedY = -speedY
-
- ballPos[0] += speedX
- ballPos[1] += speedY
-
- # Draw the ball
- img = cvzone.overlayPNG(img, imgBall, ballPos)
-
- cv2.putText(img, str(score[0]), (300, 650), cv2.FONT_HERSHEY_COMPLEX, 3, (255, 255, 255), 5)
- cv2.putText(img, str(score[1]), (900, 650), cv2.FONT_HERSHEY_COMPLEX, 3, (255, 255, 255), 5)
-
- img[580:700, 20:233] = cv2.resize(imgRaw, (213, 120))
3、控制游戏开始和退出
- cv2.imshow("Image", img)
- key = cv2.waitKey(1)
- if key == ord('r'):
- ballPos = [100, 100]
- speedX = 15
- speedY = 15
- gameOver = False
- score = [0, 0]
- imgGameOver = cv2.imread("Resources/gameOver.png")
- elif key == 27: # Check for the ESC key
- break
-
- cap.release()
- cv2.destroyAllWindows()
五、完整代码如下
- import cv2
- import cvzone
- from cvzone.HandTrackingModule import HandDetector
- import numpy as np
-
- cap = cv2.VideoCapture(0)
- cap.set(3, 1280)
- cap.set(4, 720)
-
- # Importing all images
- imgBackground = cv2.imread("Resources/Background.png")
- imgGameOver = cv2.imread("Resources/gameOver.png")
- imgBall = cv2.imread("Resources/Ball.png", cv2.IMREAD_UNCHANGED)
- imgBat1 = cv2.imread("Resources/bat1.png", cv2.IMREAD_UNCHANGED)
- imgBat2 = cv2.imread("Resources/bat2.png", cv2.IMREAD_UNCHANGED)
-
- # Hand Detector
- detector = HandDetector(detectionCon=0.8, maxHands=2)
-
- # Variables
- ballPos = [100, 100]
- speedX = 15
- speedY = 15
- gameOver = False
- score = [0, 0]
-
- while True:
- _, img = cap.read()
- img = cv2.flip(img, 1)
- imgRaw = img.copy()
-
- # Find the hand and its landmarks
- hands, img = detector.findHands(img, flipType=False) # with draw
-
- # Overlaying the background image
- img = cv2.addWeighted(img, 0.2, imgBackground, 0.8, 0)
-
- # Check for hands
- if hands:
- for hand in hands:
- x, y, w, h = hand['bbox']
- h1, w1, _ = imgBat1.shape
- y1 = y - h1 // 2
- y1 = np.clip(y1, 20, 415)
-
- if hand['type'] == "Left":
- img = cvzone.overlayPNG(img, imgBat1, (59, y1))
- if 59 < ballPos[0] < 59 + w1 and y1 < ballPos[1] < y1 + h1:
- speedX = -speedX
- ballPos[0] += 30
- score[0] += 1
-
- if hand['type'] == "Right":
- img = cvzone.overlayPNG(img, imgBat2, (1195, y1))
- if 1195 - 50 < ballPos[0] < 1195 and y1 < ballPos[1] < y1 + h1:
- speedX = -speedX
- ballPos[0] -= 30
- score[1] += 1
-
- # Game Over
- if ballPos[0] < 40 or ballPos[0] > 1200:
- gameOver = True
-
- if gameOver:
- img = imgGameOver
- cv2.putText(img, str(score[1] + score[0]).zfill(2), (585, 360), cv2.FONT_HERSHEY_COMPLEX,
- 2.5, (200, 0, 200), 5)
-
- # If the game is not over, move the ball
- else:
-
- # Move the Ball
- if ballPos[1] >= 500 or ballPos[1] <= 10:
- speedY = -speedY
-
- ballPos[0] += speedX
- ballPos[1] += speedY
-
- # Draw the ball
- img = cvzone.overlayPNG(img, imgBall, ballPos)
-
- cv2.putText(img, str(score[0]), (300, 650), cv2.FONT_HERSHEY_COMPLEX, 3, (255, 255, 255), 5)
- cv2.putText(img, str(score[1]), (900, 650), cv2.FONT_HERSHEY_COMPLEX, 3, (255, 255, 255), 5)
-
- img[580:700, 20:233] = cv2.resize(imgRaw, (213, 120))
-
- cv2.imshow("Image", img)
- key = cv2.waitKey(1)
- if key == ord('r'):
- ballPos = [100, 100]
- speedX = 15
- speedY = 15
- gameOver = False
- score = [0, 0]
- imgGameOver = cv2.imread("Resources/gameOver.png")
- elif key == 27: # Check for the ESC key
- break
-
- cap.release()
- cv2.destroyAllWindows()
六、总结
以上就是opencv的一个趣味小游戏,如果能成功运行麻烦点个?(图片资料评论邮箱即可)。
当然如果你遇到环境问题或者其他问题,可以在评论中留言,我会帮助你完成此趣味小游戏,一起学习进步!
评论记录:
回复评论: