实现碰撞开机动画的效果,要用到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()<<"停止";
}
这样就实现了碰撞开机动画的效果,碰撞结束后续还可以自己添加界面跳转等;
如果对你有帮助,欢迎点赞留言讨论哦!