在iOS上的SpriteKit中,缩放纹理的精灵会产生不正确的帧?

我正在学习SpriteKit游戏开发的乐趣,我遇到了一个看似简单的问题让我难过。

基本上,在我缩放纹理化的SKSpriteNode之后,帧不是我所期望的。 我已经想出了一些黑客来迫使它达到我想要的水平,但我正在努力了解发生了什么。 任何想法赞赏!

这是我的代码WITHOUT SCALING:

func addSpaceship() { let spaceship = SKSpriteNode.init(imageNamed: "rocketship.png") spaceship.name = "spaceship" // spaceship.setScale(0.50) let debugFrame = SKShapeNode.init(rect: spaceship.frame) debugFrame.strokeColor = SKColor.greenColor() spaceship.addChild(debugFrame) spaceship.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame) - 150) self.addChild(spaceship) } 

我的应用程序看起来像这样: 与绿色调试框架的未缩放的船

现在,如果我在缩放它的代码行中发表评论(spaceship.setScale(0.50)),我得到这个:

与绿色调试框架的缩放的船

请注意,太空船在第二张图像中按比例缩小,但帧缩放甚至更小。 为什么?

如果我将缩放线移动到我将太空船添加到场景后,它会按照我的预期进行,但这似乎是错误的:

这是在将太空船添加到场景后调用setScale的代码:

 func addSpaceship() { let spaceship = SKSpriteNode.init(imageNamed: "rocketship.png") spaceship.name = "spaceship" let debugFrame = SKShapeNode.init(rect: spaceship.frame) debugFrame.strokeColor = SKColor.greenColor() spaceship.addChild(debugFrame) spaceship.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame) - 150) self.addChild(spaceship) spaceship.setScale(0.50) } 

以下是运行我的应用程序的内容:

添加到场景后缩放

这样可行,但为什么有必要呢?

下面有人建议,这是SKShapeNode的一个错误。 但是,用SKLabelNode替换SKShapeNode具有相同的问题:

 func addSpaceship() { let spaceship = SKSpriteNode.init(imageNamed: "rocketship.png") spaceship.name = "spaceship" spaceship.setScale(0.50) let scoreNode = SKLabelNode(text: "100") scoreNode.position = CGPointMake(CGRectGetMidX(spaceship.frame), CGRectGetMaxY(spaceship.frame)) scoreNode.fontColor = SKColor.redColor() scoreNode.fontSize = 15.0 scoreNode.fontName = "Monaco" scoreNode.zPosition = 10.0 spaceship.addChild(scoreNode) spaceship.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame) - 150) self.addChild(spaceship) } 

这给了我们:

与SKLabelNode相同的问题

目的是让得分标签(scoreNode)居中于火箭上方 ,但正如您所看到的那样,它位于顶部舷窗的顶部。 在我打电话给spaceship.setScale后,宇宙飞船的框架出现了问题。

我做了一个额外的发现:在我将太空船添加到场景之后,不需要进行setScale调用。 它只需要在我将debugFrame / scoreNode添加到太空船之后。 如果我在那之后设置了比例,一切都很好:

 func addSpaceship() { let spaceship = SKSpriteNode.init(imageNamed: "rocketship.png") spaceship.name = "spaceship" let scoreNode = SKLabelNode(text: "100") scoreNode.position = CGPointMake(CGRectGetMidX(spaceship.frame), CGRectGetMaxY(spaceship.frame)) scoreNode.fontColor = SKColor.redColor() scoreNode.fontSize = 15.0 scoreNode.fontName = "Monaco" scoreNode.zPosition = 10.0 spaceship.addChild(scoreNode) spaceship.setScale(0.50) spaceship.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame) - 150) self.addChild(spaceship) } 

这导致:

这很有效

您的问题可能是这两行的顺序:

  spaceship.setScale(0.50) let debugFrame = SKShapeNode.init(rect: spaceship.frame) 

你缩小了宇宙飞船,然后用缩放的太空船计算矩形的大小。 然后,当渲染矩形时,缩小到原始太空船大小的四分之一。

如果你交换线,它应该按预期工作。

一般来说,最好在实际尺寸中进行构图,然后在将其添加到场景之前对整体进行缩放。

首先,让我SKShapeNode前言是一个非常时髦(也许是错误的类)。 至少它是在之前的spritekit迭代中。 如果您的目标是为物理目的添加调试矩形。 您可以在showsPhysics内的SKView类上打开showsPhysics

inheritance我的实验

  let redbox = SKSpriteNode(color: SKColor.redColor(), size: CGSize(width: 100, height: 100)) redbox.position = CGPoint(x: self.size.width/2, y: self.size.height/2) redbox.setScale(0.5) let debugFrame = SKShapeNode(ellipseOfSize: redbox.size) debugFrame.strokeColor = SKColor.greenColor() self.addChild(redbox) redbox.addChild(debugFrame) 

在此处输入图像描述

看起来和你的一样。 如果我在添加节点后调用setScale,那么我的圆圈会填满我的红色方块。

另外,如果我保持一切都一样,但我只是直接将我的调试帧添加到场景中,它将以正确的方式缩放,很奇怪吧?

好的另一个测试。 请注意,我将greenbox设置为红盒大小的50%,以便我们可以看到下面的红框。 如果这里发生了错误,那么greenbox将最终填满红盒的25%。

  let redbox = SKSpriteNode(color: SKColor.redColor(), size: CGSize(width: 100, height: 100)) redbox.position = CGPoint(x: self.size.width/2, y: self.size.height/2) redbox.setScale(0.5) let greenbox = SKSpriteNode(color: SKColor.greenColor(), size: CGSize(width: 50, height: 50)) self.addChild(redbox) redbox.addChild(greenbox) 

在此处输入图像描述

好的,所以我使用另一个SKSpriteNode做同样的事情,它的行为与我们期望的方式相同。 所以无论出于何种原因,当你使用SKShapeNode 作为孩子时 ,setScale被调用两次; 除非您在将节点添加到场景后设置比例。 但是SKSpriteNode不会发生这种情况。

答案是……我认为没有一个好的答案。 这可能是一个错误。 SKShapeNode有错误的历史。 SpriteKit有一些错误= /如果我错了,有人会纠正我。