プレイヤーが移動できる特定のスペースしかないゲームを作っています。この空間を何らかの多角形で表現したい。私が尋ねる主な質問は、それが特定のポイントを含んでいるかどうかです。(のようにrect.intersect()
)
XNAにはこれを行う方法がありますか?
いいえ(少なくともバージョン 3 は含まれていません)
XNA には錐台やボックスなどのバウンディング ボリュームがありますが、ポリゴンの概念はありません。
XNA を使用してポイント イン ポリゴンを実行する、シンプルで高速かつ効果的な方法を見つけることができます。ここ. 私は最近これを実装しましたが、それは素晴らしかったです。
オブジェクトのポイントがわかれば、このオブジェクトを囲むポリゴンを作成するだけです。ベクトルを使用するのが最も簡単な方法です。次に、ポイント イン ポリゴン チェックを実行します。
これが私の実装のサンプルコードです。XNA のデフォルトのポイント クラスが使用されます。Polygon は、ポリゴンを構成するベクトルのコレクションを含む単純なクラスです。
/// <summary>
/// Point in polygon check.
/// </summary>
/// <param name="point">The point.</param>
/// <param name="polygon">The polygon.</param>
/// <returns>True if point is inside, false otherwise.</returns>
/// <see cref="http://local.wasp.uwa.edu.au/~pbourke/geometry/insidepoly/"/>
public bool PointInPolygon(Point point, Polygon polygon) {
bool inside = false;
foreach (var side in polygon.Lines) {
if (point.Y > Math.Min(side.Start.Y, side.End.Y))
if (point.Y <= Math.Max(side.Start.Y, side.End.Y))
if (point.X <= Math.Max(side.Start.X, side.End.X)) {
float xIntersection = side.Start.X + ((point.Y - side.Start.Y) / (side.End.Y - side.Start.Y)) * (side.End.X - side.Start.X);
if (point.X <= xIntersection)
inside = !inside;
}
return inside;
}
Polgyon クラスは非常に基本的なもので、半疑似形式です。
class Polygon
{
public List<Line> Lines { get; set; }
}
public class Line
{
public Vector2 Start;
public Vector2 End;
}
ポリゴン クラスは非常に簡単にベクトルのコレクションを格納できますが、他の場所で線が必要になるため、線クラスを導入しました。
すべてのポリゴン形状を処理するために、foreach ループを次のように変更しました。
foreach (var side in Lines) {
if (point.Y > Math.Min(side.Start.Y, side.End.Y))
if (point.Y <= Math.Max(side.Start.Y, side.End.Y))
if (point.X <= Math.Max(side.Start.X, side.End.X)) {
if (side.Start.Y != side.End.Y) {
float xIntersection = (point.Y - side.Start.Y) * (side.End.X - side.Start.X) / (side.End.Y - side.Start.Y) + side.Start.X;
if (side.Start.X == side.End.X || point.X <= xIntersection)
result = !result;
}
}
}