【QT从零开始系列10】翻金币项目实战

文章目录

  • 项目资源获取
  • 创建项目 并导入资源
  • 设置背景图片
  • 开始按钮创建
    • 创建开始按钮
    • 开始按钮跳跃特效实现
  • 选择关卡场景配置
    • 新建关卡类
    • 选择关卡配置
    • 实现返回按钮按下效果
    • 实现返回效果
    • 创建选择关卡的按钮
  • 游戏场景设置
    • 创建游戏场景
    • 设置场景背景
    • 创建返回按钮
    • 显示关卡号
  • 金币类封装
  • 引用关卡数据
  • 使用金币数据
  • 翻金币特效
    • 解决快速点击效果不好
    • 周围金币翻转
  • 胜利后处理
    • 胜利后禁止翻金币
    • 胜利图标
  • 些许Bug
    • 初始值设置为false
    • 翻金币时禁止点击其他按钮
  • 音效设置
  • 打包项目

项目资源获取

视频链接(B站): QT从入门到实战完整版

百度云链接:https://pan.baidu.com/s/1w2knS8G-yXbjCXSTyj7nYw 提取码:07gu

完整项目源码及资源:https://pan.baidu.com/s/1ExEfEakz6v4QHLYDTcIaZQ
提取码:xnob

创建项目 并导入资源

	//配置主场景
    
    //设置固定大小
    this->setFixedSize(320,588);
    
    //设置图标
    this->setWindowIcon(QPixmap(":/res/Coin0001.png"));
    
    //设置窗口标题
    this->setWindowTitle("老帮主带你翻金币");

	//退出按钮实现
    connect(ui->actionQuit,&QAction::triggered,[=](){
        this->close();
    });
//注意QAction只能为英文,则退出写作quit,再修改text为中文退出

【QT从零开始系列10】翻金币项目实战_第1张图片

设置背景图片

//mainscene.h
	//重写paintEvent事件 画背景图
    void paintEvent(QPaintEvent *event);

//mainscene.cpp
#include 

//配置主场景

    //设置固定大小
    this->setFixedSize(320,588);

    //设置图标
    this->setWindowIcon(QPixmap(":/res/Coin0001.png"));

    //设置窗口标题
    this->setWindowTitle("翻金币主场景");

    //退出按钮实现
    connect(ui->actionQuit,&QAction::triggered,[=](){
        this->close();
    });

void MainScene::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    QPixmap pix;
    pix.load(":/res/PlayLevelSceneBg.png");
    //绘制背景图
    painter.drawPixmap(0,0,this->width(),this->height(),pix);

    //画背景上图标
    //加载标题
    pix.load(":/res/Title.png");
    //缩放图片
    pix = pix.scaled(pix.width()*0.5,pix.height()*0.5);
    //绘制标题
    painter.drawPixmap( 10,30,pix.width(),pix.height(),pix);
}

开始按钮创建

创建开始按钮

新建C++ class 命名为MyPushButton

//mypushbutton.h
#ifndef MYPUSHBUTTON_H
#define MYPUSHBUTTON_H

#include 

class MyPushButton : public QPushButton
{
    Q_OBJECT
public:
    //explicit MyPushButton(QWidget *parent = 0);

    //构造函数 参数1 正常显示的图片路径 参数2 按下后显示的图片路径
    MyPushButton(QString normalImg,QString pressImg = "");

    QString normalImgPath;
    QString pressImgPath;

signals:

public slots:
};

#endif // MYPUSHBUTTON_H

//mypushbutton.cpp
#include "mypushbutton.h"
#include 


//MyPushButton::MyPushButton(QWidget *parent) : QPushButton(parent)
//{

//}

MyPushButton::MyPushButton(QString normalImg,QString pressImg )
{
    this->normalImgPath = normalImg;
    this->pressImgPath = pressImg;

    QPixmap pix;
    bool ret = pix.load(normalImg);
    if(!ret)
    {
        qDebug() << "图片加载失败";
        return ;
    }

    //设置图片固定大小
    this->setFixedSize(pix.width(),pix.height());

    //设置不规则图片样式
    this->setStyleSheet("QPushButton{border:0px;}");

    //设置图标
    this->setIcon(pix);

    //设置图标大小
    this->setIconSize(QSize(pix.width(),pix.height()));

}

//mainscene.cpp
#include "mypushbutton.h"

//在MainScene::MainScene中写入
	//开始按钮
    MyPushButton * startBtn = new MyPushButton(":/res/MenuSceneStartButton.png");
    startBtn->setParent(this);
    startBtn->move(this->width() * 0.5 - startBtn->width()*0.5,this->height()*0.7);

【QT从零开始系列10】翻金币项目实战_第2张图片

开始按钮跳跃特效实现

//mainscene.cpp
connect(startBtn,&MyPushButton::clicked,[=](){
        //qDebug() << "点击了开始";
        //做弹起特效
        startBtn->zoom1(); //向下跳跃
        startBtn->zoom2(); //向上跳跃

    });
//mypushbutton.cpp
void MyPushButton::zoom1()
{
    //创建动态对象
    QPropertyAnimation * animation = new QPropertyAnimation(this,"geometry");
    //设置动画时间间隔
    animation->setDuration(200);

    //起始位置
    animation->setStartValue(QRect(this->x(),this->y(),this->width(),this->height()));
    animation->setEndValue(QRect(this->x(),this->y()+10,this->width(),this->height()));

    //设置弹跳曲线
    animation->setEasingCurve(QEasingCurve::OutBounce);

    //开始执行动画
    animation->start();
}

void MyPushButton::zoom2()
{
    //创建动态对象
    QPropertyAnimation * animation = new QPropertyAnimation(this,"geometry");
    //设置动画时间间隔
    animation->setDuration(200);

    //起始位置
    animation->setStartValue(QRect(this->x(),this->y()+10,this->width(),this->height()));
    animation->setEndValue(QRect(this->x(),this->y(),this->width(),this->height()));

    //设置弹跳曲线
    animation->setEasingCurve(QEasingCurve::OutBounce);

    //开始执行动画
    animation->start();

}

选择关卡场景配置

新建关卡类

添加新的C++ class文件,类名为ChooseLevelScene 选择基类为QMainWindow

 //mainscene.h
#ifndef MAINSCENE_H
#define MAINSCENE_H

#include 
#include "chooselevelscene.h"


namespace Ui {
class MainScene;
}

class MainScene : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainScene(QWidget *parent = 0);
    ~MainScene();

    //重写paintEvent事件 画背景图
    void paintEvent(QPaintEvent *event);

    //初始化选择关卡场景
    ChooseLevelScene * chooseScene = NULL;
    
private:
    Ui::MainScene *ui;
};

#endif // MAINSCENE_H
//mainscene.cpp
#include 	

	//实例化选择关卡场景
    chooseScene = new ChooseLevelScene;

    connect(startBtn,&MyPushButton::clicked,[=](){
        //qDebug() << "点击了开始";
        //做弹起特效
        startBtn->zoom1(); //向下跳跃
        startBtn->zoom2(); //向上跳跃

        //延时进入到选择关卡场景中
        QTimer::singleShot(500,this,[=](){
            //自身隐藏
            this->hide();
            //显示选择关卡场景
            chooseScene->show();
        });

    });

选择关卡配置

设置背景图片->创建返回按钮

//chooselevelscene.cpp
#include "chooselevelscene.h"
#include 
#include 
#include "mypushbutton.h"
#include 

ChooseLevelScene::ChooseLevelScene(QWidget *parent) : QMainWindow(parent)
{
    //配置选择关卡场景
    //设置窗口固定大小
    this->setFixedSize(320,588);
    //设置图标
    this->setWindowIcon(QPixmap(":/res/Coin0001.png"));
    //设置标题
    this->setWindowTitle("选择关卡");

    //创建菜单栏
    QMenuBar * bar = this->menuBar();
    this->setMenuBar(bar);
    //创建开始菜单
    QMenu * startMenu = bar->addMenu("开始");
    //创建按钮菜单项
    QAction * quitAction = startMenu->addAction("退出");
    //点击退出 退出游戏
    connect(quitAction,&QAction::triggered,[=](){this->close();});

    //返回按钮
    MyPushButton *backBtn = new MyPushButton(":/res/BackButton.png",":/res/BackButtonSelected.png");
    backBtn->setParent(this);
    backBtn->move(this->width() - backBtn->width(),this->height() - backBtn->height());

    //点击返回
    connect(backBtn,&MyPushButton::clicked,[=](){
        qDebug() << "点击了返回按钮";
    });

}

void ChooseLevelScene::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    QPixmap pix;
    pix.load(":/res/OtherSceneBg.png");
    painter.drawPixmap(0,0,this->width(),this->height(),pix);

    //加载标题
    pix.load(":/res/Title.png");
    painter.drawPixmap( (this->width() - pix.width())*0.5,30,pix.width(),pix.height(),pix);

}

实现返回按钮按下效果

//mypushbutton.h
	//重写按钮 按下 和释放事件
    void mousePressEvent(QMouseEvent *e);

    void mouseReleaseEvent(QMouseEvent *e);
//mypushbutton.cpp
void MyPushButton::mousePressEvent(QMouseEvent *e)
{
    if(this->pressImgPath != "") //传入的按下图片不为空,说明需要有按下状态,切换图片
    {
        QPixmap pix;
        bool ret = pix.load(this->pressImgPath);
        if(!ret)
        {
            qDebug() << "图片加载失败";
            return ;
        }

        //设置图片固定大小
        this->setFixedSize(pix.width(),pix.height());

        //设置不规则图片样式
        this->setStyleSheet("QPushButton{border:0px;}");

        //设置图标
        this->setIcon(pix);

        //设置图标大小
        this->setIconSize(QSize(pix.width(),pix.height()));

    }

    //让父类执行其他内容
    return QPushButton::mousePressEvent(e);

}

void MyPushButton::mouseReleaseEvent(QMouseEvent *e)
{
    if(this->pressImgPath != "") //传入的按下图片不为空,说明需要有按下状态,切换成初始图片
    {
        QPixmap pix;
        bool ret = pix.load(this->normalImgPath);
        if(!ret)
        {
            qDebug() << "图片加载失败";
            return ;
        }

        //设置图片固定大小
        this->setFixedSize(pix.width(),pix.height());

        //设置不规则图片样式
        this->setStyleSheet("QPushButton{border:0px;}");

        //设置图标
        this->setIcon(pix);

        //设置图标大小
        this->setIconSize(QSize(pix.width(),pix.height()));

    }

    //让父类执行其他内容
    return QPushButton::mouseReleaseEvent(e);
}

实现返回效果

//ChooseLevelScene.h
signals:
    //写一个自定义信号,告诉主场景 点击了返回
    void chooseSceneBack();
//ChooseLevelScene.cpp
	//点击返回
    connect(backBtn,&MyPushButton::clicked,[=](){
        //qDebug() << "点击了返回按钮";
        //告诉主场景 我返回了,主场景监听ChooseLevelScene的返回按钮
        //延时返回
        QTimer::singleShot(500,[=](){
            emit this->chooseSceneBack();
        });

    });
//mainscene.cpp
	//监听选择关卡的返回按钮的信号
    connect(chooseScene,&ChooseLevelScene::chooseSceneBack,[=](){
        chooseScene->hide(); //将选择关卡场景隐藏掉
        this->show(); //重新显示主场景
    });

创建选择关卡的按钮

//chooselevelscene.cpp
	//创建选择关卡的按钮
    for(int i = 0 ; i < 20 ; i++)
    {
        MyPushButton * menuBtn = new MyPushButton(":/res/LevelIcon.png");
        menuBtn->setParent(this);
        menuBtn->move(25 + (i%4)*70 , 130+ (i/4)*70);

        //监听按钮信号
        connect(menuBtn,&MyPushButton::clicked,[=](){
            QString str = QString("您选择的是第 %1 关").arg(i+1);
            qDebug() << str;
        });

        //按钮上显示的文字
        QLabel * label = new QLabel;
        label->setParent(this);
        label->setFixedSize(menuBtn->width(),menuBtn->height());
        label->setText(QString::number(i+1));
        label->move(25 + (i%4)*70 , 130+ (i/4)*70);

        //设置label上的文字对齐方式 水平居中 和垂直居中
        label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);

        //鼠标事件穿透
        label->setAttribute(Qt::WA_TransparentForMouseEvents,true);
    }

游戏场景设置

创建游戏场景

新建C++ class 文件 命名为 PlayScene

//playscene.h
#ifndef PLAYSCENE_H
#define PLAYSCENE_H

#include 

class PlayScene : public QMainWindow
{
    Q_OBJECT
public:
    //explicit PlayScene(QWidget *parent = 0);

    PlayScene(int levelNum);

    int levelIndex ; //内部成员属性 记录所选的关卡

signals:

public slots:
};

#endif // PLAYSCENE_H

playscene.cpp

#include "playscene.h"
#include 
#include 

//PlayScene::PlayScene(QWidget *parent) : QMainWindow(parent)
//{

//}

PlayScene::PlayScene(int levelNum)
{
    QString str = QString("进入了第 %1 关").arg(levelNum);
    qDebug() << str;
    this->levelIndex = levelNum;

    //初始化游戏场景
    //设置窗口固定大小
    this->setFixedSize(320,588);
    //设置图标
    this->setWindowIcon(QPixmap(":/res/Coin0001.png"));
    //设置标题
    this->setWindowTitle("翻金币");

    //创建菜单栏
    QMenuBar * bar = this->menuBar();
    this->setMenuBar(bar);
    //创建开始菜单
    QMenu * startMenu = bar->addMenu("开始");
    //创建按钮菜单项
    QAction * quitAction = startMenu->addAction("退出");
    //点击退出 退出游戏
    connect(quitAction,&QAction::triggered,[=](){this->close();});
}

//chooselevelscene.cpp
//ChooseLevelScene构造函数中监听	
	
	connect(menuBtn,&MyPushButton::clicked,[=](){
            QString str = QString("您选择的是第 %1 关").arg(i+1);
            qDebug() << str;

            //进入到游戏场景
            this->hide(); //将选关场景隐藏掉
            play = new PlayScene(i+1); //创建游戏场景
            play->show(); //显示游戏场景

        });

设置场景背景

//playscene.h
	//重写paintEvent事件
    void paintEvent(QPaintEvent *event);

//playscene.cpp
void PlayScene::paintEvent(QPaintEvent *event)
{
    //加载背景
    QPainter painter(this);
    QPixmap pix;
    pix.load(":/res/PlayLevelSceneBg.png");
    painter.drawPixmap(0,0,this->width(),this->height(),pix);

    //加载标题
    pix.load(":/res/Title.png");
    pix = pix.scaled(pix.width()*0.5,pix.height()*0.5);
    painter.drawPixmap( 10,30,pix.width(),pix.height(),pix);

}

创建返回按钮

//playscene.cpp
	//返回按钮
    MyPushButton *backBtn = new MyPushButton(":/res/BackButton.png",":/res/BackButtonSelected.png");
    backBtn->setParent(this);
    backBtn->move(this->width() - backBtn->width(),this->height() - backBtn->height());

    //点击返回
    connect(backBtn,&MyPushButton::clicked,[=](){
        qDebug() << "翻金币场景中,点击了返回按钮";
        //告诉主场景 我返回了,选择场景监听ChooseLevelScene的返回按钮
        //延时返回
        QTimer::singleShot(500,[=](){
            emit this->chooseSceneBack();
        });

    });
//chooselevelscene.cpp
		connect(play,&PlayScene::chooseSceneBack,[=](){
                this->show();
                delete play;
                play = NULL;
            });

显示关卡号

//playscene.cpp
	//显示当前关卡数
    QLabel * label = new QLabel;
    label->setParent(this);
    QFont font;
    font.setFamily("华文新魏");
    font.setPointSize(20);
    label->setFont(font);
    QString str = QString("Leavel: %1").arg(this->levelIndex);
    label->setText(str);
    label->setGeometry(QRect(30, this->height() - 50,120, 50)); //设置大小和位置

金币类封装

新建MyCoin的基类为QPushButton

//mycoin.h
#ifndef MYCOIN_H
#define MYCOIN_H

#include 

class MyCoin : public QPushButton
{
    Q_OBJECT
public:
    //explicit MyCoin(QWidget *parent = 0);

    //参数 代表 传入的金币路径 还是银币路径
    MyCoin(QString btnImg);
    
signals:

public slots:
};

#endif // MYCOIN_H
//mycoin.h
#include "mycoin.h"

//MyCoin::MyCoin(QWidget *parent) : QPushButton(parent)
//{

//}


MyCoin::MyCoin(QString btnImg)
{
    QPixmap pix;
    bool ret = pix.load(btnImg);
    if(!ret)
    {
        QString str = QString("图片 %1 加载失败").arg(btnImg);
        qDebug() << str;
        return;
    }
    
    this->setFixedSize(pix.width(),pix.height());
    this->setStyleSheet("QPushButton{border:0px}");
    this->setIcon(pix);
    this->setIconSize(QSize(pix.width(),pix.height()));
    
}
//playscene.cpp
			//创建金币
            
            MyCoin * coin = new MyCoin(":/res/Coin0001.png");
            coin->setParent(this);
            coin->move(59 + i*50,204+j*50);

引用关卡数据

//dataconfig.h
#ifndef DATACONFIG_H
#define DATACONFIG_H

#include 
#include 
#include 

class dataConfig : public QObject
{
    Q_OBJECT
public:
    explicit dataConfig(QObject *parent = 0);

public:

    QMap<int, QVector< QVector<int> > >mData;



signals:

public slots:
};

#endif // DATACONFIG_H

//dataconfig.cpp
#include "dataconfig.h"
#include 
dataConfig::dataConfig(QObject *parent) : QObject(parent)
{

     int array1[4][4] = {{1, 1, 1, 1},
                        {1, 1, 0, 1},
                        {1, 0, 0, 0},
                        {1, 1, 0, 1} } ;

     QVector< QVector<int>> v;
     for(int i = 0 ; i < 4;i++)
     {
         QVector<int>v1;
         for(int j = 0 ; j < 4;j++)
         {

            v1.push_back(array1[i][j]);
         }
         v.push_back(v1);
     }

     mData.insert(1,v);


     int array2[4][4] = { {1, 0, 1, 1},
                          {0, 0, 1, 1},
                          {1, 1, 0, 0},
                          {1, 1, 0, 1}} ;

     v.clear();
     for(int i = 0 ; i < 4;i++)
     {
          QVector<int>v1;
          for(int j = 0 ; j < 4;j++)
          {
             v1.push_back(array2[i][j]);
          }
          v.push_back(v1);
     }

     mData.insert(2,v);



     int array3[4][4] = {  {0, 0, 0, 0},
                           {0, 1, 1, 0},
                           {0, 1, 1, 0},
                           {0, 0, 0, 0}} ;
     v.clear();
     for(int i = 0 ; i < 4;i++)
     {
          QVector<int>v1;
          for(int j = 0 ; j < 4;j++)
          {
             v1.push_back(array3[i][j]);
          }
          v.push_back(v1);
     }

     mData.insert(3,v);


     int array4[4][4] = {   {0, 1, 1, 1},
                            {1, 0, 0, 1},
                            {1, 0, 1, 1},
                            {1, 1, 1, 1}} ;
     v.clear();
     for(int i = 0 ; i < 4;i++)
     {
          QVector<int>v1;
          for(int j = 0 ; j < 4;j++)
          {
             v1.push_back(array4[i][j]);
          }
          v.push_back(v1);
     }

     mData.insert(4,v);


     int array5[4][4] = {  {1, 0, 0, 1},
                           {0, 0, 0, 0},
                           {0, 0, 0, 0},
                           {1, 0, 0, 1}} ;
     v.clear();
     for(int i = 0 ; i < 4;i++)
     {
          QVector<int>v1;
          for(int j = 0 ; j < 4;j++)
          {
             v1.push_back(array5[i][j]);
          }
          v.push_back(v1);
     }

     mData.insert(5,v);


     int array6[4][4] = {   {1, 0, 0, 1},
                            {0, 1, 1, 0},
                            {0, 1, 1, 0},
                            {1, 0, 0, 1}} ;
     v.clear();
     for(int i = 0 ; i < 4;i++)
     {
          QVector<int>v1;
          for(int j = 0 ; j < 4;j++)
          {
             v1.push_back(array6[i][j]);
          }
          v.push_back(v1);
     }

     mData.insert(6,v);


     int array7[4][4] = {   {0, 1, 1, 1},
                            {1, 0, 1, 1},
                            {1, 1, 0, 1},
                            {1, 1, 1, 0}} ;
     v.clear();
     for(int i = 0 ; i < 4;i++)
     {
          QVector<int>v1;
          for(int j = 0 ; j < 4;j++)
          {
             v1.push_back(array7[i][j]);
          }
          v.push_back(v1);
     }

     mData.insert(7,v);

     int array8[4][4] = {  {0, 1, 0, 1},
                           {1, 0, 0, 0},
                           {0, 0, 0, 1},
                           {1, 0, 1, 0}} ;
     v.clear();
     for(int i = 0 ; i < 4;i++)
     {
          QVector<int>v1;
          for(int j = 0 ; j < 4;j++)
          {
             v1.push_back(array8[i][j]);
          }
          v.push_back(v1);
     }

     mData.insert(8,v);

     int array9[4][4] = {   {1, 0, 1, 0},
                            {1, 0, 1, 0},
                            {0, 0, 1, 0},
                            {1, 0, 0, 1}} ;
     v.clear();
     for(int i = 0 ; i < 4;i++)
     {
          QVector<int>v1;
          for(int j = 0 ; j < 4;j++)
          {
             v1.push_back(array9[i][j]);
          }
          v.push_back(v1);
     }

     mData.insert(9,v);



     int array10[4][4] = {  {1, 0, 1, 1},
                            {1, 1, 0, 0},
                            {0, 0, 1, 1},
                            {1, 1, 0, 1}} ;
     v.clear();
     for(int i = 0 ; i < 4;i++)
     {
          QVector<int>v1;
          for(int j = 0 ; j < 4;j++)
          {
             v1.push_back(array10[i][j]);
          }
          v.push_back(v1);
     }

     mData.insert(10,v);


     int array11[4][4] = {  {0, 1, 1, 0},
                            {1, 0, 0, 1},
                            {1, 0, 0, 1},
                            {0, 1, 1, 0}} ;
     v.clear();
     for(int i = 0 ; i < 4;i++)
     {
          QVector<int>v1;
          for(int j = 0 ; j < 4;j++)
          {
             v1.push_back(array11[i][j]);
          }
          v.push_back(v1);
     }

     mData.insert(11,v);

     int array12[4][4] = {  {0, 1, 1, 0},
                            {0, 0, 0, 0},
                            {1, 1, 1, 1},
                            {0, 0, 0, 0}} ;
     v.clear();
     for(int i = 0 ; i < 4;i++)
     {
          QVector<int>v1;
          for(int j = 0 ; j < 4;j++)
          {
             v1.push_back(array12[i][j]);
          }
          v.push_back(v1);
     }

     mData.insert(12,v);


     int array13[4][4] = {    {0, 1, 1, 0},
                              {0, 0, 0, 0},
                              {0, 0, 0, 0},
                              {0, 1, 1, 0}} ;
     v.clear();
     for(int i = 0 ; i < 4;i++)
     {
          QVector<int>v1;
          for(int j = 0 ; j < 4;j++)
          {
             v1.push_back(array13[i][j]);
          }
          v.push_back(v1);
     }

     mData.insert(13,v);

     int array14[4][4] = {    {1, 0, 1, 1},
                              {0, 1, 0, 1},
                              {1, 0, 1, 0},
                              {1, 1, 0, 1}} ;
     v.clear();
     for(int i = 0 ; i < 4;i++)
     {
          QVector<int>v1;
          for(int j = 0 ; j < 4;j++)
          {
             v1.push_back(array14[i][j]);
          }
          v.push_back(v1);
     }

     mData.insert(14,v);


     int array15[4][4] = {   {0, 1, 0, 1},
                             {1, 0, 0, 0},
                             {1, 0, 0, 0},
                             {0, 1, 0, 1}} ;
     v.clear();
     for(int i = 0 ; i < 4;i++)
     {
          QVector<int>v1;
          for(int j = 0 ; j < 4;j++)
          {
             v1.push_back(array15[i][j]);
          }
          v.push_back(v1);
     }

     mData.insert(15,v);


     int array16[4][4] = {   {0, 1, 1, 0},
                             {1, 1, 1, 1},
                             {1, 1, 1, 1},
                             {0, 1, 1, 0}} ;
     v.clear();
     for(int i = 0 ; i < 4;i++)
     {
          QVector<int>v1;
          for(int j = 0 ; j < 4;j++)
          {
             v1.push_back(array16[i][j]);
          }
          v.push_back(v1);
     }

     mData.insert(16,v);

     int array17[4][4] = {  {0, 1, 1, 1},
                            {0, 1, 0, 0},
                            {0, 0, 1, 0},
                            {1, 1, 1, 0}} ;
     v.clear();
     for(int i = 0 ; i < 4;i++)
     {
          QVector<int>v1;
          for(int j = 0 ; j < 4;j++)
          {
             v1.push_back(array17[i][j]);
          }
          v.push_back(v1);
     }

     mData.insert(17,v);


     int array18[4][4] = { {0, 0, 0, 1},
                           {0, 0, 1, 0},
                           {0, 1, 0, 0},
                           {1, 0, 0, 0}} ;
     v.clear();
     for(int i = 0 ; i < 4;i++)
     {
          QVector<int>v1;
          for(int j = 0 ; j < 4;j++)
          {
             v1.push_back(array18[i][j]);
          }
          v.push_back(v1);
     }

     mData.insert(18,v);

     int array19[4][4] = {   {0, 1, 0, 0},
                             {0, 1, 1, 0},
                             {0, 0, 1, 1},
                             {0, 0, 0, 0}} ;
     v.clear();
     for(int i = 0 ; i < 4;i++)
     {
          QVector<int>v1;
          for(int j = 0 ; j < 4;j++)
          {
             v1.push_back(array19[i][j]);
          }
          v.push_back(v1);
     }

     mData.insert(19,v);

     int array20[4][4] = {  {0, 0, 0, 0},
                            {0, 0, 0, 0},
                            {0, 0, 0, 0},
                            {0, 0, 0, 0}} ;
     v.clear();
     for(int i = 0 ; i < 4;i++)
     {
          QVector<int>v1;
          for(int j = 0 ; j < 4;j++)
          {
             v1.push_back(array20[i][j]);
          }
          v.push_back(v1);
     }

     mData.insert(20,v);


     //测试数据
//    for( QMap > >::iterator it = mData.begin();it != mData.end();it++ )
//    {
//         for(QVector< QVector >::iterator it2 = (*it).begin(); it2!= (*it).end();it2++)
//         {
//            for(QVector::iterator it3 = (*it2).begin(); it3 != (*it2).end(); it3++ )
//            {
//                qDebug() << *it3 ;
//            }
//         }
//         qDebug() << endl;
//    }


}

使用金币数据

//mycoin.h
//金币的属性
    int posX; //x坐标位置
    int posY; //y坐标位置
    bool flag; //正反标示

//playscene.cpp
//初始化每个关卡的二维数组
    dataConfig config;
    for(int i = 0; i < 4 ; i++)
    {
        for(int j = 0 ; j < 4 ; j++)
        {
            this->gameArray[i][j] = config.mData[this->levelIndex][i][j];

        }
    }

    //显示金币的背景图片
    for(int i = 0 ; i < 4;i++)
    {
        for(int j = 0 ; j < 4; j++)
        {
            //绘制背景图片
            QLabel* label = new QLabel;
            label->setGeometry(0,0,50,50);
            label->setPixmap(QPixmap(":/res/BoardNode.png"));
            label->setParent(this);
            label->move(57 + i*50,200+j*50);


            //创建金币
            QString str;
            if(this->gameArray[i][j] == 1)
            {
                //显示金币
                str = ":/res/Coin0001.png";
            }
            else
            {
                str = ":/res/Coin0008.png";
            }

            MyCoin * coin = new MyCoin(str);
            coin->setParent(this);
            coin->move(59 + i*50,204+j*50);
            
            //给金币属性赋值
            coin->posX = i;
            coin->posY = j;
            coin->flag = this->gameArray[i][j]; //1正面 0反面

         }
    }

翻金币特效

//mycoin.h
	//改变标志的方法
    void changeFlag();
    QTimer * timer1; //正面翻反面的定时器
    QTimer * timer2; //反面翻正面的定时器
    int min = 1;
    int max = 8;


//mycoin.cpp

MyCoin::MyCoin(QString btnImg)
{
	//初始化定时器对象
    timer1 = new QTimer(this);
    timer2 = new QTimer(this);

    //监听正面翻反面的信号 , 并且翻转金币
    connect(timer1,&QTimer::timeout,[=](){
        QPixmap pix;
        QString str = QString(":/res/Coin000%1").arg(this->min++);
        pix.load(str);

        this->setFixedSize(pix.width(),pix.height());
        this->setStyleSheet("QPushButton{border:0px}");
        this->setIcon(pix);
        this->setIconSize(QSize(pix.width(),pix.height()));

        //判断 如果翻完了,将min重置为1
        if(this->min > this->max)
        {
            this->min = 1;
            timer1->stop();
        }
    });
    
    //监听反面翻正面的信号 , 并且翻转金币
    connect(timer2,&QTimer::timeout,[=](){
        QPixmap pix;
        QString str = QString(":/res/Coin000%1").arg(this->max--);
        pix.load(str);

        this->setFixedSize(pix.width(),pix.height());
        this->setStyleSheet("QPushButton{border:0px}");
        this->setIcon(pix);
        this->setIconSize(QSize(pix.width(),pix.height()));

        //判断 如果翻完了,将max重置为8
        if(this->min > this->max)
        {
            this->max = 8;
            timer2->stop();
        }
    });
}

//改变正反面标志的方法
void MyCoin::changeFlag()
{
    //如果是正面 翻成反面
    if(this->flag)
    {
        //正面翻反面的定时器
        timer1->start(30);
        this->flag = false;
    }
    else //反面翻正面
    {
        timer2->start(30);
        this->flag = true;
    }
}

//playscene.cpp
//点击金币 进行翻转
            connect(coin,&MyCoin::clicked,[=](){
                coin->changeFlag();
                this->gameArray[i][j] = this->gameArray[i][j] == 0 ? 1 : 0;

            });

解决快速点击效果不好

在MyCoin中加入了 isAnimation 判断 是否正在做动画条件

当按下 MyCoin 判断是否在做动画,如果做动画,直接return,保证金币和银币动态切换的完整效果

//mycoin.h
//执行动画 标志
    bool isAnimation = false;

    //重写 按下
    void mousePressEvent(QMouseEvent *e);

//mycoin.cpp
#include "mycoin.h"

//MyCoin::MyCoin(QWidget *parent) : QPushButton(parent)
//{

//}


MyCoin::MyCoin(QString btnImg)
{
    QPixmap pix;
    bool ret = pix.load(btnImg);
    if(!ret)
    {
        QString str = QString("图片 %1 加载失败").arg(btnImg);
        qDebug() << str;
        return;
    }

    this->setFixedSize(pix.width(),pix.height());
    this->setStyleSheet("QPushButton{border:0px}");
    this->setIcon(pix);
    this->setIconSize(QSize(pix.width(),pix.height()));

    //初始化定时器对象
    timer1 = new QTimer(this);
    timer2 = new QTimer(this);

    //监听正面翻反面的信号 , 并且翻转金币
    connect(timer1,&QTimer::timeout,[=](){
        QPixmap pix;
        QString str = QString(":/res/Coin000%1").arg(this->min++);
        pix.load(str);

        this->setFixedSize(pix.width(),pix.height());
        this->setStyleSheet("QPushButton{border:0px}");
        this->setIcon(pix);
        this->setIconSize(QSize(pix.width(),pix.height()));

        //判断 如果翻完了,将min重置为1
        if(this->min > this->max)
        {
            this->min = 1;
            isAnimation = false; //停止做动画了
            timer1->stop();
        }
    });

    //监听反面翻正面的信号 , 并且翻转金币
    connect(timer2,&QTimer::timeout,[=](){
        QPixmap pix;
        QString str = QString(":/res/Coin000%1").arg(this->max--);
        pix.load(str);

        this->setFixedSize(pix.width(),pix.height());
        this->setStyleSheet("QPushButton{border:0px}");
        this->setIcon(pix);
        this->setIconSize(QSize(pix.width(),pix.height()));

        //判断 如果翻完了,将max重置为8
        if(this->min > this->max)
        {
            this->max = 8;
            isAnimation = false; //停止做动画了
            timer2->stop();
        }
    });

}

void MyCoin::mousePressEvent(QMouseEvent *e)
{
    if(this->isAnimation)
    {
        return;
    }
    else
    {
        QPushButton::mousePressEvent(e);

    }
}

//改变正反面标志的方法
void MyCoin::changeFlag()
{
    //如果是正面 翻成反面
    if(this->flag)
    {
        //正面翻反面的定时器
        timer1->start(30);
        isAnimation = true; //开始做动画了
        this->flag = false;
    }
    else //反面翻正面
    {
        timer2->start(30);
        isAnimation = true; //开始做动画了
        this->flag = true;
    }
}


周围金币翻转

//playscene.cpp
//翻转周围硬币
                //周围的右侧金币翻转的条件,延时翻转
                QTimer::singleShot(300,this,[=](){
                    if(coin->posX + 1 <= 3 )
                    {
                        coinBtn[coin->posX+1][coin->posY]->changeFlag();
                        this->gameArray[coin->posX+1][coin->posY] = this->gameArray[coin->posX+1][coin->posY]  == 0 ? 1 : 0;

                    }
                    //周围的左侧硬币翻转条件
                    if(coin->posX - 1 >= 0)
                    {
                        coinBtn[coin->posX-1][coin->posY]->changeFlag();
                        this->gameArray[coin->posX-1][coin->posY] = this->gameArray[coin->posX-1][coin->posY]  == 0 ? 1 : 0;

                    }
                    //周围的下侧硬币翻转条件
                    if(coin->posY + 1 <= 3)
                    {
                        coinBtn[coin->posX][coin->posY + 1]->changeFlag();
                        this->gameArray[coin->posX][coin->posY + 1] = this->gameArray[coin->posX][coin->posY+1]  == 0 ? 1 : 0;

                    }
                    //周围的上侧硬币翻转条件
                    if(coin->posY - 1 >= 0)
                    {
                        coinBtn[coin->posX][coin->posY - 1]->changeFlag();
                        this->gameArray[coin->posX][coin->posY - 1] = this->gameArray[coin->posX][coin->posY-1]  == 0 ? 1 : 0;

                    }
                });

胜利后处理

胜利后禁止翻金币

 //mycoin.h
 bool isWin = false; //是否胜利

//playscene.h
    bool isWin; //是否胜利

//mycoin.cpp
void MyCoin::mousePressEvent(QMouseEvent *e)
{
    if(this->isAnimation || this->isWin)
    {
        qDebug() << "无法点击";
        return;
    }
    else
    {
        QPushButton::mousePressEvent(e);

    }
}

//playscene.cpp
//判断是否胜利
                    this->isWin = true;
                    for(int i = 0 ; i < 4 ; i++)
                    {
                        for(int j = 0 ; j < 4 ; j++)
                        {
                            //只要有一个是反面,那就算失败
                            if(coinBtn[i][j]->flag == false)
                            {
                                this->isWin = false;
                                break;

                            }
                        }
                    }
                    if(this->isWin == true)
                    {
                        //胜利了!
                        qDebug() << "游戏胜利";
                        //将所有按钮的胜利标志改为true
                        //如果再次点击按钮,直接return,不做响应
                        for(int i = 0 ; i < 4 ; i++)
                        {
                            for(int j = 0 ; j < 4 ; j++)
                            {
                                coinBtn[i][j]->isWin = true;

                            }
                        }
                    }

胜利图标

//playscene.cpp
//胜利图片
    QLabel* winLabel = new QLabel;
    QPixmap tmpPix;
    tmpPix.load(":/res/LevelCompletedDialogBg.png");
    winLabel->setGeometry(0,0,tmpPix.width(),tmpPix.height());
    winLabel->setPixmap(tmpPix);
    winLabel->setParent(this);
    winLabel->move( (this->width() - tmpPix.width())*0.5 , -tmpPix.height());



//将胜利的图片移动下来
QPropertyAnimation * animation = new QPropertyAnimation(winLabel,"geometry");
//设置时间间隔
animation->setDuration(1000);
//设置开始位置
animation->setStartValue(QRect(winLabel->x(),winLabel->y(),winLabel->width(),winLabel->height()));
//设置结束位置
animation->setEndValue(QRect(winLabel->x(),winLabel->y()+114,winLabel->width(),winLabel->height()));
//设置缓和曲线
animation->setEasingCurve(QEasingCurve::OutBounce);
animation->start();

些许Bug

初始值设置为false

//执行动画 标志
bool isAnimation = false;

bool isWin = false; //是否胜利

翻金币时禁止点击其他按钮

//点击按钮 将所有按钮先都禁用
                for(int i = 0 ; i < 4 ; i++)
                {
                    for(int j = 0 ; j < 4 ; j++)
                    {
                        this->coinBtn[i][j]->isWin = true;
                    }
                }
//翻完周围金币后,将所有金币解开禁用
                    for(int i = 0 ; i < 4 ; i++)
                    {
                        for(int j = 0 ; j < 4 ; j++)
                        {
                            this->coinBtn[i][j]->isWin = false;
                        }c
                    }

音效设置

//mainscene.cpp
//QT += multimedia
#include   //多媒体模块下的 音效头文件
//准备开始按钮的音效
    QSound * startSound = new QSound(":/res/TapButtonSound.wav",this);
    //循环播放 -1表示无限循环
    //startSound->setLoops(10);
    //startSound->play();
	connect(startBtn,&MyPushButton::clicked,[=](){
        //qDebug() << "点击了开始";
        //播放开始音效资源
        startSound->play();
    });

//playscene.cpp
	//添加音效资源
    //翻金币音效
    QSound *flipSound = new QSound(":/res/ConFlipSound.wav",this);
    //胜利按钮音效
    QSound *winSound = new QSound(":/res/LevelWinSound.wav",this);
    //返回按钮音效
    QSound *backSound = new QSound(":/res/BackButtonSound.wav",this);

打包项目

选择release编译

找到对应的exe程序中打开cmd 输入命令 windeployqt CoinFlip.exe打包项目

NIS Edit第三方进一步进行压缩

你可能感兴趣的:(Qt笔记)