若該文爲原創文章,未經允許不得轉載
原博主博客地址: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