以前的电视机待机时,都有一个球在界面弹来弹去,碰到边界则改变颜色和方向。
设计算法实现该效果,qt实现界面,C++实现运动轨迹,及颜色变化。
详细注释
效果如图
运动轨迹控制类头文件
#ifndef CMOTIONCONTROL_H
#define CMOTIONCONTROL_H#include <vector>
#include <string>/*** @brief 坐标信息结构体* @author GGX* @date 2023-08-13*/
struct SPoint
{int x;int y;/*** @brief 重载操作符* @param [in] point 自增信息* @return 无* @author GGX* @date 2023-08-13*/SPoint & operator+=(SPoint point){x += point.x;y += point.y;return *this;}/*** @brief 判断X是否在范围内* @param [in] lX 范围左区间* @param [in] rX 范围右区间* @return true 在范围内,false不在范围内* @author GGX* @date 2023-08-13*/bool isRangeX(int lX, int rX){return x > lX && x < rX;}/*** @brief 判断Y是否在范围内* @param [in] lY 范围左区间* @param [in] rY 范围右区间* @return true 在范围内,false不在范围内* @author GGX* @date 2023-08-13*/bool isRangeY(int lY, int rY){return y > lY && y < rY;}
};/*** @brief 弹球控制类* @author GGX* @date 2023-08-13*/
class CMotionControl
{
public:CMotionControl();/*** @brief 设置坐标位置* @param [in] x 坐标轴* @param [in] y 坐标轴* @return 无* @author GGX* @date 2023-08-13*/void setPoint(int x, int y);/*** @brief 获取坐标位置* @param 无* @return SPoint 坐标位置* @author GGX* @date 2023-08-13*/SPoint getPoint();/*** @brief 设置范围右区间* @param [in] x 坐标轴* @param [in] y 坐标轴* @return SPoint 坐标位置* @author GGX* @date 2023-08-13*/void setRange(int x, int y);/*** @brief 设置步进值* @param [in] SPoint x,y步进值* @return 无* @author GGX* @date 2023-08-13*/void setStep(SPoint step);/*** @brief 在坐标范围内移动弹球位置* @param [in] SPoint x,y步进值* @return 无* @author GGX* @date 2023-08-13*/bool move();/*** @brief 获取弹球颜色* @param 无* @return std::string 弹球颜色* @author GGX* @date 2023-08-13*/std::string color();/*** @brief 获取弹球边框颜色* @param 无* @return std::string 弹球边框颜色* @author GGX* @date 2023-08-13*/std::string borderColor();protected:/*** @brief 初始化弹球颜色* @param 无* @return 无* @author GGX* @date 2023-08-13*/void initColor();private:SPoint m_Point; //弹球位置SPoint m_Range; //范围右区间SPoint m_Step; //步进值size_t m_indexColor; //当前弹球颜色std::vector<std::string> m_colors; //弹球颜色容器
};#endif // CMOTIONCONTROL_H
运动轨迹控制类源文件
#include "cmotioncontrol.h"CMotionControl::CMotionControl()
{m_Point = {0, 0};m_Range = {0, 0};m_Step = {0, 0};initColor();
}void CMotionControl::setPoint(int x, int y)
{m_Point = {x, y};
}SPoint CMotionControl::getPoint()
{return m_Point;
}void CMotionControl::setRange(int x, int y)
{m_Range = {x, y};
}void CMotionControl::setStep(SPoint step)
{m_Step = step;
}bool CMotionControl::move()
{//弹球是否碰壁bool bChange = false;if (!m_Point.isRangeX(0, m_Range.x)){//若是超出范围,则按反方向移动m_Step.x = -m_Step.x;bChange = true;}if (!m_Point.isRangeY(0, m_Range.y)){//若是超出范围,则按反方向移动m_Step.y = -m_Step.y;bChange = true;}if (bChange){//弹球碰壁,则变换颜色m_indexColor++;}if (m_indexColor >= m_colors.size()){m_indexColor = 0;}//弹球位置移动m_Point += m_Step;return bChange;
}std::string CMotionControl::color()
{return m_colors.at(m_indexColor);
}std::string CMotionControl::borderColor()
{return m_colors.at(m_colors.size() - m_indexColor - 1);
}void CMotionControl::initColor()
{m_indexColor = 0;// m_colors.emplace_back("color0");
// m_colors.emplace_back("color1");m_colors.emplace_back("black");m_colors.emplace_back("white");m_colors.emplace_back("darkGray");m_colors.emplace_back("gray");m_colors.emplace_back("lightGray");m_colors.emplace_back("red");m_colors.emplace_back("green");m_colors.emplace_back("blue");m_colors.emplace_back("darkGray");m_colors.emplace_back("cyan");m_colors.emplace_back("magenta");m_colors.emplace_back("yellow");m_colors.emplace_back("darkRed");m_colors.emplace_back("darkGray");m_colors.emplace_back("darkGreen");m_colors.emplace_back("darkBlue");m_colors.emplace_back("darkCyan");m_colors.emplace_back("darkMagenta");m_colors.emplace_back("darkYellow");
// m_colors.emplace_back("transparent");
}
QT界面头文件
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <qtimer.h>class CMotionControl;namespace Ui
{
class MainWindow;
}class MainWindow : public QMainWindow
{Q_OBJECTpublic:explicit MainWindow(QWidget *parent = 0);~MainWindow();private slots:void slTimer();void on_start_clicked();private:Ui::MainWindow *ui;int m_step; //每次移动的像素CMotionControl *m_pMotionControl; //控制弹球运动轨迹及颜色QTimer *m_pTimer; //定时器,触发移动
};#endif // MAINWINDOW_H
QT界面源文件
#include "mainwindow.h"
#include "ui_mainwindow.h"#include "qdebug.h"
#include "cmotioncontrol.h"MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);m_pTimer = new QTimer(this);connect(m_pTimer, SIGNAL(timeout()), this, SLOT(slTimer()));m_step = 10;m_pMotionControl = new CMotionControl();m_pMotionControl->setStep({m_step, m_step});
}MainWindow::~MainWindow()
{delete ui;delete m_pTimer;delete m_pMotionControl;
}void MainWindow::slTimer()
{//移动弹球坐标bool bChange = m_pMotionControl->move();//获取移动后的位置SPoint point = m_pMotionControl->getPoint();//移动弹球ui->label_point->move(point.x, point.y);//弹球碰壁则改变颜色if (bChange){QString bgColor = m_pMotionControl->color().c_str();QString bdColor = m_pMotionControl->borderColor().c_str();int length = 100;QString strColor = "";strColor.append(QString("min-width:%1px;").arg(length));strColor.append(QString("min-height:%1px;").arg(length));strColor.append(QString("max-width:%1px;").arg(length));strColor.append(QString("max-height:%1px;").arg(length));strColor.append(QString("border-radius:%1px;").arg(length / 2));strColor.append(QString("border:%1px solid %2;").arg(3).arg(bdColor));strColor.append(QString("background-color:%1;").arg(bgColor));ui->label_point->setStyleSheet(QString("QLabel{%1}").arg(strColor)); //设置样式表}qDebug() << "SPoint: {" << point.x << ", " << point.y << "}";
}void MainWindow::on_start_clicked()
{//设置弹球起点m_pMotionControl->setPoint(ui->label_point->pos().x(),ui->label_point->pos().y());//设置弹球范围m_pMotionControl->setRange(width() - ui->label_point->width() - m_step,height() - ui->label_point->height() - m_step);int msec = 50;//启停定时器if (m_pTimer->isActive()){m_pTimer->stop();}else{m_pTimer->start(msec);}
}
码云地址:svn://gitee.com/gongguixing/daily-learning/qt_ui/Pinball