SKNode的convertPoint方法中的toNode和fromNode参数让我感到困惑?

37

我对SKNode方法convertPoint:fromNode:convertPoint:ToNode:的工作方式有些困惑,我查看了文档但它们并不明显。例如,这是我使用convertPoint:fromNode:进行的小测试(见下图)。黑色区域是SKScene背景,蓝色区域是附加到SKSceneSKSpriteNode,红色区域是附加到蓝色精灵的另一个SKSpriteNode,两个精灵的锚点由小绿点表示。我想做的是获取红色精灵在场景中的位置,我使用以下代码实现:

CGPoint positionInScene = [self convertPoint:[self position] 
                                    fromNode:[self redSprite]];
这将产生的结果是:

这将产生的结果是

positionInScene = [105, 205]

这正是我所预料的,因为那将是场景空间中红色正方形的起源。但让我感到困惑的是参数。从我猜测的情况来看:

[SKNode_A convertPoint: CGPoint_B toNode: SKScene_C]
  • SKNode_A = 要转换到的节点坐标空间...
  • CGPoint_B = 要转换的点(不确定为什么上面是[self position])
  • SKNode_C = 要从中转换的节点坐标空间...

我最初尝试使用[self convertPoint:[redSprite position] fromNode:redSprite],因为我想将红色精灵的原点转换为场景。如果有人能对这两种方法convertPoint:fromNode:convertPoint:toNode:进行解释,那将非常感激。

enter image description here


1
你把这段代码 [self convertPoint:[self position] fromNode:[self redSprite]] 放在哪里了?它属于场景吗? - Andrey Gordeev
这段代码位于SKScene的方法中(或其子类)。 - fuzzygoat
您错误地列出了参数的含义,或者可能混淆了您所定义的参数。 - prototypical
http://stackoverflow.com/questions/21870605/sprite-kit-collision-detection-with-child-sprite/21886427#21886427 描述了如何使用 'convertPoint:toNode'。 - prototypical
4个回答

50

- (CGPoint)convertPoint:(CGPoint)point fromNode:(SKNode *)node

这个方法的作用是将一个在另一个节点坐标系中表示的转换到当前对象(self)坐标系中。关键在于这个点必须是在该节点的坐标系中表示的才能生效。如果您使用精灵的位置作为点,则需要将精灵的父节点作为最后一个参数传递。

示例:要获取红色正方形在场景坐标系中的位置:

CGPoint positionInScene = [self convertPoint:[redSprite position]
                                    fromNode:[self blueSprite]];

[5, 5] 在blueSprite的坐标系中 --> 在场景坐标系中为 [105, 205]

CGPoint positionInScene = [self convertPoint:[self position] 
                                    fromNode:[self redSprite]];

[0, 0]在redSprite的坐标系中,即在场景的坐标系中是[105, 205]

你的代码最终得出了相同的结果,只因为[self position]是[0,0]并且你使用了redSprite的坐标系。你的初始尝试很接近,只需要提供redSprite位置表示的坐标系,即父精灵的坐标系;在这种情况下,就是blueSprite。

- (CGPoint)convertPoint:(CGPoint)point toNode:(SKNode *)node

这个方法与第一个方法非常相反。它将调用者坐标系中的转换为另一个节点的坐标系。关键在于给定的点必须在调用者的坐标系中表示。

例子:假设你的场景在[125, 225]处收到了一个触摸,并且你想在该位置添加一个新的精灵,这恰好在redSprite的边界框内。所以要将一个新的精灵作为redSprite的子级添加,你需要获取触摸在redSprite坐标系中的位置。为此需要:

CGPoint positionInRedSprite = [self convertPoint:touchLocation 
                                          toNode:[self redSprite]];

[125, 225]在场景坐标系中 --> 在redSprite的坐标系中为[20, 20]


非常感谢你,Kevin。这确实澄清了很多问题,谢谢你提供如此清晰和有用的答案。 - fuzzygoat
2
关键是要知道谁是调用者,因为它的协调系统是参考。我读了这篇文章10遍才最终找到这个 :) - Krzysztof Przygoda

1
阅读完kevin.的精彩回答后,我能够扩展SKNode并创建一些既是良好示范又是方便工具的功能。
extension SKNode {

var frameInScene:CGRect {
    get {
        if let scene = self.scene {
            if let parent = self.parent {
                let rectOriginInScene = scene.convertPoint(self.frame.origin, fromNode: parent)
                return CGRect(origin: rectOriginInScene, size: self.frame.size)
            }
        }
        println("Just the normal frame, not the scene frame!!!")
        return frame
    }
}

var positionInScene:CGPoint {
    get {
        if let scene = self.scene {
            if let parent = self.parent {
                return scene.convertPoint(self.position, fromNode: parent)
            }
        }
        println("Just the normal position, not the scene position!!!")
        return position
    }
}
}

我认为你可以删除每一个self.,但我觉得这会让代码更加混乱。而且如果节点不属于任何场景或父节点,我也不确定该怎么做,所以我只返回了常规的框架和位置,并使用println()给出了警告。
如果有人对这段代码有任何修改/添加,我很乐意听取意见,特别是如果它有助于进一步解答问题。

0

我知道这是晚回复了,但通常情况下,我想将节点的父节点作为节点位置的坐标系。因此,我发现这个扩展非常有用:

extension SCNNode {
    func convertPosition(node:SCNNode) -> SCNVector3 {
        return self.convertPosition(node.position, fromNode:node.parentNode)
    }
}

例如,不要这样调用:
let position = scene.rootNode.convertPosition(node.position, fromNode: node.parentNode)

你只需要调用这个:

let position = scene.rootNode.convertPosition(node)

0

为了简单起见: 当比较节点B与节点A的位置(试图找出它们之间的距离)时

var BInSameCoordinateSys = NodeA.parent!.convertPoint(NodeB.position, fromNode: NodeB.parent!)

如果无法正常工作,请通过在位置添加精灵来进行故障排除,以帮助可视化位置:

let childToSeeLocation = SKShapeNode(CircleWithRadius:50)
childToSeeLocation.fillColor = UIColor.redColor
ParentofA.addChild(childToSeeLocation)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接