如何绕非原点(质心)正确旋转SKSpriteNode?
解决SpriteKit节点绕质心旋转并同步朝向的问题
需求背景
在GameScene中存在一组排列规整的SKSpriteNode,位置按固定间隔分布(例如(0, 0)、(0, 150)、(0, 300)),需要实现以下效果:
- 所有节点围绕它们的位置质心进行旋转
- 每个节点的朝向与旋转方向保持一致
初始方案与问题
最初尝试将所有节点放入一个容器SKNode,通过旋转容器实现整体旋转。这种方式虽然能完成旋转,但无法单独控制每个节点的zRotation和position,因此改用2D旋转矩阵实现。但最初的矩阵应用代码存在以下问题:
- 节点顺时针旋转至约180度后会出现原地抖动
- 反向旋转时无法回到初始位置
- 多次拖动控制滑块后,节点会逐渐向质心收敛
修正后的实现方案
核心思路是先将节点的位置平移至以质心为原点的坐标系,再应用旋转矩阵计算新位置,同时根据滑块的当前值直接设置节点的zRotation,确保朝向与旋转方向同步。
核心代码
@objc func sliderValueDidChange(_ sender: UISlider) { guard let scene = view.scene as? GameScene else { return } let nodes = scene.nodes let angleChange = (prevSliderVal - CGFloat(sender.value)) / 180 * .pi var cenX = CGFloat.zero var cenY = CGFloat.zero for node in nodes { cenX += node.position.x cenY += node.position.y } cenX = cenX / CGFloat(nodes.count) cenY = cenY / CGFloat(nodes.count) for node in nodes { let translatedPos = CGPoint(x: node.position.x - cenX, y: node.position.y - cenY) let newX = translatedPos.x * cos(angleChange) - translatedPos.y * sin(angleChange) let newY = translatedPos.x * sin(angleChange) + translatedPos.y * cos(angleChange) node.position = CGPoint(x: newX, y: newY) let a = CGFloat(sender.value) / 180 * .pi node.zRotation = -a } prevSliderVal = CGFloat(sender.value) }
内容的提问来源于stack exchange,提问作者michael.yql
相关产品推荐
相关产品推荐

