見出し画像

縦スクロールSTGを作ってみた!

こんにちは「つけらっとゲームス」プログラム担当のとちです。
現在、弊サークルでは久しぶりの展示会(兼ちょっとだけワークショップ)に向け準備中で、ものすごく大忙しでヤバいです!

展示会「ゲーム開発ウラオモテ ぷち!つけらっとゲームス展in五戸」については以下の記事にまとめています。ご覧ください。

今回の記事では、この展示会で初お目見えとなる「つけらっと防衛軍」について書きたいと思います。おそらくゲームを作る際の参考になるかもなので、ゲームを作りたい方はぜひ読んでくださいね!

また、作る際の参考になるwebページの検索キーワードも置いておきますので、チャレンジしたい方は実際にググってみてくださいね!



作ったきっかけ

つけらっと防衛軍、実はわたくし、専門学校でシステム設計の外部講師をやっていまして「Unityならこんな感じの事ができるよ!」と学生たちに見せた中途半端なシューティングを成仏(完成)させちゃおうと思ったのがきっかけです。

真っ黒な背景に三角形の自機から出る弾で、画面上部から飛来する敵を倒すという、本当に勉強用の単純なモノだったのですが…爆発エフェクトがあったりBGMとSEがあったりと、そこそこ作ってました。

そのまま放置するのはもったいないと感じたんですよね。

最初はこんな感じ

Unityで何かのゲームを作ろうと思った方なら、次の文章で何をしたのか伝わると思います。

BoxCollider2Dを自機とprefabにした敵機に持たせて、自機と敵機の存在位置に対し弾オブジェクトをInstance、弾オブジェクトにAddForceして飛ばして、OnTriggerEnter2Dに引っかかったら自機または敵機をDestroyする!

恐らくUnityで習作を作る最初期、よく教材に出てくる方法だと思います。
これなら慣れない方でも数時間あれば、それっぽいゲームになるんです。
(これから勉強しようという学生にはちょうど良いかもしれません)

「よし、では作ってみよう!」と思ったら、こんなキーワードで検索してみてください。教えてくれる動画や記事がたくさんありますよ!

Unity 2D シューティング 縦スクロール

検索してみましたか? 出てきますよね? これでゲーム作れるよ!
(わたしもいつかこのへんを詳しく解説してみようかな~と思ったり…)


楽しく明るく可愛いシューティング!

先程のスクショのゲーム。勉強のための初期段階としては非常に良い教材となります。勉強をはじめるなら基礎が必要ですからね。これは大事。

しかし、弊サークルは地域おこしの活動をしたり、子どもたちと接する機会があるので、地味な見た目は少々困りものなんですよね。

マスコットキャラクターであるネコの「めごろ」とネズミの「たわら」も可愛らしい容姿ですし、いまこそシンプルな教材から楽しく明るく可愛いゲームに進化するときがきたのです!

完成まであと少しのスクショ

変わり過ぎぃぃぃ!! 一気に明るい雰囲気になりました。
画面の右側にはUIも追加され、点数からパワーアップ表示、キャラクターの会話欄など、盛りだくさんとなりました。

さすがにね、いきなりこれを作れと言われたら大変そう…
学校の勉強と同じで応用問題からスタートしたら難しすぎて投げ出しちゃいます。なので、まずは基礎を学ぶ必要があるんです。

まぁ慌てることはありません。時間がかってもいいんです。
プロトタイプを作り、肉付けし、バージョンアップを繰り返して、ひとつのゲームを作り上げるのも立派な手法のひとつです。


コンセプト!

ゲームを作る方向性も大事です。肉付けの方向性でもあります。
前述したとおり、子どもたちに接するから明るいイメージ、可愛いイメージを大事にしようと思いました。

作っているわたしの好みとしてはカッコイイ系のシューティングでもいいのですが、コンセプト的にカワイイ系の方が良い。既存のゲームで言うと、グラディウスよりツインビーの方がイメージ的に近いわけですよ。

ただ、パワーアップはグラディウスっぽい方が好きなので…
作者の好みが入ってますが、それもまたこのゲームの味なのでそこはご了承ください。

ああ、そうだ!
スターフォックスのように味方から通信が入るのもいいですよね!
本当はボイスで通信が入るといいんですが、今回は低予算というか、実質ゼロで作る予定なので文章で対応しましょう。


まずは見た目の変更

コンセプトは決まりました。
普段、プログラミング学習の記事を書いていますが、その中ではプログラムに何をさせるのかを想像し(アルゴリズムを思い浮かべ)フローチャートを書いて、プログラムコードを書いて…という手順を踏んでいます。

今回は自分ひとりの開発チーム。
メモ書きはあるのですが、仕様書や設計書は省略です。
プログラミング学習については、こちらにまとめておりますので興味がございましたら以下からどうぞ!

さて、明るいイメージ、可愛いイメージのためには何を変更したらいいのか、答えは簡単!見た目です!
鮮やかな画面が表示されるだけで雰囲気がガラッと変わるんですね。

というわけで真っ黒な背景ではなく鮮やかな背景を目指すとしたら、こんなキーワードで検索してみてください。教えてくれる動画や記事がたくさんありますよ!

Unity 2D タイルマップ

タイルマップとは、すごくざっくりとした説明になりますが画像をタイルの様に敷き詰めてマップや画像を作り出すことができます。
RPGツクール(RPG Maker)やWOLF RPGエディターを使ったことがある方にとっては身近な作り方ですね。

マップチップ、マップタイル、タイルセットなどで検索すると素材も出てくるので試してみると良いでしょう!

さて、タイルマップで背景ができたら、次はゲーム進行と同時に自機が飛んでいるように見せないといけません。背景が動く、またはカメラ(プレイヤーが認識できる画面範囲)が動くようにしましょう。

「つけらっと防衛軍」では自機と一緒にカメラが徐々に上に動いてます。
考え方は自機や敵機を動かすのと同じ、GameObject.transform.positionの値を変更してあげればいいんです。


決まったタイミングで敵が出る!

学生に見せるために作った初期版はランダムで敵が出現するように作られていました。ランダムだと難易度調整が難しいですし、ある程度パワーアップ頻度も制御したいので、決まったタイミングで敵が出る仕組みが必要です。

「耐久力に優れる敵がいる」「中ボスがいる」といった場合は、敵の撃破によって次の敵が出るというタイミングの取り方もありますね。
「時間制限中にどれだけスコアを稼ぐか!?」というゲームスタイルならこの考え方もアリですね。

話を戻して、決まったタイミングで敵を出す方法は幾つか考えられます。
ステージスタートからの時間をカウントする方法もアリでしょう。

「つけらっと防衛軍」では、徐々にカメラを上に動かしているのでこいつを使う方法にしました。カメラ座標を基準に敵を動かします。

プレイヤーが認識できる画面範囲が近寄ってきたら敵が動き始める。
つまり、先程のGameObject.transform.positionを利用します。

敵の動きを敵の種類によって変更するとより面白くなるでしょう。
どうするのかって?

カメラのtransform.positionを動かせばカメラが動く、であれば…
敵のtransform.positionを動かせば敵も動きます。

敵の種類によって動きが違う、ということは何かを基準に種類が違うと判断しないといけません。

やり方はたくさんあります。ゲームオブジェクトにマウントされているスプライトで判断してもいいですし、ゲームオブジェクトを生成し名前を変更する時に判断できるような名前にするのも良いでしょう。

「つけらっと防衛軍」では…
CSVファイルに敵機のデータを持っていて、それを見て判断しています。

敵の情報の一部

「KBN」が敵機の区分番号です。
この数値の違いによって動き方が異なるようにしています。

「PosXX」「PosYY」が初期位置ですね。
この座標に対してカメラが近寄ると敵の動作ルーチンとなるスクリプトが動き始めます。物理接触に使用するBoxCollider2Dが有効になります。

「BletSW」は弾薬スイッチの意、弾の挙動を制御する番号です。
「Fire1~3」は敵機の射撃タイミングです。動き始めてから何Frame目に射撃をするかをデータ化しています。

「いきなり難しいことしてる!!」と興奮しちゃいますが、落ち着きましょう。大丈夫、このあたりも覚えたらそこまで大変じゃありません。
以下のキーワードで検索するとやりかたが出てきますよ。

unity テキストファイル 読み込み

データを読めるようになると、かなり複雑なゲームを作れそうな気がしてきます。なんか強くなった気がしますよね!

キャラの会話も作っちゃえ!

タイミングを計るためにカメラ位置で敵が出るのであれば、同じようにキャラの会話もカメラ位置を使うことでタイミング通り出せます。

シューティングゲームでキャラの会話なんて見てる暇はありませんが、ロボットアニメなんかで通信が入ってきて会話するシーンなんかもありますし、どちらかというと実用性よりは雰囲気で追加した要素だったりします。


地上の敵を設定する!

コンセプトはグラディウスよりツインビーに近い…
ツインビーって地上の敵がいるんです。

なので「つけらっと防衛軍」も地上の敵を設定しました。パワーアップするためのPパックは地上敵を倒すと出てきます。どうしても解決しないといけませんね。

ちなみに赤丸で囲んだところにいる戦車が地上の敵です。

地上の敵も設定したい

難しく考える必要はありません。順序良く解決しましょう。
学生に見せるだけの最初期版で、BoxCollider2Dによる接触判定で敵を撃墜してました。対空ショットで倒せないようにするためには…

そうです、対空ショットが当たっても処理しなければいいんです。
どんなモノでもゲームオブジェクトとして存在させるUnity、接触したゲームオブジェクトのTag、名前、スプライト、なんでもいいので違いが判るモノを判断基準としましょう。すると処理を抜けることができますよね?

敵に接触した場合、自機はダメージを受けますが、これも同様に地上物と接触しても処理を抜けちゃえば自機のダメージは入りません。順序良く対応していきましょう。

Pパックは接触したら自機がダメージを受けるのではなく、画面で言うと右側のUI表示が切り替わります。これも何と接触したのかの判断基準を設けるといいですね。

さて、ここまでくると自機のデータもしっかり設定してあげないと処理しきれなくなってきます。各種変数を用意しておくと良いでしょう。
「つけらっと防衛軍」での自機データの管理はこんな感じです。

Pパックに接触したら、以下のPlyPowCntが+1されるようにします。

	public struct Jiki																							//
	{																											//
		static public GameObject	PlyShip    = null;															//【変数定義】自機オブジェクト
		static public Vector3		PlyShipPos = new Vector3(0f,0f,0f);											//【   〃   】自機位置
		static public int			PlyShipHP  = 1;																//【   〃   】シールド(HP) 最大値10
		static public int           PlyScore   = 0;																//【   〃   】スコア
		static public int           PlyPowCnt  = 0;																//【   〃   】パワーパックの所持数
		static public float         PlySPD     = 4f;															//【   〃   】自機スピード
		static public int           PlyShotKBN = 0;																//【   〃   】ショット区分   [0]デフォルト [1]ツイン	[2]3Way	[3]4Way
		static public int           PlyLaserSW = 0;																//【   〃   】レーザーフラグ [0]通常弾     [1]レーザー
		static public int			PlyMissMax = 0;																//【   〃   】ミサイル個数(最大)
		static public int           PlyMissNow = 0;																//【   〃   】ミサイル個数(現在)
		static public int           PlySuppCnt = 0;																//【   〃   】サポート機数(現在) 3まで
		static public int           MutekiCnt  = 0;																//【   〃   】被弾後の無敵フレーム数
		static public GameObject	BombSite   = null;															//【   〃   】ボムのレティクル
		static public GameObject	BombKanri  = null;															//【   〃   】ボムオブジェクト
		static public int			BombTagIx  = -1;															//【   〃   】ボムターゲット(地上物)
		static public int           BombDCnt   = 0;																//【   〃   】ボムターゲットが無い場合のボム管理カウント
		static public Vector3		BombTagPos = new Vector3(0f,0f,0f);											//【   〃   】ボム目標位置(座標)
		static public Vector3[]     PosOLD     = new Vector3[180];												//【   〃   】自機の移動履歴(サポート機移動の根拠)
	}

色々考えた結果、地上の敵に対してボム投下した時の処理は、効果範囲内であれば自動で命中するようにしました。またボム投下は1回1発とします。
ボムのターゲット管理も自機データに持たせています。

「自動で命中!? ってどうすんのさ!?」
大丈夫、敵の位置は敵のGameObject.transform.positionです。ほら、もう敵の座標がわかっちゃってますよ!
つまりボムのオブジェクトを徐々に敵の座標に近寄らせればいいんですね。


ここまで来たら完成させる!

もしかしたら、なんですけど「完成させる」が一番大事と言えるでしょう。

最初はシューティングゲームの基本的な部分を解説してくれる動画や記事をお手本に真似して作りました。その後、自分のゲームにするため肉付けしました。しかし、ここまでは自分の中の行動で済むんですよね。

「完成させる」そして「誰かに見せる」もし可能であれば「遊んでもらう」という一連の流れが「ゲームを作りたい」のゴールになると思うのです。

そのためには何が必要なのか?
わたしが思うのは「タイトル」「エンディング」があれば良い!
プレイヤー単体でゲームとして完結できたら完成、すなわちゴールです。

※ 最終面をクリアしたら最初の戻るようなループするゲームなら、しっかり最初に戻るループ部分を作りましょう。

プレイヤー視点で画面が切り替わったと認識できる部分を作るのは、実は結構な労力が必要だったりするんですよ。この大変な部分を乗り越えられたら、ゲームを作る人として、ひとつ前進できたと実感できると思います。

ゲームオーバー画面からタイトル画面に戻れるか?
ハイスコアの名前入力画面からタイトル画面に戻れるか?

更に肉付けするなら?

・撃墜王ランキングを作ったならデータとして残したい!
・他のパソコンで遊んだ人とスコアを競い合いたい!

という欲が出てくると思います。レンタルサーバーを使って管理するのもありなんですが、もうちょっと手軽にできないか?
できます。これでググってみてください!

Unity スプレッドシート

Googleスプレッドシートに記録を残せばいいんですよ。

ただし、セキュリティ的には色々不安があるので今回のようなフリーで遊べるゲームだったり、展示会で遊ぶといったクローズな環境であれば、スプレッドシートでいいかなぁ…

実は「つけらっと防衛軍」を作ってる早い段階で、こいつの対応をしたんですが、展示会で不特定多数の方が同じ端末で遊ぶゲームということで、データ通信に時間をかけたくない、処理待ちで回転率を下げたくないと思いまして、端末内のハイスコア機能に留めました。

仕組みは作ったので何か別のモノに流用したいと思ってます。


おわりに

いかがでしたでしょうか?
Unityで簡易的なシューティングゲームを作る方法はネット上に結構あるのですが、それを真似た後、そのまま放置はもったいないので、どうやったら自分のゲームとして肉付けできるのかをお話しました。

今回は詳しくお話しなかったのですが雰囲気が変わる要素としてはBGMとSEもありますね。これまた素材をネット上で探すのもアリです。
やり方はググってみたら教えてくれる記事がたくさんあるでしょう。

unity bgm

足りない素材は自分で補ってもいいでしょう。
ボスの動きを自作してみるのもいいでしょう。
コンフィグ画面を追加してもいいですね。

最初はシンプルな教材だったシューティング。
「つけらっと防衛軍」は色々な要素を追加して完成までもう少し。

現在のバージョンでは「難易度選択」を追加し、こういったシューティングゲームをあまりプレイされない方に向けて自動パワーアップも追加しました。サークル内でテストプレイも行われています。

もしお近くにお住まいであれば「ゲーム開発ウラオモテ ぷち!つけらっとゲームス展in五戸」で遊べるようにしますので、ぜひ会場にきてくださいね!

現時点の最新動画(2面のボスまで)です。もうちょっと頑張りますね!
それでは、また別の記事でお会いできるのを楽しみにしております!


弊サークルの活動を応援してもいいなと感じていただけたら嬉しいです。 いただいたサポートは「地域/若者向けの展示会費用」「ゲーム開発費」として使わせていただきます! サポートよろしくお願い致します~🐱🐭