2019年08月12日

ActiveBasicとDXライブラリでゲームプログラミング!~第10回・シューティングゲームを作ろう!その2

n88_reon.gif
玲音:どうもこんにちは! B-Maga編集部の紅一点・玲音です!

n88_kaede.gif
楓:こんにちは! その玲音先輩に講座に引きずり込まれた、後輩の楓です!

n88_reon.gif
だから、引きずり込んだんじゃないってばぁ……。
さてさて、シューティング編第2回は、自機の移動と、弾の発射をやっていきますよー。

n88_kaede.gif
はーいっ。

~その前に……

n88_reon.gif
その前に……ごめんなさいっ。
前回説明した準備と、プログラムについて、いくつか間違いがありましたので、訂正させていただきますっ。

n88_kaede.gif
まず準備についてですが、画像を入れる他に、することがあったのでした。下のファイルをダウンロードして、解凍してできた二つのファイルを、プロジェクトのフォルダにコピーしてください。


n88_kaede.gif
なお、このファイルは、配布元のサイト様が閉鎖されてしまったので、やむを得ずこちらで代理公開させていただいてます。ご了承ください。

n88_reon.gif
さて、それができたら、元型のプログラムの一行目を次のように直してくださいね。

(旧)
#include "../DxLib.sbp"

(新)
#include "./DxLib.sbp"

n88_reon.gif
これができればOKですよ。この説明が抜けていたこと、改めて謝罪させていただきます。申し訳ありませんっ。

n88_kaede.gif
さて、それでは本題にいきましょうー。

~キャラを表示させてみよう

n88_reon.gif
さて。それでは、まずは自機のキャラを表示させてみようか。
まずは……

''※このほかにも必要な変数があればこの下に追加してください

n88_reon.gif
この行の下に、次の一行を追加してね。

abdx1908-l01.JPG

n88_kaede.gif
自機キャラのグラフィックのハンドルを入れる変数を用意してるんですよねっ。

n88_reon.gif
その通り。その下のpX、pYは自機の座標を入れる変数だよ。
では、そのグラフィックを読み込む処理を書いていこうっ。サブプロシージャMaterialLoadに、次の一行を書いてね。

abdx1908-l02.JPG

n88_reon.gif
そしてそれが済んだら、新しい関数、JikiDraw()を作りましょう。内容はこの通りだよ。

abdx1908-l03.JPG

n88_kaede.gif
(変数pX, 変数pY)の位置に、自機を表示させてるんですね。あっ、先輩、でもまだpXとpYの値を決めてませんよ?

n88_reon.gif
あっ、そうだったね。それじゃ、サブプロシージャPlayInitに次の行を書き加えよう。

abdx1908-l04.JPG

n88_reon.gif
さて、ここで元型にもともと備わってる定数について説明するね。
SCREEN_XとSCREEN_Yは、ゲーム画面の右上の座標だよ。

n88_kaede.gif
どうして、(0, 0)に固定しないんですか?

n88_reon.gif
それは、ゲームによっては画面を全部使わずに、画面の中央あたりにゲームの画面を置いて、その外にスコアなどの情報を置く場合があるからだよ。そういう画面構成にすることも考えて、画面左上の位置も変えられるようにしてあるんだよ。

n88_kaede.gif
なるほどー。

n88_reon.gif
それと、SCREEN_WとSCREEN_Hは、ゲーム画面の幅と高さを表す定数だよ。

n88_kaede.gif
なるほどっ。

n88_reon.gif
それじゃ後は、サブプロシージャGameMainに、さっき作ったJikiDrawを呼び出すコードを書きましょう。このコードを書いてね。

abdx1908-l05.JPG

n88_kaede.gif
できましたーっ。……あれ? 先輩。実行しても、何も起こりませんよ?

n88_reon.gif
え? あっ……! ごめんごめん。臨時的に、Title()と書かれた行の下に、次の命令を書いてくれるかな?

abdx1908-l06.JPG

n88_reon.gif
元型では、タイトル画面でスペースキーを押してゲームスタートする前提になっているので、この行が抜けていたの。もちろん今回も、タイトル画面の処理をいれたら、この行は消すからね。

n88_kaede.gif
はーい。

n88_reon.gif
それじゃ続いて、このキャラクターを移動させよう!

~自機を動かそう!

n88_reon.gif
ではまず、自機を動かすためのサブプロシージャを作ろう。名前はJikiMoveにしておこう。

abdx1908-l07a.JPG
abdx1908-l07b.JPG

n88_reon.gif
それができたら、サブプロシージャGameMainに、JikiMoveを呼び出すコードを書き加えましょう。JikiDraw()の前に、次の行を書き加えるんだよ。

abdx1908-l08.JPG

n88_reon.gif
ここまでできたら、実行してみてね。

n88_kaede.gif
おぉっ! 自機がカーソルキーで動かせますよ!

n88_reon.gif
このサブプロシージャの前半部分(赤枠の部分)は説明しなくてもいいよね。押されたカーソルキーによって、位置を表す変数の値を変えているだけ。ここのコツは後半部分(青枠の部分)だよ。

n88_kaede.gif
前半部と同じく、IF文がたくさん並んでますね。ここでは何をしてるんですか?

n88_reon.gif
ここでは、キャラクターがゲーム画面をはみ出ていないかをチェックして、もしはみ出ていたらはみ出ないように位置を修正しているんだよ。具体的には、X位置が画面の幅の範囲を超えていないか、Y位置が画面の高さの範囲を超えていないかをチェックしてるの。

abdx1908-z01.jpg

n88_kaede.gif
なるほどー。

n88_reon.gif
さて、次は弾を発射させるよ!

~弾を発射しよう!

n88_reon.gif
さて、次は弾を発射するわけだけど、弾には位置だけでなく、存在しているかどうかのフラグが必要になるよね。

n88_kaede.gif
あ、そうですね。

n88_reon.gif
その考えをさらに進めて、存在しているフラグの立っている弾だけ移動させて、表示させるようにしようと思います。そして、発射ボタンを押した時に、フラグが立っていない弾のフラグを立てて、弾が画面外に出たか敵に当たった時にフラグを倒す、と。

n88_kaede.gif
なるほどー。

n88_reon.gif
それでは、まずは弾の情報からだね。

''※このほかにも必要な変数があればこの下に追加してください

n88_reon.gif
この行の下あたりに、次の行を追加してね。

abdx1908-l09.JPG

abdx1908-r01.JPG
▲ 入れた後はこうなります(青枠が追加した部分です)

n88_kaede.gif
hndShotは、弾の画像のハンドルが入る変数ですよね。

n88_reon.gif
うん、そうだよ。そして、ShotFlag、ShotX、ShotYはそれぞれ、フラグ、X座標、Y座標を入れる配列変数ね。ではまずは、画像をロードする処理を書こうか。このコードを、サブプロシージャMaterialLoadに書いてね。

abdx1908-l10.JPG

abdx1908-r02.JPG
▲ 入れた後のMaterialLoad(枠が追加した部分です)

n88_reon.gif
ここは難しいところはないよね。それじゃ続いて、フラグを全部0にするサブプロシージャも作っておくよ。
こちらです!

abdx1908-l11.JPG

n88_reon.gif
できたら続いて、サブプロシージャStageInitに、今のサブプロシージャを呼び出すコードを書いてね。

abdx1908-l12.JPG

n88_kaede.gif
あの、先輩。どうしてこんなことをするんですか?

n88_reon.gif
やられたりした後、ゲームをやり直す時のことを考えてみて。弾を消さないでおくと、再会した時に、前のプレイの時の弾が残っちゃうでしょ?

n88_kaede.gif
あぁ、なるほどー。

n88_reon.gif
さて、次に、弾を移動させ、表示するサブプロシージャを作りましょう。こちらです!

abdx1908-l13.JPG

n88_reon.gif
やっていることは難しくないよ。まず、4行目と17行目のForとNextで、弾の数だけ繰り返し、もしチェックする弾のフラグが1だったら、7行目でその弾を上に移動。9~11行目では、もし弾が画面の上端を超えたら、フラグを0に戻してます。そしてその後再び、フラグが1だったら、弾を表示する、ということを13~15行目でやっています。

n88_kaede.gif
なるほどっ。

n88_reon.gif
では、このサブプロシージャを呼び出すコードを、GameMainに書き加えましょう。

abdx1908-l14.JPG

abdx1908-r03.JPG
▲ 入れた後のGameMain(枠が追加した部分です)

n88_reon.gif
最後は、弾を発射する処理だね。まずは、存在していない弾の番号を取得する関数を作りましょう。こちらです!

abdx1908-l15.JPG

n88_reon.gif
やってることは難しくないよ。ただ、フラグが0になっている(つまり存在していない)弾の番号を変数に入れて、その変数の値を返しているだけ。全部埋まっているときは-1を返しているよ。

n88_kaede.gif
ふむふむ。

n88_reon.gif
では続いて、弾を作る処理も作っちゃいましょう。これもやっていることは難しくないよ。さっきの関数から番号を受け取り、その番号のフラグを1にして、位置をセットしているだけ。位置は、ちょうど横位置が自機の中間地点、そして縦位置がちょうど自機の真上になるようにしているよ。

abdx1908-l16.JPG

n88_reon.gif
さて。最後に、ボタンを押したらショットを発射する処理だけど、ここはちょっと面倒。まずは、

''※このほかにも必要な変数があればこの下に追加してください

n88_reon.gif
の行の下のところに、次の文を書いてね。

abdx1908-l17.JPG

abdx1908-r04.JPG
▲ 入れた後はこうなります。(青枠の部分が追加したところです)

n88_reon.gif
そして次に、サブプロシージャJikiMoveの一番後ろあたりに、このコードをいれます。

abdx1908-l18.JPG

abdx1908-r05a.JPG
abdx1908-r05b.JPG
▲ 入れた後のJikiMoveはこうなります。(枠の部分が追加したところです)


n88_reon.gif
ここでは、発射ボタンを押してる間、カウンタの変数を加算していって、その値が、定数RAPIDの数ごとに、CreateShot()を呼び出して、弾を発射してるんだよ。

n88_kaede.gif
先輩。どうしてそんなことを?

n88_reon.gif
このようにしないと、押している間、弾が途切れなく発射されて、一本の線みたいになっちゃうんだ。だから、一定間隔ごとに発射するようにしているんだよ。

n88_kaede.gif
なるほどー。

n88_reon.gif
ここでのポイントは、2行目と4行目だよ。まず2行目は、このようにmod演算子(余りを計算する演算子)を使うことで、0~ある数を繰り返すようになるんだよ。

n88_kaede.gif
ふむふむ。

n88_reon.gif
そして4行目。このようにすることで、一定数ごとに処理をすることができるんだよ。例えば今回の例だと、RAPIDの値、つまり10の倍数になるごとにCreateShotを呼び出すことになってるんだね。

n88_kaede.gif
なるほどー。とてもためになるテクニックです!


n88_reon.gif
さて。長くなったけど、今回はここまでっ。次回は、敵の移動の処理を作っちゃいますよ! それでは……。

n88_kaede.gif
また次回~!

==========

※次の更新は、『師匠TのチャレンジARSゲーム!』の予定です。お楽しみに!