如何在 SpriteKit 中转换坐标?

How do I convert coordinates in SpriteKit?

我试图掌握 SpriteKit 中的转换内容,但尽管阅读了 SO 上的文档和几篇文章,但我似乎无法正确理解.据我所知,有两个独立工作的坐标系,一个用于 scene,一个用于 view,这就是为什么我不能使用 [=14] 之类的东西=] 来确定节点可以关联的屏幕角。我做对了吗?

无论如何,这是我转换坐标的尝试:

let mySquare = SKShapeNode(rectOf: CGSize(width: 50, height: 50))
mySquare.fillColor = SKColor.blue      
mySquare.lineWidth = 1

let myPoint = CGPoint(x: 200, y: 0)

let newPosition = mySquare.convert(myPoint, from: self)     
mySquare.position = newPosition

print(newPosition)  
self.addChild(mySquare)

print returns 与进入的位置完全相同,所以显然我没有做对,但我尝试了许多不同的星座,但几乎没有结果;坐标保持不变。我也试过 let myPoint = CGPoint(x: UIScreen.main.bounds.maxX, y: UIScreen.main.bounds.maxY) 但也一样;没有转换。

我错过了什么?在我的脑海中,我将上面的转换读作“从 view 坐标系转换 myPoint 并将其用于我的 node mySquare。

周围有很多坐标系,因此有很多潜在的混淆来源:

  1. 场景坐标:那是你的游戏世界,也是你在想象坐标以及如何整体定位事物时通常会想到的。
  2. 节点:节点有自己的坐标系。一旦开始构建层次结构,这就很重要了。想象一下,例如,一个 on-screen 操纵杆,其背景显示运动方向图形,中央 "knob" 玩家可以操纵。您可以将操纵杆表示为具有两个 children 的节点。一个 child 是背景精灵,另一个是旋钮精灵。背景精灵自然会位于位置 (0,0),这意味着整个操纵杆的中心。旋钮会四处移动,(0,0) 表示居中,也许 (0,100) 表示向上一点。场景中的整体操纵杆可能位于 (200,300)。然后背景精灵将出现在场景中的 (200,300) 处,当旋钮向上时,将出现在场景中的 (200,300)+(0,100) = (200,400) 处。 convert(from:)convert(to:) 用于在节点层次结构内进行转换。您可以通过 knob.convert(.zero, to: scene)joystick.convert(knob.position, to: scene) 询问旋钮在整个场景坐标中的位置。您很少需要进行这种转换。
  3. 视图坐标:视图是场景中的 window,即实际显示的内容。如果您玩的是全屏游戏,则视图基本上由屏幕大小(以磅为单位)决定。视图坐标映射到场景坐标的方式决定了您实际看到的场景部分。如果需要在视图坐标和场景坐标之间切换,请使用场景的 convertPoint(fromView:)convertPoint(toView:) 方法。

如果你没有做任何特殊的事情并且场景大小与视图大小相同,那么 scene-view 映射将在场景的左下角有 (0,0)看法。另一个常见的约定是通过将​​场景的 anchorPoint 设置为 (0.5,0.5),使屏幕中心的场景中有 (0,0)。或者,也许您已经设计了场景,使世界的大小为 2000x2000,并且将进行重要的缩放,并且可能涉及 letter-boxing 或裁剪(取决于场景 scaleMode 的设置)。或者,如果您的游戏有一个相机节点,例如,相机设置为跟随玩家,那么 view-to-scene 映射将随着玩家移动而改变。

在您的代码中,调用 mySquare.convert(from:) 甚至没有任何意义,因为在您执行 "conversion".[=21 时尚未将正方形添加到场景中=]

无论如何,如果你真的想做类似 "put a square in the top-left corner of the screen" 的事情,那么你可以在视图的框架中获取点并将其转换为场景坐标并将正方形的位置设置为该点。

override func didMove(to view: SKView) {
  ...
  mySquare.position = convertPoint(fromView: CGPoint(x: view.frame.minX, y: view.frame.minY))
  addChild(mySquare)
  ...
}

编辑:我鼓励您在初步考虑游戏应如何映射到具有不同尺寸和宽高比的屏幕的设备之后,主要从整体场景的角度考虑。一旦您根据场景进行思考,场景的 frame(而不是视图的框架)就会成为您想象 "at the left edge" 或 "near the bottom right" 时最自然的参考。