C++ Qt 待机弹球游戏

以前的电视机待机时,都有一个球在界面弹来弹去,碰到边界则改变颜色和方向。

设计算法实现该效果,qt实现界面,C++实现运动轨迹,及颜色变化。

详细注释

效果如图

 运动轨迹控制类头文件

#ifndef CMOTIONCONTROL_H
#define CMOTIONCONTROL_H

#include 
#include 

/**
 * @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 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 
#include 

class CMotionControl;

namespace Ui
{
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    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

你可能感兴趣的:(QT,c++,游戏,QT,待机弹球,源码)