読者です 読者をやめる 読者になる 読者になる

大西Scratch日記

Scratch初心者です。勉強するためにブログを始めてみます

複数のクローンされたスプライト同士のあたり判定

Scratchでシューティングゲームを作る時に、あたり判定が難しいな、といつも思いますので自分なりのベストプラクティスを考えてみました。

クローンを使わずに「単発の弾」と「単機の敵」の場合は問題ないのですが、クローンを使って複数複数を考えると難しいんですよね。

複数の弾をクローンで扱う

f:id:onishi:20160523180321p:plain:w230
こんな感じで「自機」「弾」「敵」の3種類のスプライトがいる簡単なシューティングゲームを作ってみましょう。

自機のスクリプトはこんな感じですね。(PCで見ている方は画像をクリックすると拡大します)
f:id:onishi:20160523180508p:plain:w205
カーソルで左右に動き、スペースで弾を撃ち、敵に当たったら終わりです。
複数の弾を撃つために、このように「弾のクローンを作る」とすれば、スペースを押す度に弾が発射されます。

弾のスクリプトはこのようにします。
f:id:onishi:20160523180912p:plain:w173
「旗がクリックされたとき」の処理は初期化に留め、「隠す」しておきます。
「クローンされたとき」に、自機の位置に表示して上に移動する処理を書きます。

より高度な弾の処理(同時発射数と連射防止)

これだけでも複数の弾を扱えるのですが、このままでは、スペースキーを押しっぱなしにすると連射されてしまうため、シューティングゲームとしては不自然です。そこで、

  • 同時発射数を制限する
  • 連射を防止する

という2つの処理を入れてみましょう。
f:id:onishi:20160523181609p:plain:w267
同時発射数を防止するために、「弾の数」という変数を用意し、画面上に表示されている弾の数を監視します。弾が消える時に変数の数字を減らすのを忘れないように。
連射を防止するために、タイマーを用いてみました。弾を撃つ際にタイマーをリセットし、一定時間以内には弾が撃てないようにします。
弾が消える処理が増えたとき用に「消える」ブロックを用意することで、「弾の数」変数の減らし漏れが無いように工夫しています。
これで、同時発射数は5発まで、0.2秒以内には連射できない、となりました。

複数の敵

複数の敵も複数の弾と同様に書きます。
f:id:onishi:20160523182051p:plain:w290
「旗がクリックされたとき」の処理は初期化と「隠す」しておき、2秒ごとにクローンを発生させるようにしました。
「クローンされたとき」に、ランダムな位置と向きで表示させています。

複数の弾と複数の敵のあたり判定

さていよいよ本題です。弾がレーザーのように敵を貫通するならよいのですが、弾が敵に当たったら両方消える、とする場合の処理はなかなか難しいです。

素朴に書くとこのようになりますが、これではうまくいきません。
f:id:onishi:20160523182351p:plain:w185 f:id:onishi:20160523182407p:plain:w199
お互いが「相手に触れたなら」という判定を使っています。これで動きそうに思えますがダメです。
なぜならプログラムは常に複数の動作を同時にこなしているように思えますが、実は高速に割り込み処理を入れているだけで順番に一つ一つの処理を行っているだけなのです。
つまりこのプログラムでは「たまたま先に実行されたどちらか」の処理だけが行われ、「弾は消えるが敵は消えない」もしくは「敵は消えるが弾は消えない」のどちらかになってしまいます。

クローンに対して個別にメッセージが送れれば良さそうなものですが、Scratchにおけるメッセージはブロードキャスト(全部のスプライトに対して一様にメッセージが送信される)のみ。なので「この弾がこの敵にあたった」という判定は難しいです。


そこで考えてみたのがこういうやり方です。

f:id:onishi:20160523183235p:plain:w205
弾の処理では、ループ内であたり判定をしますが、「メッセージを送って待つ」を利用してみます。

f:id:onishi:20160523183255p:plain:w194
敵の処理としては、「メッセージを受け取ったとき」だけあたり判定をしています。向こう(弾)はメッセージを送って待っているはずなので、この瞬間ならどちらも「相手に触れたなら」の条件が揃うはずです。

これで、どちらか片方だけ消えるという問題が解決できました。

完成

というわけで、これで複数のクローンされたスプライト同士のあたり判定が思ったようにできました。実際に動く物はこちらです。

ソースコードはこちらで見ることができます。
クローン同士のあたり判定 on Scratch

Scratch初心者なので、これがベストな方法なのか自信がないです。もっといい方法があれば是非教えてください!