Qt5.x-小游戏-翻金币

前言

    事情的起因需要从一只蝙蝠说起,那是2020年过年时,没有携带所有娱乐性工具的我回到老家后,经过麻将、电影、电视的洗礼,终于掏出来mac想学习一下c++。

    c++基础学完后,发现了Qt这门语言,经过了解是一门c++编写的跨平台桌面程序开发的框架,就继续进行学习观看,这个demo也是Qt教学视频中的老师最后带着一起完成的翻金币小游戏,日常生活中我从事的方向时J2EE方向,并不是过多的使用到学习到的东西,记录到简书中便于以后观看查阅。


    视频学习网站:B站

    视频路径:B站-Qt学习视频

    *素材是在评论中翻找好多以后某位大哥的,很多链接都失效了

    *如有侵权,请联系我进行删除及修改

    个人建议有兴趣的同学最好还是自己来一遍,如果实在敲的过程中有问题,也可以去我Github下载成品的所有代码。Github地址

    在学习的最后老师也提到过新加一些功能,我要立一个Flag:在闲暇的时候也会对这个成品进行一定程度的优化和修改。


1.代码结构说明

项目结构

主窗体-mainscene

选择关卡-chooseselevelscene

翻金币-playscene

金币封装-mycoin

关卡数据封装-dataconfig

自定义按钮类-mypushbutton

2.难点记录

    01.跳转设置新窗打开位置属性

        跳转时设置新窗体的geometry属性和本窗体相同,这样设置会解决窗体移动过后,打开的新窗体和旧窗体位置不同的bug;

    02.创建新窗体,初始化属性

        //设置固定大小,并且让窗体无法被更改

        setFixedSize(320, 588);

        //设置应用图标

        setWindowIcon(QPixmap(":/res/Coin0001.png"));

        //设置窗口标题

        setWindowTitle("选择关卡");

        //设置菜单栏

        QMenuBar * qMenuBar = menuBar();

        QAction * qAction = qMenuBar->addMenu("开始")->addAction("退出");

        this->setMenuBar(qMenuBar);

        //点击退出完成程序退出

        connect(qAction , &QAction::triggered, [=](){

            this->close();

        });

    重写窗体的画家事件,绘制窗体的背景图

    void ChooseLevelScene::paintEvent(QPaintEvent *event)   

    {

        //绘制背景图

        QPainter qPainter(this);

        QPixmap qPixmap;

        qPixmap.load(":/res/PlayLevelSceneBg.png");

        //绘制背景图

        qPainter.drawPixmap(0,0,this->width(),this->height(),qPixmap);

        //绘制左上角游戏名称

        qPixmap.load(":/res/Title.png");

        qPainter.drawPixmap(20,30,qPixmap.width(),qPixmap.height(),qPixmap);

    }

03.定时器QTimer使用

    Qt的定时器实现有两种,一个是重写定时事件(没使用过不清楚),另一个就是使用QTimer的静态方法:

    //500是延迟多少时间执行代码,单位是毫秒

    //[=](){ ... }    Lamda表达式(很屌,推荐学习而且使用不难)

    QTimer::singleShot(500, this, [=](){

        //operator code

    });

04.事件穿透设置上下对齐居中

    选择关卡时绘制关卡是通过自定义按钮MyPushButton进行绘制,显示关卡名称是通过QLabel相同大小覆盖在自定义按钮上。

    此时点击时无法触发自定义按钮上选择关卡后的操作,可使用鼠标点击事件穿透设置到QLabel上,label->setAttribute(Qt::WA_TransparentForMouseEvents);这时鼠标点击后QLabel不会阻拦点击事件,可以正常触发自定义按钮。

    在QLabel中设置text后默认时居左,设置上下左右对齐居中,label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);

05.设置开始游戏按钮的点击下沉弹回的动画

    //图标下沉

    void MyPushButton::zoom1()

    {

        QPropertyAnimation * animation1 = new QPropertyAnimation(this, "geometry");

        //设置事件间隔

        animation1->setDuration(200);

        //设置起始位置

        animation1->setStartValue(QRect(this->x(), this->y(), this->width(), this->height()));

        animation1->setEndValue(QRect(this->x(), this->y()+10, this->width(), this->height()));

        //设置动画,弹跳式,类似弹性球

        animation1->setEasingCurve(QEasingCurve::OutBounce);

        animation1->start();

    }

    //图标上浮

    void MyPushButton::zoom2()

    {

        QPropertyAnimation * animation1 = new QPropertyAnimation(this, "geometry");

        //设置事件间隔

        animation1->setDuration(200);

        //设置起始位置

        animation1->setStartValue(QRect(this->x(), this->y()+10, this->width(), this->height()));

        animation1->setEndValue(QRect(this->x(), this->y(), this->width(), this->height()));

        //设置动画,弹跳式,类似弹性球

        animation1->setEasingCurve(QEasingCurve::OutBounce);

        animation1->start();

    }

    //给start按钮绑定点击事件

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

        btn_start->zoom1();

        btn_start->zoom2();

        //点击音效

        startSound->play();

        //延时0.5秒执行切换,展示start按钮的动效

        QTimer::singleShot(500, this, [=](){

            chooseLevel->setGeometry(this->geometry());

            this->hide();

            chooseLevel->show();

        });

    });

06.绘制一个4*4的选择关卡矩阵,不使用双层for循环的前提下,一个for循环完成绘制

    //创建关卡选择icon

    for(int i = 0; i < 20 ; i++)

    {

        MyPushButton * levelIcon = new MyPushButton(":/res/LevelIcon.png");

        levelIcon->setParent(this);

        levelIcon->move(25 + (i%4)*70 , 160 + (i/4)*70);

    }

* x轴:25 + (i%4)*70    25为偏移量,70是每个矩阵x轴大小,i%4在第一行0、1、2、3四列,每一行计算的值是0*70、1*70、2*70、3*70;

*y轴:160 + (i/4)*70    160为偏移量,70是每个矩阵y轴大小,i/4在第一列0、1、2、3四行,每一行计算的值是0*70、1*70、2*70、3*70;

*在记录其中每一个金币的坐标时,构建了新的二维数组保存位置信息,因为这种构建不太好保存位置信息

成品截图
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容