基本的SAT冲突算法

时间:2013-09-26 11:24:37

标签: c# math vector xna collision

到目前为止,我所知道的关于矢量投影的一切都来自互联网,所以我有点困惑。首先,我假设当我们将多边形的顶点投影到轴上时,我们得到标量投影而不是矢量投影。其公式为(A.B)/ | A |,现在在this tutorial中,它们只是使用点积投影到轴上。这是因为矢量和轴是垂直的还是什么?尽管如此,我还是想在C#中编写一个粗略的版本,但它似乎没有返回正确的结果

    Rectangle r1 = new Rectangle(300, 200, 50, 50);
    Rectangle r2 = new Rectangle(340, 240, 50, 50);

    bool areColliding(Rectangle r1, Rectangle r2)
    {
        /* Using clockwise labelling
         * 
         *          B*
         *        .    .
         *      .       .
         *    A *         C*
         *      .       .
         *        .   .
         *          D*
         * 
         */

        //Calculate vectors and normals of Rectangle 1
        Point r1A = r1.Location;
        Point r1B = new Point(r1.Location.X + r1.Width, r1.Location.Y);
        Point r1C = new Point(r1.Location.X, r1.Location.Y + r1.Height);
        Point r1D = new Point(r1.Location.X + r1.Width, r1.Location.Y + r1.Height);

        Vector2 r1AB = new Vector2(r1B.X - r1A.X, r1B.Y - r1A.Y);
        Vector2 r1BC = new Vector2(r1C.X - r1B.X, r1C.Y - r1B.Y);
        Vector2 r1CD = new Vector2(r1D.X - r1C.X, r1D.Y - r1C.Y);
        Vector2 r1DA = new Vector2(r1A.X - r1D.X, r1A.Y - r1D.Y);

        Vector2 r1AB_Normal = getNormal(r1AB);
        Vector2 r1BC_Normal = getNormal(r1BC);
        Vector2 r1CD_Normal = getNormal(r1CD);
        Vector2 r1DA_Normal = getNormal(r1DA);

        Point[] r1Points = {r1A, r1B, r1C, r1D};
        Vector2[] Axes1 = { r1AB_Normal, r1BC_Normal, r1CD_Normal, r1DA_Normal };

        //Calculate vectors and normals of Rectangle 2
        Point r2A = r2.Location;
        Point r2B = new Point(r2.Location.X + r2.Width, r2.Location.Y);
        Point r2C = new Point(r2.Location.X, r2.Location.Y + r2.Height);
        Point r2D = new Point(r2.Location.X + r2.Width, r2.Location.Y + r2.Height);

        Vector2 r2AB = new Vector2(r2B.X - r2A.X, r2B.Y - r2A.Y);
        Vector2 r2BC = new Vector2(r2C.X - r2B.X, r2C.Y - r2B.Y);
        Vector2 r2CD = new Vector2(r2D.X - r2C.X, r2D.Y - r2C.Y);
        Vector2 r2DA = new Vector2(r2A.X - r2D.X, r2A.Y - r2D.Y);

        Vector2 r2AB_Normal = getNormal(r2AB);
        Vector2 r2BC_Normal = getNormal(r2BC);
        Vector2 r2CD_Normal = getNormal(r2CD);
        Vector2 r2DA_Normal = getNormal(r2DA);

        Point[] r2Points = { r2A, r2B, r2C, r2D };
        Vector2[] Axes2 = { r2AB_Normal, r2BC_Normal, r2CD_Normal, r2DA_Normal };

        //Start projecting each vertex on to each axis
        for (int i = 0; i < Axes1.Length; i++)
        {
            float r1Min = Vector2.Dot(Axes1[i], new Vector2(r1Points[0].X, r1Points[0].Y));
            float r1Max = float.NaN;

            for (int p = 1; p < r1Points.Length; p++)
            {
                float dot = Vector2.Dot(Axes1[i], new Vector2(r1Points[p].X, r1Points[p].Y));

                if (dot < r1Min)
                {
                    r1Min = dot;
                }
            }

            float r2Min = Vector2.Dot(Axes1[i], new Vector2(r1Points[0].X, r1Points[0].Y));
            float r2Max = float.NaN;

            for (int p = 1; p < r2Points.Length; p++)
            {
                float dot = Vector2.Dot(Axes1[i], new Vector2(r1Points[p].X, r1Points[p].Y));

                if (dot < r2Min)
                {
                    r2Min = dot;
                }
            }

            if (r1Min < r2Max)
            {
                return true;
            }
        }
        for (int i = 0; i < Axes2.Length; i++)
        {
            float r1Min = Vector2.Dot(Axes1[i], new Vector2(r1Points[0].X, r1Points[0].Y));
            float r1Max = float.NaN;

            for (int p = 1; p < r1Points.Length; p++)
            {
                float dot = Vector2.Dot(Axes1[i], new Vector2(r1Points[p].X, r1Points[p].Y));

                if (dot < r1Min)
                {
                    r1Min = dot;
                }
            }

            float r2Min = Vector2.Dot(Axes1[i], new Vector2(r1Points[0].X, r1Points[0].Y));
            float r2Max = float.NaN;

            for (int p = 1; p < r2Points.Length; p++)
            {
                float dot = Vector2.Dot(Axes1[i], new Vector2(r1Points[p].X, r1Points[p].Y));

                if (dot < r2Min)
                {
                    r2Min = dot;
                }
            }

            if (r1Min < r2Max)
            {
                return true;
            }
        }
        return false;
    }

    Vector2 getNormal(Vector2 v)
    {
        return new Vector2(-v.Y, v.X);
    }

0 个答案:

没有答案