36

我对SKNode方法convertPoint:fromNode:convertPoint:ToNode:工作方式有点困惑,我查看了文档,但它们的作用并不明显。例如,这个(见下图)是我使用convertPoint:fromNode:的一个小测试黑色区域是SKScene背景,蓝色区域是 的SKSpriteNode父级SKScene,红色区域是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 =要转换的点(不知道为什么上面的[自身位置])
  • SKNode_C = 要转换的节点坐标空间...

我最初的尝试是[self convertPoint:[redSprite position] fromNode:redSprite]因为我想将红色精灵的来源转换为场景。让你的脑袋看起来有点笨拙,如果有人能对这件事和它的朋友投一点光和逻辑,convertPoint:toNode:那将不胜感激。

在此处输入图像描述

4

4 回答 4

50

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

这本质上是说:将另一个节点坐标系中表示的转换为调用者的(自身)坐标系。关键是该点必须在节点的坐标系中表示才能工作。如果您使用精灵的位置作为点,则需要将精灵的父节点作为最后一个参数传递。

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

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

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

你的例子:

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

redSprite 坐标系中的[0, 0] -->场景坐标系中的[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]

于 2014-02-24T06:43:48.793 回答
1

在阅读了 kevin.'s great answer 之后,我能够对 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.,但我觉得这会使代码更加混乱。而且我不完全确定如果节点不属于任何场景或父节点该怎么办,所以我只是返回了常规帧和位置并使用 aprintln()给我一个警告。

如果有人对此代码有任何更改/添加,我很乐意听到它,特别是如果它有助于进一步回答问题。

于 2015-08-26T17:19:51.873 回答
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)
于 2015-08-16T22:26:12.967 回答
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)
于 2016-08-11T19:26:35.500 回答