若该文为原创文章,未经允许不得转载
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/106647346
红胖子 (红模仿) 的博文大全:开发技术集合(包含 Qt 实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中…(点击传送门)
Qt 开发专栏:项目实战(点击传送门)
OpenCV 开发专栏(点击传送门)
需求
激光射击游戏,外设激光射击目标圆圈,计分游戏。
原理
使用 OpenCV 打开摄像头,识别圆圈,识别激光,判断激光点是否在圆圈内。
注意
需要摄像头,摄像头对准白色矩形区域,游戏钱需要先对摄像头进行手动校准,提供调整校准标定的功能,调整到圆圈和激光都可识别。
相关博客
**《项目实战:Qt+OpenCV 操作摄像头拍照、调节参数和视频录制》
《OpenCV 开发笔记(一):OpenCV 介绍、编译》
《OpenCV 开发笔记(五):OpenCV 读取与操作摄像头》
《OpenCV 开发笔记(七):OpenCV 基础图形绘制》
《OpenCV 开发笔记(十):OpenCV 图像颜色通道分离和图像颜色多通道混合》
《OpenCV 开发笔记(二十一):算法基础之形态学滤波 - 膨胀》
《OpenCV 开发笔记(二十二):算法基础之形态学滤波 - 腐蚀》
《OpenCV 开发笔记(二十八):带你学习图像识别之阈值化》
《OpenCV 开发笔记(三十六):红胖子 8 分钟带你深入了解缩放与图像金字塔(图文并茂 + 浅显易懂 + 程序源码)》
《OpenCV 开发笔记(五十三):红胖子 8 分钟带你深入了解模板匹配识别(图文并茂 + 浅显易懂 + 程序源码)》**
Demo:激光射击游戏 v1.0.0
下载地址
CSDN:https://download.csdn.net/download/qq21497936/12507420
QQ 群:1047134658(点击“文件”搜索“shootGame”,群内与博文同步更新所有可开源的源码模板)
核心代码
#ifndef SHOOTGAMEWIDGET_H
#define SHOOTGAMEWIDGET_H
#include <QWidget>
#include "OpenCVManager.h"
#include <QTimer>
#include <QThread>
namespace Ui {class ShootGameWidget;}
class ShootGameWidget : public QWidget
{
Q_OBJECT
public:
explicit ShootGameWidget(QWidget *parent = 0);
~ShootGameWidget();
protected slots:
void slot_captureOneFrame(cv::Mat mat);
bool slot_recognize(cv::Mat mat, bool show = false);
void slot_timeOut();
private slots:
void on_pushButton_start_clicked();
void on_pushButton_out_clicked();
void on_pushButton_startCameraTest_clicked();
void on_pushButton_stopCameraTest_clicked();
void on_pushButton_add1_clicked();
void on_pushButton_dec1_clicked();
void on_pushButton_add2_clicked();
void on_pushButton_dec2_clicked();
void on_pushButton_add3_clicked();
void on_pushButton_dec3_clicked();
private:
void paintEvent(QPaintEvent *event);
void timerEvent(QTimerEvent *event);
private:
Ui::ShootGameWidget *ui;
OpenCVManager *_pOpenCVManager;
QThread *_pOpenCVManagerThread;
cv::Mat _srcMat;
QImage _srcImage;
int _r;
int _penWidth;
cv::Mat _circleMat;
cv::Mat _dotMat;
cv::Mat _dot2Mat;
cv::Mat _dot3Mat;
cv::Mat _dot4Mat;
cv::Mat _dot5Mat;
cv::Mat _dot6Mat;
cv::Mat _dot7Mat;
int _timerId;
double _f;
int _margin;
int _count;
int _totalTime; // 总时间,默认 60s
int _currentTime; // 当前时间
bool _running; // 是否游戏开始
QPoint _centerPoint; // 刷新圆圈的位置
bool _hitFlag; // 是否击中标志,每次刷新位置,设置 false,判断是否第一次击中用于计分
int _score; // 得分
QTimer *_pTimer; // 定时器,定时减少秒数
bool _result; // 标记是否打完出结果
};
#endif // SHOOTGAMEWIDGET_H
void ShootGameWidget::on_pushButton_start_clicked()
{if(!_pOpenCVManager->startCapture(0, 800, 600))
{QMessageBox::information(0, "错误", "检测摄像头失败");
return;
}
ui->label_title->setVisible(false);
ui->pushButton_start->setVisible(false);
ui->pushButton_out->setVisible(false);
ui->groupBox->setVisible(false);
_hitFlag = false;
_score = 0;
_currentTime = _totalTime;
_running = true;
_result = false;
_pTimer->start();}
void ShootGameWidget::paintEvent(QPaintEvent *event)
{if(ui->pushButton_stopCameraTest->isEnabled() || _running)
{QPainter painter(this);
painter.fillRect(rect(), Qt::black);
painter.setPen(QPen(Qt::white, 1));
painter.drawRect(_margin,
_margin,
rect().width() - _margin * 2,
rect().height() - _margin * 2);
QPen pen = painter.pen();
pen.setWidth(10);
pen.setColor(Qt::green);
painter.setPen(pen);
painter.drawEllipse(_centerPoint, _r/2, _r/2);
// painter.setPen(QPen(Qt::red, 10));
// painter.drawPoint(_centerPoint);
if(_running)
{painter.setPen(QPen(Qt::white, 1));
painter.drawText(300, 50, QString("得分: %1").arg(_score));
painter.drawText(500, 50, QString("倒计时: %1").arg(_currentTime));
if(_hitFlag)
{painter.drawText(700, 50, QString("已击中"));
}else{painter.drawText(700, 50, QString("未击中"));
}
}
}
if(_result)
{QPainter painter(this);
painter.setPen(QPen(Qt::black, 4));
QFont font = painter.font();
font.setPixelSize(64);
painter.setFont(font);
painter.drawText(rect(), Qt::AlignCenter, QString("游戏结束,您的得分为 %1 !!!").arg(_score));
}
}
void ShootGameWidget::slot_timeOut()
{if(_running)
{
_currentTime--;
if(_currentTime == 0)
{if(!_pOpenCVManager->stopCapture())
{ }
ui->label_title->setVisible(true);
ui->pushButton_start->setVisible(true);
ui->pushButton_out->setVisible(true);
ui->groupBox->setVisible(true);
_hitFlag = false;
_currentTime = _totalTime;
_running = false;
_pTimer->stop();
_result = true;
}
update();}
}
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/106647346