我在SpriteKit中有3个SKScenes,Swift:
等级1
游戏结束
在等级1和等级2中,我的角色移动由以下代码完成:
class Level1: SKScene, SKPhysicsContactDelegate {
func swipedRight(sender:UISwipeGestureRecognizer){
let moveRIGHT = SKAction.moveBy(CGVectorMake(60, 0), duration: 1)
Character.runAction(moveRIGHT)
}
func swipedLeft(sender:UISwipeGestureRecognizer){
let moveLEFT = SKAction.moveBy(CGVectorMake(-60, 0), duration: 1)
Character.runAction(moveLEFT)
}
let swipeRight:UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: Selector("swipedRight:"))
swipeRight.direction = .Right
view.addGestureRecognizer(swipeRight)
let swipeLeft:UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: Selector("swipedLeft:"))
swipeLeft.direction = .Left
view.addGestureRecognizer(swipeLeft)
当角色在第1级死亡时,我转换到" Game Over" SKScene,如果您愿意,可以重试1级。
然而,在第1级 - 游戏结束 - 第1级 - 游戏结束 - 第1级 - 游戏结束等来回之后,无论何时在第1级和第2级进行UISwipeGesture,FPS都会大幅下降。
然后我决定从级别1中删除UISwipeGestureRecognizer,然后故意在级别1和游戏结束之间来回,然后转到级别2.在执行此操作后,在级别2中使用UISwipeGestures时没有FPS丢失。
因此,我的结论是每当我一遍又一遍地使用UISwipeGestureRecognizer加载SKScene时,无论何时尝试启动滑动,它都会创建此FPS丢弃。
所以: 1)我是否错误地实现了这个UISwipeGestureRecognizer?
2)有没有其他方法可以在不使用UISwipeGestureRecognizer的情况下获得相同的角色移动效果?
谢谢大家!
答案 0 :(得分:2)
您需要在转换到新场景之前删除手势,否则会反复添加相同的手势,这会导致FPS问题。 例如,如果您在第2级场景中的行为与第1级场景不同,则游戏将会崩溃,因为旧的level1手势尚未移除。在更改场景之前尝试此操作
guard let view = view else { return }
guard view.gestureRecognizers != nil else { return }
for gesture in view.gestureRecognizers! {
if let recognizerTap = gesture as? UITapGestureRecognizer {
view.removeGestureRecognizer(recognizerTap)
}
if let recognizerSwipe = gesture as? UISwipeGestureRecognizer {
view.removeGestureRecognizer(recognizerSwipe)
}
}
为了让您的生活更轻松,您应该开始进行子类化。考虑制作一个BaseScene类,其中包含您在所有级别场景中显示的所有属性,控件,播放器精灵,标签等。否则,如果您有20个级别,则需要复制太多代码。它超级简单
像这样制作一个BaseScene
class BaseScene: SKScene, SKPhysicsContactDelegate {
只需在ViewDidLoad方法中设置所有关卡所需的手势和所有内容。还可以使用baseScene作为联系方法以及您需要在关卡之间共享的其他内容(gameOver方法等)
在你的关卡场景中,你应该像这样继承它们
class Level1Scene: BaseScene {
override func didMoveToView(view: SKView) {
super.didMoveToView(view) // imports everything from ViewDidLoad in base scene
// do other setUps specific to level 1 only
这将使您的代码更灵活。假设您使用BaseScene中的Update func暂停游戏,它将在子类级场景中工作,如上所述。但是,例如,如果在Level2中,您需要向仅在Level2中运行的Update func添加方法,您可以执行类似于ViewDidLoad方法的操作。 所以在你的2级场景中你可以说这个
override func update(currentTime: CFTimeInterval) {
super.update(currentTime) // will use all BaseScene update methods
// do something specific for level 2 only
现在,如果你想要更新的东西只在Level2场景中运行并忽略BaseScene中的所有更新方法而不是你根本不打电话
super.update(currentTime)
这几乎适用于所有方法,例如接触方法,触摸开始等。它是要走的路。