当前位置: 首页 > news >正文

翻金币项目 QT项目 (利用Qt 5.80 实现 )

1.项目的性质:游戏


2.项目的名字:翻金币


3.实现的软件 ; QT creator 4.2.1   , NisEdit  , Nsis


4.游戏介绍: 

        1.包括游戏界面

        2.游戏音效

        


5.游戏的资源(res)

已经上传

整个的代码包: CoinFilp

已经上传


6.文件:

1.chooselevelscene.h

2.dataconfig.h

3.mainsence.h

4.mycoin.h

5.mypushbutton.h

6.playscene.h

7.main.cpp

8.chooselevelscene.cpp

9.dataconfig.cpp

10.mainsence.cpp

11.mycoin.cpp

12.mypushbutton.cpp

13.playscene.cpp


7.ui ->  设计界面 (添加了一个菜单栏  开始  ,退出的菜单项 )


8.资源文件

res


9.代码:

 CoinFlip.pro  (这里注意  添加了  一个   multimedia    第7 行 )

#-------------------------------------------------
#
# Project created by QtCreator 2022-09-23T10:33:56
#
#-------------------------------------------------

QT       += core gui multimedia

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = CoinFlip
TEMPLATE = app

# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0


SOURCES += main.cpp\
        mainsence.cpp \
    mypushbutton.cpp \
    chooselevelscene.cpp \
    playscene.cpp \
    mycoin.cpp \
    dataconfig.cpp

HEADERS  += mainsence.h \
    mypushbutton.h \
    chooselevelscene.h \
    playscene.h \
    mycoin.h \
    dataconfig.h

FORMS    += mainsence.ui

RESOURCES += \
    res.qrc

 

1.chooselevelscene.h

#ifndef CHOOSELEVELSCENE_H
#define CHOOSELEVELSCENE_H

#include <QMainWindow>
#include "playscene.h"

class ChooseLevelScene : public QMainWindow
{
    Q_OBJECT
public:
    explicit ChooseLevelScene(QWidget *parent = 0);
    //重写绘画事件
    void paintEvent(QPaintEvent *);
    //游戏场景的对象指针
    PlayScene * paly = NULL;

signals:
    //写一个自定义的信号,告诉主场景,点击了返回
    void chooseSceneBack();

public slots:
};

#endif // CHOOSELEVELSCENE_H

2.dataconfig.h

#ifndef DATACONFIG_H
#define DATACONFIG_H

#include <QObject>
#include <QMap>//STL 地图
#include <QVector>//STL  动态数组

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

    QMap<int ,QVector< QVector<int> > >mData;//一个地图
    //地图的 key  是 int 类型   value  是 int 的二维的数组QVector< QVector<int> >

signals:

public slots:
};

#endif // DATACONFIG_H

3.mainsence.h

#ifndef MAINSENCE_H
#define MAINSENCE_H

#include <QMainWindow>
#include <QPainter>
#include <QDebug>
#include <chooselevelscene.h>

namespace Ui {
class Mainsence;
}

class Mainsence : public QMainWindow
{
    Q_OBJECT

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

    //重新paintEvent 事件, 画背景图
    void paintEvent(QPaintEvent *);//括号里面是数据类型,不需要写参数,没事

    ChooseLevelScene * chooseScene =NULL;

private:
    Ui::Mainsence *ui;
};

#endif // MAINSENCE_H

4.mycoin.h

#ifndef MYCOIN_H
#define MYCOIN_H

#include <QWidget>
#include <QPushButton>
#include <QString>
#include <QDebug>
#include <QTimer>

class MyCoin : public QPushButton
{
    Q_OBJECT
public:
    //explicit MyCoin(QWidget *parent = 0);
    //参数表示 传进来的金币路径  还是银币路径
    MyCoin(QString btnImg);

    //金币的属性
    int posX;//x坐标
    int posY;//y坐标
    bool flag;//正反的标志


    void changeFlag();//改变金币的状态
    QTimer *timer1;//正面翻反面的定时器
    QTimer *timer2;//反面翻正面的定时器
    int min=1;//图片的最小号码数
    int max=8;//图片的最大号码数

    //执行动画  标志
    bool isAnimation = false;// 判断他是否在执行翻转的操作 防止用户狂点的行为

    //重写 鼠标按下的事件
    void mousePressEvent(QMouseEvent * e);

    //设置一个是否可以翻转的标志
    bool ispaly=true;

signals:

public slots:
};

#endif // MYCOIN_H

5.mypushbutton.h

#ifndef MYPUSHBUTTON_H
#define MYPUSHBUTTON_H

#include <QWidget>
#include <QPushButton>
#include <QString>
#include <QDebug>
#include <QPropertyAnimation>

class mypushbutton : public QPushButton
{
    Q_OBJECT
public:
    //explicit mypushbutton(QWidget *parent = 0);
    //构造函数 参数1 正常显示的图片路径 参数2 按下后显示的图片的路径
    mypushbutton(QString normalImg,QString pressImg = "");

    //成员属性 保存用户传入的默认显示路径 以及按下后显示的图片路径
    QString normaLImgPath;
    QString pressImgPath;


    //弹跳特效
    void zoom1();//向下跳
    void zoom2();//向上跳

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

    void mouseReleaseEvent(QMouseEvent * e);//释放

signals:

public slots:
};

#endif // MYPUSHBUTTON_H

6.playscene.h

#ifndef PLAYSCENE_H
#define PLAYSCENE_H

#include <QMainWindow>
#include "mycoin.h"

class PlayScene : public QMainWindow
{
    Q_OBJECT
public:
    //explicit PlayScene(QWidget *parent = 0);
    PlayScene(int levelNum);//构造函数
    int levelIndex;//内部成员属性;记录所选的关卡数字

    //重写paintEvent事件
    void paintEvent(QPaintEvent * );

    int gameArray[4][4];//二维数组 维护每个关卡的具体数据


    //下面这个指针数组是用来存储 金币的  就是下一个关卡的所有的金币对象
    MyCoin * coinBtn[4][4];//维护上一个数组的数据正常

    //是否胜利的标志
    bool isWin;

signals:
    void chooseSceneBack();

public slots:
};

#endif // PLAYSCENE_H

7.main.cpp

#include "mainsence.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Mainsence w;
    w.show();

    return a.exec();
}

8.chooselevelscene.cpp

#include "chooselevelscene.h"
#include <QMenuBar>
#include <QDebug>
#include <QPainter>
#include "mypushbutton.h"
#include <QTimer>
#include <QString>
#include <QLabel>
#include <QSound>

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

    //设置标题
    this->setWindowTitle("选择关卡场景");

    //创建菜单栏
    QMenuBar * bar = menuBar();
    setMenuBar(bar);

    //创建开始菜单
    QMenu * startMenu = bar->addMenu("开始");

    //创建退出  菜单栏
    QAction * quitAction = startMenu->addAction("退出");

    //点击退出 实现退出游戏 建立连接
    connect(quitAction,&QAction::triggered,[=](){
        this->close();

    });

    //选择关卡的音效
    QSound * chooseSound = new QSound(":/res/TapButtonSound.wav",this);
    //返回按钮的音效
    QSound * backSound = new QSound(":/res/TapButtonSound.wav",this);



    //返回按钮
    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,[=](){
        //点击了返回按钮的音效
        backSound->play();

       qDebug()<<"点击了选择关卡的 返回按键";

       //告诉主场景,我返回了,主场景监听 chooseLeveScene 的返回按键

       //延时发送信号

       QTimer::singleShot(500,this,[=](){
           emit this->chooseSceneBack();//激发信号  返回开始界面

       });

    });

    //创建选择关卡的按钮
    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,[=](){

            //选择关卡之后播放音效
            chooseSound->play();

           QString str  =QString("你选择的是第 %1 关").arg(i+1);
            qDebug()<<str;

            //


            //进入游戏场景
            this->hide();//进入游戏关卡 ,隐藏游戏选择界面
            paly =new PlayScene(i+1);//创建一个游戏的界面

            //设置游戏场景出现的初始位置
            paly->setGeometry(this->geometry());

            paly->show();//显示游戏界面


            //退出游戏的信号连接
            connect(paly,&PlayScene::chooseSceneBack,[=](){
                this->setGeometry(paly->geometry());//窗口的位置的调整
                this->show();
                delete paly;
                paly=NULL;
            });

        });

        //设置选择关卡上的数字
        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);

        //设置让鼠标进行穿透  51号属性

        label->setAttribute((Qt::WA_TransparentForMouseEvents));


    }


}
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);//加载下一张图片进去
}

9.dataconfig.cpp

//dataconfig.cpp
#include "dataconfig.h"
#include <QDebug>
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);//把二维数组 计入到之前的 map  地图中  key =1  value = 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);
}

10.mainsence.cpp

#include "mainsence.h"
#include "ui_mainsence.h"
#include <QPushButton>
#include "mypushbutton.h"
#include <chooselevelscene.h>
#include <QTimer>
#include <QSound>

Mainsence::Mainsence(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::Mainsence)
{
    ui->setupUi(this);

    //配置主场景

    //设置固定大小
    setFixedSize(320,588);//设置窗口的初始大小

    //设置图标
    setWindowIcon(QIcon(":/res/Coin0001.png"));

    //设置标题
    setWindowTitle("翻金币主场景");

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

    //准备开始的音效
    QSound * startSound = new QSound(":/res/TapButtonSound.wav",this);
    //startSound->setLoops(-1);   // 这个函数是播放几次  -1 是无限的播放


    //开始的按钮
    mypushbutton * startBtn  = new mypushbutton(":/res/MenuSceneStartButton.png");
    startBtn->setParent(this);
    startBtn->move((this->width() *0.5) - (startBtn->width()*0.5),this->height()*0.7);
    //实列化选择关卡场景
    chooseScene =new ChooseLevelScene;


    //返回按钮的信号连接
    connect(chooseScene,&ChooseLevelScene::chooseSceneBack,this,[=](){
        this->setGeometry(chooseScene->geometry());//保证两个窗口出现的位置相同
        chooseScene->hide();//选择关卡场景  隐藏
        this->show();//重新显示主场景

    });


    connect(startBtn,&mypushbutton::clicked,[=](){

        //播放点击了开始的音效
        startSound->play();


        qDebug()<<"点击了开始";
        //弹起特效
        startBtn->zoom1();
        startBtn->zoom2();

        //延时进入到选择关卡场景中
        QTimer::singleShot(500,this,[=](){

            //设置chooseScene 场景的位置
            chooseScene->setGeometry(this->geometry());//这个函数的作用就是把 新的这个窗口放到 之前要隐藏的窗口的位置,防止返回的时候,两个窗口位置的不同

            //自身隐藏
            this->hide();

            //进入选择关卡场景中
            //显示选择关卡
            chooseScene->show();

            //监听选择关卡场景的返回按钮的信号



        });

    });
}

Mainsence::~Mainsence()
{
    delete ui;
}


//重新paintEvent 事件, 画背景图
void Mainsence::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);//再次放置图片 开始的位置是10,30



}

11.mycoin.cpp

#include "mycoin.h"
#include <QDebug>


//MyCoin::MyCoin(QWidget *parent) : QWidget(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:Opx}");//设置为不规则图像的过滤
    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 str1 = QString(":/res/Coin000%1").arg(this->min++);
           bool ret1=pix.load(str1);
           if(!ret1)
           {
               qDebug()<<"错误  金币正面翻转 "<<str1;
           }
        this->setFixedSize(pix.width(),pix.height());//设置 金币按钮的大小
        this->setStyleSheet("QPushButton{border:Opx}");//设置为不规则图像的过滤
        this->setIcon(pix);//加载图片,给这个按钮
        this->setIconSize(QSize(pix.width(),pix.height()));//图片大小的设置

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

    });

    //监听反面的金币的点击 信号
    connect(timer2,&QTimer::timeout,[=](){
         QPixmap pix;//建立一个图片的对象
         QString str1 = QString(":/res/Coin000%1").arg(this->max--);
           bool ret1=pix.load(str1);
           if(!ret1)
           {
               qDebug()<<"错误  金币正面翻转 "<<str1;
           }
        this->setFixedSize(pix.width(),pix.height());//设置 金币按钮的大小
        this->setStyleSheet("QPushButton{border:Opx}");//设置为不规则图像的过滤
        this->setIcon(pix);//加载图片,给这个按钮
        this->setIconSize(QSize(pix.width(),pix.height()));//图片大小的设置

           //判断 如果翻完了  将min 重置为 1;
           if(this->max < this->min)
           {
               this->max=8;
               timer2->stop();//定时器发出信号停止
               isAnimation=false;//停止做动画了
           }

    });

}

void MyCoin::changeFlag()//改变金币的状态
{
    //如果是正面  翻成反面
    if(this->flag)
    {
        //开始运行正面翻反面的定时器
        timer1->start(30);//启动定时器 时间间隔为30毫秒
        this->flag=false;//把金币的状态改变
        isAnimation=true;//开始做动画了
    }
    else
    {
        //开始运行反面翻正面的定时器
        timer2->start(30);//启动定时器 时间间隔为30毫秒
        this->flag=true;//把金币的状态改变
        isAnimation=true;//开始做动画了
    }

}

//重写 鼠标按下的事件
void MyCoin::mousePressEvent(QMouseEvent * e)
{
    if(this->isAnimation || this->ispaly== false)//当他翻转动作正在执行的时候,我们点击按钮 ,使按钮失效
    {
        return;
    }
    else//没有进行翻转动作的时候,我们把这个信号交给父类处理
    {
        QPushButton::mousePressEvent(e);
    }


}

12.mypushbutton.cpp

#include "mypushbutton.h"

//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:Opx;}");//去掉周围的空白,只剩图形
    //设置图片
    this->setIcon(pix);
    //设置图标大小
    this->setIconSize(QSize(pix.width(),pix.height()));


}

//弹跳特效
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();
}



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:Opx;}");//去掉周围的空白,只剩图形
        //设置图片
        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:Opx;}");//去掉周围的空白,只剩图形
        //设置图片
        this->setIcon(pix);
        //设置图标大小
        this->setIconSize(QSize(pix.width(),pix.height()));
    }

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


}

13.playscene.cpp

#include "playscene.h"
#include <QDebug>
#include <QMenuBar>
#include <QPainter>
#include "mypushbutton.h"
#include <QTimer>
#include <QLabel>
#include "mycoin.h"
#include "dataconfig.h"
#include <QPropertyAnimation>
#include <QSound>


//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 = menuBar();//创建一个菜单栏的对象,这个对象是空的
    setMenuBar(bar);//把菜单栏对象,放置到窗口

    //创建开始菜单
    QMenu * startMenu = bar->addMenu("开始");

    //创建退出  菜单选项
    QAction * quitAction = startMenu->addAction("退出");

    //点击退出  实现退出游戏
    connect(quitAction,&QAction::triggered,[=](){
       this->close();
    });


    //添加音效
    //返回按钮的音效
    QSound * backSound = new QSound(":/res/TapButtonSound.wav",this);
    //翻金币的音效
    QSound * flipSound = new QSound(":/res/ConFlipSound.wav",this);
    //成功胜利的音效
    QSound * winSound = new QSound(":/res/LevelWinSound.wav",this);

    //返回按钮
    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,[=](){
        //点击了返回的音效
        backSound->play();

       qDebug()<<"点击了 游戏场景里面的 返回按键";

       //告诉主场景,我返回了,主场景监听 chooseLeveScene 的返回按键

       //延时发送信号
       QTimer::singleShot(500,this,[=](){
           emit this->chooseSceneBack();//激发信号  返回开始界面

       });

    });

    //显示当前关卡数
    QLabel * label = new QLabel;
    label->setParent(this);//设置父亲
    QFont font;//设置字体的对象
    font.setFamily("华文新魏");//字体的格式
    font.setPointSize(20);//字体大小为 20

    //输出的标签显示的内容
    QString  str1=QString("Level: %1").arg(this->levelIndex);

    //将字体的设置加入标签空间之中
    label->setFont(font);

    label->setText(str1);//设置关卡的标签显示的内容
    //label->setFixedSize(20,20);//设置标签的大小
    //label->move(100,500);//设置标签的显示的位置在哪里
    label->setGeometry(30,this->height() -50 ,150,50);//这个上面 两个命令的合并的功能


    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];//赋值
        }
    }

    //胜利的图片显示,
    //开始的时候我们把他放到屏幕之外  等到胜利之后我们直接让他掉下来
    QLabel * winLabel = new QLabel;
    QPixmap tmaPix;
    tmaPix.load(":/res/LevelCompletedDialogBg.png");//加载图片
    winLabel->setGeometry(0,0,tmaPix.width(),tmaPix.height());//设置标签里面放置的位置
    winLabel->setPixmap(tmaPix);//把图片放入到标签
    winLabel->setParent(this);//设置标签的父亲
    winLabel->move((this->width() - tmaPix.width())*0.5,-tmaPix.height());//设置标签在窗口的位置


    //显示金币背景图案 灰色的方形框框
    for(int i=0;i<4;i++)
    {
        for(int j=0;j<4;j++)
        {
            //绘制背景图片
            QPixmap pix = QPixmap(":/res/BoardNode(1).png");//加载图片
            QLabel * label = new QLabel;//新建一个标签
            label->setGeometry(0,0,pix.width(),pix.height());//设置标签里面放置的位置
            label->setPixmap(pix);//把图片放入到标签
            label->setParent(this);//设置标签的父亲
            label->move(57+i*50,200+j*50);//设置标签在窗口的位置


            //创建金币
            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;//x 坐标
            coin->posY=j;//y 坐标
            coin->flag=this->gameArray[i][j];//正面是 1  反面是 0

            //将金币放到  金币的二维数组里  以便后期的维护
            coinBtn[i][j]=coin;//


            //点击金币  进行翻转
            //他的本质 继承的是  QPushButton
            //监听点击信号
            connect(coin,&MyCoin::clicked,[=](){
                //翻金币的音效
                flipSound->play();

                coin->changeFlag();//点击之后进行翻转
                this->gameArray[i][j]=(this->gameArray[i][j]==0 ? 1:0);

                //加一个延时的翻转
                QTimer::singleShot(100,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);
                    }

                    //判断是否胜利
                    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)//胜利了
                    {
                        //游戏胜利的音效
                        winSound->play();


                        qDebug()<<"第"<<levelNum<<"关  "<<"游戏胜利了";
                        //把所有的金币按钮禁用
                        for(int i=0;i<4;i++)
                        {
                            for(int j=0;j<4;j++)
                            {
                                   coinBtn[i][j]->ispaly=false;//金币按钮不可以使用
                            }
                        }






                        //创建一个动态对象
                        QPropertyAnimation * animation1 =new QPropertyAnimation(winLabel,"geometry");
                        //设置动画的事件间隔
                        animation1->setDuration(1000);

                        //起始位置
                        animation1->setStartValue(QRect(winLabel->x(),winLabel->y(),winLabel->width(),winLabel->height()));
                        //结束位置
                        animation1->setEndValue(QRect(winLabel->x(),winLabel->y()+144,winLabel->width(),winLabel->height()));

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

                        //执行动画
                        animation1->start();


                    }


                });



            });


        }
    }

}

//QWidget中的paintEvent事件处理器可以在子类中被重写来接收绘图事件,然后在指定区域完成图形的绘制。
//重写paintEvent事件
void PlayScene::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);//再次放置图片 开始的位置是10,30

}


相关文章:

  • Java项目:JSP员工出差请假考勤管理系统
  • OP-TEE driver(三):OP-TEE驱动中的数据结构体
  • 人工智能轨道交通行业周刊-第15期(2022.9.19-9.25)
  • python process模块的使用简介
  • 回调函数等作业
  • 不要再盯着大厂了,这16家中小厂我建议你也试试
  • Linux-常见命令(一)
  • 什么是C语言?
  • 封装——C++
  • 【Java高级】框架底层基础:Java的反射机制剖析
  • verilog移位寄存器实现序列检测
  • 前端性能优化方法与实战02 性能瓶颈点:从 URL 输入到页面加载整过程分析
  • 34.0、C语言——C语言预处理(2) - 预编译(预处理)详解(2)
  • ES优化实战 - 小操作节省百分之三十以上的磁盘空间
  • [Go WebSocket] 多房间的聊天室(五)用多个小锁代替大锁,提高效率
  • angular学习第一篇-----环境搭建
  •  D - 粉碎叛乱F - 其他起义
  • HTTP中的ETag在移动客户端的应用
  • jquery cookie
  • Python 使用 Tornado 框架实现 WebHook 自动部署 Git 项目
  • vue2.0开发聊天程序(四) 完整体验一次Vue开发(下)
  • windows-nginx-https-本地配置
  • 得到一个数组中任意X个元素的所有组合 即C(n,m)
  • 函数式编程与面向对象编程[4]:Scala的类型关联Type Alias
  • 基于 Ueditor 的现代化编辑器 Neditor 1.5.4 发布
  • 使用iElevator.js模拟segmentfault的文章标题导航
  • 事件委托的小应用
  • 手写双向链表LinkedList的几个常用功能
  • 微信小程序--------语音识别(前端自己也能玩)
  • 我看到的前端
  • 7行Python代码的人脸识别
  • Mac 上flink的安装与启动
  • # 达梦数据库知识点
  • #QT(TCP网络编程-服务端)
  • $jQuery 重写Alert样式方法
  • (01)ORB-SLAM2源码无死角解析-(56) 闭环线程→计算Sim3:理论推导(1)求解s,t
  • (6)添加vue-cookie
  • (JSP)EL——优化登录界面,获取对象,获取数据
  • (八)Spring源码解析:Spring MVC
  • (二开)Flink 修改源码拓展 SQL 语法
  • (附源码)spring boot北京冬奥会志愿者报名系统 毕业设计 150947
  • (附源码)springboot 智能停车场系统 毕业设计065415
  • (含react-draggable库以及相关BUG如何解决)固定在左上方某盒子内(如按钮)添加可拖动功能,使用react hook语法实现
  • (一)Java算法:二分查找
  • (一)Neo4j下载安装以及初次使用
  • (原創) 如何讓IE7按第二次Ctrl + Tab時,回到原來的索引標籤? (Web) (IE) (OS) (Windows)...
  • (转)Android中使用ormlite实现持久化(一)--HelloOrmLite
  • (转)C#开发微信门户及应用(1)--开始使用微信接口
  • (转)编辑寄语:因为爱心,所以美丽
  • .htaccess配置重写url引擎
  • .NET CF命令行调试器MDbg入门(一)
  • .net 写了一个支持重试、熔断和超时策略的 HttpClient 实例池
  • .NET/C# 判断某个类是否是泛型类型或泛型接口的子类型
  • /etc/fstab 只读无法修改的解决办法
  • [28期] lamp兄弟连28期学员手册,请大家务必看一下