Qt - 碰撞检测的圆 [英] Qt - circles for collision detection

查看:2074
本文介绍了Qt - 碰撞检测的圆的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在使用Qt中的圆圈进行物理模拟。到目前为止,定义圆的最简单的方法是找到一个 QRect 对象,然后绘制椭圆与该矩形作为蓝图。现在我只是有一个问题,它画一个圆,但命中检测的命中框仍然是一个正方形,这看起来相当尴尬。我迄今为止找不到解决方案,希望在这里找到一些帮助。

I've been working on a physics simulation with circles in Qt. Thus far the easiest way to define circles I found is to make a QRect object and then draw the ellipse with that rectangle as a "blueprint". Now I've just got the problem that it paints a circle but the hit box for the hit detection is still a square, which looks rather awkward. I've not been able to find a solution for it thus far and hope to find some help here.

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);
}


推荐答案

QPainterPath QGraphicsItem::shape() const




作为本地坐标中的QPainterPath。
形状用于许多事情,包括碰撞检测,命中
测试和QGraphicsScene :: items()函数。

Returns the shape of this item as a QPainterPath in local coordinates. The shape is used for many things, including collision detection, hit tests, and for the QGraphicsScene::items() functions.

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

The default implementation calls boundingRect() to return a simple rectangular shape, but subclasses can reimplement this function to return a more accurate shape for non-rectangular items.

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

For fine collision detection you have to use:

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

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

which you can also reimplement, because checking for collision between circles is faster than checking painterpaths for intersection.

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

I haven't used that myself, but it seems like the function you use will only give you "coarse detection" so then you must manually check if any of those actually intersect with the fine grained method. This saves on performance, you use the rough check to isolate potential collision candidates, and then check only those items using the slower method. In your case it is not a convenience, because a circle collision test would be as fast, if not faster than the bounding box test, but that's how Qt is designed. Ideally, you should be able to pass your own collision detection function to collidingItems().

最少,一旦你得到 collidingItems 列表,你可以很容易地检查现场的圆碰撞,而不使用 shape() collidesWithItem() ...它会节省你一些CPU时间从不必调用额外的虚拟函数,加上重新实现这些...的时间...

Also last but not least, once you get the collidingItems list you can easily check for circle collisions on the spot, without using shape() and collidesWithItem()... It will actually save you some CPU time from not having to call extra virtual functions, plus the time to reimplement those...

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

So you can use something like this:

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;
}

...并且现场执行:

... and do it on the spot:

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

这篇关于Qt - 碰撞检测的圆的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆