【Swift】UIKitベースの画面でSpriteKitでエフェクトを追加する
iOSオールスターズでSpriteKitがUIKit上で使えることを知った
iOSオールスターズというイベントに行ってきた。イベントレポート書こうと思ったけど、最速でいいのがまとまってたのでさぼりましたw
ためになる発表が多かったけど、その中でも @ryusukefuda さんのSpriteKitでリッチな演出を追加するって発表で、UIKit上でも簡単にSpriteKitを取り込めるというのを初めて知ったので試してみた。
今更ながら昨日の登壇の資料です。
"まだiOSでリッチな演出に疲弊してるの?" https://t.co/6q5Px3CkcB
#dotsios
— Ryusuke Fuda (@ryusukefuda) February 15, 2015
目指すもの
Twitterのファボしたときのきらりーんってアニメーション。これっぽいのが作りたい。
まずはSpriteKitの基本を知る
そもそもどうやってUIKit上にSpriteKitのオブジェクトを追加できるかがわからないのでそれを調べてみた。SpriteKitのビューを貼るだけの最低限の作業を簡単にまとめるとこんな感じ。
- SKSceneを作る。
- SKViewを作る
- SKViewで1をpresentする
- SKViewをself.viewにはる
パーティクルをUIKit上にはる
基本がわかったところでパーティクルを表示してみる。
SKSceneをつくる
SKSceneが実際に画面上でユーザーの目に触れる部分。なので、clearColor
を指定してる。
// STEP1: 100×100の大きさのものを作る let w = CGFloat(100), h = CGFloat(100) let scene = SKScene(size: CGSizeMake(w, h)) scene.backgroundColor = UIColor.clearColor()
SKViewを作ってはる
View
と名乗っておきながらこいつは画面上では目に見えない。backgroundColor
は持ってるんだけど、色を指定しても表示されない。UIKitでいうContainerViewに近いかなー。SKScene
をpresentして、addSubviewしておく。
// STEP2: self.viewの中心付近に貼る let centerX = CGRectGetMidX(self.view.frame) let centerY = CGRectGetMidY(self.view.frame) let skFrame = CGRectMake(centerX - w / 2, centerY - h / 2, w, h) let skView = SKView(frame: skFrame) // インスタンス変数で宣言してる skView.allowsTransparency = true // UIKit上で使うときは必須。後ろが黒くなっちゃう skView.userInteractionEnabled = false // UIKitで使うときは必須。UIKit側でイベントがとれない skView.presentScene(scene) // STEP3: add sk view self.view.addSubview(skView)
ここまでで、SpriteKitの表示領域が見えるようになってる。(試しにClearColorじゃなくしたりすればみれる) 次は、パーティクルの表示
きらりーんってなるパーティクルを作る
パーティクルの種類ってテンプレートだと、bokeh、fire、spark、smokeとか色々あって、どれを選べばいいのかーとかよくわからなかったけど全部見てみたらどれももとは同じもので、パラメータだけが違うものだということが分かった。要は、fireとsparkって同じでtextureとしてspark.pngを使っていて、あとはパラメータを変えれば、fireにもsparkにもなるってこと。
パラメータをいじってみる
sparkが一番近そう。で、色々いじってるとX方向の加速度とかY方向の加速度がいじれたりパーティクルが飛び散ったりする方向とかランダム具合とかで設定するんだなーってことが分かった。色々いじってなんか無理やりきらりーんに一番近そうっぽくしてみた。まぁ全然違うんだけどw まぁこれをtwinkle.sksって名前で保存する。
パーティクルをコードからシーンに追加する
さっき作ったsksファイルから SKEmitterNode
を作る。それをscene
にaddChild
することで表示される。
// STEP4: add particle to scene let path = NSBundle.mainBundle().pathForResource(kParticleName, ofType: "sks") let particle = NSKeyedUnarchiver.unarchiveObjectWithFile(path!) as SKEmitterNode particle.name = kParticleName particle.position = CGPointMake(w / 2, h / 2) scene.addChild(particle)
完成品
星が拡大するアニメーションもつけて、追加したのがこれ。全然似てないw
まとめ
ほんとうに簡単だった。まぁ理解するまではちょっと時間かかったけど。大量にオブジェクトをはったときのパフォーマンスとかは考える必要ありそうだけど。 そして、Twitterのきらりーんのアニメーションとはまったく似てないw