SpriteKitは簡単に作って遊べる、パーティクルって面白いということを伝える記事になります。
SpriteKitとは
- アニメーションや物理ボディを利用できるフレームワーク。
- グラフィック処理が速く、ゲーム制作で主に使われる。2D、物理演算に関わるクラスを含んでいる。
- Appleが提供している
- iOS7 / Mac OS 10.9以降に対応
- cocos2dと異なり、Android対応不可
- UIKit × SpriteKitのコラボもできる
画面表示のイメージ
左はいつも見慣れているUIKitの場合、右はSpriteKitの場合です。こうやってみるとUIKitとSpriteKitは似てますね。
今回登場するSpriteKitの要素
SKNode
SpriteKitコンテンツのほとんどの根底にあるクラス。このクラス自体は何か視覚的なコンテンツを提供するわけではなく、ベースラインの挙動を提供するのが主な役割。NSObject的なもの。
SKScene
シーンを表す。ゲームの1画面に相当する。
SKView
SpriteKitを表示する専用のView。UIView的なもの。
Particle
型のレンダリング技術では再現が難しい、「高度に無秩序」なもの。爆発した時の演出等に使われる。
作ってみる
完成物
起動するとTableViewが表示されます。各セルをタップするとその名前に合ったパーティクルが表示されます。
画面遷移した時にTableViewが上下してしまうというバグがあるのはわかってます。。。そのうち直します。
コード
ここに上げてます。
https://github.com/akatsuki174/SpriteKitParticleSample
動作環境
Xcode: 7.3.1
Swift: 2.2
プロジェクト作成
いつもは通り、Single View Applicationを選択して作成します。ちなみにSpriteKitだけを扱う場合はGameというものを選択すればOKです。
パーティクルファイル追加
File -> New -> FileからSpriteKit Particle Fileというものを選択してください。
8種類の中から選択することができます。今回はFireしてみます。
これでNextをクリックして名前を付ければとりあえずパーティクルファイルの完成です。
パーティクルの設定値をいじる
すでにSpriteKitで使用できるパーティクルのパラメータ一覧、【SpriteKit】爆発や雪などの表現ができる「Particle File」についてという記事が上がっているので説明は省略します。いろいろいじって遊んでみると面白いと思います。
パーティクルを表示させる
まずspriteを表示しているVCの中身です。
class ContentsViewController: UIViewController {
var text: String?
@IBOutlet weak var skView: SKView!
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.grayColor()
self.setupParticle()
}
func setupParticle() {
//skView.allowsTransparency = true // 今回は不要。普通はtrueにする。
//skView.userInteractionEnabled = false // 今回は不要。必要であればfalseにする。
let scene = ParticleScene.unarchiveFromFile("ParticleScene") as! ParticleScene
skView.presentScene(scene)
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
let scene = self.skView.scene as! ParticleScene
if let t = text {
scene.show(t)
}
}
}
extension SKNode {
class func unarchiveFromFile(file : NSString) -> SKNode? {
if let path = NSBundle.mainBundle().pathForResource(file as String, ofType: "sks") {
let sceneData = try! NSData(contentsOfFile: path, options: .DataReadingMappedIfSafe)
let archiver = NSKeyedUnarchiver(forReadingWithData: sceneData)
archiver.setClass(self.classForKeyedUnarchiver(), forClassName: "SKScene")
let myScene = archiver.decodeObjectForKey(NSKeyedArchiveRootObjectKey) as! ParticleScene
archiver.finishDecoding()
return myScene
} else {
return nil
}
}
}
■unarchiveFromFile(file : NSString)
引数で指定されたファイル名のsksファイルをバンドルからロードしています。
■setupParticle()
今回はskView.allowsTransparency = trueの指定をしていません。そのためskViewの背景は黒になっています。UIKitを使っていて背景を透明にしておきたい時はtrueに設定しておいてください。
また、skView.userInteractionEnabled = falseの指定も今回はしていません。UIKit側でイベントを取りたいときはfalseにしておいてください。
class ParticleScene: SKScene {
func show(type: String) {
if (self.children.count == 0) {
guard let path = NSBundle.mainBundle().pathForResource("\(type)Particle", ofType: "sks") else {
return
}
let particle = NSKeyedUnarchiver.unarchiveObjectWithFile(path) as! SKEmitterNode
particle.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
self.addChild(particle)
}
}
}
■position
今回あまり意識することはないですが、SpriteKitでいう座標(0,0)は左下なので注意してください。
■addChild
sceneにパーティクルが追加されます。
基本はこれで完成です。パーティクルを表示して遊ぶだけの簡単なアプリを作ることが出来ました。
おまけ:あれ?パーティクルが表示されない!
いろいろいじっているとこんな自体に遭遇することがあると思います。
再現方法
- パーティクルファイルを開き、左ペインで値をいじる
- 別のファイルに移動
- 再び1のファイルに戻る
原因
Xcodeのバグらしいです。stackoverflowに上がってました。
解決方法
先ほどのstackoverflowに書かれている通りの方法で解決できます。一番簡単なのは該当のファイルを開いた状態でcommand + control + wを実行することです。これで、別のファイルに移動→再び該当のファイルに戻るという動作をすればパーティクルが復活しています。