我有一个1500 x 600像素的移动背景,并使用以下代码不断在屏幕上垂直移动:
let bgTexture = SKTexture(imageNamed: "bg.png")
let moveBGanimation = SKAction.move(by: CGVector(dx: 0, dy: -bgTexture.size().height), duration: 4)
let shiftBGAnimation = SKAction.move(by: CGVector(dx: 0, dy: bgTexture.size().height), duration: 0)
let moveBGForever = SKAction.repeatForever(SKAction.sequence([moveBGanimation, shiftBGAnimation]))
var i: CGFloat = 0
while i < 3 {
bg = SKSpriteNode(texture: bgTexture)
bg.position = CGPoint(x: self.frame.midX, y: bgTexture.size().height * i)
bg.size.width = self.frame.width
bg.zPosition = -2
bg.run(moveBGForever)
self.addChild(bg)
i += 1
}
我现在想要在x个时间后进入屏幕的新背景,让玩家感觉游戏正在进入游戏的不同部分。
我可以将此代码放入一个函数中,并在说出20秒之后用NSTimer触发它,但是将新bg的开始位置更改为屏幕外?
答案 0 :(得分:1)
repeatForever操作的麻烦在于你不知道他们在某个时刻的位置。 NSTimers并不像你想的那么精确,所以使用定时器可能会错过正确的时间或过早跳转,具体取决于渲染速度和帧速率。
我建议用bgAnimation替换你的moveBGForever作为你移动的序列&amp;轮班行动。然后,当您运行bgAnimation操作时,使用{self.cycleComplete = true}的完成块运行它。 cycleComplete将是一个布尔变量,指示动作序列是否完成。在场景更新方法中,您可以检查此变量是否为真,如果是,则可以再次运行序列操作。别忘了将cycleComplete var重置为false。
也许这听起来更复杂,但可以控制您是否要再运行一个周期。如果没有,那么你可以改变纹理并再次运行循环。
或者你可以保持原样,只有在确保精灵位于可见区域之外时才改变纹理,例如:其Y位置>查看大小高度。
在SpriteKit中,您可以使用完成块的等待操作。这比使用NSTimer更直接。
所以,回答你的问题 - 当使用动作在屏幕上移动精灵时,你不应该随时改变精灵的位置 - 这就是动作的作用。您只需要确保在位置不在屏幕时更新纹理。到时候,显然会显示一些精灵,所以你不能同时改变所有3个精灵的纹理。为此,您可能需要一个辅助变量来检查更新周期(如上所述)并在时间正确时替换纹理(精灵Y pos在屏幕外)。