![]()
前回は自機から弾丸を発射する方法について解説をしました。敵キャラと弾丸が衝突した場合の簡単な当たり判定も作ってみました。次第にシューティング・ゲームらしくなってきたと思います。
前回で作った敵キャラと弾丸の当たり判定では、弾丸は敵キャラを貫通してしまいます。今回は弾丸を貫通させない方法について考えてみることにしましょう。スプライト間やスクリプト間で実行のタイミングを知らせるための「メッセージ」を使うことで問題の解決を試みます。
今回の記事で完成させるプロジェクトを以下に埋め込みました。左右のキーで自機が左右に移動でき、スペース・キーを押すと弾丸が発射できる点は前回までと同じです。弾丸が敵キャラに命中すると、敵キャラだけでなく、弾丸も消えます。
前回の作業結果の読み込み
前回の作業の続きをはじめたいと思いますので、前回保存したプロジェクトのファイルを読み込みましょう。ファイルを読み込むためにはファイル・メニューから「開く」を選択してください(図1)。

前回紹介したように、プロジェクトの共有ページ(http://scratch.mit.edu/projects/eleki-jack/2299119)からもダウンロードできます。ScratchのWebサイトにログインした状態で、画面右の「プロジェクトのダウンロード」という部分のリンク(ScratchWeekly8)からファイルをダウンロードすることができます(図2)。

図2と同様のファイルはここからもダウンロードできます。
当たり判定の改善(1)まずは弾丸を貫通させないようにする一番簡単に考えつきそうな方法を試してみましょう。現在は敵キャラのスプライトに、図3のような当たり判定のスクリプトが用意してあります。弾丸の色に当たったら、自分自身を隠すというスクリプトですね。

これと同じように、弾丸のスプライトにも敵キャラに使ってある色に当たったら自分自身を隠すというスクリプトを組み込めばよいのではないでしょうか。実際に作って試してみましょう。
実験用のプロジェクトを以下に埋め込みました。敵キャラは動かないようにしてありますので、緑旗をクリックしてから、スペースキーで弾丸を発射してみてください。
何度か緑旗をクリックして、弾丸を発射してみるとわかると思いますが、敵キャラが消えるときと、弾丸が消えるときがあります。そして同時に消えることはありません。これはスクリプトが実行されるタイミングが関係しています。弾丸と敵キャラそれぞれにお互いの色に触れたら自分自身を隠すというスクリプトが用意されています。どちらかのスプライトが先に消えれば、他方のスクリプトの当たり判定が効かなくなり、隠すというブロックが実行されません。これがどちらか一方が消えてしまう原因です。先に弾丸のスプライトの当たり判定のスクリプトが実行されれば、敵キャラに作った当たり判定のスクリプトは(既に弾丸は隠されているので)実行されません。逆も同じです。
当たり判定の改善(2)先ほど紹介した方法では各スプライトに用意したスクリプトの実行の順番が制御できず、うまくいかないことがわかりました。弾丸が敵キャラに着弾して自分自身を隠した後に、そのことを他方のスプライトに伝えることができれば、この問題は解決できそうです。Scratchには、自分自身を含めたすべてのスプライトにお知らせを送り、それを受け取ったタイミングでスクリプトを実行するための仕組みが用意されています。これを「メッセージ」と呼びます。プログラミングの概念としての詳しい解説が知りたければ、阿部 和広氏の「簡単だけど奥深い!Scratchプログラミングの魅力」(http://itpro.nikkeibp.co.jp/article/COLUMN/20111019/371080/)を参照ください。
基本的には各スプライトに自分自身に関係するスクリプトを作っていくという方針で作業をしていけばよいのですが、「○キーが押されたとき」や「緑旗がクリックされたとき」のように既に用意されているイベント以外を使って、スクリプトの実行の制御をしたいという場面があります。このような場合にメッセージを利用するとよいわけです。
先ほどの問題を解決しながら、具体的にメッセージの送信方法と受信方法を説明しましょう。まず、弾丸が敵キャラに当たったら、自分自身を消した後に、弾丸のスプライトにもその旨を伝えるようなスクリプトを作ります。まず、敵キャラのスクリプトを表示させたら、「制御」のカテゴリにある「○を送る」というブロックがあることを確認してください(図4)。これがメッセージを送信するためのブロックです。

ブロックの先頭にあるプルダウン・メニューにある黒い三角形をクリックすると、「新規...」というメニューが表示されます(図5)。

新規をクリックすると、新しいメッセージの名前を入力するダイアログが表示されます。メッセージの名前は自由に付けることができます。ここでは「敵キャラに着弾した」という名前を入力し、OKボタンをクリックします(図6)。

これでメッセージを送信する準備ができたので、メッセージを送信するブロックを「隠す」ブロックの下に追加します(図7)。なお、「隠す」を実行しても色判定が実行される場合があるようなので、念のため隠した後に自機の後ろにワープさせるために、y座標を-180に変更しておきます。すべての敵キャラに対してこのスクリプトの更新を行ってください。

次に弾丸のスプライトでこのメッセージを受信し、自分自身を隠すスクリプトを実行させましょう。メッセージを受信するブロックは、キーボードの入力や緑旗クリックのイベントを受け取るためのブロックと同じように、先頭が丸くなっているブロックを使います(図8)。

「敵キャラに着弾した」というメッセージを弾丸が受け取ったら、自分自身を隠すスクリプトを作ります(図9)。これで必ず敵キャラが消えてから、弾丸が消えるようになります。

メッセージの活用
メッセージは当たり判定のためだけに使うものではありません。例えば、現在は弾丸のスプライト自身が、スペース・キーが押されたことを検知していますが、これは弾丸の連射を実現しようとする時にはあまり良い方法でありません。単に弾丸をコピーするだけでは、それぞれの弾丸が一斉に同じ動きをしてしまい、順番に発射することはできないからです。メッセージを使うと、自機のスプライトでスペース・キーが押されたというイベントを検知し、弾丸を順番に発射できるように適切なメッセージを送信するスクリプトを作るといったことができるようになります。最初から後々の改造を考慮してスクリプトを作れるようになるには慣れが必要ですので、必要に応じてスクリプトを更新していくという方法で作業をするのがオススメです。
では、将来の連射の実現に備え、自機でスペース・キーが押されたことを検知するようにスクリプトを変更しておきましょう。メッセージを送信するためのブロックを作る方法は先に紹介しました。今回は「弾丸を発射する」というメッセージを送信するスクリプトを自機に作っておきましょう(図10)。今回は「○を送って待つ」というブロックを使います。このブロックはメッセージを送った後に、そのメッセージを受け取ったスクリプトの実行が終わるまで待つためのブロックです。これを使えば、弾丸が画面にある状態で再度スペースキーを押しても弾丸は発射されません。

弾丸のスクリプトを変更して、「弾丸を発射する」というメッセージを受け取ったら、発射の動作を行うように変更します(図11)。現在は自機と敵キャラが衝突し、自機が消えても弾丸が発射できるという問題がありますが、この問題の解決は今後取り組みましょう。

スプライトの衝突判定について
Week5で少し触れましたが、現在はスプライトの衝突判定に色を使っています。色を使うことにより、例えば自機と敵キャラとの当たり判定は図12のようなシンプルなスクリプトになります。ただし、敵キャラの一部分に共通の色(この場合は紫色)を採用する必要がありますから、スプライトのコスチューム(見た目)に関する制約があります。

衝突判定にはスプライトを指定する方法も使うことができます。これにより、コスチュームに関する制約は回避できますが、敵キャラが複数になる場合は、図13のようにそれぞれのスプライトについて判定を作る必要があり、スクリプトが長くなりますし、敵キャラが増えるたびに図13のスクリプトも更新する必要があります。

こうした問題について、メッセージを使うことにより改善を行うことができそうです。例えば、敵キャラに自機のスプライトを指定した判定のスクリプトを用意します(図14)。衝突時には敵キャラからメッセージを送信するようにし、それを自機で受け取ります。

自機には図15のようなスクリプトを用意するわけです。これにより、コスチュームに関する制約もなくなり、敵キャラのスプライトをコピーして増やした場合についても、とくにスクリプトの変更なしに動作させることができます。しかし、この方法は良いことばかりではなく、メッセージが増えることで、スクリプト間の関係性がわかりにくくなるという欠点もあります。

同じ動作を実現するスクリプトでも、作り方はたくさんあって、唯一絶対の正解というものはないことが多いです。いろいろな方法を考えてみて、それぞれの方法の利点と欠点を分析し、最適なものを選ぶことが重要であり、これがプログラミングの面白さの一つではないかと思います。
次回は効果音やBGMを付けて更にゲームの完成度を高めていきます。
Facebookのファンページ(http://www.facebook.com/ScratchWeekly)もご覧ください。「いいね!」を押していただけると、ニュースフィードに記事の更新情報やお知らせが届きます。


コメントする