手游《奔跑吧?骚年!》技术分享(五):三角形碰撞检测

来源:互联网 发布:js控制disabled的属性 编辑:程序博客网 时间:2024/05/01 18:27

今天来分享一下我游戏里面的三角型碰撞,原理就是判断两个图形中是否有一对或者一对以上的边相交。如果有相交,那么着两个图形一定是相互碰撞(两个图形可能会嵌套,但是游戏中物体都是慢慢移动的,就像现实中的物体一样,嵌套之前一定会相交。so 该情况就直接忽略)。游戏写的算法还欠考虑,但还是可以正常检测的。

以下是为三角碰撞准备的变量:

/** * 储存三角形,三边坐标的数组,用于碰撞计算,非同步 */public static float[][] TriangLineArray = new float[3][4];/** * 储存矩形,四边的坐标,用于碰撞计算,非同步 */public static float[][] RectLineArray = new float[4][4];

然后就是碰撞算法:

/** * 判断矩形和三角形是否相碰撞 *  * @param triang *            三角形 * @param rect *            矩形 * @return 碰撞数据 */public static CollisionType TriangCollisionRect(Triangular triang,Front rect) {// ABRectLineArray[0][0] = rect.x;RectLineArray[0][1] = rect.y;RectLineArray[0][2] = rect.x;RectLineArray[0][3] = rect.y - rect.height;// BCRectLineArray[1][0] = rect.x;RectLineArray[1][1] = rect.y - rect.height;RectLineArray[1][2] = rect.x + rect.width;RectLineArray[1][3] = rect.y - rect.height;// DCRectLineArray[2][0] = rect.x + rect.width;RectLineArray[2][1] = rect.y;RectLineArray[2][2] = rect.x + rect.width;RectLineArray[2][3] = rect.y - rect.height;// ADRectLineArray[3][0] = rect.x;RectLineArray[3][1] = rect.y;RectLineArray[3][2] = rect.x + rect.width;RectLineArray[3][3] = rect.y;// ABTriangLineArray[0][0] = triang.getNeedle1()[0];TriangLineArray[0][1] = triang.getNeedle1()[1];TriangLineArray[0][2] = triang.getNeedle2()[0];TriangLineArray[0][3] = triang.getNeedle2()[1];// BCTriangLineArray[1][0] = triang.getNeedle2()[0];TriangLineArray[1][1] = triang.getNeedle2()[1];TriangLineArray[1][2] = triang.getNeedle3()[0];TriangLineArray[1][3] = triang.getNeedle3()[1];// ACTriangLineArray[2][0] = triang.getNeedle1()[0];TriangLineArray[2][1] = triang.getNeedle1()[1];TriangLineArray[2][2] = triang.getNeedle2()[0];TriangLineArray[2][3] = triang.getNeedle2()[1];CollisionType cd = CollisionType.COLLISION_TOP_FALSE;for (float[] l : RectLineArray)CollFlagFor: {for (float[] t : TriangLineArray) {if (TwoLineIsIntersect(l[0], l[1], l[2], l[3], t[0], t[1],t[2], t[3])) {cd = CollisionType.COLLISION_TOP_TRUE;break CollFlagFor;}}}return cd;}


核心算法,判断两条直线是否相交:

/** * 判断两条线段是否相交 *  * @param x0 * @param y0 * @param x1 * @param y1 * @param x2 * @param y2 * @param x3 * @param y3 * @return 相交返回TRUE */public static boolean TwoLineIsIntersect(float x0, float y0, float x1,float y1, float x2, float y2, float x3, float y3) { // 两条线段是否相交X0X1// AND X1X2float x, y;float Minx01 = Min(x0, x1);float Miny01 = Min(y0, y1);float Minx23 = Min(x2, x3);float Miny23 = Min(y2, y3);float Maxx01 = Max(x0, x1);float Maxy01 = Max(y0, y1);float Maxx23 = Max(x2, x3);float Maxy23 = Max(y2, y3);if (x1 != x0 && x2 != x3) {float k1 = (y1 - y0) / (x1 - x0);float k2 = (y3 - y2) / (x3 - x2);float Den = (y1 - y0) * (x3 - x2) - (y3 - y2) * (x1 - x0);if (k1 == k2) { // 平行不相交float d1 = Math.abs(y0 * (x1 - x0) - x0 * (y1 - y0) - y2* (x3 - x2) + x2 * (y3 - y2)); // 距离公式d = abs(c1-c2) /// sqrt(a*a+b*b)if (d1 == 0) {// 直线重合if ((x2 > Minx01 && x2 < Maxy01 && y2 > Miny01 && y2 < Maxy01)|| (x3 > Minx01 && x3 < Maxy01 && y3 > Miny01 && y3 < Maxy01)|| (x0 > Minx23 && x0 < Maxy23 && y0 > Miny23 && y0 < Maxy23)|| (x1 > Minx23 && x1 < Maxy23 && y1 > Miny23 && y1 < Maxy23)) { // 实际碰撞问题线段重合认为相交了return true;} else {return false;}} else {return false;}}x = ((y2 - y0) * (x1 - x0) * (x3 - x2) + (y1 - y0) * (x3 - x2) * x0 - (y3 - y2)* (x1 - x0) * x2)/ Den;y = ((y1 - y0) * (x - x0)) / (x1 - x0) + y0;if (Minx01 <= x && x <= Maxx01 && Miny01 <= y && y <= Maxy01&& Minx23 <= x && x <= Maxx23 && Miny23 <= y && y <= Maxy23) {return true;}} else if (x1 == x0 && x2 != x3) {x = x0;y = ((y3 - y2) * (x0 - x2)) / (x3 - x2) + y2;if (Minx01 <= x && x <= Maxx01 && Miny01 <= y && y <= Maxy01&& Minx23 <= x && x <= Maxx23 && Miny23 <= y && y <= Maxy23) {return true;}} else if (x1 != x0 && x2 == x3) {x = x2;y = ((y1 - y0) * (x2 - x0)) / (x1 - x0) + y0;if (Minx01 <= x && x <= Maxx01 && Miny01 <= y && y <= Maxy01&& Minx23 <= x && x <= Maxx23 && Miny23 <= y && y <= Maxy23) {return true;}}return false;}


如果不知道到算法里面使用的对象,请到前几篇文章寻找。

0 0
原创粉丝点击