QT5-实现小球运动碰撞

QT实现小球运动碰撞反弹

    • 思路
    • 结构
    • 设置运动速度
    • 画出小球
    • BoundingRect和Shape函数
    • 运动和碰撞反弹

编程工具为vs2010+qt 5.1.2

思路

由于第一次刚使用qt,所以就写写博客分享一个qt新手从入门到放弃这个过程。

这个小设计使用QT中的QGraphics框架,这个框架适用于2D图像和动画的操作,包括各种变换以及检测等,而在其中的Colliding函数对于碰撞检测这一功能的实现非常简单。

结构

  QRectF boundingRect() const;
  void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
             QWidget *widget);
  QPainterPath shape() const;
  void setSpeed(qreal i,qreal j);        //速度
  void advance(int phase);  

私有成员有X,Y方向上的运动速度。

设置运动速度

这里采用QDialog对话框获取速度,再通过函数setSpeed设置物体的速度。

    QString Xspeed = QInputDialog::getText(NULL, " item Xspeed",
                                                   "Please input your item XSpeed",
                                                   QLineEdit::Normal,
                                                   "Xspeed Input",
                                                   &isOK);
    QString Yspeed = QInputDialog::getText(NULL, " item Yspeed",
                                                   "Please input your item YSpeed",
                                                   QLineEdit::Normal,
                                                   "Yspeed Input",
                                                   &isOK);
    qreal xspeed = Xspeed.toDouble( );
	qreal yspeed = Yspeed.toDouble( );
	setSpeed( xspeed , yspeed );

画出小球

painter->drawEllipse(pos().x(),pos().y(),radius*2,radius*2);

BoundingRect和Shape函数

boundingRect函数是返回包含Item的最小矩形,一般用于绘图和碰撞检测。而shape函数与boundingrect函数类似,但是shape更为精确,因为shape返回的是PainterPath而boundingRect返回的是一个矩形。

QRectF MyItem::boundingRect() const
{
    qreal penWidth = 1;
    return QRectF(pos().x() - penWidth / 2, pos().y() - penWidth / 2,
                  radius*2 + penWidth, radius*2 + penWidth);
}

QPainterPath MyItem::shape() const
{
    QPainterPath path;
	path.addEllipse( pos().x() , pos().y() , radius*2 , radius*2 );  //图形项的真实大小
    return path;
}

运动和碰撞反弹

运动函数利用advance和计时器就可以实现,反弹就要使用colliding函数和坐标计算判断。

void MyItem::advance( int phase )
{
    if(!phase) return;  //如果phase为0,则结束
	qreal x=this->pos().x();//更新位置
	qreal y=this->pos().y();
	if(y<=0||y+radius>=SceneHeight/2)//碰撞Y方向的墙
	{
		yspeed*=-1;
	}
	else 	if(x<=0||x+radius>=SceneWidth/2) //碰撞X方向的墙
	{
		xspeed*=-1;
	}
   
   if(!collidingItems().isEmpty()) //碰撞检测
	{
		xspeed*=-1;
		yspeed*=-1;
	}
		moveBy( xspeed , yspeed  );	
}

遗憾没有实现边界和视图窗口的自适应,就是拉大视图,小球的运动边界也改变。
不知道怎么实现这个功能~


2019.11.7:
可以通过重写ResizeEvent事件来实现上述窗口的自适应功能。
ps:
QGraphicsView::ResizeEvent函数已实现,需要继承GraphicsView来重写resizeEvent函数。

void QGraphicsView::resizeEvent(QResizeEvent *event)
{
	SceneHeight=this->height();
    SceneWidth =this->width();
}

参考文档

你可能感兴趣的:(QT)