Qt_翻金币01

游戏首界面

窗口

创建一个MainScene主体,继承自QMainWindow,这里我们重写父类的一个方法void paintEvent(QPaintEvent *event);
mainscene.cpp

// 绘图事件
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);

}

箭头指向的CoinFlip,就是Title.png




菜单栏的开始菜单,有个退出的菜单项,实现退出游戏

窗口标题,窗体标题的图标等等同样是在cpp中实现

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

    this->setFixedSize(320,588);
    this->setWindowTitle("翻金币");
    this->setWindowIcon(QIcon(":/res/Coin0001.png"));




开始按钮的实现


自定义一个按钮类,是继承了QPushButton的类MyPushButton,只需要用C++类文件创建


封装


设置按钮的形状

#ifndef MYPUSHBUTTON_H
#define MYPUSHBUTTON_H


// 这个类是用来封装我们自己设计的 按钮 类
#include <QDebug>
#include <QPushButton>

class MyPushButton : public QPushButton
{
    Q_OBJECT
public:

    QString normalImgPath;			// 默认显示的图片
    QString pressImgPath;			// 按下后显示的图片
    MyPushButton(QString normalImg,QString pressImg = "");

signals:

};

#endif // MYPUSHBUTTON_H




MyPushButton类的构造函数,成员函数等都在这里mypushbutton.cpp实现

#include "mypushbutton.h"
#include <QPropertyAnimation>
MyPushButton::MyPushButton(QString normalImg,QString pressImg){
    // 保存图片路径
    this->normalImgPath = normalImg;		
    this->pressImgPath = pressImg;			

    // 图片
    QPixmap pix;
    // 加载图片  		不直接用绝对路径 
    bool ret = pix.load(this->normalImgPath);

    if(!ret){
        QString str = QString("%1 图片路径加载失败").arg(this->normalImgPath);

        qDebug()<<str;
        return ;

    }

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

    // 设置图片不规则样式  字符串内是用花括号!!!
    this->setStyleSheet("QPushButton{border:0px;}");

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

    // 设置放进框中的图片大小
    this->setIconSize(QSize(pix.width(),pix.height()));
}


这里有一点需要注意

不管是类的构造函数还是普通函数,声明和实现时是不能够同时给参数缺省值的




设置按钮的特效

MyPushButton.h添加成员函数void up();void down();的声明,同时需要头文件#include <QPropertyAnimation>

然后在mypushbutton.cpp中进行实现


// 按钮向下跳跃的动画
void MyPushButton::down(){
    // 动画  第一个参数是动画的对象 第二个是以什么形式
    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()));

    // 设置按钮弹跳效果   curve 曲线
    animation->setEasingCurve(QEasingCurve::OutBounce);

    // 开始
    animation->start();

}

void MyPushButton::up(){
    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();

}



使用mypushbutton

mainscene.cpp


	// 创建按钮
	// 第二个参数为空字符串 表示按下后没有变化为哪个图片
    MyPushButton * startBtn = new MyPushButton(":/res/MenuSceneStartButton.png");
    startBtn->setParent(this);

	// 这里就别傻傻的写具体数字!!!
    startBtn->move( this->width() * 0.5 - startBtn->width() * 0.5 ,this->height() * 0.7 );
	
	
	// 按下
    connect(startBtn,&QPushButton::clicked,this,[=](){
        startBtn->down();
        startBtn->up();
    });




游戏第二个界面

点击开始后显示的页面,也就是选择关卡的界面



界面设置


这里Add New一个C++类文件,取名为ChooseLevelScene,就不选用ui文件进行创建该界面,下面会用代码实现

chooselevelscene.h

#ifndef CHOOSELEVELSCENE_H
#define CHOOSELEVELSCENE_H

#include <QMainWindow>

class ChooseLevelScene : public QMainWindow
{
    Q_OBJECT
public:
    explicit ChooseLevelScene(QWidget *parent = nullptr);
    
    // 设置第二界面的背景菜单大小等
    void paintEvent(QPaintEvent *event);
signals:

};

#endif // CHOOSELEVELSCENE_H



chooselevelscene.cpp

#include "chooselevelscene.h"
#include<QMenuBar>
#include<QPainter>
ChooseLevelScene::ChooseLevelScene(QWidget *parent) : QMainWindow(parent)
{
    this->setFixedSize(320,588);
    this->setWindowTitle("翻金币");
    this->setWindowIcon(QIcon(":/res/Coin0001.png"));


    // 这里用代码进行创建菜单栏
    QMenuBar * bar = menuBar();
    this->setMenuBar(bar);


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

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

    connect(quitAction,&QAction::triggered,this,[=](){
        this->close();
    });

}


// 绘图事件
void ChooseLevelScene::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");

        painter.drawPixmap((this->width()-pix.width())*0.5,30,pix.width(),pix.height(),pix);

}



接着在mainscene.cpp中实例化一个第二界面的对象,通过点击开始按钮,隐藏首界面,展示第二界面

    // 创建游戏的第二个界面
    chooseScene = new ChooseLevelScene;

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

        startBtn->down();
        startBtn->up();

        // 延时执行下面的代码  不然按钮的特效都看不见	
        // #include <QTimer>
        QTimer::singleShot(500,this,[=](){

            // 隐藏第一个界面
            this->hide();

            // 进入第二个界面
            chooseScene->show();
        });

    });



返回按钮

这个按钮是在第二个界面

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



这里给返回按钮也整一个特效,按下是一个样子,释放又是另一个样子

这两个事件Qt也就有了,只需要在头文件声明,在源文件中重写


// 鼠标按下事件
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.cpp

	// 点击返回按钮  返回到首页面
    // 但有个问题 这里没法直接show第一个界面 因为第二界面是第一界面的成员变量而已
    // 只有通过自定义的信号和槽 并在第一个界面实时监听
    connect(backBtn,&QPushButton::clicked,[=](){
        // 延时
        QTimer::singleShot(100);
        
        
        // 告诉上一层 这里返回了
        emit this->chooseSceneBack();
    });

而在第一个界面中进行监听

mainscene.cpp

    // 监听第二个界面的返回信号
    connect(chooseScene,&ChooseLevelScene::chooseSceneBack,[=](){
        chooseScene->hide();
        this->show();
    });



别忘了在chooselevelscene.h声明信号

signals:
    // 自定义信号  只声明不实现
    void chooseSceneBack();




关卡选择

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);

        // 设置关卡等级

        // 这个不太好 效果可以自行看
        // menuBtn->setText(i+1);

        QLabel * label = new QLabel(this);
        // 设置标签大小
        label->setFixedSize(menuBtn->width(),menuBtn->height());

        // int转QString
        label->setText(QString::number(i+1));

        label->move(25+(i%4)*70,130+(i/4)*70);

        // 标签居中
        label->setAlignment(Qt::AlignCenter);

        // 因为标签在按钮上层 所以点击时标签优先响应
        // 鼠标穿透  51号属性
        label->setAttribute(Qt::WA_TransparentForMouseEvents);


		// 测试
         connect(menuBtn,&QPushButton::clicked,[=](){
            QString str = QString("进入第 %1 关").arg(i+1);
            qDebug()<<str;
         });
        
    }



新建C++类文件PlayScene,因为在选择关卡,有20关,那构造函数肯定得传入一个整型参数的

playscene.h 修改构造函数

#ifndef PLAYSCENE_H
#define PLAYSCENE_H

#include <QMainWindow>

class PlayScene : public QMainWindow
{
    Q_OBJECT
public:
   // explicit PlayScene(QWidget *parent = nullptr);
    PlayScene(int index);
signals:

};

#endif // PLAYSCENE_H



playscene.cpp

#include "playscene.h"
#include<QDebug>
PlayScene(int index){
    QString str = QString("打开第%1关").arg(index);
    qDebug()<<str;
}
    

chooselevelscene.h维护一个playscene类的指针,再在chooselevelscene.cppfor循环中实现进入关卡的功能

        connect(menuBtn,&QPushButton::clicked,[=](){
            this->hide();
            
            //进入到具体的游戏场景
            playScene = new PlayScene(i+1);
            playScene->show();
        });



第三个界面

关卡界面

点击选择,进入关卡后,大部分和前面两个常见一样,其余都是新的,左下角Level的显示,中心的金币阴影,其中返回按钮也稍有更新

同样的,在类中声明paintEvent函数,再定义一个整型levelIndex来记录关卡数,还有一个从第三个界面,关卡界面,返回到第二个界面的信号

    int levelIndex;
	// 重写绘图事件
	void paintEvent(QPaintEvent * e);

signals:
    void playSceneBack();



#include "playscene.h"
#include<QMenuBar>
#include<QPainter>
#include "mypushbutton.h"
#include <QLabel>
PlayScene::PlayScene(int index)
{
    this->levelIndex = index;
    this->setFixedSize(320,588);
    this->setWindowTitle("翻金币");
    this->setWindowIcon(QIcon(":/res/Coin0001.png"));


    // 这里用代码进行创建菜单栏
    QMenuBar * bar = menuBar();
    this->setMenuBar(bar);


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

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

    connect(quitAction,&QAction::triggered,this,[=](){
        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());

    // 点击返回按钮  返回到首页面
    // 但有个问题 这里没法show第一个界面 因为第二界面是第一界面的成员变量而已
    // 只有通过自定义的信号和槽 并在第一个界面实时监听
    connect(backBtn,&QPushButton::clicked,[=](){
        // 告诉上一层 这里返回了
        emit this->playSceneBack();
    });


    // 显示具体关卡号
    QLabel * label = new QLabel(this);
    QFont font;
    font.setFamily("华文新魏");
    // 字号
    font.setPointSize(20);
    label->setFont(font);
    QString str = QString("Level: %1").arg(this->levelIndex);
    label->setText(str);
    // 设置位置
    label->setGeometry(QRect(30,this->height()-50,120,50));




    // 设置金币的背景阴影
    for(int i=0;i<4;++i){
        for(int j=0;j<4;++j){

            // 用QLabel显示图片
            QLabel * bg = new QLabel(this);


//            bg->setGeometry(0,0,50,50);     //这里的50 50不太好 这样写死了

//            bg->setPixmap(QPixmap(":/res/BoardNode.png"));
//            bg->move(57+i*50,200+j*50);

            QPixmap pix;
            pix.load(":/res/BoardNode.png");
            bg->setGeometry(0,0,pix.width(),pix.height());
            bg->setPixmap(pix);
            bg->move(57+i*pix.width(),200+j*pix.height());
        }
    }
}
// 重写绘图事件
void PlayScene::paintEvent(QPaintEvent * e){
    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);
}



Level显示,金币阴影,以及第三界面的整体画面都写好了,现在还剩返回按钮的信号和槽的链接

chooselevelscene.cpp

connect(menuBtn,&QPushButton::clicked,[=](){
            this->hide();
            
            //进入到具体的游戏场景
            playScene = new PlayScene(i+1);
            playScene->show();

            // 选择在这里进行链接 是因为每次new的playScene都不一样啊    放外面就不会有反应
            // playScene 隐藏  选择关卡 显示
            connect(playScene,&PlayScene::playSceneBack,[=](){
                playScene->close();			// 这里就不是hide了 每次进入都是重新开始的吧
                delete playScene;			// 而且playScene是指针 不是类的对象
                playScene = NULL;
                this->show();
            });
        });
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值