点と点の当たり判定(前編)

アバター
ナムアニクラウド
記事: 16
登録日時: 15年前
住所: 茨城県

点と点の当たり判定(前編)

投稿記事 by ナムアニクラウド » 14年前

 みなさん、どうもこんばんは。いよいよ寒くなって来まして、自分は風邪をひいてしまいました。皆さん気をつけてくださいね。
さて、今回は当たり判定について話したいと思います。前編は分かりやすく、ゲームプログラミングなどでの実用性を重視してあっさり話しますが、後編はマニアックに定義や証明をしていきます。
とはいえ、自分に十分な知識と力量があるという自信もないので、間違っていたらご指摘くださいね。
「たかが点どうしの当たり判定で前後編とはなんのこっちゃ」と思った方も居るかもしれませんが、1つの投稿が長くなりすぎると読む気がしないなぁ、と思って分けることにしました。
この投稿もだいぶ長いですが、多めに見てやってください(^^;)

 ゲーム制作をしている人は知っている人も多いと思いますが、「当たり判定」とは主に2つの図形が当たっているかどうかを調べることです。
人間からすれば図を描いて確かめれば済むのですが、コンピューターに図を見せても分かりませんから、図形をデータにして計算によって当たっているかどうかを判定する必要があります。

 今回は「平面上の点と点の当たり判定」です。今後も準備ができ次第いろんな当たり判定を紹介する予定です。

点と点の当たり判定

 平面上の「点」は、2つの実数の組で表されるのがふつうです。ゲームプログラミングの際も、double型やfloat型などの実数型を2つセットで持つクラスなどが多くなるはずです。
今回は、この点が2つあるとき、どのような条件を満たせば2つの点が当たるのかを考えましょう。

 といっても、「点」と「点」が当たっている状況といったら、2つの点が一致している時しか考えられないと思います。
つまり、点( x1, y1 ) と 点( x2, y2 ) は、x1 = x2 かつ y1 = y2 ならば、当たっているということになります。
これは次の図のような状態のことです。点と点が重なっているのでちょっと分かりづらいですが、当たっています。
point.png
point.png (3.81 KiB) 閲覧数: 151 回
 さて、これをプログラムに書けば当たり判定ができる・・・と思ってしまいそうですが、実はこのままではうまくいきません。
ご存じの方もいるかと思いますが、double型やfloat型で計算をする時は計算誤差を免れることはできません。(C#などではdecimal型などで誤差なく計算できますが、あまり使いません)
そこで、「x1 とx2が等しい」ではなく「x1がx2に近い」と考えて判定する必要があります(yに関しても同じように考えます)。
「近い」というのは、2つの位置のあいだの距離が短いということです。x1とx2の距離は、| x1 - x2 |です。(記号|a|はaの絶対値を表します)
これが十分に小さければよいので、0に近い正の実数εを用いて、次のような条件を書けます。
  | x1 - x2 | < ε かつ | y1 - y2 | < ε
これを満たす2つの点が当たっているということにすれば問題ないでしょう。

プログラムでは、例えばC#では次のように書きます。

CODE:

//1つの点のx座標、y座標、もう1つの点のx座標、y座標を引数にとり、2つの点が当たっているならばtrueを返す関数(メソッド)です。
public bool Detect( float x1, float y1, float x2, float y2 )
{
    float aboutZero = 1e-12f;        //計算誤差の許容範囲(この値は一例です)
    return Math.Abs( x1 - x2 ) < aboutZero && Math.Abs( y1 - y2 ) < aboutZero;
}
まあ、ゲームで点どうしの当たり判定をすることなんてほとんど無いと思いますがね(爆


 ・・・しかし、本当にこれでいいのでしょうか (おい
先ほどは「2つの点が一致している時しか考えられないと思います」などと書きましたが、それはつまり「なんとなく・・・」という意味ではないでしょうか。
自分としてはここまでの考え方では納得いかず、もっときちんと考えることにしました。
という訳で、もっとしっかりと点どうしの当たり判定について考えましょう。後半へ続く。

ISLe
記事: 2650
登録日時: 15年前

Re: 点と点の当たり判定(前編)

投稿記事 by ISLe » 14年前

C#はSingle.Epsilonを使ったら良いのではないでしょうか。

処理系で浮動小数点数をメンバに持つことが多いのは、内部的にポリゴン描画だったりピクセル座標系以外も扱ったりするからだと思います。

個人的に平面(というか2Dゲーム)では浮動小数点数同士の比較はしないですね。
当たっているというのは画面上のピクセルが重なっている、というふうに考えます。

アバター
ナムアニクラウド
記事: 16
登録日時: 15年前
住所: 茨城県

Re: 点と点の当たり判定(前編)

投稿記事 by ナムアニクラウド » 14年前

>ISLeさん
 アドバイスをありがとうございます。Epsilonという値があったのですね。後で試してみます。
 「画面上のピクセルが重なっている」というふうに考えるときは、それぞれの座標の値の小数点以下を切り捨ててから == で比較する、という方法でいいのでしょうか?
それともはじめから座標を整数型などで持つのでしょうか?

ISLe
記事: 2650
登録日時: 15年前

Re: 点と点の当たり判定(前編)

投稿記事 by ISLe » 14年前

浮動小数点数をいったん整数型の変数に入れたりキャストしたりすることになるでしょうか。

実のところ2Dゲームで浮動小数点数を使わないんですよね。
てっとりばやくサンプルプログラムを書きたいときくらいしか。
浮動小数点数を使えないプラットフォームとのクロス開発とかありますし。

なのでC/C++では整数部16ビット小数部16ビットの構造体で表現した固定小数点数を使ったりします。
そうすると簡単に整数部だけ整数型としてアクセスできるので。
いちいちビットシフトしてもいまのCPUはその辺あまり速度落とさず動きますけど。
ガラケーJavaアプリのときはプリプロセッサ通したりしてましたけど、C/C++以外は見た目と効能を両立するコーディングが難しいですね。
最後に編集したユーザー ISLe on 2011年11月13日(日) 18:06 [ 編集 1 回目 ]