SpriteKit 中的缩放怪异

Zooming Weirdness in SpriteKit

我正在使用 Swift 和 SpriteKit 构建应用程序。该应用程序加载一个 SKSpriteNode,它正好是屏幕的大小,并将其放置在正好覆盖屏幕的位置。但是,用户可以随意移动和缩放此 SKSpriteNode。我关心 SKSpriteNode 的绝对位置,因为如果节点移动太多,我喜欢将它带回中心,或者 "snap" 它到屏幕的边缘。 (SKSpriteNode最终会持有一张地图)。

当节点的比例恰好为 1.0 时,位置值按我预期的方式工作。但是,当我缩放节点(使用捏合手势)并且比例增长到 1.0 以上时,位置值没有意义。这里有一些图片来说明我的意思。

在这里,您可以看到未缩放的节点与放置它的场景具有完全相同的尺寸和位置。X 和 Y 对于每个地图和场景都是 0:

但是,正如您在下一张图片中看到的,当我将地图缩放为更大的 SKSpriteNode 并移动它时,地图的左下角正好位于屏幕的左下角,缩放节点的 X 和 Y 值关闭。我希望 X 为 0,Y 为 0,但它们不是。

这里发生了什么,如何计算缩放节点的绝对位置?当我说 "absolute" 位置时,也许我的意思是相对于场景的位置?无论如何,感谢您的想法。

我想通了,尽管这并不容易。原来是"AnchorPoint Dorkitis"的情况。这种情况的主要症状是根据错误的假设编写代码,在我的例子中,让我陷入困境的假设是:

我节点的(X,Y)点是节点的左下角。 (假)

我一直都知道我将我的 AnchorPoints(场景和 SKSpriteNode 的)设置为 (x: 0.5, y: 0.5) 但我还没有意识到这也在改变位置在屏幕上实际存在的 (X,Y) 坐标(提示:中心)。

对于那些感兴趣的人,我为我的场景和我的 SKSpriteNode 计算了一组很好的计算属性 return X、Y、高度、宽度、顶部、底部、左侧和右侧值.我在这里与您分享它们:

var map_x: Int {
    get {
        return Int(self.position.x)
    }
}

var map_y: Int {
    get {
        return Int(self.position.y)
    }
}

var map_h: Int {
    get {
        return Int(self.frame.height)
    }
}

var map_w: Int {
    get {
        return Int(self.frame.width)
    }
}

var map_t: Int {
    get {
        return Int(self.position.y + self.frame.height/2)
    }
}

var map_b: Int {
    get {
        return Int(self.position.y - self.frame.height/2)
    }
}

var map_l: Int {
    get {
        return Int(self.position.x - self.frame.width/2)
    }
}

var map_r: Int {
    get {
        return Int(self.position.x + self.frame.width/2)
    }
}

var scene_x: Int {
    get {
        return Int((scene?.position.x)!)
    }
}

var scene_y: Int {
    get {
        return Int((scene?.position.y)!)
    }
}

var scene_h: Int {
    get {
        return Int((scene?.frame.height)!)
    }
}

var scene_w: Int {
    get {
        return Int((scene?.frame.width)!)
    }
}

var scene_t: Int {
    get {
        return Int((scene?.position.y)! + (scene?.frame.height)!/2)
    }
}

var scene_b: Int {
    get {
        return Int((scene?.position.y)! - (scene?.frame.height)!/2)
    }
}

var scene_l: Int {
    get {
        return Int((scene?.position.x)! - (scene?.frame.width)!/2)
    }
}

var scene_r: Int {
    get {
        return Int((scene?.position.x)! + (scene?.frame.width)!/2)
    }
}

我本可以让它们成为 CGFloat 值,而不是将它们包装在 Int() 中,但我在代码的其他地方需要整数,所以我想也可以在这里这样做。我认为我的下一步是弄清楚如何用更少的代码行来做到这一点 :)