衝突判定①
衝突判定の考え方
自機と★が接触したかどうかの判定を行います。
「衝突判定」「あたり判定」「ヒット判定」「コリジョン」・・・
いろいろな呼び方がされますが、ゲームを作るうえで非常に重要な要素の一つです。
少し長くなりますが、しっかり理解してください。
さて、「自機と★が接触している」というのは、
具体的(論理的)にいうとどういう状態でしょうか?
まず間違いないのは、「player_xとstar_x、player_yとstar_yが
等しければ自機と★は接触している」ということ。
たとえば、自機が(100, 50)の位置にいて、
星も(100, 50)の位置にいれば、当然ぶつかっていますよね?
これをプログラムにするとどうなるでしょうか?
二つの条件
「player_xとstar_xが等しい場合」というのは
if(player_x = star_x){ ・・・・・ } |
こう書けますね?
同様に「player_yとstar_yが等しい場合」というのは
if(player_y = star_y){ ・・・・・ } |
となります。
今回はこの二つの条件が両方成り立った時に衝突してると判定します。
そのためには次のように書きます。
;★が左端に出た
if(star_x < -32){
star_x = 800 ;ふたたび右端へ
star_y = rnd(480-32) ;高さはランダム
star_speed = rnd(5) + 2 ;速度もランダム
}
;自機と★の衝突判定
if((player_x = star_x) and (player_y = star_y)){
end ;プログラム終了
}
await 16
goto *メインループ
このように、二つの条件が成り立った時の処理を書きたい場合は、
if( (条件1)and(条件2) ){ ・・・・ } |
と書きます。
andは何個つなげてもいいので、条件が3つあるのあれば
if( (条件1)and(条件2)and(条件3) ){
となります。
【メモ】
「and」の代わりに「&」と書いてもいいです。
(例)
if( (条件1)&(条件2) ){
・・・・・
}
ちなみに、自機と★がぶつかったときの処理に「end」と書いてありますが、
これはコメントにもあるように「プログラムをそこで終了しなさい」という命令です。
つまり、ぶつかったらとりあえずプログラムが終了するはずです・・・・
ですが・・・・?
衝突範囲
さて、上のプログラムを実行してみて自機を★の位置に
移動してやるとプログラムは終了するでしょうか?
おそらく、ほとんどすり抜けていくと思います。
なぜなら、上で書いたif文の通りだと、
自機と★が1ドットのズレもなく重なったときのみ、
ぶつかったと認識されます。
自機が5ドットずつ移動してることから考えても、
全く同じ位置に重なるのはほぼ不可能です。
(偶然重なることはあるかもしれませんが・・・)
これではゲームにならないですね?
そこで普通はある範囲内に入ったらぶつかったと判定します。
今回のゲームではどの範囲に入ったらぶつかったことにすればいいでしょうか?
自機を基準に考えれば★が下図の位置に入ったら“ぶつかった”と言っていいでしょう。
これをどのようにプログラムにしていけばいいでしょうか・・・
論理的思考
どのようにプログラムを書いたらいいか考えるには、
やりたいことを論理的に考える必要があります。
・・・というと難しく聞こえますが、
簡単に言うと「やりたいことをバカみたいに細かく、具体的に説明する」と
考えてもらえればいいかと思います。
やってみましょう。
先ほどの図を見てもらえれば、
「だいだいこの範囲に来たら“ぶつかってる”って言っていいんだなぁ」
ってのがわかると思います。
でも、これは「感覚的」であって、「論理的」でも「具体的」でもないですね。
まず最低限「だいたいこの範囲」というのを
具体的な数値にしなければいけません。
今回は、自機も★もフォントサイズが32なので、
下図の赤い範囲に★が入ったら“ぶつかってる”ということにしましょう。
これで具体的にはなりましたが、まだ論理的には遠いです。
「★が赤い範囲」というのはどういう状況か・・・
これを4つにばらします。
★が上図の赤い範囲ということは・・・・
この赤いラインより右側で | |
この赤いラインより下で | |
この赤いラインより左側で | |
この赤いラインより上 |
ということですね?
「あたりまえだ」とか「そりゃそうだ」と思うのが人間だと思います。
でも、コンピューターはここまで噛み砕いてあげないと伝わらないんです。
たとえば、人間に道を教えてあげるなら
「この道を直進して、大きい通りに出たら左に曲がると看板があるよ」
くらいで伝わると思います。
でもコンピューターの場合はこれじゃダメです。
「直進」なんて言ったら、ちょっと道が曲がっていたり、
車が止まっていてもガンガン直進していってしまいます。
「大きい通り」と言われても、
道幅何メートル以上が大きい通りなのか分かりません。
「看板」? どんな材質で何色の板に、
何色で字が書かれたもののことを言ってるんでしょうか?
めんどくさいと思わないでください。
コンピューターは、素直で正直者なだけです。
だからこそ、何でも言うことを聞いてくれる、いい奴なんです。
今回のポイント
- 複数の条件が成り立った時の処理を書きたい場合は
if((条件1)and(条件2)){
・・・
}
または
if((条件1)&(条件2)){
・・・
}
と書く。 - 「やりたいこと」をどのようにプログラムで書くか考えるときは
「バカみたいに細かく、具体的に説明する」ことを心がけるとよい。