将boundingRect()映射到父项并相交会产生意外的碰撞处理结果

问题描述 投票:0回答:1

这是我如何处理两个图形项的碰撞。它在mouseMoveEvent以及itemChange中被调用。像这样:

void GraphicsItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    auto delta = event->pos() - event->lastPos();
    auto new_pos = handleCollisions(pos() + delta);
    setPos(new_pos);
}

new_pos事情是这样我可以在itemChange中调用它并将其作为值返回。但是,此版本的碰撞处理使new_pos保持不变。相反,我们移动与此碰撞的物品(因为我们通过鼠标移动它)。我试图采取两个相关的边界的交叉点,并将另一个移动到矩形交叉点的较短维度。结果是出乎意料的是,矩形不会移动那么少的数量,而是移动到任何boundingRects()的整个宽度(或高度)(它们的大小相同)。我已经跟踪到了这一点,所以下面的代码计算父级位置空间中的边界值的交集(其中pos(),setPos()是相对的)是错误的。

那么我该怎么办呢?

这是我想要的图片:enter image description here

QPointF GraphicsItem::handleCollisions(const QPointF& new_pos) const {
    auto collisions = collidingItems();
    auto rect = mapToParent(boundingRect().translated(new_pos - pos())).boundingRect();
    for(int k=0; k < collisions.count(); k++)
    {
        auto item = collisions[k];
        if (item->parentItem() == parentItem()) {
            auto rect1 = mapToParent(item->boundingRect()).boundingRect();
            rect1 = rect1.intersected(rect);
            qDebug() << (rect1.width());
            qDebug() << (rect1.height());
            auto v = rect1.center() - rect.center();
            if (v.x() >= 0) {
                if (v.y() >= 0) {
                    if (rect1.width() <= rect1.height())
                        item->setPos(item->pos() + QPointF(-rect1.width(), 0));
                    else
                        item->setPos(item->pos() + QPointF(0, -rect1.height()));
                }
                else {
                    if (rect1.width() <= rect1.height())
                        item->setPos(item->pos() + QPointF(rect1.width(), 0));
                    else
                        item->setPos(item->pos() + QPointF(0, rect1.height()));
                }
            }
            else {
                if (v.y() >= 0) {
                    if (rect1.width() <= rect1.height())
                        item->setPos(item->pos() + QPointF(rect1.width(), 0));
                    else
                        item->setPos(item->pos() + QPointF(0, -rect1.height()));
                }
                else {
                    if (rect1.width() <= rect1.height())
                        item->setPos(item->pos() + QPointF(rect1.width(), 0));
                    else
                        item->setPos(item->pos() + QPointF(0, rect1.height()));
                }
            }
        }
    }
    return new_pos;     // return this position unchanged
}
qt 2d collision-detection rectangles affinetransform
1个回答
0
投票

我找到了。

item->mapToParent(...)

代替

mapToParent(...)

应该在循环中调用。

© www.soinside.com 2019 - 2024. All rights reserved.