Qt实战之接金币小游戏

zyg 3年前 (2021-12-03) 阅读数 2189 #GUI开发

自学了大概两个月Qt,今天做了一个小小的项目,参照书为Qt图形界面编程入门(清华大学仇国巍编著),本次项目主要是为了实现一个以接金币目的的小游戏,主要包括图片导入,大小规划,Qt重新绘图Event,鼠标事件和定时器事件的使用,使用随机数生成金币,界面是这样的:屏幕截图 2021-12-03 162508.jpg

代码主要有以下部分:

H文件:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QLabel>


struct Money{
    QRect rc;//金币位置矩形
    int Value;//分数
    int type;//-1 隐藏 0:5分 1:10分 2:20分
};


class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
    QRect pplRect;//包含人物的矩形
    //人物 背景位图 以及分数 剩余时间背景位图
    QPixmap picPPL,picBack,picScore,picTime;
    //三种分数的位图
    QPixmap goldPic[3];
    //最多产生200个各种金币
    Money gold[200];
    //定时器编号,第一个用于倒计时,后三个用于控制金币产生和下落
    int timer0,timer1,timer2,timer3;
    //现有金币数
    int numOfCoins;
    //下一次产生金币前调用函数次数,分数,秒表
    int interval,score,stopWatch;
protected:
    void paintEvent(QPaintEvent *);
    void keyPressEvent(QKeyEvent *e);
    void timerEvent(QTimerEvent * event);
};
#endif // WIDGET_H

C文件,包括构造函数,定时器事件,鼠标时间以及重绘事件:

#include "widget.h"
#include <QDebug>
#include <ctime>
#include <QPainter>
#include <QKeyEvent>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    //加载背景位图
    picBack.load(":/prj1/bg.jpeg");
    picBack = picBack.scaled(650,500,Qt::IgnoreAspectRatio,Qt::FastTransformation);
    //加载人物背景位图
    picPPL.load(":/prj1/1.png");
    picPPL = picPPL.scaled(100,100,Qt::IgnoreAspectRatio,Qt::FastTransformation);
    pplRect = QRect(5,400,picPPL.width(),picPPL.height());
    //加载分数背景位图
    picScore.load(":/prj1/5.png");
    picScore = picScore.scaled(100,100,Qt::IgnoreAspectRatio,Qt::SmoothTransformation);
    picTime.load(":/prj1/time.png");
    picTime = picTime.scaled(100,100,Qt::IgnoreAspectRatio,Qt::SmoothTransformation);
    goldPic[0].load(":/prj1/2.png");
    goldPic[0] = goldPic[0].scaled(30,30,Qt::IgnoreAspectRatio,Qt::SmoothTransformation);
    goldPic[1].load(":/prj1/3.png");
    goldPic[1] = goldPic[1].scaled(50,50,Qt::IgnoreAspectRatio,Qt::SmoothTransformation);
    goldPic[2].load(":/prj1/4.png");
    goldPic[2] = goldPic[2].scaled(100,100,Qt::IgnoreAspectRatio,Qt::SmoothTransformation);
    //创建并且启动定时器
    timer0=this->startTimer(1000);
    timer1=this->startTimer(300);
    timer2=this->startTimer(700);
    timer3=this->startTimer(1400);
    //实际获得的金币数量
    numOfCoins = 0;
    //使得产生的随机序号每次不同
    srand(time(0));
    interval = 0;
    //分数
    score = 0;
    //剩余时间
    stopWatch = 90;
    setFocusPolicy(Qt::StrongFocus);
    resize(picBack.width(),picBack.height());
}

Widget::~Widget()
{
}


void Widget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    //绘制背景位图
    painter.drawPixmap(0,0,picBack.width(),picBack.height(),picBack);
    painter.drawPixmap(0,0,picScore.width(),picScore.height(),picScore);
    painter.drawPixmap(picBack.width()-picTime.width(),0,
                       picTime.width(),picTime.height(),picTime);
    //卡通人物
    painter.drawPixmap(pplRect,picPPL);
    //绘制金币
    for(int i = 0;i < numOfCoins;i ++)
    {
        if(gold[i].type >= 0)
            painter.drawPixmap(gold[i].rc,goldPic[gold[i].type]);
    }
    QFont font(tr("微软雅黑"),15,QFont::Normal,false);
    painter.setFont(font);
    QRect rect(62,18,50,18);
    painter.drawText(rect,Qt::AlignCenter,QString::number(score)+ "分");
    QRect rect2(593,18,50,18);
    painter.drawText(rect2,Qt::AlignCenter,QString::number(stopWatch)+ "秒");
}

void Widget::keyPressEvent(QKeyEvent *e)
{
    switch (e->key())
    {
        case(Qt::Key_Left):
        {
            if(pplRect.left() >= 20)//没有超出左边界
            {
                int x = pplRect.left() - 20;
                pplRect.moveLeft(x);
            }
            update();
            break;
        }
        case(Qt::Key_Right):
        {
            if(pplRect.right() <= (picBack.width() - 20))//没有超出边界
            {
                int x = pplRect.right() + 20;
                pplRect.moveRight(x);
            }
            update();
            break;
        }
    }
    QWidget::keyPressEvent(e);

}


void Widget::timerEvent(QTimerEvent * event)
{
    if(numOfCoins >= 200) return;
    if(event->timerId() == timer0)
    {
        stopWatch --;
        return;
    }
    if(stopWatch == 0)
    {
        killTimer(timer0);
        killTimer(timer1);
        killTimer(timer2);
        killTimer(timer3);
    }
    //处理金币消失的情况
    for(int i = 0;i < numOfCoins;i ++)
    {
        if(gold[i].type != -1 && pplRect.intersects(gold[i].rc))
        {
            score = score + gold[i].Value;
            gold[i].type = -1;
        }
        if(gold[i].type != -1 && pplRect.bottom() < gold[i].rc.top())
        {
            gold[i].type = -1;
        }
    }
    //处理金币移动
    for(int i = 0;i < numOfCoins;i ++)
    {
        int y;
        if(gold[i].type == 0)
            y = gold[i].rc.top() + 10;
        if(gold[i].type == 1)
            y = gold[i].rc.top() + 18;
        if(gold[i].type == 2)
            y = gold[i].rc.top() + 26;
        gold[i].rc.moveTop(y);
    }
    //若interval大于0,返回
    if(interval > 0)
    {
        interval --;
        update();
        return;
    }
    //若interval等于0,则产生金币
    //产生第一种分数
    if(event->timerId() == timer1)
    {
        //随机产生横坐标
        int x = rand() % (picBack.width() - goldPic[0].width() - 20) + 10;
        gold[numOfCoins].type = 0;
        gold[numOfCoins].rc = QRect(x,77,goldPic[0].width(),goldPic[0].height());
        gold[numOfCoins].Value = 5;
        numOfCoins++;
    }
    //产生第二种分数
    if(event->timerId() == timer2)
    {
        //随机产生横坐标
        int x = rand() % (picBack.width() - goldPic[0].width() - 20) + 10;
        gold[numOfCoins].type = 1;
        gold[numOfCoins].rc = QRect(x,77,goldPic[1].width(),goldPic[1].height());
        gold[numOfCoins].Value = 10;
        numOfCoins++;
    }
    //产生第三种分数
    if(event->timerId() == timer3)
    {
        //随机产生横坐标
        int x = rand() % (picBack.width() - goldPic[0].width() - 20) + 10;
        gold[numOfCoins].type = 2;
        gold[numOfCoins].rc = QRect(x,77,goldPic[2].width(),goldPic[2].height());
        gold[numOfCoins].Value = 20;
        numOfCoins++;
    }
    //再次产生间隔次数3~5
    interval=rand()%3 + 3;
    update();
}

Qt大概学了个一知半解,准备去肝图像处理了。

版权声明

本文仅代表作者观点。
本文系作者发表,未经许可,不得转载。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

yanguo

yanguo

管理员
作者文章
最新文章
标签列表
    欢迎你第一次访问网站!