【SpriteKit】ジャンプアクションを実装してみた

こんにちは、のっくんです。

今日はSpriteKitを使ってキャラクターをジャンプさせる方法をご紹介します。

実装してみた内容としては以下の通り。

  • ジャンプのアニメーションを作る
  • ジャンプボタンでジャンプする

順番に見ていきます。

ジャンプのアニメーションを作る

7枚の画像をパラパラ漫画のように表示させてアニメーションを作ります。

1枚あたりの表示時間は0.08秒にしました。

表示時間はコードを動かしつつ調整するのが良いです。

func createAnimations() {
    // ジャンプのアニメーションを追加するよ
    let jumpFrames:[SKTexture] =
        [textureAtlas.textureNamed("2_entity_000_JUMP_000"),
         textureAtlas.textureNamed("2_entity_000_JUMP_001"),
         textureAtlas.textureNamed("2_entity_000_JUMP_002"),
         textureAtlas.textureNamed("2_entity_000_JUMP_003"),
         textureAtlas.textureNamed("2_entity_000_JUMP_004"),
         textureAtlas.textureNamed("2_entity_000_JUMP_005"),
         textureAtlas.textureNamed("2_entity_000_JUMP_006"),
    ]
    
    // 1フレームあたりの表示時間は0.05秒
    jumpAnimation = SKAction.animate(with: jumpFrames,timePerFrame: 0.08)

}

func startJumpAnimation(){
    self.run(jumpAnimation)
}

アイドル状態やランニングと違って、一回限りのアクションになっています。

何回も実行する必要はありません。

ジャンプの制御

ジャンプボタンが押されたらジャンプのフラグをオンにします。

指がボタンから離れたらフラグをオフにします。

ボタンに名前をつけて、押されたボタンを判別するようにしています。

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    // タッチしたボタンによって処理を分ける
    for touch: AnyObject in touches {
        let location = touch.location(in: self)
        let node = self.atPoint(location)
        
        if ( node.name == "Jump") {
            self.nokkuman.jump = true
        }
    }
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    
    for touch: AnyObject in touches {
        let location = touch.location(in: self)
        let node = self.atPoint(location)
        
        if node.name == "Jump" {
            self.nokkuman.jump = false
        }
    }
}

ジャンプの処理は、GameScene.swiftのupdateに記載します。

updateはフレームが更新されるたびに呼ばれます。

var updateTime:Double = 0
// ジャンプ時間のインターバルを設定する
var jumpInterval:Double = 0.8

override func update(_ currentTime: TimeInterval) {
    
    // ジャンプフラグが立っていなければ終了
    guard self.nokkuman.jump else {
        return
    }
            
    // インターバルを空けないと再度ジャンプできないようにする
    if updateTime == 0 || currentTime - updateTime > jumpInterval {
        startJump()
        updateTime = currentTime
    }
}

ジャンプのフラグを確認してオンだったら、ジャンプ処理とアニメーションを開始します。

ジャンプ中に再度ジャンプボタンを押す行為を防ぐために、インターバル時間を設定しています。

連続してジャンプができてしまうと、鳥のように空を飛ぶことができてしまいます。

それはそれでゲームとしては面白いかもしれませんが、今回は人間キャラなので空を飛ぶのは禁止します。

updateTimeが0なのは初回時のジャンプ時です。

初回時は無条件でジャンプできるようにしています。

2回目以降は、現在時刻から前回のジャンプ時刻の差分を計算し、インターバル時間より大きいか比較しています。

ジャンプ処理

func startJump(){
    self.nokkuman.physicsBody?.applyImpulse(CGVector(dx: 0, dy: 15000))
    self.nokkuman.startJumpAnimation()
}

applyImpulseでy軸方向に衝撃を与えてキャラクターを浮かせます。

すいません、dyの値は割と適当です。

小さい値だとジャンプの高さが低かったので大きめにしました。

SKPhysicsBodyにはapplyImpulseとapplyForceがあります。

applyForceは連続的に加速度を与える時に使います。

上昇するロケットや鳥が羽ばたく時ですね。

今回は一瞬だけ衝撃を与えてジャンプさせるため、applyImpulseを使います。

アニメーションを開始するのもこのタイミングで行います。

ABOUTこの記事をかいた人

個人アプリ開発者。Python、Swift、Unityのことを発信します。月間2.5万PVブログ運営。 Twitter:@yamagablog