【スクラッチ】スプライトのあたり判定が上手くいかない

敵に向けて弾を発射して敵をやっつけていくシューティングゲームを作る時に、思い通りに敵を消したり、敵をやっつけた時にスコアが思い通りに上がらない事がありますよね。
ここでは、そんな時に解決方法となるヒントをいくつかご紹介します。

ここで紹介する内容は、FOM出版さんの”Scratchで楽しむレッツプログラミング”のブロンズ級で紹介されているプログラムを引用させていただいています。この本ではエントリ―、ブロンズ、シルバー、ゴールドとステップ別にプログラミングのレベルを上げながらスクラッチの楽しみ方を紹介しており、これからScratchを始めるお子様にも分かりやすい教材となっているお薦めの教材です。
FOM出版

当たり判定が正しく行われない原因は?

スプライトのあたり判定を正しくする方法

敵に弾が当たってもスコアが変わらない

このスクリプトを見てみましょう。

”ずっと” のブロックの中にドラゴン(敵)が魔法(弾)に触れたら”スコアを1ずつ変える”があるので、ドラゴンに弾が当たったらスコアが増えそうですよね。

でも、全くスコアは変わりません。理由はどうしてか分かりますか?

スコアの変わらないスクリプト
”スコアの変わらないスクリプト”

”ずっと”のブロックの中は、赤い矢印の順番で繰り返し処理されています。

このドラゴンのスクリプトの意味は

2秒待つ=>Y座標の位置を変えて出現する=>出現した時に魔法に触れたらスコアを変える=>2秒待つ

 

だから出現した時のタイミングで運よく魔法に触れたらスコアは変わりますが、そのタイミングを逃した後に、いくら弾をドラゴンに当ててもスコアは変わらないんです。

敵に弾が当たった時にめちゃくちゃスコアが変わる

それでは、

”ずっと”のブロックの中に

”魔法に触れたらスコアを1つずつ変える” としたらどうでしょう。

2つのスクリプトのうち右側のスクリプトは、上の”スコアの変わらないスクリプト””ずっと”のブロックを加えたものです。

これでドラゴン出現のタイミングに関係なく当たり判定が行われます。

左側のスクリプト別のスクリプトに”ずっと”のブロックを付け加えたもので(上にある動画を見てね)、結果は同じ動きとなります。

どちらのやり方でもドラゴンの出現タイミングに関係なく、魔法が当たるとスコアが変わるのですが、残念ながらスプライト同士が触れている回数(6~8回)だけスコアがカウントされてしまいます

これだと、”弾が敵に当たったらスコア1点” または ”複数回当てたら敵が消える”というような当たり判定回数をカウントするゲームを作る事ができないですよね。

 

”○○まで待つ” を使うと上手くいく

もし○○に触れたら”というブロックは条件指定する時に選びやすいですが、このブロックの代わりに”○○まで待つ”の方が上手くいくことが多いです

ここで、その一つの例を説明しますね。

”まで待つ”のブロックを使うとうまくいく
”○○まで待つ”を使うスクリプト

このスクリプトのように”魔法に触れたまで待つ”を使うことで、
2秒待つ=>ドラゴン出現=>2秒待つ=>出現
をずっと繰り返す中で、”魔法に触れたらスコアを変える”というアクションをじっと待たせることができます。

”ずっと”のブロックの中で、魔法に触れるタイミングは関係なく魔法に触れたら1度だけスコアを変える事になります。

ですから、ドラゴンが魔法に当たるとスコアが1点だけカウントされて、スプライト同士(魔法とドラゴン)が触れ合う回数だけスコアがあがる事はありません。

その証拠に、魔法に当たった後も同じ場所にいるドラゴンに2回、3回目の魔法を当ててもスコアはあがりませんね。

ドラゴンに魔法を当てたのに、ドラゴンが消えずスコアもあがらないのも変なので、魔法が当たったらドラゴンには消えてもらいましょう。

当たり判定でスプライトを正しく消す方法

ここからは魔法が当たるとドラゴンが消えていなくなるゲームの例を見ていきましょう。

”○○まで繰り返す”と”もし○○なら”のコンビネーション

敵を消すとスコア1点だけこのスクリプトは、最初に紹介した”スコアの変わらないスクリプト”に赤線で囲んだ線の部分が加えられただけですが、この違いだけで魔法がドラゴンに当たったらスコアが一つずつカウントされて、ドラゴンも消えるようになりました。

  • 魔法に触れるまたは端に触れるまでドラゴンは3歩ずつ動きます
  • 魔法に触れたことで3歩ずつの動きが止まり
  • 次のブロックのスコアを変えるの処理
  • そしてドラゴンを隠す

”スコアの変わらないスクリプト”では、”もし魔法にふれたなら”の処理タイミングがドラゴン出現の後の一瞬しかないのに比べて、○○まで繰り返す”をコンビネーションで使う事で、そのタイミングを逃す事がないのです。

このコンビネーションを使う事で、ドラゴンに魔法が当たった時に必ずスコアを1つずつカウントしてくれます。

因みに、赤線で囲んだ”隠す”は無くても、正しいスコアのカウントはしてくれます。 この”隠す”のブロックはドラゴンが魔法に触れるか端に触れた時にドラゴンを隠す役割をしています。

魔法が当たるまで色を変える
魔法が当たるまで色を変えるドラゴン

スコアの変わらないスクリプト”に魔法に触れるまで色を25%ずつ変える というブロックをいれたら、スコアがキチンとカウントされるようになりました。

”○○まで繰り返す” と ”もし○○なら” のコンビネーションがきちんと機能している事がわかりますね。

スプライトを隠す

コンビネーションを使わない例
スプライトを消してスコアを正しくカウントする

ゲームを作る時に、最初にドラゴンが魔法使いに向かって動くだけを考えると、”端に触れたまで繰り返す”の条件しか入れないことも多いですね。

そして、途中で魔法を当てるとか、魔法使いに当たるとかの条件を後から試す場合は、コンビネーションで必要となる”魔法に触れたまで繰り返す”のブロックを入れないことも多いです。

もし魔法に当たるまで繰り返すの条件が無い場合、例えば”端に触れるまで繰り返す”だけの条件の場合は、繰り返す指示のブロックの中に”もし○○なら”のブロックを入れて、弾が当たった直後に敵を消す(隠す)と、スコアは1つ(指定した数)ずつカウントされるようになります。

 

 

当たり判定時に両方のスプライトを消す方法

さて、最後は魔法(弾)がドラゴン(敵)に当たった時に消えるようにプログラムをしてみましょう。

魔法が手前のドラゴンに当たったあと、そのまま他のドラゴンにも当たってしまうのはゲームとして簡単すぎます。

魔法がドラゴンに当たった時に、魔法を消すためには次のスクリプトにどのような変更を加えたら良いかわかりますか?

魔法(弾)のスクリプトBefore

魔法(弾)のスプライトのプログラムに、”端に触れたまで10歩動かすを繰り返す”というブロックがあるので、この魔法が10歩ずつ動いている最中にドラゴンに触れたら魔法が消えるというスクリプトにすれば良いですね。 ではやってみましょう。

ほんの少し待つスクリプト

あれ、魔法は消えるのに、なぜだかドラゴンが消えなくなってしまいませんか?

これは、魔法がドラゴンに当たった瞬間に消えるので、ドラゴンが魔法に当たったことに気づかないために起こります。

実際にはドラゴンが気付かないのではなくて、コンピュータ処理のタイミングが間に合わないことから起きています。 そこで、ドラゴンを消す処理を行えるまでほんの少しだけ魔法を消す時間を待ってあげるようにします。

待つ時間は0秒で良いですよ。
これで魔法もドラゴンも当たった瞬間に消えてなくなり、スコアも正しくカウントされるようになったはずです。

どうしても、自分でできなかった方は次の ”0秒でドラゴンを消す” をクリックして確認してみて下さい。

0秒待つでドラゴンを消す

両方のスプライトを消す別の方法

二つのスプライトがぶつかった時に、片方のスプライトAからメッセージを送って待つ
そのメッセージを受取ったスプライトBは、メッセージを受取った瞬間にスプライトAに触れていたら消える
スプライトBがメッセージを受けた後の処理が終わったら、スプライトAも消える

メッセージを送るスクリプトメッセージを受けるスクリプト

 

 

 

 

 

 

 

 

 

 

 

具体的には、上のスクリプトのようにボールがメッセージを送って待つ
3つのドラゴンはメッセージを受け魔法に触れているドラゴンだけが消える
ドラゴンの消える処理が終わったら、ボールも隠すのブロックが有るので消える。

同じ様な内容が下の記事で、もう少し詳しく説明してあるので興味がある方はご覧ください。
一番下の方で説明しています。