QT实现打地鼠小游戏

看吴健吴老师的视频做了一个打地鼠的小游戏,主要利用了qt中的2D显示器QGraphicsView,
QGraphicsScence场景,以及图元QgraphicsItem下的像素图元QGraphicsPixmapItem。
关系为一个个图元构成场景,场景显示在显示器中。

##效果如下(手机)
在这里插入图片描述
图元类
图元类主要设置每个图元上的图片是什么,该图元的状态(开始状态和暂停、停止状态),以及该图元上是否有老鼠(通过一个bool类型的成员变量来决定);图元类还需要设置置鼠标的状态为一个锤子;图元类还需要重写父类的基类QGraphicsItem中的鼠标按压事件和鼠标抬起事件。当鼠标按下时,如果在开始状态下该图元的mouse变量为true(有老鼠),则 说明打到了老鼠,此时利用获取到的单例对象向mainwindow发送一个beat信号,更新lcdnumber上的分数。

#include "myitem.h"
#include <QDebug>
myitem::myitem()
{
    this->setPixmap(QPixmap(":/pic/2"));//默认背景图片
    mouse = false;//没有老鼠
    start = false;//没开始
    this->setCursor(QCursor(QPixmap(":/pic/up1.png")));//鼠标为锤子抬起形态
}

void myitem::setpic(QString path) //用于设置该图元的图片
{
    this->setPixmap(QPixmap(path));
}

void myitem::setmouse(bool m) //设置该图元上是否有老鼠
{
    this->mouse = m;
}

bool myitem::ismouse()//返回该图元上是否有老鼠
{
    return this->mouse;
}

 void myitem::mousePressEvent(QGraphicsSceneMouseEvent *event)//鼠标点击事件重写,继承自父类QGraphicItem
 {
     this->setCursor(QCursor(QPixmap(":/pic/down.png")));//鼠标点击锤子落下
     if(this->start)//判断是否是开始状态
     {
         if(ismouse())//判断是否有老鼠
         {
             this->setPixmap(QPixmap(":/pic/3"));//设置该图元为击中效果
             score* s = score::getscore();//获取单例对象
             s->addscore();//通知加分
         }
     }
 }

 void myitem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)//鼠标释放事件,锤子抬起
 {
     this->setCursor(QCursor(QPixmap(":/pic/up1.png")));
 }
 void myitem::setstart(bool m)//设置是否为开始状态
 {
     this->start = m;
 }
 bool myitem::isstart()
 {
     return this->start;
 }

场景类
场景类首先要进行背景的布局,将图元添加进场景并且依次排列成4*4的矩阵。然后需要设置定时器让游戏动起来。然后设置开始、暂停、停止三个按钮的槽函数(主要是改变定时器的状态)。

#include "myscene.h"

myScenr::myScenr(QObject *parent) : QGraphicsScene(parent)
{
    int i = 0;
    for(i = 0;i<16;i++)//在该场景上添加(4*4)个图元
    {
        itm[i] = new myitem;
        itm[i]->setPos(i/4 * itm[i]->boundingRect().width(),i%4 * itm[i]->boundingRect().height());
        this->addItem(itm[i]);//依次添加进场景
    }
    this->life_time = 2000;//初始化老鼠刷新时间
    this->mouse_count = 4;//初始化每次刷新的最大数量
    pt = new QTimer(this);//刷新老鼠的定时器
    ppt = new QTimer(this);//更新老鼠刷新速度和数量定时器
    connect(pt,SIGNAL(timeout()),this,SLOT(showmouse()));
    connect(ppt,SIGNAL(timeout()),this,SLOT(change_time()));
}

void myScenr::showmouse()//老鼠出动
{
    int count = rand()%this->mouse_count+1;//随机数获取出现几只老鼠
    int i = 0;
    for( i = 0;i<16;i++)//老鼠出现之前上一波老鼠回洞
    {
        itm[i]->setpic(":/pic/2");
        itm[i]->setmouse(false);
    }
    for(i = 0;i < count;i++)
    {
        int pos = rand()%16;//随机数获取老鼠出现在那个图元
        itm[pos]->setpic(":/pic/4");
        itm[pos]->setmouse(true);
    }
}

void myScenr::change_time()//改变刷新速度和数量
{
    this->life_time -= 500;//每30s将刷新时间减小0.5s,一局游戏控制在2min
    this->mouse_count += 2;
    if(this->life_time == 0)//如果时间耗尽,发送finshed信号
    {
        emit finshed();
    }
}

void myScenr::start()//开始
{
    int i = 0;
    for( i = 0;i<16;i++)
    {
        itm[i]->setstart(true);//设置每一个图元的start状态
    }
    ppt->start(30000);//启动定时器
    pt->start(this->life_time);
}

void myScenr::spause()//暂停
{
    pt->stop();
    ppt->stop();
    int i = 0;
    for( i = 0;i<16;i++)
    {
        itm[i]->setstart(false);
    }
}

void myScenr::stop()//停止
{
   pt->stop();
   ppt->stop();
   this->life_time = 2000;
   this->mouse_count = 4;
   int i = 0;
   for( i = 0;i<16;i++)
   {
       itm[i]->setpic(":/pic/2");
       itm[i]->setmouse(false);
       itm[i]->setstart(false);
   }
   emit clear();//向mainwindow发送停止清空分数信号
}

#单例
因为是否打到老鼠是在图元上判断的,而分数的显示则在mainwindow里。所以设计了一个单例对象让图元和mainwindow都可以获取到同一个对象。图元类利用该对象发送beat信号,mainwindow则关联beat信号和用来更新分数的槽函数。

#include <QObject>
//单例
class score : public QObject
{
    Q_OBJECT
public:
    static score* getscore();
    void addscore();
private:
    explicit score(QObject *parent = nullptr);

signals:
    void beat();//砸到老鼠后通知mainwindow加分

public slots:
private:
    static score *s;
};

#mainwindow
mainwindow主要将场景加入显示器、并设置弹窗(重写关闭事件的函数、和一局游戏结束后的弹窗)、以及背景音乐的播放。

#源码地址
https://gitee.com/hou_yuan_hao/whacamole

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值