Какое максимальное количество категорийBitMask разрешено в Sprite Kit?

Я слышал, что в игре Sprite Kit разрешено использовать только 32 битмаски разных категорий. Есть ли способ обойти это? Мне абсолютно нужно больше (примерно в 3-4 раза больше, так как игра с открытым миром). Я установил свою битовую маску категории следующим образом:

static const uint64_t boundaryCategory    = 0x1 << 0;
static const uint64_t mainCharCategory    = 0x1 << 1;
...
static const uint64_t someOtherCategory   = 0x1 << 31;

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


person Krekin    schedule 10.06.2015    source источник
comment
Ты прав. Поскольку Sprite Kit использует битовую маску для 32-битного целого числа, представляющего 32 различные физические категории, вы не можете иметь больше (это верно даже в Xcode 7). Для максимального значения (UInt32 * 2), 4294967295, которое равно 111111111111111111111111111111111 в двоичном формате, вы заставляете этот объект сталкиваться со всеми остальными.   -  person hippo_san    schedule 10.06.2015
comment
Хорошо. Значит, нет абсолютно никакого способа взломать это ограничение? Может быть, есть какой-то другой метод, который я могу использовать, который даст ту же или аналогичную функциональность, что и char1.physicsBody.categoryBitMask = char1Category;?   -  person Krekin    schedule 10.06.2015


Ответы (2)


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

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

Создание словаря SKNode:

myNode.userData = [NSMutableDictionary dictionary];
[myNode.userData setObject:@"goblin" forKey:@"enemyType"];

Чтение словаря:

NSString *myString = [myNode.userData objectForKey:@"enemyType"];
person sangony    schedule 10.06.2015
comment
Великолепно! Почему я не подумал об этом? Спасибо. - person Krekin; 10.06.2015
comment
Хорошо! Первый пример, относящийся к свойству имени узла, работает блестяще! Вот так (firstBody.categoryBitMask == [_worldNode childNodeWithName:@charRed].physicsBody.categoryBitMask) && (и т. д.). Тем не менее, sangony, не могли бы вы показать пример того, как сделать 2-й метод в отношении свойства словаря SKNode? - person Krekin; 10.06.2015

Вы можете иметь более 32 объектов, определенных с помощью UInt32.

Один из способов сделать это — зарезервировать последние биты. Это уменьшит количество битов, которые у вас есть для элементов, но вы умножите это на количество битов, которые вы используете. Таким образом, если мы используем только 32-битную маску для элементов выше 31, у нас может быть 2*31 количество объектов. Если мы зарезервируем 32-й и 31-й бит для большего количества элементов, у нас может быть 4 * 30 объектов и так далее.

т.е. обычный 32 бит от SKScene

(void)didBeginContact:(SKPhysicsContact *)contact
{
    uint32_t catagoryContactBitMask = (contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask); 

    if (catagoryContactBitMask == (carCategory | wallCategory))
    {    ....
    }

}

например, если нам нужно больше категорий выше 32... Итак, давайте зарезервируем 32-й бит как бит «второго уровня» для элементов более 31... это даст нам 2*31 или 62 элемента.

статическая константа uint32_t 32bitMask = 0x1 ‹‹ 32; //10000000000000000000000000000000

статическая константа uint32_t wallCategory = 0x1 ‹‹ 0; // 00000000000000000000000000000001

статическая константа uint32_t porcheCategory = 0x1 ‹‹ 1; // 000000000000000000000000000000010

статическая константа uint32_t lamboCategory = 0x1 ‹‹ 1 | 32-битная маска; //100000000000000000000000000000010

обнаружение столкновений должно быть таким же

снова из SKScene

(void)didBeginContact:(SKPhysicsContact *)contact
{
    uint32_t catagoryContactBitMask = (contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask); 

    if ( catagoryContactBitMask == (wallCategory|porcheCategory))
    {    ....
    }
    else if ( catagoryContactBitMask == (wallCategory|lamboCategory))
    {    ....
    }

}
person ScottS    schedule 05.01.2020