Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does XNA have a Polygon, like Rectangle?

Tags:

c#

polygon

xna

I'm making a game where there is only a certain space the player can move around. I want to represent this space with a polygon of some sort. The main question I would ask of it is whether it contains a given point. (Like rect.intersect())

Does XNA have any way to do this?

like image 548
Nick Heiner Avatar asked Mar 04 '10 14:03

Nick Heiner


2 Answers

No. (Not up and including version 3 at least)

XNA has bounding volumes such as frustums or boxes but it has no notion of polygons.

A simple, fast and effective way of performing point in polygon with XNA can be found here. I've recently implemented this and it was excellent.

You know the point of your object, all you need to do is create a polygon surrounding this object - using vectors would be the best and easiest method. Then perform the point in polygon check.

Here is the example code of my implementation. The default point class in XNA is used. Polygon is a simple class which contains a collection of vectors making up the 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;
}

The Polgyon class is very basic, in semi pseudo form:

class Polygon 
{
    public List<Line> Lines { get; set; }
}

public class Line   
{
    public Vector2 Start;
    public Vector2 End;
}

The polygon class could very easily just store a collection of vectors, but I introduced a line class as lines were required elsewhere.

like image 114
Finglas Avatar answered Oct 14 '22 08:10

Finglas


Modified the foreach loop to the following to handle all polygon shapes:

       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;
                        }
                    }
        }
like image 24
ViNull Avatar answered Oct 14 '22 07:10

ViNull