mypushbutton.h
#ifndef MYPUSHBUTTON_H#define MYPUSHBUTTON_H#include <QPushButton>class MyPushButton : public QPushButton{ Q_OBJECTpublic: // explicit MyPushButton(QWidget *parent = nullptr); // 构造函数 参数1:正常显示的图片路径,参数2:按下后显示的图片路径 MyPushButton(QString normalImg, QString pressImg = ""); // 成员属性 保存用户传入的默认显示路径 以及按下后显示的图片路径 QString normalImgPath; QString presslImgPath; // 弹跳特性 void zoom1(); // 向下跳 void zoom2(); // 向上跳 // 重写按钮的按下和释放 void mousePressEvent(QMouseEvent *e); void mouseReleaseEvent(QMouseEvent *e);signals:public slots:};#endif // MYPUSHBUTTON_H
mypushbutton.cpp文件
#include "mypushbutton.h"#include <QDebug>#include <QPropertyAnimation>//MyPushButton::MyPushButton(QWidget *parent) : QPushButton(parent)//{//}MyPushButton::MyPushButton(QString normalImg, QString pressImg){ this->normalImgPath = normalImg; this->presslImgPath = 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()));}// 向下跳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->presslImgPath != "") // 传入的按下图片不为空 说明需要有按下状态,切换图片 { QPixmap pix; bool ret = pix.load(this->presslImgPath); 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->presslImgPath != "") // 传入的按下图片不为空 说明需要有按下状态,切换成初始图片 { 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);}
mainscene.h文件
#ifndef MAINSCENE_H#define MAINSCENE_H#include <QMainWindow>#include "chooselevelscene.h"namespace Ui {class MainScene;}class MainScene : public QMainWindow{ Q_OBJECTpublic: explicit MainScene(QWidget *parent = 0); ~MainScene(); // 重现paintEvent事件 画背景图 void paintEvent(QPaintEvent *event); ChooseLevelScene * chooseScene = NULL;private: Ui::MainScene *ui;};#endif // MAINSCENE_H
mainscene.cpp文件
#include "mainscene.h"#include "ui_mainscene.h"#include "mypushbutton.h"#include <QPainter>#include <QDebug>#include <QTimer>#include <QSound> // 多媒体模块下的头文件MainScene::MainScene(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainScene){ ui->setupUi(this); // 配置主场景 // 设置固定大小 setFixedSize(320, 588); // 设置图标 setWindowIcon(QIcon(":/res/Coin0001.png")); // 设置标题 setWindowTitle("翻金币主场景"); // 退出按钮实现 connect(ui->actionquit, &QAction::triggered, [=](){ this->close(); }); // 准备开始按钮的音效 QSound * startSound = new QSound(":/res/TapButtonSound.wav", this); // 开始按钮 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, [=](){ // 设置chooseScene返回的场景位置 this->setGeometry(chooseScene->geometry()); // 隐藏关卡 chooseScene->hide(); // 重新显示主场景 this->show(); }); connect(startBtn, &MyPushButton::clicked, [=](){ qDebug() << "点击了开始"; // 播放开始音效资源 startSound->play(); // 做弹起的特效 startBtn->zoom1(); startBtn->zoom2(); // 延时进入选择关卡场景中 QTimer::singleShot(500, this, [=](){ // 设置chooseScene去的场景位置 chooseScene->setGeometry(this->geometry()); // 将自身隐藏掉 this->hide(); // 显示选择关卡场景 chooseScene->show(); }); });}// 创建画家,指定绘图设备// 重现paintEvent事件 画背景图void MainScene::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);}MainScene::~MainScene(){ delete ui;}
chooselevelscene.h文件
#ifndef CHOOSELEVELSCENE_H#define CHOOSELEVELSCENE_H#include <QMainWindow>#include "playscene.h"class ChooseLevelScene : public QMainWindow{ Q_OBJECTpublic: explicit ChooseLevelScene(QWidget *parent = nullptr); // 重写paintEvent事件 画背景图 void paintEvent(QPaintEvent *event); // 游戏场景对象指针 PlayScene * play = NULL;signals: // 写一个自定义信号,告诉主场景点击了返回 void chooseSceneBack();public slots:};#endif // CHOOSELEVELSCENE_H
chooselevelscene.cpp文件
#include "chooselevelscene.h"#include <QMenuBar>#include <QPainter>#include <QDebug>#include <QTimer>#include <QLabel>#include "mypushbutton.h"#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 * startSound = new QSound(":/res/TapButtonSound.wav", this); // 返回按钮的音效 QSound * backSound = new QSound(":/res/BackButtonSound.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() << "点击了返回"; // 告诉主场景 返回了,主场景监听chooseSceneBack的返回按钮 // 延时返回 QTimer::singleShot(200, 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, [=](){ QString str = QString("你选择的是第 %1 关").arg(i+1); qDebug() << str; // 音效 startSound->play(); // 进入到游戏场景 this->hide(); // 将选关场景隐藏掉 play = new PlayScene(i+1); // 设置游戏场景的初始位置 play->setGeometry(this->geometry()); play->show(); // 显示游戏场景 connect(play, &PlayScene::playSceneBack, this, [=](){ this->setGeometry(play->geometry()); // 重新显示关卡场景 this->show(); // 销毁退出的关卡场景 delete play; play = NULL; }); }); // 使用label添加数字 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 label->setAttribute(Qt::WA_TransparentForMouseEvents); }}void ChooseLevelScene::paintEvent(QPaintEvent *event){ QPainter painter(this); QPixmap pix; pix.load(":/res/OtherSceneBg.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((this->width() - pix.width()) * 0.5, 30, pix.width(), pix.height(), pix);}
mycoin.h
#ifndef MYCOIN_H#define MYCOIN_H#include <QPushButton>#include <QTimer>class MyCoin : public QPushButton{ Q_OBJECTpublic:// explicit MyCoin(QWidget *parent = nullptr); // 参数代表传入的金币路径还是银币路径 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; // 是否胜利标志 bool isWin = false;signals:public slots:};#endif // MYCOIN_H
mycoin.cpp
#include "mycoin.h"#include <QDebug>#include <QSound>//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:0px;}"); this->setIcon(pix); this->setIconSize(QSize(pix.width(),pix.height())); // 初始化定时器对象 timer1 = new QTimer(this); timer2 = new QTimer(this); // 点击金币音效 QSound * flipSound = new QSound(":/res/ConFlipSound.wav", 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) {// // 开始点击金币音效// flipSound->play(); this->min = 1; isAnimation = false; // 停止做动画了 timer1->stop(); } }); // 监听反面翻正面信号,并且翻转金币 connect(timer2, &QTimer::timeout, [=](){ QPixmap pix; QString str2 = QString(":/res/Coin000%1").arg(this->max--); pix.load(str2); // 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) {// // 开始点击金币音效// flipSound->play(); this->max = 8; isAnimation = false; // 停止做动画了 timer2->stop(); } });}// 正反面标志的方法void MyCoin::changeFlag(){ // 点击金币音效 QSound * flipSound = new QSound(":/res/ConFlipSound.wav", this); if(!this->isAnimation && !this->isWin) { // 开始点击金币音效 flipSound->play(); qDebug() << "zc"; if(this->flag) { // 如果是正面 翻成反面 timer1->start(30); isAnimation = true; // 开始做动画了 this->flag = false; }else{ // 如果是正面 翻成反面 timer2->start(30); isAnimation = true; // 开始做动画了 this->flag = true; } }}
playscene.h
#ifndef PLAYSCENE_H#define PLAYSCENE_H#include <QMainWindow>#include "mycoin.h"class PlayScene : public QMainWindow{ Q_OBJECTpublic: // explicit PlayScene(QWidget *parent = nullptr); PlayScene(int levelNum); int levelIndex; // 内部成员属性,记录所选关卡 // 重现paintEvent事件 画背景图 void paintEvent(QPaintEvent *event); int gameArray[4][4]; // 二维数组 维护每个关卡的具体数据 // 二维数组 维护每个关卡的具体数据 MyCoin * coinBtn[4][4]; // 是否胜利标志 bool isWin = false; // bool isSucc = false;signals: // 写一个自定义信号,告诉关卡场景点击了返回 void playSceneBack();public slots:};#endif // PLAYSCENE_H
playscene.h
#include "playscene.h"#include <QDebug>#include <QMenuBar>#include <QTimer>#include <QPainter>#include <QLabel>#include <QFont>#include "mypushbutton.h"#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(str); // 创建菜单栏 QMenuBar * bar = menuBar(); setMenuBar(bar); // 创建开始菜单 QMenu * startMenu = bar->addMenu("开始"); // 创建退出菜单项 QAction * quitAction = startMenu->addAction("退出"); // 点击退出 实现退出游戏 connect(quitAction, &QAction::triggered, [=](){ this->close(); }); // 返回按钮的音效 QSound * backSound = new QSound(":/res/BackButtonSound.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() << "点击了返回"; // 告诉选关场景 返回了,主场景监听playSceneBack的返回按钮 // 延时返回 QTimer::singleShot(200, this, [=](){ emit this->playSceneBack(); }); }); // 显示当前关卡 QLabel * label = new QLabel; label->setParent(this); label->setFixedSize(150, 50); label->setFont(QFont("华文新魏", 20)); QString str2 = QString("Leavel: %1").arg(levelIndex); label->setText(str2); label->move(20, this->height()-40); // 初始化每个关卡的二维数组 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 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()); // 显示金币的背景图案 for(int i=0; i<4; i++) { for(int j = 0; j<4; j++) { // 绘制金币背景图 QLabel * label2 = new QLabel; label2->setGeometry(0, 0, 50, 50); label2->setPixmap(QPixmap(":/res/BoardNode(1).png")); label2->setParent(this); label2->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反面 // 将金币放入金币的二维数组中,以便后期的维护 coinBtn[i][j] = coin; // 点击金币 进行翻转 connect(coin, &MyCoin::clicked, [=](){ coin->changeFlag(); this->gameArray[i][j] = this->gameArray[i][j] == 0 ? 1 : 0; // 翻转周围金币 // 右侧 QTimer::singleShot(200, this, [=](){ if(coin->posX + 1 <= 3) { qDebug() << coin->posX; 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) { qDebug() << coin->posX; 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) { qDebug() << coin->posY; 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) { qDebug() << coin->posY; 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 && !this->isSucc) { // 胜利了 //胜利音效 winSound->play(); qDebug() << "游戏胜利"; this->isSucc = true; // 将所有按钮的胜利标志改为true for(int i=0; i<4; i++) { for(int j=0; j<4; j++) { coinBtn[i][j]->isWin = true; } } // 将胜利的图片移动下来 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(); } }); }); } }}// 创建画家,指定绘图设备// 重现paintEvent事件 画背景图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);}
