【Swift】SpriteKitの使い方。SKVideoNodeで動画の再生、リピート(繰り返し)、アニメーションを実行する。
SKVideoNodeとは
本記事ではSKVideoNode(以下、ビデオノード)について説明する。ビデオノードとは、シーンで動画を作成するノードである。
背景を動画で見せたり、ゲームのチュートリアルでプレイ動画を再生したりするといった使い方が想像できる。
ビデオノードを試してみる。
実際にビデオノードを使ってシーンに動画を追加してみよう。以降の手順を行う前のXcodeプロジェクトをGitHubに置いたので、試してみる方はご利用下さい。⇒「テスト用プロジェクト」
事前準備ではパンダが踊る動画(movファイル)をプロジェクトに追加しておいた。この動画をシーンに追加して再生する。
TestScene.swiftを以下のコードに変更する。画面をタッチしたらビデオノードを再生するようにした。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
// // TestScene.swift // import Foundation import SpriteKit class TestScene:SKScene { let videoNode = SKVideoNode(fileNamed: "dance.mov") //現在シーン設定時の呼び出しメソッド override func didMove(to view: SKView) { //ビデオノードを画面中央に配置する。 videoNode.position = CGPoint(x: self.frame.midX, y: self.frame.midY) //ビデオノードのサイズを設定する。 videoNode.size = CGSize(width: 200, height: 230) //ビデオノードをシーンに配置する。 scene?.addChild(videoNode) } //画面タッチ開始時の呼び出しメソッド override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { //ビデオノードを再生する。 videoNode.play() } } |
以下は実際のプレイ動画
当初、動画(dance.mov)をアセットカタログ(Assets.xcassets)に格納して使おうと思っていたが、そうすると何故か動画が表示されないので、プロジェクトのフォルダに格納している。理由が分かったら追記する。
ビデオノードをアニメーションさせる
ビデオノードはSKSpriteNodeと同じように移動、回転、拡大縮小などのアクションでアニメーションさせられる。
実際にやってみよう。TestScene.swiftを以下のコードに変更する。サイズを2倍に変えながらタップした場所まで移動するようにした。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
// // TestScene.swift // import Foundation import SpriteKit class TestScene:SKScene { let videoNode = SKVideoNode(fileNamed: "dance.mov") //現在シーン設定時の呼び出しメソッド override func didMove(to view: SKView) { //ビデオノードを画面中央に配置する。 videoNode.position = CGPoint(x: self.frame.midX, y: self.frame.midY) //ビデオノードのサイズを設定する。 videoNode.size = CGSize(width: 100, height: 115) //ビデオノードをシーンに配置する。 scene?.addChild(videoNode) } //画面タッチ開始時の呼び出しメソッド override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { //タッチした座標を取得する。 let location = touches.first!.location(in: self) //タッチした位置まで移動するアクションを作成する。 let moveAction = SKAction.move(to: CGPoint(x:location.x, y:location.y), duration:0.5) //サイズを2倍にするアクションを作成する。 let scaleAction = SKAction.scale(to: 2.0, duration: 0.5) //アクションをまとめる。 let actionAll = SKAction.group([moveAction,scaleAction]) //アクションを実行する。 videoNode.run(actionAll) //ビデオノードを再生する。 videoNode.play() } } |
以下は実際のプレイ動画
動画をループさせる
実はビデオノードの動画を操作するメソッドにはplayメソッドとstopメソッドしか無い。なので、上記のビデオノードの作り方では動画をリピートしたり、再生速度を変えたりといったことができない。
公式リファレンスには以下のように記載されている。
⇒「公式リファレンス:SKVideoNode」
If you need more precise control over the video playback behavior, you can use AV Foundation to create an AVPlayer object for your video content and then use this object to initialize the SKVideoNode node. Then, instead of using the node’s playback methods, you use the AVPlayer object to control playback. The video content is automatically displayed in the video node. For more information, see AVFoundation Programming Guide.
つまり、再生をコントロールしたかったらAVPlayerクラスのインスタンスでビデオノードを初期化するということ。実際にやってみよう。TestScene.swiftを以下のコードに変更する。
AVPlayerの動画の再生が最後に到達したときにコールバックメソッドを呼び出すようにNotification Centerに登録し、コールバックメソッドが動画の再生位置を最初に戻している。
⇒参考「stackoverflow:How do you loop AVPlayer in Swift?」
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
// // TestScene.swift // import Foundation import SpriteKit import AVFoundation class TestScene:SKScene { var videoNode:SKVideoNode! //現在シーン設定時の呼び出しメソッド override func didMove(to view: SKView) { //AVPlayerクラスのインスタンスを作成する。 let url = NSURL.fileURL(withPath: Bundle.main.path(forResource: "dance", ofType: "mov")!) let asset = AVAsset(url: url) let playerItem = AVPlayerItem(asset: asset) let avPlayer = AVPlayer(playerItem: playerItem) //動画の最後に到達したときに何もしないようにする。 avPlayer.actionAtItemEnd = AVPlayerActionAtItemEnd.none; //動画の最後に到達したら通知するようにNotificationCenterに登録する。 NotificationCenter.default.addObserver(self, selector: #selector(self.reachEnd), name: NSNotification.Name("AVPlayerItemDidPlayToEndTimeNotification"), object: avPlayer.currentItem) //ビデオノードを作成する。 videoNode = SKVideoNode(avPlayer: avPlayer) //ビデオノードを画面中央に配置する。 videoNode.position = CGPoint(x: self.frame.midX, y: self.frame.midY) //ビデオノードのサイズを設定する。 videoNode.size = CGSize(width: 200, height: 230) //ビデオノードをシーンに配置する。 scene?.addChild(videoNode) } //画面タッチ開始時の呼び出しメソッド override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { //ビデオノードを再生する。 videoNode.play() } //動画終了時の呼び出しメソッド func reachEnd(notification: NSNotification) { //動画を最初の位置に戻す。 let avPlayerItem = notification.object as? AVPlayerItem avPlayerItem?.seek(to: kCMTimeZero) } } |
以下は実際のプレイ動画。パンダのダンスがループした。