SpriteKit - 在 SKAction 期间正确定位精灵
SpriteKit - correct location of sprites during SKAction
我正在编写一个具有连续(横向)滚动地形的应用程序,它由图像动态组成。所以我创建了一个 sprite,将它横向滚动,当它继续滚动时即将显示其右边缘时,我在它的右侧添加了第二个 sprite,它也会滚动,等等。当它们从左侧消失时,它们'已删除。
问题是当我添加新的精灵时,它和之前的精灵之间有一个小间隙(大约 4 像素),好像在将它放到屏幕上时,滚动动画已经移动了几个像素。
滚动class是这个-
import UIKit
import SpriteKit
private let lagOffset: CGFloat = 4.0 // currently, this is the only way I can get rid of the gap between terrain blocks
class GameScene: SKScene
{
private var terrainNumber = 2
private var followingTerrainBlock: TerrainBlock? = .None
override init(size: CGSize)
{
super.init(size: size)
// create the first terrain block
let terrainBlock = TerrainBlock(size: Size.terrainBlock, terrainNumber: 1)
terrainBlock.position = CGPoint(x: size.width / 2.0 + Size.terrainBlock.width, y: size.height / 2.0)
addChild(terrainBlock)
followingTerrainBlock = terrainBlock
moveTerrainBlock(terrainBlock)
}
required init?(coder aDecoder: NSCoder)
{
fatalError("init(coder:) has not been implemented")
}
func moveTerrainBlock(terrainBlock: TerrainBlock)
{
// create the next terrain block on a background thread as it's quite expensive
// it'll be ready in plenty of time for when it's needed
GCD.async { () -> () in
self.followingTerrainBlock = TerrainBlock(size: Size.terrainBlock, terrainNumber: self.terrainNumber)
}
var targetX = size.width / 2.0
let y = terrainBlock.position.y
let move = SKAction.moveTo(CGPoint(x: targetX, y: y), duration: Time.terrainScroll)
// move the terrain block to centre on the screen - at this point we add the following terrain block immediately behind it, off-screen
// the scroll animation lasts 5 seconds before the completion closure runs, by which time self.followingTerrainBlock has been ready for ages
terrainBlock.runAction(move) { [weak self]() -> Void in
if let strongSelf = self
{
strongSelf.terrainNumber++
// we have to put an offset into the position of the new terrain block, or there'll be a gap between the old & new blocks
strongSelf.followingTerrainBlock!.position = CGPoint(x: targetX + Size.terrainBlock.width - lagOffset, y: y)
strongSelf.addChild(strongSelf.followingTerrainBlock!)
// now we tell the new terrain block to follow the existing one
strongSelf.moveTerrainBlock(strongSelf.followingTerrainBlock!)
// then we continue moving the existing terrain block until it's off-screen, then remove the sprite
targetX -= Size.terrainBlock.width - lagOffset
let move = SKAction.moveTo(CGPoint(x: targetX, y: y), duration: Time.terrainScroll)
terrainBlock.runAction(move) { () -> Void in
terrainBlock.removeFromParent()
}
}
}
}
}
我想知道的是如何将以下地形块放在屏幕上,以便它们与前一个地形块的右边缘完全对齐。如果我停止动画并添加一个,没有偏移的位置是正确的,所以位置计算没有问题。
在创建每个块时,创建一个约束(常量 = 0),将其附加到前一个块...之后的每个块等等。
我相信随着每个块离开视图,约束也会解除分配,但您可能也必须考虑这部分。
我正在编写一个具有连续(横向)滚动地形的应用程序,它由图像动态组成。所以我创建了一个 sprite,将它横向滚动,当它继续滚动时即将显示其右边缘时,我在它的右侧添加了第二个 sprite,它也会滚动,等等。当它们从左侧消失时,它们'已删除。
问题是当我添加新的精灵时,它和之前的精灵之间有一个小间隙(大约 4 像素),好像在将它放到屏幕上时,滚动动画已经移动了几个像素。
滚动class是这个-
import UIKit
import SpriteKit
private let lagOffset: CGFloat = 4.0 // currently, this is the only way I can get rid of the gap between terrain blocks
class GameScene: SKScene
{
private var terrainNumber = 2
private var followingTerrainBlock: TerrainBlock? = .None
override init(size: CGSize)
{
super.init(size: size)
// create the first terrain block
let terrainBlock = TerrainBlock(size: Size.terrainBlock, terrainNumber: 1)
terrainBlock.position = CGPoint(x: size.width / 2.0 + Size.terrainBlock.width, y: size.height / 2.0)
addChild(terrainBlock)
followingTerrainBlock = terrainBlock
moveTerrainBlock(terrainBlock)
}
required init?(coder aDecoder: NSCoder)
{
fatalError("init(coder:) has not been implemented")
}
func moveTerrainBlock(terrainBlock: TerrainBlock)
{
// create the next terrain block on a background thread as it's quite expensive
// it'll be ready in plenty of time for when it's needed
GCD.async { () -> () in
self.followingTerrainBlock = TerrainBlock(size: Size.terrainBlock, terrainNumber: self.terrainNumber)
}
var targetX = size.width / 2.0
let y = terrainBlock.position.y
let move = SKAction.moveTo(CGPoint(x: targetX, y: y), duration: Time.terrainScroll)
// move the terrain block to centre on the screen - at this point we add the following terrain block immediately behind it, off-screen
// the scroll animation lasts 5 seconds before the completion closure runs, by which time self.followingTerrainBlock has been ready for ages
terrainBlock.runAction(move) { [weak self]() -> Void in
if let strongSelf = self
{
strongSelf.terrainNumber++
// we have to put an offset into the position of the new terrain block, or there'll be a gap between the old & new blocks
strongSelf.followingTerrainBlock!.position = CGPoint(x: targetX + Size.terrainBlock.width - lagOffset, y: y)
strongSelf.addChild(strongSelf.followingTerrainBlock!)
// now we tell the new terrain block to follow the existing one
strongSelf.moveTerrainBlock(strongSelf.followingTerrainBlock!)
// then we continue moving the existing terrain block until it's off-screen, then remove the sprite
targetX -= Size.terrainBlock.width - lagOffset
let move = SKAction.moveTo(CGPoint(x: targetX, y: y), duration: Time.terrainScroll)
terrainBlock.runAction(move) { () -> Void in
terrainBlock.removeFromParent()
}
}
}
}
}
我想知道的是如何将以下地形块放在屏幕上,以便它们与前一个地形块的右边缘完全对齐。如果我停止动画并添加一个,没有偏移的位置是正确的,所以位置计算没有问题。
在创建每个块时,创建一个约束(常量 = 0),将其附加到前一个块...之后的每个块等等。
我相信随着每个块离开视图,约束也会解除分配,但您可能也必须考虑这部分。