Контакты физики в SpriteKit

Можно ли объяснить, как работает битовая маска только для этой упрощенной ситуации:

 A big (blue) ball.    Contact BitMask 0b0001

 A medium (red) ball.  Contact BitMask 0b0010

 A small (white) ball. Contact BitMask 0b0100

Между ними нет столкновений, потому что это как-то отключено между ними. Я полагаю, установив их маски столкновений на 00 на протяжении всех 32 бит... но давайте оставим это для другого вопроса, я еще не понял, как их отключить.

Установив для каждого шара уникальную контактную битовую маску, что делается для предоставления контактной информации при контакте?

Как можно узнать, какие два шара коснулись друг друга?

Возможно ли, чтобы информация о контакте получала только самый большой шар в любом заданном контакте?


ОБНОВИТЬ:

Я не обязательно после кода. Если вам нужен код, объясняющий, что к чему, как это работает и почему что-то делает, сделайте это.

Но на самом деле мне нужно понять, как работает битовая маска, чтобы обеспечить логику, позволяющую определить, «кто» был вовлечен в любой контакт.

Причина, по которой я дал каждому размеру мяча разные битовые маски, заключается в том, что я подумал, что это может помочь определить больший мяч в любом заданном контакте между двумя мячами. Хотя я могу ошибаться в этом.

ОБНОВЛЕНИЕ 2:

Понимание происходящих процессов:

Насколько я понимаю, это части процесса:

  1. Зарегистрируйте подкласс SKScene SKView как соответствующий делегату уведомления о контактах мира физики. Скажи, что это тоже так.

  2. Установите битовую маску в качестве категорий для каждого типа телесного взаимодействия, о котором нужно знать и / или контролировать в симуляции.

  3. Используйте эти битовые маски, чтобы сформулировать природу каждого объекта, который желает быть частью контактов и/или столкновений, применяя их надлежащим образом (здесь примите какое-то волшебное решение).

  4. Переопределите обратный вызов контактов кодом, который делает что-то, в том же подклассе SKView, который зарегистрирован как делегат.

  5. Создайте какой-нибудь магический код, определяющий, кто/что с кем связался.


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


person Confused    schedule 08.10.2016    source источник


Ответы (2)


Во-первых, вам нужно определить, какие у вас спрайты, для этого и нужен categoryBitMask. Думайте об этом как о двоичном имени вашего спрайта, где каждая цифра является уникальным именем. Теперь можно дать вашему спрайту более одного имени, но для простоты давайте ограничимся одним.

contactBitMask сообщает спрайтам, какие имена следует искать.

Таким образом, на этапе физики движок возьмет заданный спрайт и будет искать все остальные физические спрайты с именем поиска, указанным в файле contactBitMask.

После этого выполняются оценки исходного спрайта и спрайтов в отфильтрованном списке.

На контакте вызывается didBegin(contact:), а контакт содержит всю необходимую информацию, включая 2 тела контакта. Затем вы проверяете categoryBitMask, чтобы получить имена рассматриваемых спрайтов, и выполняете кондиционирование на основе этих имен.

person Knight0fDragon    schedule 08.10.2016

Практически во всех физических движках слои столкновений представлены битовыми масками. Все объекты в одних и тех же слоях столкновения будут сталкиваться друг с другом. В битовой маске каждый слой представлен битом. Если бит в позиции 0 включен, объект будет сталкиваться с другими объектами, у которых бит в той же позиции в их битовой маске включен.

При проверке столкновений широкофазная процедура физического движка сообщает только о тех парах как о потенциально сталкивающихся, у которых хотя бы один общий бит установлен в 1 в их битовой маске столкновений. Эта проверка просто выполняется с помощью И (&) двух битовых масок. О потенциально конфликтующей паре сообщается узкофазной подпрограмме только в том случае, если приведенная выше проверка возвращает ненулевой результат.

Например, если вы хотите, чтобы синий шар сталкивался с красным и белым шарами, но чтобы красный и белый шары не сталкивались друг с другом, вы должны установить следующие битовые маски: :

Blue  -> 0b0011
Red   -> 0b0001
White -> 0b0010

В вашем примере, поскольку ни одно из тел не имеет общего бита, установленного в их битовой маске столкновения, ни одно из них не сталкивается друг с другом. В приведенном выше примере, поскольку красный и белый шары не имеют общего бита в своей битовой маске, они не сталкиваются.

Возможно, вы захотите установить для всех битовых масок коллизий значение -1 (что включает все биты) и удалить биты/категории из маски с помощью XOR. Приведенный выше пример затем будет реализован с помощью следующего псевдокода:

blueBody.collisionMask = -1;
whiteBody.collisionMask = -1;
redBody.collisionMask = -1;

redBodyCategory   = 0b0001;
whiteBodyCategory = 0b0010;

whiteBody.collisionMask ^= redBodyCategory;
redBody.collisionMask ^= whiteBodyCategory;

Я не использую SpriteKit, но из небольшой информации, которую я получил из этого ответа SO, contactTestBitmask устанавливает категории, с которыми события будут вызываться при контакте, в то время как collisionBitmask устанавливает категории, с которыми на самом деле будет сталкиваться тело. Поэтому, если вам нужна контактная информация только из контактов, которые включают синий шар, вы должны установить contactTestBitmask в значения, как в моем примере выше.

Чтобы проверить, какие шары сталкиваются друг с другом, вам нужно проверить значения битовой маски и определить, какой из них какой. В приведенном выше примере синий шар можно распознать, проверив наличие body.contactTestBitmask == 0b0011 и т. д. для каждого другого тела.

В качестве примечания: вы можете рассмотреть возможность использования подходящего игрового движка, такого как Unity, который сделает все это намного проще.

person EvilTak    schedule 08.10.2016
comment
правильный игровой движок, такой как Unity, заставил меня смеяться. В Unity нет ничего правильного. Но спасибо за остальное. Я все еще не уверен, что понял. Но это очень хороший ответ. Мне нужно будет подумать об этом еще немного. - person Confused; 08.10.2016
comment
@Confused Я лично считаю Unity одним из лучших и самых модульных движков, но если вам не нравится Unity, есть много других вариантов, таких как Unreal. Также проверьте мое последнее редактирование. - person EvilTak; 08.10.2016
comment
Я думаю, что самые большие проблемы, с которыми я сталкиваюсь, это 1. Побитовые операции, побитовые отношения и побитовая логика. - person Confused; 08.10.2016
comment
Размер как Unity, так и Unreal является проблемой для разработки под iOS, а также их хреновая производительность. Unreal, соглашусь, это правильный игровой движок. - person Confused; 08.10.2016
comment
Маскирующая часть, кажется, имеет довольно хороший смысл. это, как вы говорите, вроде слоев. Меня действительно раздражает проблема, заключающаяся в том, что я не вижу, как вы определяете что-то вроде моей 3-й части этого вопроса: какой из двух шаров, которые соприкоснулись друг с другом, является самым большим? - person Confused; 08.10.2016
comment
Возможно, я тоже не очень ясно изложил вопрос. Я хочу отключить все столкновения и знать обо всех контактах, и в этих контактах я всегда хочу быть информированным о том, какой шар был большим, участвовавшим в контакте между любыми двумя шарами. КАК это делается. Мне не нужен код, просто объяснение того, как работают процессы, что происходит и почему... - person Confused; 08.10.2016
comment
Вот почему я присвоил шарам уникальные битовые маски. Я думал, что это часть пути к решению проблемы определения того, какой из мячей больше при любом контакте. - person Confused; 08.10.2016
comment
@Confused, затем вы должны установить categoryBitmask как уникальное, как вы это сделали, но установить значения contactTestBitmask в моем примере. Объяснение за кулисами находится в моем ответе. - person EvilTak; 08.10.2016
comment
В вашем примере вы устанавливаете CollisionBitmasks только для двух из трех объектов. И другой пример касается предотвращения столкновений. - person Confused; 08.10.2016
comment
Я не вижу закулисной части вашего ответа, которая объясняет, как узнать, какой мяч больше в любом контакте. - person Confused; 08.10.2016
comment
Если можно, расшифруйте, как я тупой, без кода. Просто что-то вроде: создание уникальной битовой маски каждого контакта гарантирует, что любые контакты ИЛИ указывают, что два тела являются этими двумя из трех, потому что... (я понятия не имею...) - person Confused; 08.10.2016
comment
@Confused установка уникальных масок столкновений не поможет. Установка уникальных битовых масок категорий поможет вам делать то, что вы хотите. Вам нужно проверить, равна ли маска категории уникальному значению маски каждого объекта или нет. Например, redCategory = 0b0010; if(contactBody.categoryMask == redCategory) { // contactBody is the red ball } Битовая маска категории помогает определить, к какой категории принадлежит тело. Каждый бит в битовых масках проверки коллизии и контакта соответствует категории. Если бит включен, события коллизий/контактов для этой категории включены. - person EvilTak; 08.10.2016
comment
ааа, для меня это большое озарение! - person Confused; 09.10.2016
comment
Я добавил небольшое обновление того, где я понимаю, можете ли вы помочь с последними двумя пунктами, которые я делаю в нижней части обновления 2? - person Confused; 10.10.2016