円と矩形の当たり判定つくってみた

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

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

▷▷▷ 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を返すようになってます。

 

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

 

と楽勝だったな、なんて思ってたんですけど、よく見てください。

これあんまり良くないですよね?

当たらないときに一番多く計算している

ちょっとして気づいたんですよ。

 

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

 

それって無駄じゃない?

基本的に画面内の小さなキャラ同士が当たる確率なんて当たらない確率と比べたら圧倒的に低いですよね?

なのに当たらない時に全部の判定するなんて無駄過ぎる。

無駄は嫌いなんだよ。無駄だから。無駄無駄無駄無駄。。

当たらないことを判定する

どこが無駄だったのかを考えてみると当たることを判定するようにしたから、当たらない場合に全部の当たる判定を確認しなくちゃいけないんだろうとなりました。

だったら当たらない判定をしたらいいんじゃね?(・∀・)

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

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;//すべての条件が外れたときに当たっている
}

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

簡単な解説

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

解説図

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

まとめ

どっちも判定回数が多いですが通常のゲームではキャラ同士が当たっていない確立の方が高いと思うので当たらない条件で処理を書いた方が処理が軽くて良いんやないかな、と思います。

ひょっとしたらまだもっと処理を軽くできるところがあるかもしれないですね。

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

タイルマップでブロックの角をヌルっと滑らせる当たり判定

この当たり判定を使っている私のゲームも遊んでみてください★

同カテゴリー記事

記事の感想・コメント

※コメントはまだありません※

コメントを残す

メールアドレスが公開されることはありません。

最近作ったゲーム