はじめに
こんにちは。
つい先日、Apple純正のゲーム開発フレームワークである「SpriteKit」を使ったゲームアプリをリリースしました。
「Bumping Ball+」というタップ操作のみで簡単に遊べる、シューティングゲームです。
SpriteKitの動きや操作感などが気になる方は気楽に遊んでみてください。
ダウンロードはこちら
背景
私はSwiftで書きたかったということと物理演算を使いたかったという2つの理由で、Spritekitを採用しました。ゲームアプリであればcocos2d-xやUnityなどが有名ではありますが、簡易的に物理演算を使いたかったということと学習コストの低さを優先して、今回これらは採用しませんでした。
より本格的なゲームを作りたい方やC++が得意な方はSpritekitをわざわざ採用する理由は少ないかもしれません。unityなどはAndroidでもビルドできますし。最近では海外の9割弱はAndoridユーザであるという調査も出ていて、海外ユーザを視野に入れいているゲームであるならば、なおさらAndoroidに対応する必要があるといえますね。
概要
Spritekitでは主にview・scene・node・actionという4つの要素が存在し、これらの役割さえ理解できてしまえば、あとはリファレンス見ながらコツコツ開発をすすめることができると思います。以下に当アプリのプレイ画面を例に要素を並べてみました。
要素 | 役割 | クラス |
---|---|---|
view | UIViewのサブクラスです。描画を担当します。 | SKView |
scene | ゲームの画面です。この上にノードやビューを重ねていきます。 | SKScene |
node | テキストやキャラクター、画像などの物体を表示します。 | SKNode, SKSpriteNode, SKLabelNode... |
action | 爆発や移動などnodeをアニメーションさせます。 | SKAction |
上記の例のようにSKViewにSKScene、SKSceneにSKNodeを重ねて描画を制裁しています。SKActionでフェードアウトアニメーションや爆発などを表現できます。ステージ制ゲームの場合、一つのSKViewにステージごとに複数枚用意したSKSceneを重ねかえていく処理になると思います。
シーンの土台を作成してみる
では、実際にシーンを表示するために必要なコンポーネントを作成します。
まずSKViewのViewControllerを通常通り作成し、SceneViewController.swift
とします。
次にsksファイルを作成します。
File > New > File からSpriteKit Sceneを選択し、MyScene.sks
を作成します。
これで準備が整ったので、SceneViewControllerのUIViewをSKViewとして定義し、SKSceneを重ねます。
import SpriteKit
class SceneViewController: UIViewController {
let skView = SKView()
override func viewDidLoad() {
super.viewDidLoad()
if let scene = MyScene(fileNamed:"MyScene") {
let screensize = UIScreen.main.bounds.size
skView.frame = CGRect(x: 0, y: 0, width: screensize.width, height: screensize.height)
skView.showsFPS = true //sceneのfpsを表示します(開発用)
skView.showsNodeCount = true //sceneに表示されているノード数を表示します(開発用)
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = true
/* Set the scale mode to scale to fit the window */
scene.scaleMode = .resizeFill
skView.allowsTransparency = true
skView.presentScene(scene) //sceneをskviewに重ねます
self.view.addSubview(skView) //skviewをuiviewに重ねます
}
}
}
とりあえずこれでSKViewController > SKView > SKScene
という構図ができあがりました。
シーンを作成してみる
では、実際にシーンを作成していきます。
File > New > FileからCocoa Touch Classを選択してください。subclassをSKSceneに設定します。
必要に応じてメソッドをオーバーライドしてください。
import SpriteKit
import UIKit
class MyScene: SKScene, SKPhysicsContactDelegate {
override func didMove(to view: SKView) {
//シーンが生成されたタイミングで呼ばれます
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
//sceneにタッチした処理
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
//タッチして動かした処理
}
//このメソッドが毎回呼ばれます
override func update(_ currentTime: TimeInterval) {
super.update(currentTime)
}
//衝突判定処理
func didBegin(_ contact: SKPhysicsContact) {
}
}
まず継承しているSKPhysicsContactDelegate
クラスですがこちらを継承することで物理演算処理が可能になります。 他にもtouchBeganやtouchEndなどシーンのタッチ処理をかんたんに取得できます。update処理はシーンが動き出してから毎回呼ばれます。試しにprint出力してみると動きがわかりやすいと思います。updateを止めたい場合はskviewにisPaused
というプロパティが用意されており、こちらをfalse
にすることでシーン上のすべての処理が停止します。(一時停止処理などが使用用途でしょうか)
とりあえずこの状態でビルドしてみます。
まっさらではありますが、右下にノードとfpsが表示されていれば問題ないです。
ノードを重ねてみる
適当にラベルと画像を表示させてみます。
ラベルはSKLabelNode
、画像はSKSpriteNode
をそれぞれ使用します。
背景もbackgroudColorで変更できます。また座標位置に関して、sksceneとUIViewで異なりますので注意してください。
override func didMove(to view: SKView) {
//シーンが生成されたタイミングで呼ばれます
// 背景を変更します
self.backgroundColor = SKColor.black
// イメージ
let node = SKSpriteNode(imageNamed:"sample")
addChild(node)
// ラベル
let label = SKLabelNode(fontNamed: "Chalkduster")
label.text = "Hello, World!!"
let labelSize: CGFloat = 50.0
label.fontSize = labelSize
label.position = CGPoint(x:self.frame.midX, y:self.frame.height/2 - labelSize)
label.fontColor = SKColor.yellow
self.addChild(label)
}
今回は、SpriteKitの入門として要素の役割の紹介や、簡単なシーンの作成までを紹介しました。他要素のアクションや当たり判定などもこんな感じでサクッとできちゃいますので、色々試してみると楽しいかもしません。何か間違っている箇所などありましたらご指摘くださいませ。