サンプルゲーム
本チュートリアルの集大成として、シンプルなゲームを作ってみましょう。
題材は単純なミニゲームで、前方から襲ってくる敵から宝箱を守るゲームです。
タップで主人公が移動し、主人公をタップすると攻撃します。
タイトルはたからもりとでもしておきましょう。
完成イメージは以下のようになります。
完成イメージ
タイトル画面
ゲームのタイトルとはじめるボタンがあるだけのシンプルな画面です。
タイトルは、SKLabelNodeを使って、もさもさフォントで表示しています。
独自フォントの利用については、特にSprite Kit特有の設定は不要です。
Info.plistでFonts provided by application
を設定すれば使えます。
うまく表示できない場合は、Copy Bundle Resourcesに入っているかチェックしてみましょう。
はじめるボタンは、ボタンらしく動作させるため、ハイライト状態によって色が変わるサブクラスを使っています。
touchesBegan:withEvent:
でハイライトさせ、touchesEnded:withEvent
で画面繊維の処理を実行しています。
ハイライト状態を保持するプロパティを追加しています。
ハイライト時は、グレーをブレンドして色を変えています。
SJTitleScene.m
シーンの初期化時にラベルやボタンを追加しています。
ただ表示するではゲームっぽくないため、SKActionでタイトルを上にアニメーションさせています。
それが終わったらボタンが表示されます。タップに合わせてボタンのハイライトや画面遷移の処理を行なっています。
今回は設定機能もないため、タイトル画面はこれで完成です。
タイトル画面
note
AppleのAdventureでは、SKViewにUIButton・NSButtonを追加して、本編プレイ中は非表示にするという方法でボタンが実装がされています。SKViewはUIViewのサブクラスなのでUIKitやAppKitと簡単に組み合わせられるのが良い所です。ただ、クロスプラットフォームにするためにはプラットフォームに応じたフレームワークを使用する必要があります。
ゲーム画面
それではメインのゲーム画面を作ります。実装ファイルはSJExampleScene.m
です。
定数とインスタンス変数
ゲーム画面で使う定数や変数等を以下のように冒頭で定義しています。特別なものはありません。
変数については、createSceneContents
内で初期化しています。
それぞれの使われ方については、この後のソースをご参照ください。
表示
まずは、キャラクターや背景の描画です。
以下のように、それぞれ表示用のメソッドを用意して、呼び出しています。
背景
Sprite Kitには、タイルマップの機能がありません。
必須の場合は、Kobold Kit 等のサードパーティ製ツールを使うのがてっとり早いでしょう。
ここではwood.png
を並べるだけの簡易的な実装にしています。なお、メモリ節約のため、SKTextureは再利用しています。
wood.png
主人公
静止・歩行・攻撃と状態に応じてアニメーションの種類が変わるため、SJHeroNode
クラスにまとめています。
SJPlaySceneではそのインスタンスを子ノードとして追加するだけです。
SJHeroNode.h
状態の一覧と現在の状態を保持するプロパティ、状態を変化させるメソッドを追加しています。
SJHeroNode.m
少し長いですが、状態に応じて画像を切り替えて、アニメーションさせているだけです。
SKActionのanimateWithTextures:timePerFrame:
を使ってパラパラ漫画風の動きを実現しています。
攻撃状態の時だけ、剣も表示しています。アニメーションのさせ方はキャラクターと同じです。
敵
敵は表示するだけで、状態も持たないため単純です。
メソッドが呼ばれるごとに、ランダムな座標にコウモリを表示しています。
アニメーションの方法はSJHeroNode
と同様です。
宝箱
宝箱は画面いっぱいに横一列で並べています。
ラベル
時間とスコアを表示するラベルです。
ステータスバーと被らないように、少しずらしています。
ここまでで表示処理は終わりです。
これらを、ユーザの操作・物理シミューレション・時間の経過等によって更新していくことで、ゲームになっていきます。
表示だけ
操作
本ゲームはタップのみで操作します。
タップされた位置に主人公がいたら攻撃します。
そうでなければ、タップされた座標と今いる座標の差分を取り、一定速度になるよう移動させます。
更新
今回は、時間の経過に応じてフレーム毎に処理を行ないため、update:
をオーバーライドしています。
_timeSinceStart
にはゲーム開始からの合計時間を保持し、_timeLabel
に表示しています。
_timeSinceSecond
には前回の秒からの時間を保持し、1秒以上経過したら、敵を表示させたり、単位度を上げる判定をしたりする処理を実行しています。
物理シミュレーション
ゲーム画面最後の処理は、物理演算です。
これによって、登場人物同士が干渉しあうようになり、ゲームが成立します。
まず、画面の周囲をかこうようにbodyを設定します。
また、当たり判定を行なうため、contactDelegate
を自分自身で受けるようにします。
categoryBitMaskにはworldCategory
を設定していますが、これは敵が枠と接触したことを判定するためです。
主人公
主人公は他の物体と衝突(collision)はせず、敵とのみ接触(contact)します。
敵
敵は宝箱と枠と接触します。衝突はしません。
重力を無視し、velocity
を設定することで上から下へ移動させています。
サイズは小さくないですが、ゲーム後半になると速く動くようになるため、usesPreciseCollisionDetection
をYESにしています。
宝箱
宝箱も衝突しないように設定します。
物体間の接触時によばれるDelegateメソッドです。
主人公が攻撃中だったら、sparkのパーティクルを表示させると共に接触した敵を消滅させます。
敵は宝箱か枠と接触しても消滅します。
宝箱と接触した場合は、fireのパーティクルを表示させ、宝箱を消します。
敵を倒すとスコアがプラスになり、宝箱が0になるとゲームオーバーです。
これでゲーム画面ができました。
操作への反応や物理演算により、プレイできる状態になりました。
プレイできる
ゲームオーバー画面
最後にゲームオーバー画面です。
少し待った後、タイトル画面に戻しているだけの単純な実装です。
このゲームにはクリアがないので、画面はこれで終わりです。
このようにSprite Kitを使うと、特別なツールの力を借りず、簡単にミニゲームを作ることができます。
comments powered by