使用spriteKit在动画后恢复第一个图像

时间:2017-06-23 16:49:22

标签: swift sprite-kit

当该功能检测到我的播放器与炸弹之间发生碰撞时,我会对爆炸图像进行动画处理,但我的炸弹停留在最后一个并且不会重置为炸弹的第一张图像(炸弹停留在爆炸的最后一张图像上) )

我怎么能重置它?

非常感谢

// Contact Between Player and the Bomb

    if ( body1.categoryBitMask == PhysicsCategories.Player && body2.categoryBitMask == PhysicsCategories.Rock ) {


        let time = SKAction.wait(forDuration: 0.20)

        // Play sound of explosion
        let sound = SKAction.playSoundFileNamed("explosion.wav", waitForCompletion: false)

        //explosion image
        let explosion = SKAction.run(){

            let p0 = SKTexture.init(imageNamed: "bombe")
            let p1 = SKTexture.init(imageNamed: "bombe2")
            let p2 = SKTexture.init(imageNamed: "bombe3")
            let p3 = SKTexture.init(imageNamed: "bombe4")
            let p4 = SKTexture.init(imageNamed: "bombe5")
            let p5 = SKTexture.init(imageNamed: "bombe6")
            let p6 = SKTexture.init(imageNamed: "bombe7")
            let p7 = SKTexture.init(imageNamed: "bombe8")
            let p8 = SKTexture.init(imageNamed: "bombe10")

            let frame: [SKTexture] = [p1, p2, p3, p4, p5, p6, p7, p8]

            let animations = SKAction.animate(with: frame, timePerFrame: 0.1)
            self.rock.run(SKAction.repeat(animations, count: 1))


        }

        // Move Player position Backward -30
        let playerPosition = SKAction.run(){


            self.player.position.x += -30


        }



        self.run(SKAction.sequence([sound, explosion, time, playerPosition]))

    }

1 个答案:

答案 0 :(得分:1)

首先我不会在didBeginContact中设置动画......没有理由在每次联系时都这样做。它可能会导致奇怪的行为。

制作纹理图集对象。 在其他地方设置你的动画。

来自Xcode:

“SKTextureAtlas对象是相关纹理对象的集合,可以从存储在应用程序包中的纹理图集创建,也可以在运行时创建的创建。 纹理图集可以提高内存使用率和渲染性能。 每当您拥有始终一起使用的纹理时,请将它们存储在地图集中。

E.g为您的GameScene或Rock类创建一个存储的属性......无论什么都是最有意义的。如果你在Rock类中这样做...尽管调整代码。我假设GameScene。

var explodeAction:SKAction?

创建一个存储爆炸动作的动画设置功能。如果您想在动画中使用它,请不要忘记p0。如果(对于动画)恢复为真,它将返回到初始纹理。

func setUpExplodeAnimation() {
        var atlasTextures = [SKTexture]()

        let p0 = SKTexture.init(imageNamed: "bombe")
        let p1 = SKTexture.init(imageNamed: "bombe2")
        let p2 = SKTexture.init(imageNamed: "bombe3")
        let p3 = SKTexture.init(imageNamed: "bombe4")
        let p4 = SKTexture.init(imageNamed: "bombe5")
        let p5 = SKTexture.init(imageNamed: "bombe6")
        let p6 = SKTexture.init(imageNamed: "bombe7")
        let p7 = SKTexture.init(imageNamed: "bombe8")
        let p8 = SKTexture.init(imageNamed: "bombe10")

// Note: I'm guessing p0 should be in here... so I added it. You left it out in your version. Decide if it should be a frame in the animation //

       let frame: [SKTexture] = [p0, p1, p2, p3, p4, p5, p6, p7, p8]

       for texture in frame {
           atlasTextures.append(texture)
       }


// By setting restore to true. When the action completes, the sprite’s texture is restored to the texture it had before the action completed //

// Also for resize . If true, the sprite is resized to match each new texture. If false, the size of the sprite remains at a constant size. //

// You want it to repeat so the first runthrough restore is false. 
        let animationRun1 = SKAction.animate(with: atlasTextures, timePerFrame: 0.1, resize: false, restore: false)

// restore is true so it goes back to initial texture on the 2nd runthrough // 

        let animationRun2 = SKAction.animate(with: atlasTextures, timePerFrame: 0.1, resize: false, restore: true)

        let seq = SKAction.sequence( [ animationRun1, animationRun2] )
        explodeAction = self.run(seq)

    }

注意:您需要在GameScene()didMove中调用setUpExplodeAnimation()(以查看:SKView),以便在加载时进行设置。这样,explodeAction就有了一个值。

现在你的didBegin函数看起来像这样

// Contact Between Player and the Bomb

    if ( body1.categoryBitMask == PhysicsCategories.Player && body2.categoryBitMask == PhysicsCategories.Rock ) {


        let time = SKAction.wait(forDuration: 0.20)

        // Play sound of explosion
        let sound = SKAction.playSoundFileNamed("explosion.wav", waitForCompletion: false)

        // Move Player position Backward -30
        let playerPosition = SKAction.run(){


           self.player.position.x += -30


        }



        self.run(SKAction.sequence([sound, explodeAction, time, playerPosition]))

    }

你可能想要添加一个if语句,或者某种程度上阻止你在didBegin中的代码多次触发。我发现didBeginContact经常意外地不止一次发生。 所以这可能会阻止这种情况。

创建名为

的GameScene存储属性

var explodeActionRunning:Bool = false

然后在你的didBegin

// Contact Between Player and the Bomb

    if ( body1.categoryBitMask == PhysicsCategories.Player && body2.categoryBitMask == PhysicsCategories.Rock ) {


        let time = SKAction.wait(forDuration: 0.20)

        // Play sound of explosion
        let sound = SKAction.playSoundFileNamed("explosion.wav", waitForCompletion: false)

        // Move Player position Backward -30
        let playerPosition = SKAction.run(){
            self.player.position.x += -30
        }

       let explodeActionStart = SKAction.run{
            self.explodeActionRunning = true
        }

       let explodeActionDone = SKAction.run{
            self.explodeActionRunning = false
        }

   // if statement prevents sequence from running twice. //
        if !self.explodeActionRunning {
                 self.run(SKAction.sequence([explodeActionStart, sound, explodeAction, time, playerPosition, explodeActionDone]))
        }

    }

让我知道这是否有帮助,或者是否有任何意义/不起作用。 我可能写了一两个错字。