C学习项目中的碰撞检测分离轴定理

问题描述 投票:0回答:1

我最近出于兴趣学习了 C,并且正在学习 C++。作为一个学习项目,我正在使用 ALLEGRO5 库用 C 语言制作一个游戏进行显示。我有一名球员在场上二维等轴测图的运动。我已经创建了 2 个平行四边形,并且已经完成了非旋转正方形碰撞。一个简单的例子: 1https://i.stack.imgur.com/t28VD.png 当然,玩家移动而房子不移动。我正在使用顶点检测碰撞,因此我发送了一些顶点:

fresh(house.vertices_x, house.vertices_y, player.vertices_x, player.vertices_y, 5);
玩家顶点都添加了位置,以便计算可以移动。

struct flipped_y { double y; double yp; };
    struct flipped_y flip_y[10];
    struct vectors { double x; double y; double xp; double yp; };
    struct vectors vector[10];
    struct Normals { double x; double y; double xp; double yp; };
    struct Normals normvec[10];
    struct Normalized { double x; double y; double xp; double yp; };
    struct Normalized normalized[10];
    struct projectpts { double pts; double ptsp; double ptspoly2rhom; double ptspoly2player; };
    struct projectpts project[20];
    struct maxmin { double max; double min; double maxp; double minp; double maxon2; double minon2; double maxpon2; double minpon2; };
    struct maxmin mm[5];
    double flipp_y_func(double verts[], double vertsp[], int numvert);
    double createvector(double vert_x[], struct flipped_y flip_y[], double vert_xp[], int numvert);
    double Normals(struct vectors vector[], int numvecs);
    double Normalize(struct Normals normvec[], int numvec);
    double ProjectPoints(double verts_x[], double verts_xp[], struct flipped_y flip[], struct Normalized normalized[], int numpts);
    double Compareminandmax(double max[], double maxp[], double min[], double minp[], double maxon2[], double maxpon2[], double minon2[], double minpon2[], int nummaxmin);
    int fresh(double vertices_x[], double vertices_y[], double pvertices_x[], double pvertices_y[],int numverts) {
        int i = 0, i2 = 0, i3 = 0, i4 = 0, i5 = 0, i6 = 0, i7 = 0,i8=0; double max[5] = { -INFINITY,-INFINITY,-INFINITY,-INFINITY,-INFINITY }, min[5] = { INFINITY,INFINITY,INFINITY,INFINITY,INFINITY }, maxp[5] = { -INFINITY,-INFINITY,-INFINITY,-INFINITY,-INFINITY }, minp[5] = { INFINITY,INFINITY,INFINITY,INFINITY,INFINITY };
        double maxon2[5] = { -INFINITY,-INFINITY,-INFINITY,-INFINITY,-INFINITY }, minon2[5] = { INFINITY,INFINITY,INFINITY,INFINITY,INFINITY }, maxpon2[5] = { -INFINITY,-INFINITY,-INFINITY,-INFINITY,-INFINITY }, minpon2[5] = { INFINITY,INFINITY,INFINITY,INFINITY,INFINITY };
        double wishbone = 1;
    

这是快板左上角坐标,所以我们将 Y 翻转为笛卡尔坐标(vertices_y 和玩家 pvertices_y)

flipp_y_func(vertices_y, pvertices_y, 5);

现在我们创建一个向量

createvector(vertices_x, flip_y, pvertices_x, 5);

然后我们得到两者的法线

  Normals(vector, 4);

将两者标准化

Normalize(normvec, 4);

现在我们将两者投影到它们自身和另一个形状上

ProjectPoints(vertices_x, pvertices_x, flip_y, normalized, 4);

这是获取归一化向量 1-4 上的房子和归一化向量 1-4 上的玩家的最大值和最小值

for (i6; i6 < 4; i6++) {
            for (i7 = 0; i7 < 4; i7++) {

                // polygon1
                if (project[i6 * 4 + i7].pts > max[i6]) { max[i6] = project[i6 * 4 + i7].pts; }
                if (project[i6 * 4 + i7].pts < min[i6]) { min[i6] = project[i6 * 4 + i7].pts; }

                //player

                if (project[i6 * 4 + i7].ptsp > maxp[i6]) { maxp[i6] = project[i6 * 4 + i7].ptsp; }
                if (project[i6 * 4 + i7].ptsp < minp[i6]) { minp[i6] = project[i6 * 4 + i7].ptsp; }
                //polygon2
                if (project[i6 * 4 + i7].ptspoly2rhom > maxon2[i6]) { maxon2[i6] = project[i6 * 4 + i7].ptspoly2rhom; }
                if (project[i6 * 4 + i7].ptspoly2rhom < minon2[i6]) { minon2[i6] = project[i6 * 4 + i7].ptspoly2rhom; }
                //player
                if (project[i6 * 4 + i7].ptspoly2player > maxpon2[i6]) { maxpon2[i6] = project[i6 * 4 + i7].ptspoly2player; }
                if (project[i6 * 4 + i7].ptspoly2player < minpon2[i6]) { minpon2[i6] = project[i6 * 4 + i7].ptspoly2player; }

            }
            
                

打印值

//1

    /* printf("\nmax %f normvec%d", max[i6], i6);
            printf("\nmin %f normvec%d\n", min[i6], i6);
            printf("\nmaxPLAYER %f normvecPLAYER%d", maxp[i6], i6);
            printf("\nminPLAYER %f normvecPLAYER%d\n", minp[i6], i6);
            //on2
            printf("\nmaxon2 %f normvecon2%d", maxon2[i6], i6);
            printf("\nminon2 %f normvecon2%d\n", minon2[i6], i6);
            printf("\nmaxPLAYERon2 %f normvecPLAYERon2%d", maxpon2[i6], i6);
            printf("\nminPLAYERon2 %f normvecPLAYERon2%d\n", minpon2[i6], i6);*/

        }
    
now we compare min and max of each shape on all the normalized vectors of both shaoes        
       

wishbone = Compareminandmax(max, maxp, min, minp, maxon2, maxpon2, minon2, minpon2, 4);

我希望它能起作用,哈哈

printf("\nwishbone %f", wishbone);

参考

/aminbmin 或者 bmin amin/ 打印值以查看它们如何比较,并且它们在应该报告碰撞时没有报告碰撞,但通常仅在 1 个或两个轴上

/*while (i < 4) {
            printf("\nmin%f < maxp%f and min%f > minp%f\n \t\t\t or \nminp%f < max%f and minp%f> min%f\n\n", min[i], maxp[i], min[i], minp[i], minp[i], max[i], minp[i], min[i]); 
            printf("\nminon2%f < maxpon2%f and minon2%f > minpon2%f\n \t\t\t or \nminpon2%f < maxon2%f and minpon2%f> minon2%f\n\n", minon2[i], maxpon2[i], minon2[i], minpon2[i], minpon2[i], maxon2[i], minpon2[i], minon2[i]); i++;
        
        }*/

        return 0;
    }
    
   

 //player and house flipped
    double flipp_y_func(double verts[], double vertsp[], int numvert) {
        int i;  for (i = 0; i < numvert; i++) {
            flip_y[i].y = verts[i] * -1;
            flip_y[i].yp = vertsp[i] * -1;


        }
    
 

       return 0;
    }

// 创建向量

double createvector(double vert_x[], struct flipped_y flip_y[], double vert_xp[], int numvert) {
    int i = 0; double vector_x[10], vector_y[10], vector_xp[10], vector_yp[10];
    for (i = 0; i < numvert; i++) {
        vector_x[i] = vert_x[i + 1] - vert_x[i];
        vector_y[i] = flip_y[i + 1].y - flip_y[i].y;
        vector[i].x = vector_x[i];
        vector[i].y = vector_y[i];
        //player
        vector_xp[i] = vert_xp[i + 1] - vert_xp[i];
        vector_yp[i] = flip_y[i + 1].yp - flip_y[i].yp;
        vector[i].xp = vector_xp[i];
        vector[i].yp = vector_yp[i];
    }

    return 0;
}
    

//恢复正常

double Normals(struct vectors vector[], int numvecs) {
    int i;
    for (i = 0; i < numvecs; i++) {
        normvec[i].y = vector[i].x;
        normvec[i].x = vector[i].y * -1;
        //player

        normvec[i].yp = vector[i].xp;
        normvec[i].xp = vector[i].yp * -1;
    }


    return 0;
}

//标准化任何添加 p 的内容意味着玩家

double Normalize(struct Normals normvec[], int numvec) {
    int i; double Normalizedx[6], Normalizedy[6], Normalizedxp[6], Normalizedyp[6], lengthp[6], length[6];
    for (i = 0; i < numvec; i++) {
        length[i] = sqrt(pow(normvec[i].x, 2) + pow(normvec[i].y, 2));
        Normalizedx[i] = normvec[i].x / length[i];
        Normalizedy[i] = normvec[i].y / length[i];
        normalized[i].x = Normalizedx[i];
        normalized[i].y = Normalizedy[i];


        lengthp[i] = sqrt(pow(normvec[i].xp, 2) + pow(normvec[i].yp, 2));
        Normalizedxp[i] = normvec[i].xp / lengthp[i];
        Normalizedyp[i] = normvec[i].yp / lengthp[i];
        normalized[i].xp = Normalizedxp[i];
        normalized[i].yp = Normalizedyp[i];
        
    }

    return 0;
}







double ProjectPoints(double verts_x[], double verts_xp[], struct flipped_y flip_y[], struct Normalized normalized[], int numpts) {
        int i = 0, g = 0; double dot[20], dotp[20], dotrhomonpoly2norm[20], dotplayeronpoly2norm[20];
        for (i = 0; i < numpts; i++) {
            for (g = 0; g < numpts; g++) {
                //polygon one projection of both polys verts
                dot[i * numpts + g] = ((verts_x[g] * normalized[i].x) + (flip_y[g].y * normalized[i].y));
                project[i * numpts + g].pts = dot[i * numpts + g];

                //player

                dotp[i * numpts + g] = ((verts_xp[g] * normalized[i].x) + (flip_y[g].yp * normalized[i].y));
                project[i * numpts + g].ptsp = dotp[i * numpts + g];


                //polygon two projection of both polys verts double ptspoly2rhom;double ptspoly2player;

               
                
                dotrhomonpoly2norm[i * numpts + g] = ((verts_x[g] * normalized[i].xp) + (flip_y[g].y * normalized[i].yp));
                project[i * numpts + g].ptspoly2rhom = dotrhomonpoly2norm[i * numpts + g];

                //player

                dotplayeronpoly2norm[i * numpts + g] = ((verts_xp[g] * normalized[i].xp) + (flip_y[g].yp * normalized[i].yp));
                project[i * numpts + g].ptspoly2player = dotplayeronpoly2norm[i * numpts + g];
                
                //dotplayeronpoly2norm[i * numpts + g] = ((verts_xp[g] * normalized[i].xp) + (flip_y[g].yp * normalized[i].yp));
                //project[i * numpts + g].ptspoly2player = dotplayeronpoly2norm[i * numpts + g];
                dotplayeronpoly2norm[16] = ((verts_xp[3] * normalized[3].xp) + (flip_y[3].yp * normalized[3].yp));

             

            }
        }



        return 0;
    }


double Compareminandmax(double max[], double maxp[], double min[], double minp[], double maxon2[], double maxpon2[], double minon2[], double minpon2[], int nummaxmin) {
        int i=0;
        /*amin<bmax and amin>bmin
                                      or
                bmin<amax and bmin> amin*/
        for (i = 0; i < nummaxmin;i++) {
           /* if ((min[i] < maxp[i] && min[i] > minp[i] || minp[i] < max[i] && minp[i] > min[i]) ||
                (minon2[i] < maxpon2[i] && minon2[i] > minpon2[i] || minpon2[i] < maxon2[i] && minpon2[i] > minon2[i])) {
                return 2;
            }*/
            if (((min[i]<maxp[i] && min[i]>minp[i]) || (minp[i]<max[i] && minp[i]>min[i])) || 
                ((minon2[i]<maxpon2[i] && minon2[i]>minpon2[i]) || (minpon2[i]<maxon2[i] && minpon2[i]>minon2[i]))) { return 22; }
           
        }
        
        
       
    return 4;}

现在我已经尝试使用不等式公式,但是出了点问题,我一直在检查并修复一些问题,并且通过 if 语句中的一些不等式,我可以在某种程度上接近正确的碰撞。像这样Collision detection I've been able to get

到目前为止,我无法检测到我做错了什么,并且我已经使用图形计算器仔细检查了我的点积标准化。如果您有任何建议或更简单的方法,请告诉我。但一旦我做对了,我就会简化和组织很多事情。

c collision-detection
1个回答
0
投票

好吧好吧,事实证明我可能已经正确了好几次了。但这是正确的条件

 if ((minpon2[i]<minon2[i] && maxpon2[i]<minon2[i] || maxpon2[i]>maxon2[i] && minpon2[i]>maxon2[i]) || 
                    (min[i]>maxp[i] && min[i]>minp[i] || max[i]<minp[i] && max[i]<maxp[i])) { return 22; }
            }

事实证明,问题是,当我的条件正确并且我注意到向下移动的碰撞时,我正在为我的玩家使用另一组顶点,这些顶点我曾用于其他目的。它在播放器上比我认为我正在使用的碰撞盒高出 100 像素。我认为我做得很好,因为这通常是我刚刚扫描过的一个简单问题。我肯定会简化我的代码并摆脱我一直在尝试的所有垃圾。

© www.soinside.com 2019 - 2024. All rights reserved.