我对swift非常熟悉,但我已经开始在spritekit中涉足我的手了。我一直在关注创建一个无尽的跑步者的教程。作者采用的方法是创建一个包含所有子节点的单个SKNode。然后移动此容器节点,而不是单独移动所有子节点。但令我难过的是容器节点没有与之相关的大小,所以我对它如何/为何起作用感到有点困惑,作者并没有真正解释它。
所以我们有
let containerNode = SKNode()
let thePlayer = Player("image":"player") //SKSpriteNode
let inc = 0
override func didMoveToView(){
self.anchorPoint = CGPointMake(0.5,0)
addChild(containerNode )
containerNode.addChild(player)
moveWorld()
}
func moveWorld(){
let moveWorldAction = SKAction.moveByX(-screenWidth, y:0, duration:6)
let block = SKAction.runBlock(movedWorld)
let seq = SKAction.sequence([moveWorldAction,block])
let repeatAction = SKAction.repeatActionForever(seq)
containerNode.runAction(repeatAction)
}
func movedWorld() {
inc = inc + 1
addObjects()
}
func addObjects() {
let obj = Object()
containerNode.addChild(obj)
let ranX = arc4random_uniform(screenWidth)
let ranY = arc4random_uniform(screenHeight)
obj.position = CGPointMake(screenWidth * (inc + 1) + ranX, ranY)
}
我在上面的代码中省略了一些从int到float的转换,但是对于我想要理解的点,没有必要。
我明白为什么在创建新对象时我们通过增量来做多次,但是我没有得到的是containerNode没有大小,所以为什么它的子节目显示?这是最有效的方法吗?
我假设它只是方便而不是单独移动所有其他对象,但事实上它没有大小让我感到困惑。
答案 0 :(得分:3)
由于未呈现SKNode
,因此它不需要(或具有)size属性。只有SKLabelNode
子类(SKShapeNode
,SKSpriteNode
等)可见,需要大小(显式声明或隐式计算)。例如,SpriteKit需要知道具有20 x 20纹理的SKNode
的大小才能正确呈现它。您可以使用calculateAccumulatedFrame
的{{1}}方法确定其节点树中所有后代(除了其他SKNode
之外)的总大小(矩形)。
答案 1 :(得分:2)
如果我正确理解了SKNode的文档,这一小部分应该回答你的问题:
节点树中的每个节点都为其提供一个坐标系 儿童。将子项添加到节点树后,将其定位 通过设置其位置,在其父坐标系内 属性。节点的坐标系可以缩放和旋转 更改其xScale,yScale和zRotation属性。当一个节点的时候 坐标系缩放或旋转,应用此变换 既包含节点的内容,也包括其后代的内容。 Source
同样,如果我正确地读到这个,似乎当节点被添加到节点树时,它继承了它的父坐标系。因此,在这种情况下,默认情况下containerNode
与self
的大小相同。
另外根据SKNode的frame
属性:
框架是包含节点内容的最小矩形, 考虑节点的xScale,yScale和zRotation 属性。 Source
再次听起来如果没有设置框架,它会采用最小的矩形(在这种情况下为self
,或者可能会理解它是containerNode
的孩子,我不确定)它是自己的框架。
无论是什么情况,它都是从另一个SKNode继承它。