2015-08-14 1 views
1

Le nodeAtPoint: ne donne pas le même résultat si vous utilisez SKShapeNode et SKSpriteNode. Si je suis correct nodeAtPoint: utilisera containsPoint: pour vérifier quels nœuds sont au point donné. Le docu indique que containsPoint: utilisera sa boîte de délimitation.SKNode nodeAtPoint:/containsPoint: comportement différent pour SKSpriteNode et SKShapeNode

J'ai mis en place une scène simple, où dans la situation 1, le cercle est le parent du nœud violet et dans la situation 2, le nœud vert est parent du nœud violet. J'ai cliqué dans les deux cas dans une zone où la boîte de délimitation du parent devrait être.

Le résultat est différent. Si j'utilise un SKSpriteNode le nodeAtPoint: me donnera le parent. Si j'utilise SKShapeNode il renvoie le SKScene.

(Les marques croix où j'emboutie avec la souris.)

enter image description here enter image description here

Le code:

Première installation:

-(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]; 
} 

configuration Deuxième:

-(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]; 

}

Appelez le clic de souris:

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

Ai-je raté quelque chose? Est-ce un bug dans SpriteKit? Est-ce censé fonctionner de cette façon?

Répondre

1

Les réponses courtes: oui, non, oui

La réponse longue ...

La documentation nodeAtPoint dit qu'il

retourne le plus profond descendant qui croise un point

et dans la section Discussion

un point est considéré comme étant dans un noeud si elle se trouve à l'intérieur du rectangle renvoyé par la méthode calculateAccumulatedFrame

La première instruction et applique à SKSpriteNodeSKShapeNode noeuds, tandis que le second applique uniquement aux SKSpriteNode noeuds. Pour SKShapeNode s, Sprite Kit ignore la zone de délimitation du noeud et utilise la propriété path pour déterminer si un point croise le noeud avec CGPathContainsPoint. Comme le montrent les figures ci-dessous, les formes sont sélectionnées pixel par pixel, les points blancs représentant les points de clic.

Bounding Box for Shape Node

Figure 1. Forme de boîtes englobantes (bleu) et Shape + Carré (brun)

containsPoint Test

Figure 2. Résultats de nodeAtPoint

calculateAccumulatedFrame renvoie une boîte englobante (BB) qui est relatif à son parent comme indiqué dans la figure ci-dessous (la boîte brune est le BB du carré). Par conséquent, si vous n'ajustez pas correctement le CGPoint pour containsPoint, les résultats ne seront pas conformes à vos attentes. Pour convertir un point des coordonnées de la scène en coordonnées du parent (ou vice versa), utilisez convertPoint:fromNode ou convertPoint:toNode. Enfin, containsPoint utilise une forme path au lieu de sa boîte de délimitation, tout comme nodeAtPoint.

enter image description here

+0

Mais pourquoi est SpriteKit si inconsistant? Je m'attendais à ce que le retour de nodeAtPoint: soit soit le nœud que je vois au point soit un autre résultat cohérent. Comme l'utilisation de l'image accumulée. Maintenant, cela dépend fortement du type de nœuds, qui peut même être différent pour d'autres types de nœuds ... – NieLernend

+0

Si vous avez besoin d'un comportement cohérent, vous pouvez utiliser la même sous-classe de nœud (par exemple, SKSpriteNode) pour toutes vos entités de jeu. Vous pouvez créer les formes (par exemple, des cercles, des polygones) avec une application de retouche d'image. – 0x141E

+0

Ce n'est malheureusement pas approprié pour mon utilisation. Je construis un cadre qui me permet de reconnaître les touches de presque n'importe quel matériel d'entrée dans les applications MacOS SpriteKit. Je ne peux donc pas empêcher tous les utilisateurs de mon framework d'utiliser uniquement SpriteNodes. Ce problème d'incohérence survient lorsque j'essaie d'identifier le nœud sur lequel j'ai appuyé. Probablement je vais le rendre cohérent en n'utilisant pas nodeAtPoint, mais en vérifiant les images accumulées par moi-même. C'est dommage, mais merci encore pour l'aide. – NieLernend