【问题标题】:SKNode nodeAtPoint: / containsPoint: not the same behaviour for SKSpriteNode and SKShapeNodeSKNode nodeAtPoint: / containsPoint: SKSpriteNode 和 SKShapeNode 的行为不同
【发布时间】:2015-08-14 16:13:17
【问题描述】:

如果使用SKShapeNodeSKSpriteNodenodeAtPoint: 会给出不同的结果。如果我是正确的nodeAtPoint: 将使用containsPoint: 来检查哪些节点在给定点。

docu 声明containsPoint: 将使用其边界框。

我设置了一个简单的场景,在情况 1 中,圆圈是紫色节点的父节点,在情况 2 中,绿色节点是紫色节点的父节点。 在这两种情况下,我都单击了父级边界框应位于的区域。

结果不同。如果我使用SKSpriteNode nodeAtPoint: 会给我父母。如果我使用SKShapeNode,它会返回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 中的错误吗?它是按这种方式工作的吗?

【问题讨论】:

    标签: sprite-kit skspritenode hittest skshapenode


    【解决方案1】:

    简短的回答:是的,不是的,是的

    长答案...

    nodeAtPoint 的文档说它

    返回与点相交的最深后代

    在讨论区

    如果一个点位于 calculateAccumulatedFrame 方法返回的矩形内,则认为该点位于节点中

    第一个语句适用于SKSpriteNodeSKShapeNode 节点,而第二个语句仅适用于SKSpriteNode 节点。对于SKShapeNodes,Sprite Kit 会忽略节点的边界框并使用path 属性来确定一个点是否与CGPathContainsPoint 的节点相交。如下图所示,形状是按像素选择的,其中白点代表点击点。

    图 1. Shape(蓝色)和 Shape + Square(棕色)的边界框

    图 2.nodeAtPoint 的结果

    calculateAccumulatedFrame 返回一个相对于其父级的边界框(BB),如下图所示(棕色框是正方形的BB)。因此,如果您不适当调整 CGPointcontainsPoint,结果将不是您所期望的。要将点从场景坐标转换为父坐标(反之亦然),请使用convertPoint:fromNodeconvertPoint:toNode。最后,containsPoint 使用形状的path 而不是它的边界框,就像nodeAtPoint 一样。

    【讨论】:

    • 但是为什么SpriteKit会如此不一致呢?我预计 nodeAtPoint: 的返回要么是我在该点看到的节点,要么是另一个一致的结果。喜欢使用累积帧。现在它确实高度依赖于节点类型,对于其他节点类型甚至可能有所不同......
    • 如果您需要一致的行为,您可以为所有游戏实体使用相同的节点子类(例如,SKSpriteNode)。您可以使用图像编辑应用程序创建形状(例如,圆形、多边形)。
    • 不幸的是,这不适合我的使用。我构建了一个框架,让我能够识别 MacOS SpriteKit 应用程序中几乎任何输入硬件的触摸。所以我不能限制我的框架的每个用户只使用 SpriteNodes。当我尝试确定按下了哪个节点时,就会出现这种不一致的问题。可能我会通过不使用 nodeAtPoint 而是通过自己检查累积的帧来使其保持一致。很遗憾,但仍然感谢您的帮助。
    • 还有一个问题。您从哪里知道 containsPoint: 将使用形状路径?文档说明 containsPoint: 实际上应该使用边界框 ...
    • 我创建了一个项目,该项目显示containsPoint: 的结果,类似于我在图 2 中对nodeAtPoint: 所做的操作。通过单击圆形节点及其周围,我得出结论,Sprite Kit 正在使用圆的路径而不是它的边界框。
    猜你喜欢
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-28
    • 1970-01-01
    相关资源
    最近更新 更多