Почему SKNode nodeAtPoint возвращает неправильный узел?

Документы Apple утверждают, что метод nodeAtPoint на SKNode возвращает самый глубокий узел в дереве. Я понимаю, что это означает, что если вы рисуете дерево с узлом сцены наверху, ответ следует ожидать как один из узлов в самой нижней позиции дерева. Это не происходит для меня. Вот как выглядит мое дерево:

                           scene
                             |
                           world
                             |
           +------------+----+---------+------------+
           |            |              |            |
       leftArrow    rightArrow    boardLayer   statusLayer
                                       |
      +-----------+-----------+--------+-+---------------+ 
      |           |           |          |               |
    arrow     highlight     trough     rotating(0)    testDump
                (21)                     |
                                +--------+----------+
                                |        |          |
                             guides   board    playerPiece
                              (24)     (20)      (13)

Цифры в скобках - это z-позиция узлов. Когда я запрашиваю сцену для «nodesAtPoint» и даю ей расчетную точку, соответствующую местоположению playerPiece, я получаю: «мир, boardLayer, вращение, подсветка, доска, playerPiece». Это то, что я ожидаю. Однако, когда я запрашиваю сцену для «nodeAtPoint», используя ту же точку, я получаю «подсветку». Я ожидал playerPiece. Почему этот узел не вернулся? Что я упускаю из виду?

Я не уверен, что код принесет пользу, но вот он. Этот код находится в Board.m (внизу дерева).

    CGPoint pt = [CheckerUtilities locationFromColumn:column row:row];
    CGPoint p = [self.parent.parent convertPoint:pt toNode:[Globals sharedGlobals].scene];
    NSArray *nodes = [[Globals sharedGlobals].scene nodesAtPoint:p];
    for (SKNode *node in nodes)
      NSLog(@"%@, %@, %f", [node class], node.name, node.zPosition);
    SKNode *checker = [[Globals sharedGlobals].scene nodeAtPoint:p];
    NSLog(@"node: %@", [checker class]);

Результат:

SKNode, world, 0.000000
BoardLayer, boardLayer, 0.000000
SKSpriteNode, rotating, 0.000000
Highlight, highlight, 21.000000
Board, board, 20.000000
CheckerSprite, checker, 13.000000
node: Highlight

person user3641874    schedule 17.08.2014    source источник
comment
Разместите соответствующий код.   -  person sangony    schedule 18.08.2014


Ответы (1)


Из документов:

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

Другими словами, тестирование попадания начинается с последнего дочернего элемента, добавленного в узел, до первого (как вы сказали). Однако zPosition не только переопределяет порядок прорисовки, но и порядок проверки попаданий:

Sprite Kit использует значение zPosition только для определения проверки попадания и порядка отрисовки.

Узел с наибольшим значением z будет выбран первым, если несколько узлов перекрываются в точке касания.

person Epsilon    schedule 18.08.2014
comment
Я думал, что проверка попаданий касается только физических контактов и столкновений. Это также не тот случай, когда кто-то постучал по чему-либо — это программно рассчитанная точка (см. первую строку фрагмента кода). Кроме того, исходя из значения z, играющего бросок, разве z не имеют только относительное значение среди своих сверстников (узлов на одном уровне дерева)? Основываясь на ваших фактах z, не вернется ли тогда nodeAtPoint с доской - если предположить, что мое предположение сверстников верно)? - person user3641874; 18.08.2014
comment
ОК, я только что провел небольшой тест, удалив спрайт подсветки. Ответ действительно вернулся в качестве доски, поддерживающей утверждение z. Однако описание Apple функции «nodeAtPoint»: потомок в поддереве, пересекающем точку, или получатель, если ни один узел не пересекает точку. Если несколько потомков пересекают точку, то возвращается самый глубокий узел в дереве. Если несколько узлов находятся на одном уровне, возвращается пересекающийся узел с наименьшей позицией z. - person user3641874; 18.08.2014
comment
Хит-тест не имеет ничего общего с коллизиями и контактами. Это процесс поиска в иерархии представлений, чтобы найти представление, которое примет прикосновение пользователя. Это также относится к SKNodes. - person Epsilon; 18.08.2014
comment
Я тоже это читал. Если несколько узлов находятся на одном уровне, возвращается пересекающийся узел с наименьшей позицией z. Это неправильно. Проверка на попадание ищет от самого высокого к самому низкому z (имеет больше смысла, верно?). Вы можете создать простую тестовую программу, чтобы доказать это самому себе. - person Epsilon; 18.08.2014