はじめに
Swiftを使ってドラクエ風のRPGゲームを作ってみました。
宣伝も兼ねて、ゲームを作るまでの簡単な軌跡や苦労した事を書きます。
これからゲームやサービスを作ろうとしている人の参考になれば幸いです。
なお、僕が作ったゲームの時系列は以下になります。
※下に行くほど新しいです。
以下の歴史的背景を説明する時に使うので、なんとなく覚えておいてもらえればと思います。
対象読者
- これからゲームを作ってみたいと思っている人
- 企画から実装〜販売まで全て自分でやってみたい人
- 気苦労を知りたい人w
作ったもの
まずは宣伝、失礼します。
僕が作ったゲームは「偽りの物語」というRPGゲームです。
2016年の5/5までセール中なので、こちらの記事を読む参考(?)にと購入していただけると幸いです。
(iPhoneのみでAndroid版はありません。)
ドラクエ風のRPGゲームのUIを踏襲してますが、ゲームを進めていくとシステムは随分違います。
よければやってみてください。
「これをSwiftで作ったのか。」と思っていただけると嬉しいです。
作ろうと思った動機
作ろうと思った動機は幾つかあります。
1. Swiftを使ってみたかった。
一番の動機はSwiftを使ってゲームを作ってみたかったからです。
このゲームを作成する前に「Space Debris」 というSwiftを使ったゲームを作ってみたのですが、もっとがっつりSwiftを使ってゲームを作りたいというのが動機でした。
Space Debrisを作ったあとにチュートリアルを作成していたのですが、ストック数も伸びなく需要がないのだろうと思い記事の途中でRPGゲームを作る事を思い立って作り始めました。
2. 守破離の守をやってみたかった。
僕は5作ほどゲームを出してますが、当たった事がありません。
僕としてはどのゲームも面白いと思って作っていたのですが、残念ながらどれも不発に終わりました。
なので、初心に戻って守破離のうちの「守」をやろうと思ったのです。
今までのゲームは「離」に近く、基本的な事が出来てませんでした。
今回はドラクエ風のUIを踏襲する事で、UIを守りつつオリジナルの要素を入れていこうと思い作りました。
今までのゲームに比べてUIが格段に良くなっているかと思います。
(とはいえ、素人UIなのは否めませんが・・・)
3. 駆り立てられた。
今までものを作った事がある人ならわかると思いますが、ある日突然
「これを作らなければならない!」
と言う神のお告げのような形で、作らなければいけない欲求に駆り立てられる事があります。
そんな感じで、僕はこのゲームを作らなければいけない気になって作り始めました。
はじめに決める事
と、作る気になってもいきなりモノは作れません。
チュートリアルを作ってる時に、必要でありそうな技術を調査しました。
例えば今回の偽りの物語では以下の要素が不可欠でした。
1. フレームワーク
フレームワークは決まってました。
FlickRPG2まではフレームワークを使ってなかったのですが進撃の魔城でCocos2dを使って、開発効率がはるかに上がったのでCocos2dを使う事にしました。
※Unityも検討したのですが、覚える事が多いのとオブジェクトにコードを書くというスタイルに慣れなくてやめました。
(メインループをどこに書けば良いかわからなく断念・・・と言う初歩的なところで引っかかったというのは秘密です。)
2. マップ
RPGなので、マップ画面は必須でした。
これは進撃の魔城で使ったTiled Map Editerを使う事で解決しました。
余談ですが、FlickRPG2のマップはTiled Map Editerを知らなかったため二次元配列を駆使してマップを作ってました。
マップ作りはどうやっても苦行なので、できるだけ簡単なツールを使ってやるといいと思います。
Tiled Map Editerを使っても苦行ではありますが、二次元配列管理よりもはるかに作業は楽になります。
Tiled Map Editerの素晴らしいところはマップを作る事以外にもあります。
マップチップに属性を付けれたり、マップにオブジェクトを配置できたりするのでマップとプログラムを連動させる事が楽にできます。
もし、RPGゲームを作ろうと考えている方は一度触ってみると良いでしょう。
マップを読み込んで、キャラクターを配置して動かせる事まで確認できた時点でマップ部分は完成です。
(Y軸が逆になっているため、座標計算にちょっとはまりました。)
3. 戦闘シーン
RPGゲームの肝というと、やはりバトルシーンです。
ここができないとゲームは作れないので、マップの確認が終わった後は戦闘シーンのインターフェースと中身を作りました。
戦闘シーンで重要なのは呼び出すインターフェースと終わったあとのコールバック部分です。
僕は以下の情報を受け渡すインターフェースを作って解決しました。
[インプット]
- 戦闘に参加する敵モンスター
- 戦闘に参加するパーティー(イベントによっては戦闘に参加するメンバーが変わるため)
- 戦闘背景
- 戦闘音楽
[アウトプット]
- ステータス(勝利、敗北、引き分け)
を返すインターフェースを用意したのですが、「引き分け」は使いどころがなく結局使いませんでした。
4. 戦闘シーン2
インターフェースが決まった後は内部実装です。
内部実装は正直いけてませんでした・・・。
詳しくは書けない(実際にゲームをやってください♪)のですが、偽りの物語では1ターンの間に複数回行動する場合があるためデータの保持の仕方が複雑になりました。
また、行動をするたびにエフェクトをかけるので手続き型言語っぽくプログラムを書く事ができず、コールバックを多用する必要がありました。
(今ならRxSwiftで対応できるのですが、当時はその技術を知らなかったためコールバックの管理がとても大変でした。)
何かしらのゲームを作った事がある人ならわかると思いますが、コールバックとメインループの処理はプログラムの相性が悪く劣悪なコードが生まれてしまいました。
結果、戦闘用のクラスはextension
を駆使してコードを分割するという情けない対応になってしまいました。
コードがどうあれ、この部分が出来上がればゲームの中核はある程度出来上がります。
5. 画面やエフェクトの作成
画面やエフェクトの作成機能はCocos2dを使えば作れるのですが、、、今回はSpriteBuilderを使用しました。
Space Debrisを作る時に初めて使ったのですが、素人がUIを作る上では非常に秀逸なツールでした。
残念ながら半年前くらいから開発が止まっており、AppStoreでの配布も終わってしまってます。
次回作から何を使おうか悩ましいのですが、使い方を覚えたため次回作まではこれを使う可能性が高いです。
(ただ、大量のワーニングと実行時エラーが出るので将来的な事を考えると使わないほうが無難かもしれません・・・・。)
※だれかオススメのUIツールを知ってたら教えてください。
SpriteBuilderの良い点は以下のところです。
- UIを%で作れる。(ユニバーサルアプリに対応できる。)
- パーティクルやアニメーションも作れる。(エフェクトを自分で作れるのは魅力的です。)
- SpriteSheetにも対応している。(画像を纏めてもコードを変えなくても良いのが魅力)
などなどで、XCodeのXibを作るより素晴らしいと個人的に思います。
(XCodeはちょっとやりすぎ感があるので、個人的にはあまり好きではないです。最後は制約だらけになって他の人が作ったxibは触りたくなくなります・・・)
初めに決めることが決まった後に
これらの確認ができた時点でRPGを作れる事を確信したので、実際にゲームを作り始めました。
これ以外にも音楽や効果音の部分など、他にも事前に考慮した部分がありますが細くなるので割愛します。
余談ですが、iPhoneでは効果音を32個までしかpreloadできないので使用する際には注意が必要です。
(使用するシーンに合わせてunloadEffectを使って効果音の読み込みを行っていく必要があります。特に戦闘中は使用する効果音が多くて困りました・・・)
次にやる事を決める
ここまではプログラムの基礎部分で偽りの物語の基礎部分を作成する、いわばフレームワークの作成だったので楽しく行ってました。
(今思えばここのプログラムがやりたくて作ったのかもしれません。このあとはデータ打ち込みとマップの作成が主流になるため茨の道でした。)
偽りの物語は一人で作っているため、企画から開発まで全て僕が行ってます。
そのため、
- 作るものを自分で決める
- 自分でプログラムをする
- 自分でチェック
- 自分でバグを直す
- やっていて欲しい機能があればTODOに追加
を繰り返していく事になります。
これを行うためにEvernote
を使ってTodoリストの管理
をしてました。
Todoリスト
を作らないと、自分に妥協してしまうため「作るもの」と「バグ」をリストで纏めてどんどん消化していきました。
Evernote
を使ったのは、電車の中などではiPhoneでゲームのテストをしてバグなどをリストに書き込み、PCが使える環境ではPCでリストを消化させるためでした。
なので、できるだけ簡単なインターフェース・・・と考えたところEvernote
が一番フィットしました。
素材について
僕は絵が描けないので、素材集めには結構苦しみました。
自分のイメージ通りの素材が見つからず、泣く泣くゲーム内の設定(シナリオ)を変えて対応した事もあります。
この辺りはフリー素材を使用している以上仕方がない事だと諦めました・・・。
いつかは、自分の思い通りに作ってみたいものです。
※使用した素材はゲーム内にURL付きで提示してますので、興味のある方は是非ご購入をお願いしますw
捨てた機能
偽りの物語を作るにあたって、いくつか諦めた事があります。
1. グローバル対応
今までのゲームは英語対応までは行っていたのですが、今回は日本語オンリーにしました。
その理由としては、英語対応はそれなりにコストがかかる上に売れなかったためです。
売れる事がわかっているならとにかく、売れるかどうかわからないゲームにそれなりのコストを入れると完成すらしないかもと思い対応をやめました。
また、文言の切り出しもしていないのでこのゲームはグローバル対応を後付けで行う事ができません。
これは完成させるために仕方なく切り捨てた事です。
2. Android対応
今までのゲームもそうですが、Android対応は基本的に行ってません。
理由は簡単で、Androidのプログラムはあまり得意ではないのとAndroid端末を持ってないためテストができないためです。
初めにグローバル化を捨てていたので、実装がある程度やっつけ(適当)でもなんとかなったという・・・良い事だか悪い事だがわかりませんが完成させれた事を考えると良い決断だったと思います。
失敗した事
失敗した事は結構あります。
その中でも一番大きな失敗はモデルの粒度
がバラバラだった事です。
例えばスキル
はあまり機能が無いと思って一つのクラスに機能を纏めて、モンスター
は種類がたくさんあると思って継承クラスを作ったのですが・・・
これが大間違いでした。
スキル
はマップで使う場合はエフェクトがいらないけれど、戦闘で使う場合はエフェクトをつけないRPGゲームっぽくならないため各スキルにエフェクトをつけていく事に。そうするとスキル
が一つのクラスだととてもコーディングが難しいという。
他にもモデル部分はイケテナイ実装が多かったです。
この辺りは次のゲームで改善しようと思います。
(※Realm
を使ってしまうと頻繁にトランザクションが発生してしまうし、継承を多用した時に上手くデータが保存されるかわからないので・・・まだまだ悩みどころです。)
あとはインターフェースの粒度がバラバラだったので、昔作ったクラスを使おうとした時にコードを読んでからしか使えないというのも開発速度を遅くする要因でした。
Layer
の読み込みをするための便利メソッドを用意しているクラスと用意していないクラスがあったり、扱うデータが複数の種類(装備アイテム
と販売アイテム
の表示画面など)になってちょっとした修正に時間がかかったりしました。
この辺りは生成用のstatic func create()
などをすべてのクラスで用意すべきでした。
(Swift
にはabstractクラス
が無いので、この辺りを強制させるのが難しい・・・。ついつい楽な方法を使ってしまう自分を後で呪いましたw)
上記にも書いたメインループ内のコールバック処理が全然ダメでした。
主に戦闘画面ですが、戦闘は1ターンの中を更にカウントで分けて
- 1カウント目は◯◯の攻撃
- 2カウント目は××の魔法
- 3カウント目は...
などのようにカウントループをしていたのですが、そのカウント内にエフェクトが入るとコールバックが必須になりコールバック待ちの間はカウントを進めない・・・などのコードがあまり綺麗に書けませんでした。
この辺りはRxSwift
などを使って次回はすっきり書こうと思います。
発生したバグ集
自分でコードを書いた後に、ゲームをテストした時に発生した恥ずかしいバグを上げておきます。
- HPがマイナスになる
- 自分の装備が壊れるところを相手の装備を壊してしまった。(武器の耐久性をゲームに取り入れています。)
- 魔法の武器は壊れないようにしてたのに、耐久力がどんどん落ちてしまう。
- ゲーム画面に変な線が入る。(ゴミLayerを消し忘れ)
- 画面遷移時に落ちる。(マップに埋め込んだオブジェクトの処理コードを書き忘れ)
などなど、本当に変なバグが沢山でました。
期間
ちなみに作成期間は約9ヶ月です。
Cocos2d v3 Particleの設定内容について調べてみたの記事を書き終えてから3/30にアプリ審査を行いました。
別の仕事をしながら作っていたので、生産性としてはまぁまぁ良かったかなと思います。
最後にAppleの証明書が切れていて、アプリ審査には結構戸惑いました。。。
(これは、2月をまたいでアプリを作った人はほとんどはまったのでは無いでしょうか?)
2月ごろになってからは、アプリの作成以外にもアイコンの作成やスクリーンショットの作成を依頼したりしていたので、プログラムを作っていたのは8ヶ月くらいかな。
最後に
ゲームでもアプリでもなんでもそうですが、何かを作ろうとしたときに必要なのは根気
です。
ゲーム風に言うと諦めない心
が必要になります。(笑)
僕はこのゲームを作るにあたってここまで出来れば後は作れる!
というここまで
のラインをマイルストーンで引きました。
今回で言うと
- マップを移動できる
- 戦闘ができる
- アイテムをもてる
- 武器防具を装備できる
- スキルを覚えて使える
- イベントが進む
という機能が出来れば後はなんとかなると思ったので、まずはこれらを目標に頑張りました。
その後に
- 転職できる
- 武器の追加効果
- 派手なエフェクトの武器
- 全体効果、特殊効果のあるスキル
などを盛り込んでゲームのシナリオを作っていきました。
長くなりましたが、Swiftでがっつりプログラムを書くのは楽しかったです。
マップをひたすら作ってる時は苦行でしたw
RPGゲームを作りたい方は、根気がいることをお忘れなく!
では、良いSwiftライフを!
製作
TownSoftでした