Qt – круги для обнаружения столкновений

Я работал над физическим моделированием с кругами в 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); } 

     QPainterPath QGraphicsItem::shape() const 

    Возвращает форму этого элемента как QPainterPath в локальных координатах. Форма используется для многих вещей, включая обнаружение столкновений, тесты ударов и функции QGraphicsScene :: items ().

    Реализация по умолчанию вызывает boundingRect (), чтобы вернуть простую прямоугольную форму, но подclassы могут переопределить эту функцию, чтобы вернуть более точную форму для непрямоугольных элементов .

    Для обнаружения мелкого столкновения вам необходимо использовать:

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

    которые вы также можете переопределить, потому что проверка на столкновение между кругами быстрее, чем проверка painterpaths для пересечения.

    Я сам этого не использовал, но, похоже, функция, которую вы используете, даст вам «грубое обнаружение», поэтому вы должны вручную проверить, действительно ли кто-то из них пересекается с мелкозернистым методом. Это экономит производительность, вы используете грубую проверку, чтобы изолировать потенциальных кандидатов на столкновение, а затем проверять только те элементы, используя более медленный метод. В вашем случае это не удобство, потому что тест столкновения с кругом будет таким же быстрым, если не быстрее, чем тест с ограничивающей коробкой, но именно так разработан Qt. В идеале вы должны иметь возможность передавать свою собственную функцию обнаружения столкновений в collidingItems() .

    Кроме того, последнее, но не менее важное: после того, как вы получите список collidingItems вы можете легко проверить наличие столкновений с кругами на месте, не используя shape() и collidesWithItem() … Это фактически избавит вас от некоторого времени процессора от необходимости не вызывать дополнительные виртуальные функции, а также время для их повторного использования …

    Поэтому вы можете использовать что-то вроде этого:

     inline bool circCollide(QGraphicsItem * item, QList 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 

    Прочитайте документацию! Просто выкопайте документацию базового classа и его предков. См. QGraphicsItem :: содержит и форму

    Еще кое-что. Существует class QGraphicsEllipseItem, поэтому большая часть необходимых вам функций должна быть покрыта там.