2015-08-14 70 views
1

如果使用SKShapeNodeSKSpriteNode,則nodeAtPoint:的結果不一樣。如果我正確nodeAtPoint:將使用containsPoint:來檢查哪些節點在給定點。SKNode nodeAtPoint:/ containsPoint:與SKSpriteNode和SKShapeNode的行爲不同

docu指出containsPoint:將使用其邊界框。

我設置了一個簡單的場景,其中在情境1中,圓圈是紫色節點的父親,情況2中綠色節點是紫色節點的父親。 我在父母的邊界框所在的區域中點擊了兩種情況。

結果有所不同。如果我使用SKSpriteNodenodeAtPoint:會給我父母。如果我使用SKShapeNode,則返回SKScene

(橫標記,其中i按壓鼠標。)

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文檔說,它

返回相交的點最深的後裔

and in the Discussion section

的點被認爲是在一個節點,如果它位於由calculateAccumulatedFrame方法

第一聲明適用於SKSpriteNodeSKShapeNode節點返回的矩形內,而第二隻適用於SKSpriteNode節點。對於SKShapeNode s,Sprite套件會忽略節點的邊界框並使用path屬性來確定點是否與節點相交CGPathContainsPoint。如下圖所示,在每個像素的基礎上選擇形狀,其中白點代表點擊點。

Bounding Box for Shape Node

圖1包圍盒爲形狀(藍色)和形狀+廣場(棕色)

containsPoint Test

圖2的nodeAtPoint

calculateAccumulatedFrame結果返回一個邊界框(BB),如下圖所示(棕色框是方塊BB)。因此,如果您不適當地調整的containsPoint,結果將不會是您的預期。要將點從場景座標轉換爲父座標(或反之),請使用convertPoint:fromNodeconvertPoint:toNode。最後,containsPoint使用形狀的path而不是像nodeAtPoint那樣的邊界框。

enter image description here

+0

但是爲什麼SpriteKit如此不一致呢?我預計nodeAtPoint:的返回將是我在該點看到的節點或另一個一致的結果。就像使用累積幀一樣。現在它高度依賴於節點類型,對於其他節點類型甚至可能不同... – NieLernend

+0

如果您需要一致的行爲,則可以對所有遊戲實體使用相同的節點子類(例如,SKSpriteNode)。您可以使用圖像編輯應用程序創建形狀(例如,圓形,多邊形)。 – 0x141E

+0

這不幸的是不適合我的使用。我構建了一個框架,使我能夠識別MacOS SpriteKit應用程序中幾乎所有輸入硬件的觸摸。所以我不能限制我的框架的每個用戶只使用SpriteNodes。當我嘗試識別哪個節點被按下時,會出現這種不一致問題。也許我會通過不使用nodeAtPoint來使其一致,但通過檢查我自己的累積幀。這是一個恥辱,但仍然感謝您的幫助。 – NieLernend