Qt - 用于碰撞检测的圆圈

时间:2015-08-11 13:17:55

标签: c++ qt collision-detection qpainter

我一直在用Qt中的圆圈进行物理模拟。到目前为止,我发现定义圆的最简单方法是创建一个QRect对象,然后用该矩形绘制椭圆作为“蓝图”。现在我遇到的问题是它画了一个圆圈,但是命中检测的命中框仍然是一个正方形,看起来很尴尬。到目前为止,我还没能找到解决方案,希望能在这里找到一些帮助。

QRectF Ball::boundingRect() const
{    
  return QRect(0,0,20,20);
}
void Ball::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    QRectF rec = boundingRect();
    QBrush Brush(Qt::gray);

    //basic Collision Detection

    if(scene()->collidingItems(this).isEmpty())
    {
        //no collision
        Brush.setColor(Qt::green);
    }
    else
    {
        //collision!!!!!
        Brush.setColor(Qt::red);

        //Set position
        DoCollision();
    }

    //painter->fillEllipse(rec,Brush);
    painter->drawEllipse(rec);
}

2 个答案:

答案 0 :(得分:6)

QPainterPath QGraphicsItem::shape() const
  

以本地坐标中的QPainterPath形式返回此项的形状。   形状用于许多事情,包括碰撞检测,命中   测试,以及QGraphicsScene :: items()函数。

     

默认实现调用boundingRect()返回一个简单的   矩形形状,但子类可以重新实现此功能   为非矩形项目返回更准确的形状

对于精细碰撞检测,您必须使用:

bool QGraphicsItem::collidesWithItem(const QGraphicsItem * other, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const

你也可以重新实现,因为检查圆之间的碰撞比检查交叉的画家路径要快。

我自己还没有使用它,但看起来你使用的功能只会给你"粗略检测"所以你必须手动检查是否有任何实际上与细粒度方法相交的。这样可以节省性能,使用粗略检查来隔离潜在的碰撞候选,然后使用较慢的方法仅检查这些项目。在你的情况下,这不是一个方便,因为圆形碰撞测试会比边界框测试快,如果不快,但这就是Qt的设计方式。理想情况下,您应该能够将自己的碰撞检测功能传递给collidingItems()

同样最后但并非最不重要的是,一旦获得collidingItems列表,您就可以轻松地在现场检查圆圈碰撞,而无需使用shape()collidesWithItem() ...它实际上会保存你需要一些CPU时间,而不必调用额外的虚函数,加上重新实现这些功能的时间......

所以你可以使用这样的东西:

inline bool circCollide(QGraphicsItem * item, QList<QGraphicsItem *> items) {
    QPointF c1 = item->boundingRect().center();
    foreach (QGraphicsItem * t, items) {
        qreal distance = QLineF(c1, t->boundingRect().center()).length();
        qreal radii = (item->boundingRect().width() + t->boundingRect().width()) / 2;
        if ( distance <= radii ) return true; 
    }
    return false;
}

...并在现场进行:

if (circCollide(this, collidingItems())) ... we have a collision

答案 1 :(得分:2)

阅读文档!只需挖掘基类及其祖先的文档。 请参阅QGraphicsItem::containsshape

还有一件事。有一个班级QGraphicsEllipseItem,所以你需要的大部分功能都应该包含在那里。