Tom*_*hor 3 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);
}
Run Code Online (Sandbox Code Playgroud)
QPainterPath QGraphicsItem::shape() const
Run Code Online (Sandbox Code Playgroud)
以本地坐标中的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;
}
Run Code Online (Sandbox Code Playgroud)
......并在现场进行:
if (circCollide(this, collidingItems())) ... we have a collision
Run Code Online (Sandbox Code Playgroud)