【Qt】GraphicsView框架结构的碰撞开机动画实现流程

实现碰撞开机动画的效果,要用到QT中的图形视图框架,也就是Graphics View框架结构;该结构的三要素分别是图元,场景和视图;场景类提供了一个用于管理位于其中的众多图元容器,视图类用于显示场景中的图元,一个场景可以通过多个视图表现。

1.自定义图元

基本的图元类无法满足我们需要的动画图片,所以我们自定义一个图元,用来读取要插入的图片;

继承QObject和QGraphicsItem图元类;

因为QGraphicsItem中这两个函数是纯虚函数,所以自定义图元主要就是实现这两个函数,分别是设置图片的边界和绘制图元;

自定义图元还需要从本地获取图片,所以需要

QString filename;设置图片路径
QPixmap pix;图片容器
type因为需要碰撞,这边插入了两个图片,用type作区分哪个是左哪个是右边的图片
MyItem::MyItem(QString filename,int type)
{
    this->type=type;
    pix.load(filename);
}

QPixmap MyItem::getPix()
{
    return this->pix;
}

QRectF MyItem::boundingRect() const
{
    return QRectF(0-pix.width()/2,0-pix.height()/2,pix.width(),pix.height());
}

void MyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    painter->drawPixmap(0-pix.width()/2,0-pix.height()/2,pix.width(),pix.height(),pix);
}

2.创建图元,视图和场景

我这边是创建了一个自定义视图类继承QGraphicsView,用来存放所有需要的图元和场景,方便操作;

①设置场景

Scene = new QGraphicsScene(0,0,500,600);

场景的坐标设置为(0,0),就可以与视图的坐标体系(以窗口左上角为原点)统一,方便看位置

②创建图元

Item1 = new MyItem("icon/9.png",typeenum::LEFT);//创建图元
Item2 = new MyItem("icon/18.png",typeenum::RIGHT);//创建图元
Item1->setPos(100,150);//设置位置
Item2->setPos(400,150);
Scene->addItem(Item1);
Scene->addItem(Item2);
this->setScene(Scene);//视图关联场景

③添加图元到场景中,视图关联场景

3.移动图元

Qt中有提供一个用于移动图元的虚函数advance(),x为正则向右移动,x为负则向左移动,y同理;

timer = new QTimer(this);
connect(timer,SIGNAL(timeout()),Scene,SLOT(advance()));//移动
timer->start(1000);

connect在自定义视图中定义,用定时器进行多次、自动地调用advance函数;

advance是在自定义图元中定义的,因为要根据图元的type类型判断哪个是左哪个是右并进行moveBy移动;

void MyItem::advance(int phase)
{
    if(phase !=0)//phase是系统自带的;会调用两次一次=0,一次=1
    {
        return;
    }
    else if(!collidingItems().empty())//不为空,说明碰撞了
    {
        qDebug()<<"碰撞";
        emit bangSign();
    }
    else if(this->type == typeenum::LEFT)//左边那个
    {
        moveBy(40,0); //向右移动
    }
    else if(this->type == typeenum::RIGHT)
    {
        moveBy(-40,0); //向左移动
    }

4.碰撞检测

在上图中有一个Qt提供的collidingItems()可以进行碰撞检测,它的返回值是一个QList链表,如果

它不为空就说明碰撞了;

此时就可以关掉定时器,bangSign()是我自定义的一个信号,在advance中碰撞后emit发出该信号;bangSign()可以不用在源文件中实现

connect(Item1,SIGNAL(bangSign()),this,SLOT(timeStopSlot())); //碰撞后关闭定时器
void MyViem::timeStopSlot()
{
    timer->stop();
    qDebug()<<"停止";
}

这样就实现了碰撞开机动画的效果,碰撞结束后续还可以自己添加界面跳转等;

如果对你有帮助,欢迎点赞留言讨论哦!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

logani

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值