SKNode nodeAtPoint: / containsPoint: SKSpriteNode 和 SKShapeNode 的行为不同
SKNode nodeAtPoint: / containsPoint: not the same behaviour for SKSpriteNode and SKShapeNode
如果使用 SKShapeNode
和 SKSpriteNode
,nodeAtPoint:
给出的结果不同。如果我是正确的 nodeAtPoint:
将使用 containsPoint:
检查给定点处的节点。
docu 声明 containsPoint:
将使用其边界框。
我设置了一个简单的场景,在情况 1 中,圆圈是紫色节点的父级,在情况 2 中,绿色节点是紫色节点的父级。
我在这两种情况下都单击了父边界框所在的区域。
结果不同。如果我使用 SKSpriteNode
,nodeAtPoint:
会给我父对象。如果我使用 SKShapeNode
它 returns SKScene
.
(我用鼠标按下的十字标记。)
代码:
第一次设置:
-(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 中的错误吗?是这样工作的吗?
简短的回答:是,不是,是
长答案...
nodeAtPoint
的文档说
returns the deepest descendant that intersects a point
并在讨论部分
a point is considered to be in a node if it lies inside the rectangle returned by the calculateAccumulatedFrame method
第一个语句适用于SKSpriteNode
和SKShapeNode
个节点,而第二个仅适用于SKSpriteNode
个节点。对于 SKShapeNode
s,Sprite Kit 忽略节点的边界框并使用 path
属性 来确定点是否与节点相交 CGPathContainsPoint。如下图所示,形状是按像素选择的,其中白点代表点击点。
图 1. 形状(蓝色)和形状 + 方形(棕色)的边界框
图 2. nodeAtPoint
的结果
calculateAccumulatedFrame
returns 如下图所示相对于其父级的边界框(BB)(棕色框是正方形的 BB)。因此,如果您没有适当地为 containsPoint
调整 CGPoint
,结果将不是您所期望的。要将点从场景坐标转换为父级坐标(反之亦然),请使用 convertPoint:fromNode
或 convertPoint:toNode
。最后,containsPoint
使用形状的 path
而不是它的边界框,就像 nodeAtPoint
.
如果使用 SKShapeNode
和 SKSpriteNode
,nodeAtPoint:
给出的结果不同。如果我是正确的 nodeAtPoint:
将使用 containsPoint:
检查给定点处的节点。
docu 声明 containsPoint:
将使用其边界框。
我设置了一个简单的场景,在情况 1 中,圆圈是紫色节点的父级,在情况 2 中,绿色节点是紫色节点的父级。 我在这两种情况下都单击了父边界框所在的区域。
结果不同。如果我使用 SKSpriteNode
,nodeAtPoint:
会给我父对象。如果我使用 SKShapeNode
它 returns SKScene
.
(我用鼠标按下的十字标记。)
代码:
第一次设置:
-(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 中的错误吗?是这样工作的吗?
简短的回答:是,不是,是
长答案...
nodeAtPoint
的文档说
returns the deepest descendant that intersects a point
并在讨论部分
a point is considered to be in a node if it lies inside the rectangle returned by the calculateAccumulatedFrame method
第一个语句适用于SKSpriteNode
和SKShapeNode
个节点,而第二个仅适用于SKSpriteNode
个节点。对于 SKShapeNode
s,Sprite Kit 忽略节点的边界框并使用 path
属性 来确定点是否与节点相交 CGPathContainsPoint。如下图所示,形状是按像素选择的,其中白点代表点击点。
图 1. 形状(蓝色)和形状 + 方形(棕色)的边界框
图 2. nodeAtPoint
calculateAccumulatedFrame
returns 如下图所示相对于其父级的边界框(BB)(棕色框是正方形的 BB)。因此,如果您没有适当地为 containsPoint
调整 CGPoint
,结果将不是您所期望的。要将点从场景坐标转换为父级坐标(反之亦然),请使用 convertPoint:fromNode
或 convertPoint:toNode
。最后,containsPoint
使用形状的 path
而不是它的边界框,就像 nodeAtPoint
.