最近老师让用Qt写一个可视化界面,然后就给了一个小视频,好奇的不得了,就照着做了一下
视频链接如下:C++案例教学–一个类游戏小程序的设计与实现全过程–用到QT-简单的STL容器
创建项目
1、打开QT
如果不知道怎么下载的话,可以参考这篇文章
2、在这里可以修改项目的名字和保存位置
3、之后就按照默认的,一直按[next]就可以了
代码如下
开始写代码了,具体操作老师在视频里全都说明了,这里只附上代码,希望对不想敲代码的朋友有帮助
以下这些代码都是自动生成后修改过的代码
ballobject.h
#ifndef BALLOBJECT_H
#define BALLOBJECT_H
#include <string>
#include <random>
//需要一些ball的共有属性和方法
class BaseBall
{
public:
BaseBall();
virtual ~BaseBall();
int x, y;//位置
int r;//半径
virtual void LiveOneTimeSlice()=0;//存活在一个时间片里面
virtual std::string GetClassName()
{
return "BaseBall";
//获取对象所属的类的名字
};
};
class PassiveBall :public BaseBall
{
public:
PassiveBall():BaseBall(){};
void LiveOneTimeSlice() override;
std::string GetClassName() override;
};
class PlayerBall : public PassiveBall
{
public:
PlayerBall():PassiveBall(){};
std::string GetClassName() override;
};
class RandomMoveBall :public BaseBall
{
public:
RandomMoveBall():BaseBall(){};
void LiveOneTimeSlice() override;
std::string GetClassName() override;
};
#endif // BALLOBJECT_H
mainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <vector>
#include "ballobject.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
QTimer *timer;
std::vector<BaseBall*> objList;//障碍物列表
PlayerBall *playerball;//玩家来控制的小球
void paintEvent(QPaintEvent *);
void keyPressEvent(QKeyEvent *ev);
void TimerEvent();
};
#endif // MAINWINDOW_H
ballobject.cpp
#include "ballobject.h"
std::default_random_engine generator;
std::uniform_int_distribution<int> distribution(0,100);
BaseBall::BaseBall()
{
x = y = 0;
r = 30;
}
BaseBall::~BaseBall()
{
}
void PassiveBall::LiveOneTimeSlice()
{
}
std::string PassiveBall::GetClassName()
{
return "PassiveBall";
}
std::string PlayerBall::GetClassName()
{
return "PlayerBall";
}
void RandomMoveBall::LiveOneTimeSlice()
{
bool bLeft = distribution(generator)>49;
x = bLeft ?x-20:x+20;
bool bUp = distribution(generator)>49;
y = bUp?y-10:y+10;
}
std::string RandomMoveBall::GetClassName()
{
return "RandomMoveBall";
}
mainWindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPainter>
#include <QTimer>
#include "ballobject.h"
#include <QDebug>
#include <QKeyEvent>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//设定定时器Timer,每秒刷新30次,FPS=30,大概是三十毫秒
timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &MainWindow::TimerEvent);
timer->start(50);
//创建游戏对象1
int objectsNum = 10;
int H = this->height();
int W = this->width();
int xstep = (W - objectsNum*20)/(objectsNum-1);
for(int i = 0;i < objectsNum;i++)
{
PassiveBall* obj = new PassiveBall();
//排放障碍物
obj->x=i*(obj->r*2 + xstep)+obj->r;
obj->y=H/2;
obj->r=10;
objList.push_back(obj);
}
//创建游戏对象2
for(int i = 0;i < objectsNum;i++)
{
RandomMoveBall* obj = new RandomMoveBall();
//排放障碍物
obj->x=i*(obj->r*2 + xstep)+obj->r;
obj->y=H/2 - 20;
obj->r=20;
objList.push_back(obj);
}
//创建游戏对象3
for(int i = 0;i < objectsNum;i++)
{
RandomMoveBall* obj = new RandomMoveBall();
//排放障碍物
obj->x=i*(obj->r*2 + xstep)+obj->r;
obj->y=H/2 - 20;
obj->r=20;
objList.push_back(obj);
}
//初始化玩家位置TODO
playerball = new PlayerBall();
playerball->x = W/2;
playerball->y = H;
playerball->r=10;
}
MainWindow::~MainWindow()
{
delete ui;
delete timer;//不删除就会内存泄露
for(auto itm:objList)
{
delete itm;
}
delete playerball;
}
void MainWindow::paintEvent(QPaintEvent *)
{
// static int x = 0;
// QPainter painter(this);
// painter.setPen(Qt::red);
// painter.setFont(QFont("楷体", 50));
// painter.drawText(rect(), Qt::AlignCenter, "我爱你中国");
// painter.setPen(Qt::blue);
// painter.setFont(QFont("楷体",500));
// painter.drawEllipse(x,0,100,100);
// x+=20;
//给每一个游戏对象存活一个时间片
for(auto itm:objList)
{
itm->LiveOneTimeSlice();
}
//绘制整个游戏场景
QPainter painter(this);
painter.setPen(Qt::black);
for(auto itm:objList)
{
QBrush brush(QColor(0,200,250),Qt::Dense4Pattern);
painter.setBrush(brush);
painter.drawEllipse(itm->x-itm->r,itm->y-itm->r,itm->r*2,itm->r*2);
}
painter.setPen(Qt::darkBlue);
QBrush brush(QColor(250,20,80),Qt::Dense4Pattern);
painter.setBrush(brush);
painter.drawEllipse(playerball->x-playerball->r,playerball->y-playerball->r,playerball->r*2,playerball->r*2);
}
void MainWindow::keyPressEvent(QKeyEvent *ev)
{
if(ev->key()==Qt::Key_Up)
{
playerball->y-=10;
qDebug()<<"Press Key Up";
return ;
}
if(ev->key()==Qt::Key_Down)
{
playerball->y+=10;
qDebug()<<"Press Key Down";
return ;
}
if(ev->key()==Qt::Key_Left)
{
playerball->x-=10;
qDebug()<<"Press Key Left";
return ;
}
if(ev->key()==Qt::Key_Right)
{
playerball->x+=10;
qDebug()<<"Press Key Right";
return ;
}
}
void MainWindow::TimerEvent()
{
//还要判断失败
for(auto itm:objList)
{
float distSqure = (itm->x - playerball->x)*(itm->x - playerball->x)+
(itm->y - playerball->y)*(itm->y - playerball->y);
if(distSqure<=((itm->r + playerball->r)*(itm->r + playerball->r)))
{
qDebug() <<"Failed!";
timer->stop();
}
}
//判断成功
if(playerball->y <= 0)
{
qDebug() <<"Success!";
timer->stop();
}
update();
}
效果如下
按动键盘上的上下左右键可以控制红色小球从下面往上跑,在不碰到蓝色小球的情况下安全到达最上方就挑战成功啦~
一点小问题
如果你下载的QTcreator版本在6以上,很有可能不能输入中文,虽然可以输出,如果是6以下的版本,可以采用一下方法修改配置,使其可以输入中文。
由Qt开发的软件界面不能输入中文
安装fcitx-libs-qt或fcitx-libs-qt5,在计算机中搜索libfcitxplatforminputcontextplugin.so文件,例如在我的计算机上,此文件位于
/usr/lib/x86_64-linux-gnu/qt5/plugins/platforminputcontexts/libfcitxplatforminputcontextplugin.so
找到Qt的安装目录,将上述文件复制到安装目录下的plugins/platforminputcontexts子目录下。
重新运行程序即可。
QtCreator本身的编辑器不能输入中文
如果是QtCreator本身编辑器不能输入中文,则将上述文件拷贝至Qt安装目录的[Qt安装目录]/Tools/QtCreator/lib/Qt/plugins/platforminputcontexts或者[Qt安装目录]/Tools/QtCreator/bin/plugins/platforminputcontexts。
对于不同版本的Qt,插件路径可能略有不同,但一定是在[Qt安装目录]/Tools/QtCreator/中,可以自己搜索一下。拷贝完成后,重新启动QtCreator即可生效。
看了老师的视频就知道老师想要实现一个HuntPlayerBall去追踪玩家,但是由于时间的限制没能实现,那我这个垃圾实现了更简单的功能,希望老师看到了不要嫌弃。
代码如下
ballobject.h
#ifndef BALLOBJECT_H
#define BALLOBJECT_H
#include <string>
#include <random>
//需要一些ball的共有属性和方法
class BaseBall
{
public:
BaseBall();
virtual ~BaseBall();
int x, y;//位置
int r;//半径
virtual void LiveOneTimeSlice()=0;//存活在一个时间片里面
virtual std::string GetClassName()
{
return "BaseBall";
//获取对象所属的类的名字
};
};
class PassiveBall :public BaseBall
{
public:
PassiveBall():BaseBall(){};
void LiveOneTimeSlice() override;
std::string GetClassName() override;
};
class PlayerBall : public PassiveBall
{
public:
PlayerBall():PassiveBall(){};
std::string GetClassName() override;
};
class RandomMoveBall :public BaseBall
{
public:
RandomMoveBall():BaseBall(){};
void LiveOneTimeSlice() override;
std::string GetClassName() override;
};
class HuntPlayerBall :public BaseBall
{
public:
HuntPlayerBall():BaseBall(){};
void LiveOneTimeSlice() override;
std::string GetClassName() override;
};
#endif // BALLOBJECT_H
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <vector>
#include "ballobject.h"
#include <random>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
QTimer *timer;
std::vector<BaseBall*> objList1;//障碍物列表
std::vector<BaseBall*> objList2;//障碍物列表
std::vector<BaseBall*> objList3;//障碍物列表
PlayerBall *playerball;//玩家来控制的小球
void paintEvent(QPaintEvent *);
void keyPressEvent(QKeyEvent *ev);
void TimerEvent();
};
#endif // MAINWINDOW_H
ballobject.cpp
#include "ballobject.h"
std::default_random_engine generator;
std::uniform_int_distribution<int> distribution(0,100);
BaseBall::BaseBall()
{
x = y = 0;
r = 30;
}
BaseBall::~BaseBall()
{
}
void PassiveBall::LiveOneTimeSlice()
{
}
std::string PassiveBall::GetClassName()
{
return "PassiveBall";
}
std::string PlayerBall::GetClassName()
{
return "PlayerBall";
}
void RandomMoveBall::LiveOneTimeSlice()
{
bool bLeft = distribution(generator)>49;
x = bLeft ?x-10:x+10;
bool bUp = distribution(generator)>49;
y = bUp?y-10:y+10;
}
std::string RandomMoveBall::GetClassName()
{
return "RandomMoveBall";
}
void HuntPlayerBall::LiveOneTimeSlice()
{
bool bLeft = distribution(generator)>49;
x = bLeft ?x-20:x+20;
bool bUp = distribution(generator)>49;
y = bUp?y-10:y+10;
}
std::string HuntPlayerBall::GetClassName()
{
return "HuntPlayerBall";
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPainter>
#include <QTimer>
#include "ballobject.h"
#include <QDebug>
#include <QKeyEvent>
#include <math.h>
#include <QRandomGenerator>
//添加随机数种子,作用:利用当前系统时间生成随机数,以此来防止每一次的随机数相同
#include <ctime> //添加头文件
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//设定定时器Timer,每秒刷新30次,FPS=30,大概是三十毫秒
timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &MainWindow::TimerEvent);
timer->start(50);
// start = new QTimer(this);
// connect(start, &QTimer::timeout, this, &MainWindow::StartEvent);
//创建游戏对象1
int objectsNum = 10;
int H = this->height();
int W = this->width();
int xstep = (W - objectsNum*20)/(objectsNum-1);
for(int i = 0;i < 30;i++)
{
PassiveBall* obj = new PassiveBall();
//排放障碍物
int bLeft = QRandomGenerator::global()->bounded(100,1200);
//qDebug()<<bLeft;
obj->x=bLeft;
int bRight = QRandomGenerator::global()->bounded(100,1200);
//qDebug()<<bRight;
obj->y=bRight;
obj->r=15;
objList1.push_back(obj);
}
//创建游戏对象2
for(int i = 0;i < objectsNum;i++)
{
RandomMoveBall* obj = new RandomMoveBall();
//排放障碍物
obj->x=i*(obj->r*2 + xstep)+obj->r;
obj->y=H/2 - 20;
obj->r=20;
objList2.push_back(obj);
}
//创建游戏对象3
for(int i = 0;i < objectsNum;i++)
{
HuntPlayerBall* obj = new HuntPlayerBall();
//排放障碍物srand
obj->x=i*(obj->r*2 + xstep)+obj->r;
obj->y=H/2 - 20;
obj->r=10;
objList3.push_back(obj);
}
//初始化玩家位置TODO
playerball = new PlayerBall();
playerball->x = W/2;
playerball->y = H;
playerball->r=10;
}
MainWindow::~MainWindow()
{
delete ui;
delete timer;//不删除就会内存泄露
for(auto itm:objList1)
{
delete itm;
}
for(auto itm:objList2)
{
delete itm;
}
for(auto itm:objList3)
{
delete itm;
}
delete playerball;
}
void MainWindow::paintEvent(QPaintEvent *)
{
// static int x = 0;
// QPainter painter(this);
// painter.setPen(Qt::red);
// painter.setFont(QFont("楷体", 50));
// painter.drawText(rect(), Qt::AlignCenter, "我爱你中国");
// painter.setPen(Qt::blue);
// painter.setFont(QFont("楷体",500));
// painter.drawEllipse(x,0,100,100);
// x+=20;
//给每一个游戏对象存活一个时间片
for(auto itm:objList1)
{
itm->LiveOneTimeSlice();
}
for(auto itm:objList2)
{
itm->LiveOneTimeSlice();
}
for(auto itm:objList3)
{
itm->LiveOneTimeSlice();
}
//绘制整个游戏场景
QPainter painter(this);
painter.setPen(Qt::black);
for(auto itm:objList1)
{
QBrush brush(QColor(0,200,0),Qt::Dense4Pattern);
painter.setBrush(brush);
painter.drawEllipse(itm->x-itm->r,itm->y-itm->r,itm->r*2,itm->r*2);
}
for(auto itm:objList2)
{
QBrush brush(QColor(0,200,250),Qt::Dense4Pattern);
painter.setBrush(brush);
painter.drawEllipse(itm->x-itm->r,itm->y-itm->r,itm->r*2,itm->r*2);
}
for(auto itm:objList3)
{
QBrush brush(QColor(250,20,20),Qt::Dense4Pattern);
painter.setBrush(brush);
painter.drawEllipse(itm->x-itm->r,itm->y-itm->r,itm->r*2,itm->r*2);
}
painter.setPen(Qt::darkBlue);
QBrush brush(QColor(255,255,0),Qt::Dense4Pattern);
painter.setBrush(brush);
painter.drawEllipse(playerball->x-playerball->r,playerball->y-playerball->r,playerball->r*2,playerball->r*2);
}
void MainWindow::keyPressEvent(QKeyEvent *ev)
{
if(ev->key()==Qt::Key_Up)
{
playerball->y-=30;
qDebug()<<"Press Key Up";
return ;
}
if(ev->key()==Qt::Key_Down)
{
playerball->y+=30;
qDebug()<<"Press Key Down";
return ;
}
if(ev->key()==Qt::Key_Left)
{
playerball->x-=30;
qDebug()<<"Press Key Left";
return ;
}
if(ev->key()==Qt::Key_Right)
{
playerball->x+=30;
qDebug()<<"Press Key Right";
return ;
}
}
void MainWindow::TimerEvent()
{
//还要判断失败
for(auto itm:objList1)
{
float distSqure = (itm->x - playerball->x)*(itm->x - playerball->x)+
(itm->y - playerball->y)*(itm->y - playerball->y);
if(distSqure<=((itm->r + playerball->r)*(itm->r + playerball->r)))
{
qDebug() <<"Failed!";
timer->stop();
}
}
for(auto itm:objList2)
{
float distSqure = (itm->x - playerball->x)*(itm->x - playerball->x)+
(itm->y - playerball->y)*(itm->y - playerball->y);
if(distSqure<=((itm->r + playerball->r)*(itm->r + playerball->r)))
{
qDebug() <<"Failed!";
timer->stop();
}
}
for(auto itm:objList3)
{
float distSqure = (itm->x - playerball->x)*(itm->x - playerball->x)+
(itm->y - playerball->y)*(itm->y - playerball->y);
if(distSqure<=((itm->r + playerball->r)*(itm->r + playerball->r)))
{
qDebug() <<"Failed!";
timer->stop();
}
}
for(auto itm:objList3)
{
float distSqure = sqrt((itm->x - playerball->x)*(itm->x - playerball->x)+
(itm->y - playerball->y)*(itm->y - playerball->y));
if(distSqure<=(itm->r + playerball->r+200))
{
float x_dis=(playerball->x - itm->x)/distSqure;
float y_dis=(playerball->y - itm->y)/distSqure;
itm->x+=x_dis*10;
itm->y+=y_dis*10;
}
}
//判断成功
if(playerball->y <= 0)
{
qDebug() <<"Success!";
timer->stop();
}
update();
}
效果如下
红色小球会追踪,顺便绿色小球每次编译刷新