Хотя этому вопросу больше года, я недавно столкнулся с подобной проблемой. Благодаря небольшому исследованию TRectF
(используется примитивами FMX и FM2), я придумал следующую очень простую функцию:
var
aRect1, aRect2 : TRectF;
begin
aRect1 := Selection1.AbsoluteRect;
aRect2 := Selection2.AbsoluteRect;
if System.Types.IntersectRect(aRect1,aRect2) then Result := True else Result := False;
end;
Самоочевидно, но если 2 прямоугольника / объекта пересекаются или перекрываются, то результат равен true.
Альтернатива - та же процедура, но уточненный код
var
aRect1, aRect2 : TRectF;
begin
aRect1 := Selection1.AbsoluteRect;
aRect2 := Selection2.AbsoluteRect;
result := System.Types.IntersectRect(aRect1,aRect2);
end;
Вам нужно будет поработать над ним, чтобы принять некоторые входные объекты (в моем случае я использовал TSelection
, известные как Selection1 и Selection2) и, возможно, найти способ добавить смещение (взгляните на TControl.GetAbsoluteRect
в FMX.Types
), но теоретически он должен работать практически с любым примитивом или любым элементом управления.
Так же, как дополнительное примечание, для таких объектов используется множество TRectF
;
AbsoluteRect
BoundsRect
LocalRect
UpdateRect
(может не относиться к данной ситуации, требуется расследование)
ParentedRect
ClipRect
ChildrenRect
Важно использовать тот, который наиболее подходит для вашей ситуации (поскольку результаты будут сильно отличаться в каждом случае). В моем примере TSelection
были дочерними элементами формы, поэтому использование AbsoluteRect
было очень лучшим выбором (так как LocalRect
не вернул правильные значения).
Реально, вы могли бы перебирать каждый дочерний компонент вашего родителя, чтобы иметь возможность выяснить, есть ли конфликт между любым из них и потенциально, вы могли бы создать функцию, которая точно скажет вам, какие из них сталкиваются (хотя для этого, вероятно, потребуется рекурсивная функция).
Если вам когда-нибудь понадобится разобраться с «базовой физикой», при которой обнаружение столкновений будет считаться единым (по крайней мере, в этом случае, это базовый уровень) в Firemonkey, тогда вам нужно обратиться к TRectF
, В System.Types
(XE3 и, скорее всего, XE2) встроено множество подпрограмм для автоматического решения этого вопроса, поэтому вы можете избежать математических операций, обычно связанных с этой проблемой.
Дополнительные примечания
Что-то, что я заметил, было то, что процедура выше не была очень точной и имела несколько пикселей. Одно из решений состоит в том, чтобы поместить вашу форму в родительский контейнер с выравниванием alClient
, а затем с отступом в 5 пикселей по всем сторонам. Затем вместо измерения на TSelection.AbsoluteRect
измерьте на AbsoluteRect
.
дочернего объекта.
Например, я поместил TCircle
внутри каждого TSelection, установил выравнивание окружностей на alClient
, отступ до 5 на каждой стороне и изменил подпрограмму для работы с Circle1
и Circle2
в отличие от Selection1
и Selection2
. Это оказалось точным в том смысле, что если бы сами круги не перекрывались (точнее, их области не перекрывались), то они не будут рассматриваться как сталкивающиеся до тех пор, пока края фактически не коснутся. Очевидно, что углы самих кругов представляют собой проблему, но вы, возможно, могли бы добавить еще один дочерний компонент внутри каждого круга с его видимостью, установленной в false, и с немного меньшими размерами, чтобы имитировать старый метод столкновения «Ограничивающий прямоугольник». обнаружение.
Пример приложения
Я добавил пример приложения с источником, показывающим выше. На вкладке 1 приведен полезный пример, а на второй вкладке приводится краткое объяснение того, как работает TRectF (и показаны некоторые ограничения, связанные с использованием визуального интерфейса, похожего на радар. Есть третья вкладка, демонстрирующая использование TBitmapListAnimation
для создания анимированные картинки.
Обнаружение столкновения FMX - пример и источник