为什么从未调用完成?
我非常抱歉,代码转储......因为我不知道为什么每个部分都有效,除了调用完成。
除完成外,所有未调用完成的SKAction都会运行。就是这样:
curtain.run(fadeMoveWipeAndReveal, completion: {onDone(), print("I'm done!!!!")})
在以下课程中:
import SpriteKit
class WipeCurtain: SKSpriteNode {
var wipeCurtainBase: SKSpriteNode?
var returnable = SKNode()
var moveRight = SKAction()
var node = SKNode()
init( color: SKColor,
size: CGSize,
time: TimeInterval,
reveal: @escaping () -> (),
onDone: @escaping () -> ())
{
super.init(texture: nil, color: color, size: size)
wipeCurtainBase = SKSpriteNode(color: color, size: size)
let show = SKAction.run(reveal)
let fadeIn = createFadeIn(duration: time)
let moveRight = createMoveRight(duration: time)
let wipeRight = createWipeRight(duration: time)
let fadeAndMove = SKAction.group( [ fadeIn, moveRight ] )
let wipeAndReveal = SKAction.group( [ show, wipeRight ] )
let fadeMoveWipeAndReveal = SKAction.sequence( [ fadeAndMove, wipeAndReveal ] )
if let curtain = self.wipeCurtainBase {
curtain.anchorPoint = CGPoint(x: 1, y: 0)
curtain.position = CGPoint(x: frame.size.width, y: 0)
curtain.zPosition = -1
curtain.name = "wipe"
curtain.run(fadeMoveWipeAndReveal, completion: {
onDone()
print("I'm done!!!!")
})
}
}
func createFadeIn(duration: TimeInterval) -> SKAction {
let fadeIn = SKEase
.fade(
easeFunction: .curveTypeLinear,
easeType: .easeTypeIn,
time: duration,
fromValue: 0,
toValue: 1
)
return fadeIn
}
func createMoveRight(duration: TimeInterval) -> SKAction {
let moveRight = SKEase
.move(
easeFunction: .curveTypeExpo,
easeType: .easeTypeOut,
duration: duration,
origin: CGPoint(
x: 0,
y: 0),
destin: CGPoint(
x: frame.size.width,
y: 0)
)
return moveRight
}
func createWipeRight(duration: TimeInterval) -> SKAction {
let wipeRight = SKEase
.createFloatTween(
start: 1,
ender: 0,
timer: duration,
easer: SKEase
.getEaseFunction(
.curveTypeExpo,
easeType: .easeTypeOut
),
setterBlock: {(node, i) in
node.xScale = i}
)
return wipeRight
}
func wipeWith() -> SKNode {
if let curtain = wipeCurtainBase?.copy() as! SKSpriteNode? {
returnable = curtain
}
return returnable
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
以下是使这项工作的gameScene,Xcode SpriteKit模板的一个非常轻微的修改版本:
import SpriteKit
import GameplayKit
class GameScene: SKScene {
private var swipe: WipeCurtain?
override func didMove(to view: SKView) {
swipe = WipeCurtain(color: .brown, size: frame.size, time: 1,
reveal: self.showOrNot,
onDone: self.previewer
)
}
func showOrNot(){
print(" Deciding to show or not.......")
}
func previewer(){
print("now running the previewer")
}
func touchDown(atPoint pos : CGPoint) {
addChild(swipe!.wipeWith())
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { self.touchDown(atPoint: t.location(in: self)) }
}
}
答案 0 :(得分:4)
在最终序列中使用run(block :() - &gt;())操作可获得所需的结果,但仍然无法理解为什么永远不会调用完成。这只是一种解决方法:
import SpriteKit
class WipeCurtain: SKSpriteNode {
var wipeCurtainBase: SKSpriteNode?
var returnable = SKNode()
var moveRight = SKAction()
var node = SKNode()
init( color: SKColor,
size: CGSize,
time: TimeInterval,
reveal: @escaping () -> (),
onDone: @escaping () -> ())
{
super.init(texture: nil, color: color, size: size)
wipeCurtainBase = SKSpriteNode(color: color, size: size)
let show = SKAction.run( reveal )
let endBlock = SKAction.run( onDone )
let fadeIn = createFadeIn(duration: time)
let moveRight = createMoveRight(duration: time)
let wipeRight = createWipeRight(duration: time)
let fadeAndMove = SKAction.group( [ fadeIn, moveRight ] )
let wipeAndReveal = SKAction.group( [ show, wipeRight ] )
let fadeMoveWipeAndReveal = SKAction.sequence(
[ fadeAndMove, wipeAndReveal, endBlock ]
)
if let curtain = self.wipeCurtainBase {
curtain.anchorPoint = CGPoint(x: 1, y: 0)
curtain.position = CGPoint(x: frame.size.width, y: 0)
curtain.zPosition = -1
curtain.name = "wipe"
curtain.run(fadeMoveWipeAndReveal)
}
}
func createFadeIn(duration: TimeInterval) -> SKAction {
let fadeIn = SKEase
.fade(
easeFunction: .curveTypeLinear,
easeType: .easeTypeIn,
time: duration,
fromValue: 0,
toValue: 1
)
return fadeIn
}
func createMoveRight(duration: TimeInterval) -> SKAction {
let moveRight = SKEase
.move(
easeFunction: .curveTypeExpo,
easeType: .easeTypeOut,
duration: duration,
origin: CGPoint(
x: 0,
y: 0),
destin: CGPoint(
x: frame.size.width,
y: 0)
)
return moveRight
}
func createWipeRight(duration: TimeInterval) -> SKAction {
let wipeRight = SKEase
.createFloatTween(
start: 1,
ender: 0,
timer: duration,
easer: SKEase
.getEaseFunction(
.curveTypeExpo,
easeType: .easeTypeOut
),
setterBlock: {(node, i) in
node.xScale = i}
)
return wipeRight
}
func wipeWith() -> SKNode {
if let curtain = wipeCurtainBase?.copy() as! SKSpriteNode? {
returnable = curtain
}
return returnable
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
答案 1 :(得分:2)
我想把注意力集中在以下几行:
违规代码是:
curtain.run(fadeMoveWipeAndReveal, completion: {
onDone()
print("I'm done!!!!")
})
您可以将fadeMoveWipeAndReveal
替换为show
之类的其他操作:
let show = SKAction.run(reveal)
您将看到永远不会调用完成。为什么?因为它在WipeCurtain初始化期间第一次运行但操作在完成之前被删除,所以下次重新调用此操作以运行touchesBegan
时,将永远不会调用完成。
您可以通过在curtain.run
代码中添加断点并启动项目来测试它:
正如您可以看到断点在初始化期间立即停止项目,在此阶段,操作在完成之前被删除。
关于您的解决方法,这是正确的,它可以正常运行,因为您删除completion
并使用每次调用时都正确执行的SKAction.sequence
。
<强>详情:
copy
方法适合我,我怀疑有些人有问题,因为在互联网上有更多关于SKEase的版本,可能其中一些可能有问题,但this版本运行良好通过以下两个屏幕截图:
答案 2 :(得分:1)
.copy()
不会以这种方式复制块或闭包。这不是一个错误,苹果缺乏计划,或者他们没有向任何人透露的一些原则。它可能是NSObject的东西,因为你不能持久阻塞,或者使用NSCoder(afaik)。
从Xcode 8之前的角度来看,除了CRASH之外,这一切都不应该在所有AFAIK上做任何事情。你只需要调用一次初始化程序(用curtain
实际工作的东西),你没有& #39; t最初将它添加到场景中。
我建议采取不同的方法,或者在你提出时使用解决方法。也许初始化新节点甚至比.copy()
更快。需要进行测试才能看出它的性能如何。
我的猜测是SKNode的NSObject和NSCoder一致性......所有节点都符合NSCoder,你不能将NSCoder与闭包/块一起使用,至少不是我知道的..甚至试图转换为/来自NSData或NSString。