今回はインベーダーゲームのオブジェクトについての簡単なメモです。
SKSpriteNode についての話になります。
SKSpriteNode を使ったオブジェクト
最初の回で説明した通りゲームに登場するオブジェクトは基本的に SKSpriteNode の子クラスになっています。特にアニメーションするものは全てが SKSpriteNode の子クラスです。SKSpriteNode は SpriteKit の Node の中でも画像(SKTexture)を指定して作ることができる、ゲームで良く言われる「スプライト」を簡単に操作することができるクラスです。更に最初の回でも説明したように SKPhysicsBody によって衝突の判定もできます。
オブジェクトの画像を変える
インベーダーが移動する際に足?を閉じたり開いたりするアニメーションをしますが、これは閉じている状態と開いている状態の2種類の画像を用意して移動するたびに順番に表示しています。コードだとこんな感じです。
private func changeTexture() {
currentTextureNum += 1
self.texture = textures[currentTextureNum % textures.count]
}
SKSpriteNode の texture プロパティにセットする SKTextrure を変更するだけです。
今回のインベーダーは1フレームに1匹づつ動くので移動時にテクスチャを変えることでアニメーションさせていますが、フレーム毎にアップデートするような作りでない場合は SKSpriteNode に一連のアニメーション画像をループさせる SKAction.animate(with: timePerFrame: resize: restore:) を使う方法もあります。この場合は with に [SKTexture] を渡せば [SKTexture] の中身を順番に timePerFrame: のスピードで表示してアニメーションします。
オブジェクトを連続して動かす
例えば UFO が出現してから撃墜された時、その後のアニメーション?はこんな感じになっています。
- UFO を SKScene に addChild してから move(to:) で画面の端から端まで動かす
- UFO が撃墜されたら UFO のテクスチャを撃墜のテクスチャに変更
- 0.15 秒待ってから UFO を removeFromParent してテスクチャをUFO に戻す
- UFO のスコアを計算してその数字のテクスチャを UFO のあった場所に addChild する
- 1.0 秒待って数字のテクスチャを removeFromParent する
UFO の撃墜以降は基本的に SKSpriteNode.run(SKAction:, completion:) や SKAction.xxx(yyy:, completion:)、もしくは SKAction.sequence([SKAction]) を使って以下のように繋げて記述されています
removeAllActions()
texture = deadTexture
run(SKAction.wait(forDuration: UFOFinishWaitDuration), completion: {
self.removeFromParent()
self.texture = self.ufoTexture
self.running = false
let scoreValue: Int = UFOScore[shootCount % UFOScore.count]
addScore(scoreValue)
if let sprite = self.scoreSprites[scoreValue] {
sprite.position = self.position
scene.addChild(sprite)
sprite.run(SKAction.wait(forDuration: UFOScoreSpriteDuration), completion: {
sprite.removeFromParent()
})
}
})
ここで注意するのは一番最初の removeAllActions() です。
UFO は画面の端から端まで移動する move(to:) で動いていますが、このアクションが終わらない状態で撃墜されます。最初この removeAllActions() を入れないで実行していたのですが、それだと一度目の撃墜はちゃんと動作するのですが、撃墜された後の 2回目の UFO の出現時に UFO が出てこなくなってしまいました。多分きちんと終わらせなかったアクションがあったために、2回目の move(to:) がちゃんと動作しなかったのだと思います。
最後に
オブジェクトのメモでしたが初回に SKPhysicsBody の話や move(to:) move(by:) の話をしているので、今回は残るアニメーションや動作の繋げ方の話になりました。SKAction を sequence に入れて繋げたり、それを completion でまた繋げたりして、個々のオブジェクトに勝手に動いてもらって衝突したらそこで何かを行うって動かし方は面白いです。インベーダーゲームだと動きが少ないのであまり派手でないですが、個々のオブジェクトが別々の動きをしながら画面上にたくさんあるようなゲームを作って試してみたいと思います。
次回はデモ画面で使っているオブジェクトを順次表示させるリストのお話です。
が、ちょっと忙しいので少し先のアップデートになるかもしれません。