2015-08-14 8 views
1

nodeAtPoint: дает не тот же результат при использовании SKShapeNode и SKSpriteNode. Если я прав nodeAtPoint: будет использовать containsPoint:, чтобы проверить, какие узлы находятся в данной точке.SKNode nodeAtPoint:/containsPoint: не то же поведение для SKSpriteNode и SKShapeNode

docu указывает, что containsPoint: будет использовать его рамку.

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

Результат отличается. Если я использую SKSpriteNode, то nodeAtPoint: предоставит мне родителя. Если я использую SKShapeNode, он возвращает SKScene.

(крестики, где я спрессованные с помощью мыши.)

enter image description here enter image description here

Код:

Первая установка:

-(void)didMoveToView:(SKView *)view { 
self.name = @"Scene"; 

SKShapeNode* circle = [SKShapeNode node]; 
circle.path = CGPathCreateWithEllipseInRect(CGRectMake(0, 0, 50, 50), nil); 
circle.position = CGPointMake(20, 20); 
circle.fillColor = [SKColor redColor]; 
circle.name = @"circle"; 

SKSpriteNode* pnode = [SKSpriteNode node]; 
pnode.size = CGSizeMake(50, 50); 
pnode.position = CGPointMake(50, 50); 
pnode.color = [SKColor purpleColor]; 
pnode.name = @"pnode"; 


[self addChild: circle]; 
[circle addChild: pnode]; 
} 

Вторая установка:

-(void)didMoveToView:(SKView *)view { 
self.name = @"Scene"; 

SKSpriteNode* gnode = [SKSpriteNode node]; 
gnode.size = CGSizeMake(50, 50); 
gnode.position = CGPointMake(30, 30); 
gnode.color = [SKColor greenColor]; 
gnode.name = @"gnode"; 

SKSpriteNode* pnode = [SKSpriteNode node]; 
pnode.size = CGSizeMake(50, 50); 
pnode.position = CGPointMake(30, 30); 
pnode.color = [SKColor purpleColor]; 
pnode.name = @"pnode"; 


[self addChild: gnode]; 
[gnode addChild: pnode]; 

}

Призываем мыши:

-(void)mouseDown:(NSEvent *)theEvent { 
CGPoint location = [theEvent locationInNode:self]; 
NSLog(@"%@", [self nodeAtPoint: location].name); 
} 

ли я что-то пропустил? Это ошибка в SpriteKit? Это значит работать таким образом?

ответ

1

Короткий ответ: да, нет, да

Длинный ответ ...

Документация nodeAtPoint говорит, что

возвращает глубочайшее потомка, который пересекает точку

и в разделе обсуждения

точка считается в узле, если она лежит внутри прямоугольника, возвращаемого методом calculateAccumulatedFrame

Первое утверждение относится к SKSpriteNode и SKShapeNode узлов, в то время как вторая относится только к SKSpriteNode узлов. Для SKShapeNode s Sprite Kit игнорирует ограничивающий блок узла и использует свойство path, чтобы определить, пересекает ли точка узел с CGPathContainsPoint. Как показано на рисунках ниже, фигуры выбираются по пикселю, где белые точки представляют точки щелчка.

Bounding Box for Shape Node

Рисунок 1. обрамлению Ящики для Shape (синий) и Shape + Square (коричневый)

containsPoint Test

Рисунок 2. Результаты nodeAtPoint

calculateAccumulatedFrame возвращает ограничивающий прямоугольник (BB), что относительно его родителя, как показано на рисунке ниже (коричневый ящик - это квадрат BB). Следовательно, если вы не настроите CGPoint на containsPoint соответственно, результаты не будут такими, какие вы ожидали. Чтобы преобразовать точку из координат сцены в координаты родителя (или наоборот), используйте convertPoint:fromNode или convertPoint:toNode. Наконец, containsPoint использует форму path вместо ее ограничивающей рамки, как nodeAtPoint.

enter image description here

+0

Но почему SpriteKit так непоследовательны? Я ожидал, что возвращение nodeAtPoint: будет либо узлом, который я вижу в точке или другом согласованном результате. Как использование накопленного кадра. Теперь он сильно зависит от типа узлов, который может быть даже другим для других типов узлов ... – NieLernend

+0

Если вам требуется согласованное поведение, вы можете использовать один и тот же подкласс класса (например, SKSpriteNode) для всех ваших игровых объектов. Вы можете создавать фигуры (например, круги, полигоны) с помощью приложения для редактирования изображений. – 0x141E

+0

Это, к сожалению, не подходит для моего использования. Я создаю фреймворк, который позволяет мне распознавать штрихи практически любого входного оборудования в приложениях MacOS SpriteKit. Поэтому я не могу запретить каждому пользователю моей инфраструктуры использовать только SpriteNodes. Эта проблема несогласованности возникает, когда я пытаюсь определить, какой узел был нажат. Вероятно, я сделаю это согласованным, не используя nodeAtPoint, но, проверив накопленные фреймы самостоятельно. Это позор, но все же спасибо за помощь. – NieLernend