日本語自由帳

分かりやすく、伝わりやすく。

C++を使った簡単なゲーム作りに挑戦しました

社会人3ヶ月目のうるるです。 今は楽しく研修をこなしております。

当社の研修にある「OJT(On Job Training)」は、全ての部署に1週間ずつ 配属され、部署独特の雰囲気を味わいながら、実務に近い仕事を行ったり、実務ではないけど今後の仕事に必要な知識を得るための課題に取り組んだりしています。 その中でも希望部署でもある技術系の部署では4日間かけてゲーム作りに取り組みました。

言語はC++、今回は統合開発環境(C++ Builder)を利用しました。 といってもほとんどC言語で作っているようなものです。 C言語は大学時代に学び、統合開発環境も学部時代にVisual Studioを使って券売機を作成したこともあり、先輩社員からのプレッシャーも感じながらの制作でした。

またグループでiOSアプリとしてのゲームは制作したことがありましたが、ひとりで一からゲームを作ったことがありませんでした。 なので現在の知識と経験でどのくらいゲームが作れるかを試すよい機会でした。

コンセプト

せっかくゲームを作るなら、私の好きなゲームである「FINAL FANTASY」っぽいゲームを作ろう、と考えました。 そしてFFを象徴するものといえば「ATB(Active Time Battle)」だと思いました。

基本的には敵・味方共に一定の時間が溜まったキャラクターから行動を選ぶ仕組みである。ほとんどの作品で、次の行動選択可能までの時間を表したATBゲージが味方キャラクター1人1人に表示され、時間の流れを視覚的に捉えることができる。(Wikipedia: アクティブタイムバトルシステム)

このATBの対義語は「ターン制バトル」で、ドラクエなどRPGの戦闘の多くはターン制バトルです。 ターン制バトルとは敵のターンと味方のターンを(基本的に)交互に行う戦闘形式のことです。 よって自分のターンは敵は襲ってこないので、じっくりと次の行動を考えながら戦闘することになります。

しかし、実際に敵が襲ってきた時に自分のターンなんて言っている暇がありません。 そしてこのATBの「リアルタイムで戦うおもしろさ」を体感してもらおうと作ったのが

f:id:hsmdlily:20160612214154p:plain

「ターン制バトルに甘えるな勇者よ」

です。 (Windowsアプリのキャプチャをすると色がすごいチカチカする。)

ゲーム内容

通常戦闘

f:id:hsmdlily:20160612214157p:plain

ゲーム内容は一言で言うと「出てくる敵を倒すゲーム」です。 ただ、それだけだと「もぐら叩き」と同じなので、RPGのバトルっぽく属性の相性に合わせて攻撃する方法にしました。 これはATBで苦労する点のひとつとして「まほうを選ぶ」ことがあるからです。

例えば「火の攻撃が弱い敵にフォーカスを当て、その敵に『まほう』から『ファイア』を選ぶ」という操作は意外と面倒です。 この面倒さが少しでも伝わるようにと思い、(本来ならPopup Windowで出てくるのですが)TreeViewを使った実装にしました。 敵に合わせた適切な攻撃方法を選択しないと減点になります。

さらに敵に攻撃される緊迫感を体感してもらうべく、敵は時間が経つにつれ、どんどん近づいていき味方ユニットを攻撃します。 攻撃されても減点になるので、できるだけ素早く、適切に敵を倒すようにしました。

ボス戦闘

f:id:hsmdlily:20160612214200p:plain

通常戦闘も大変ですが、ボスになるともっと大変です。 一回の攻撃では倒せず、色々な方法でボスを倒さなくてはいけません。

そこでボスはいくつかの行動を行うことで倒せるように実装しました。

画面右下のウィンドウにある「このとおりに こうげきしろ!」の指示に従って、正しい順番で行動をとります。 もし、順番と違った行動をとってしまうとボスは逃げてしまいます。 また、ボスも近づいて強力な攻撃してきます。

こだわった点

主に2つのことを考えた実装にしました。

  1. ATBっぽさを表現し、リアルタイム戦闘の苦労を教えたい
  2. 1.以外のところはユーザ・エクスペリエンスをよくしたい

そして細かく4つのことを考えました。

1.1. ATBっぽく、行動を選択する度にTreeViewが折りたたまれる

ATBは行動をするごとに行動の画面が閉じます。 それっぽさを出すために行動をする度に、「まほう」のツリービューが折りたたまれるように設計しました。 ただコマンドの記憶は固定です。

1.2. ボスバトルで複数行動パターンによる攻撃方法を採用

ボスバトルは単純な行動で倒せないことを強調したかったので、ランダムに行動を指定して、その行動通りに選択するとボスが倒せるようにしました。

2.1. 敵の位置を毎回変えたり、ダメージ表示を出す

ユーザが行った行動、敵の行った行動が反映されるように行動を行う度に画面に変化をつけるようにしました。

2.2. 行動を選択する度に味方ユニット上に行動を表示

ユーザの行った操作にレスポンスをつけるべく、行動をするごとに味方ユニットの上に選択した行動が表示されるようにしました。 また敵ユニットが味方ユニットに攻撃した際も、味方ユニットの上に攻撃されてスコアが減ったことを表示されるようにしました。

苦労した点

  • Sleep関数の利用

本当はゲーム終了時に画面にそのまま「Finish」の画面を数秒間出したかったのですが、Sleep関数の挙動が不明で断念しました。 ただ、結果としてFinishを時間差でポップアップ風に出すことで、ENTERキー連打によるキーボード操作の暴走を止めることができました。

  • ボタンやツリービューの初期位置の設定

新しい画面が出てきた時に、キーボード用にボタンやツリービューの初期位置を設定したかったのですが、その設定に苦労しました。 また、敵を倒した時もツリービューの選択項目を初期位置「たたかう」に設定したかったのですが、それもうまくいかなったので、ツリービューを強制的に閉じるようにしました。

  • ランキングの設計

ゲームは毎回新規で呼び出されるのに対してランキングのスコアの配列は保存しなければいけない。 本当はポインタを使って場所だけ指定してランキングの配列を呼び出せばよかったのですが、あまりポインタは得意ではなかったので、フォーム同士の受け渡しによって実現させました。

本当はやりたかったこと

  • 複数敵の登場

複数敵の場合は「敵を選択→行動を選択」をしなければいけませんが、敵の動きなどを考慮すると結構大変そうだったので、今回は諦めました。

  • ランキングに自分の名前を入れる

ランキング機能をこれ以上追加すると死ぬし、コードが汚くなる。

感想

「一人でゲームを作る」ということをしたことがなかったので、4日間真剣に取り組むことができ、非常に楽しかったです。 コーディングしている時間も楽しかったのですが、家に帰ってお風呂に入りながら「こういうのを入れたら面白そう」など考えている時間も楽しかったです。

実際の業務はゲームほど楽しくはいかないと思いますが、このような考える癖を身につけられるようにしていきたいです。

それにしてもまだまだ汚いコードを書いている気がするので、関数やポインタを使った綺麗なコードを書けるように努力していきたいです。

使用した素材