JavaScriptでゲーム作ろう

今作ってるゲームで円と矩形の当たり判定が必要になったのでそれについて自分なりにわかったことを書いておきます(‘ω’)ノ

今回参考にさせていただいた記事はこちらでござる

▷▷▷ http://ftvoid.com/blog/post/300

とりあえず作ってみた

参考記事の通り上下左右を円の半径分大きくとるのと、四隅で円の当たり判定を取るような感じでプログラムを作ると以下のようになりました。

function collision(L, R, T, B, x, y, radius){
  //L,R,T,Bは矩形キャラの四隅の座標、x,y,radiusは円形キャラの座標と半径 
  if(L - radius < x && R + radius > x && T < y && B > y){
    //矩形の領域判定1 
    return true; 
  } 
  if(L < x && R > x && T - radius < y && B + radius > y){
    //矩形の領域判定2 
    return true; 
  } 
  if((L - x) * (L - x) + (T - y) * (T - y) < radius * radius){
    //左上の当たり判定 
    return true; 
  } 
  if((R - x) * (R - x) + (T - y) * (T - y) < radius * radius){
    //右上の当たり判定 
    return true; 
  } 
  if((L - x) * (L - x) + (B - y) * (B - y) < radius * radius){
    //左下の当たり判定 
    return true; 
  } 
  if((R - x) * (R - x) + (B - y) * (B - y) < radius * radius){
    //右下の当たり判定 
    return true; 
  } 
  return false; 
}

 

上から順番に重なってたら当たったということでtrueを返すようになってます。

 

なぁーんだ簡単じゃーん(*´ω`)

 

と楽勝だったな、なんて思ってたんですけどちょっとして気づいたんですよ。

これ、当たらない時って全部判定してるの?

当たることを判定するようにしたから、当たらない場合に全部の当たり判定を確認しなくちゃいけないってことになってる。

だったら当たらない場合から判定した方が処理が軽くなる気がする。。

※(あとで参考の記事をちゃんと読んだら高速化のことを書いた記事のリンク貼ってありました→https://ftvoid.com/blog/post/329。ちゃんと読めよな、俺!でもやり方全然違うのでまぁいろんな方法があるよね!ってことで(^^;))

ちょっと改造してみた

ということで作り直したのがこちら

function collision(L, R, T, B, x, y, radius){ 
  if(L - radius > x || R + radius < x || T - radius > y || B + radius < y){
    //矩形に円の半径分を足した範囲 
    return false; 
  } 
  if(L > x && T > y && !((L - x) * (L - x) + (T - y) * (T - y) < radius * radius)){
    //左上の当たり判定 
    return false; 
  } 
  if(R < x && T > y && !((R - x) * (R - x) + (T - y) * (T - y) < radius * radius)){
    //右上の当たり判定 
    return false; 
  } 
  if(L > x && B < y && !((L - x) * (L - x) + (B - y) * (B - y) < radius * radius)){
    //左下の当たり判定 
    return false; 
  } 
  if(R < x && B < y && !((R - x) * (R - x) + (B - y) * (B - y) < radius * radius)){
    //右下の当たり判定 
    return false; 
  } 
  return true;//すべての条件が外れたときに当たっている 
}

 

全部の条件に合わなかったときに当たっていることになります。

簡単な解説

当たらない条件を考えるとまず下図の黄色の部分が一番範囲が広く、キャラ同士(グレーのがキャラね)当たらない場合ほとんどこの条件ではじくことができます(最初のif文)。

解説図

後は赤い部分の判定です。各頂点に半径を足した(または引いた)分より外側だった場合で、円の当たり判定でも重なってなければ当たっていないといえるはずです。

おしまい

この円と矩形の判定を使ってマップのブロックの角をヌルっと滑らせるような感じにするプログラムの記事もあるので良かったらどうぞ。

角に引っかからず滑らせる当たり判定のやり方