六角形のクリックボックスを認識する


17

私はあえぎ六角形を含むゲームに取り組んでいます。

現在、私は使用している六角形の画像を持っています(すべての辺は同じ長さです... 50x50ピクセルの画像に収まります)。

私はC#にやや新しい、XNAには本当に新しいですが、ポイントと角度に基づいた複雑なifステートメントを実行するのではなく、呼び出すことができる簡単な方法がありますか?


16進クリック検出を実装するgamedev.stackexchange.com/questions/6382/…を参照してください。
ティム・ホルト

4
私は完全に「あえぎ六角形」をグーグルで検索し、「それはどんな六角形ですか?!」一日が遅いと思います。
マイケルハウス

2
うーん、六角形ではなくあえぎをクリックするとどうなりますか?
ティム・ホルト

1
必要に応じて、クリック領域だけの場合は単純な円で対応します。それ以外の場合、ワインディングサムまたはサムサッチなどのポリゴンテクニック上のポイントを使用する必要があります。
PhilCK

16進マップを任意に回転させない限り、ポリゴン上のポイントは大幅に過剰になります。1000x1000ヘクスのマップで何をしますか?みんなチェックして?RE:サークル、彼らは動作しません。3つのヘクス間のジャンクション頂点の近くに、3つの円が重なり合っています。ヘクス内に完全にある小さな円には、合法的なクリックがどの円にも入らないギャップがあります。
ティム・ホルト

回答:


18

六角形は、角が切り取られた長方形です。私がこれを見て、Civilizationシリーズが直交マップでこのように行うことを聞いた方法は、ホワイトスペース(直交または六角形)と赤、緑、青、黄色のビットマップを作成することですコーナー。(またはあなたが好きな色。)

六角形:六角マスクまたはここに画像の説明を入力してください

直交: ここに画像の説明を入力してください

次に、カーソルがどの長方形の上にあるかを判断し、その場所のピクセルの色をテストします。それが白い場合、彼らはそのスペースの上に浮かんでいます。他の各色はオフセットにマッピングされ、代わりにその六角形の上に移動します。この方法は効率的で、ジオメトリをほとんど必要とせず、任意のテッセレーション空間に使用できます。


注:六角形には6つの等しい長さの辺があります。実際に提示した画像には六角形が含まれていません。代わりに、6つの多角形が含まれています。それ以外は、この方法が機能します。ただし、この方法では、より大きな六角形に対してより大きなスペースが必要になるため(ピクセルごとの精度を維持したい場合)、六角形の境界の計算よりも遅くなります。小さな六角形(およびハードウェアに依存)の場合、この方法はおそらく境界の計算よりも高速です。
Olhovsky

9
六角形は、6辺の多角形です。あなたが考えていることである等辺六角形の(実際には、あなたはおそらく考えている通常の正三角形の一種で、六角形、および等角六角)
Random832

私はあなたの答えが悪いと言っていなかったことに注意してください。私はそれが良い答えだと思うし、解決策があります。とはいえ、境界を計算する方がはるかに拡張可能な方法であるため、現代のプラットフォームで六角形の境界を計算するため、六角形の境界を計算するよりもこの方法を選択しません。たとえば、六角形のサイズを変更したい場合、イメージを再構築する必要がありますか?ピクセル完璧な六角形マスクを作成するのは大変です。ここで作成していないという事実は、その証拠です。
Olhovsky

2
@Olhovsky-仕事中の数分間の休憩中にコミュニティサービスとして質問に答えており、実際にビデオゲームを書いているわけではないため、ここでは完璧な六角形のマスクを作成していません。OPはあまり数学と解決策を探していた、と私は共有したいと思ってからだと私は何か、これはきちんとしたと思った確かに自分で考えていないだろう。
dlras2

18

六角ヒットテストを行うXNAメソッドはありません。

この記事では、テストを行う関数の作成方法を説明し、その関数を提供します。

ポイントが六角形の内側にあるかどうかを確認する方法

その記事の要約は次のとおりです。 六角形のクリックボックス

そして、テストを行う関数は次のようになります。

  1. 六角形の周囲のバウンディングボックスをテストし、交差しない場合は早期にテストします。
  2. 上記のように、ポイントをローカル象限に変換します。
  3. isInsideローカル象限に対して次のテストを実行します。

public function isInside(pos:Vec2Const):Boolean
{
    const q2x:Number = Math.abs(pos.x - _center.x);       
    const q2y:Number = Math.abs(pos.y - _center.y);
    if (q2x > _hori || q2y > _vert*2) 
        return false;
    return 2 * _vert * _hori - _vert * q2x - _hori * q2y >= 0;
}

詳細については、記事を参照してください。


他の有用な関連ソースは次のとおりです。


1

ここで、ポリゴン内のクリックを検出するために使用できるメソッドを取得しました:

public bool PointInPolygon( Vector2 p, Vector2[] poly )
    {
        Vector2 p1, p2;
        bool inside = false;

        if( poly.Length < 3 )
        {
            return inside;
        }

        Vector2 oldPoint = new Vector2( poly[poly.Length - 1].X, poly[poly.Length - 1].Y );

        for( int i = 0; i < poly.Length; i++ )
        {
            Vector2 newPoint = new Vector2( poly[i].X, poly[i].Y );

            if( newPoint.X > oldPoint.X )
            {
                p1 = oldPoint;
                p2 = newPoint;
            }
            else
            {
                p1 = newPoint;
                p2 = oldPoint;
            }

            if( ( newPoint.X < p.X ) == ( p.X <= oldPoint.X )
                && ( (long)p.Y - (long)p1.Y ) * (long)( p2.X - p1.X )
                 < ( (long)p2.Y - (long)p1.Y ) * (long)( p.X - p1.X ) )
            {
                inside = !inside;
            }

            oldPoint = newPoint;
        }

        return inside;
    }

六角形の角をvector2配列(poly)とクリックした位置(p)でメソッドに与える必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.