H5中优化碰撞检测

Posted jlfw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了H5中优化碰撞检测相关的知识,希望对你有一定的参考价值。

微信端口的小游戏相信大家已经做了很多,
类似于碰撞检测这种也是数不胜数.因为障碍物和主角都是图片,也就意味着碰撞检测实际上是两个矩形直接是否有交叉的判断.包括phaser这样的框架也是这样子做的.
当然这种方法也无可厚非.

然而, 唯一的问题是如果素材(障碍物和主角)并不能铺满整个矩形的话一旦程序检查到碰撞而实际上两个素材并没有真正意义上的接触就会略显尴尬,
如下面这个图所示:

技术图片

为了方便演示和对比起来更直观, 我给两个png图片加了背景, 如果是简单的矩形相交判断这个时候判断了碰撞就会很尴尬...

所以, 我们需要稍微高级点儿的办法来解决, 虽然我数学很差, 但是还是要考数学来解决:
用判断矩形的四条边是否有与多边形上的边相交来替代单纯的两个矩形相交.

在案例中, 因为我的障碍物都比较小 而且填的比较满, 所以就不做拆分(如上图的绿色的血), 主角有棱有角 需要做一下拆分转换为多边形.
在程序中我是取障碍物的坐标和主角的坐标来做判断的, 因此, 获取主角的坐标就是首要任务, 最快捷的方法就是借住ps的钢笔工具, 如下图所示:

技术图片

用钢笔工具沿着猪脚的实际图片区域走一次, 然后把相对坐标点记录下来. 所谓的相对坐标点是基于该图片左上角水平和垂直方向的距离,

比如第一个点的坐标是x:42, y:8.

我做这些小游戏的思路是 主角和障碍物都在一个canvas上做, 程序先记录下猪脚的起点坐标 然后根据相对坐标即可计算出多边形的每个点在canvas上的实际坐标了. 拿到实际坐标后我们就可以做公式的运算判断是否相撞了, 公式如下:

/**
 *@param {Array} point 障碍物4个点坐标的集合
 *@param {String} x 主角的x坐标
 *@param {String} x 主角的y坐标
 *@param {Array} area 主角偏移坐标的集合
 */
function lineJudge(point, x, y, area){
    var p1, p2, p3, p4;
    for(var i = 0; i < 4; i++) {
        p1 = point[i];
        if(3 == i) {
            p2 = point[0]
        }
        else {
            p2 = point[i + 1];
        }
        
        for(var j = 0, lenA = area.length; j < lenA; j++) {
            p3 = [area[j][0] + x, area[j][3] + y];
            if(j == lenA - 1) {
                p4 = [area[0][0] + x, area[0][4] + y];
            }
            else {
                p4 = [area[j + 1][0] + x, area[j + 1][5] + y];
            }
            
            if(‘boolean‘ != typeof _getIntersectionPoint(p1, p2, p3, p4)) return true;
        }
    }
    return false;
}

function _getIntersectionPoint(a, b, c, d){
     // 三角形abc 面积的2倍  
    var area_abc = (a[0] - c[0]) * (b[1] - c[1]) - (a[1] - c[1]) * (b[0] - c[0]);  
  
    // 三角形abd 面积的2倍  
    var area_abd = (a[0] - d[0]) * (b[1] - d[1]) - (a[1] - d[1]) * (b[0] - d[0]);   
  
    // 面积符号相同则两点在线段同侧,不相交 (对点在线段上的情况,本例当作不相交处理);  
    if ( area_abc*area_abd>=0 ) {  
        return false;  
    }  
  
    // 三角形cda 面积的2倍  
    var area_cda = (c[0] - a[0]) * (d[1] - a[1]) - (c[1] - a[1]) * (d[0] - a[0]);  
    // 三角形cdb 面积的2倍  
    // 注意: 这里有一个小优化.不需要再用公式计算面积,而是通过已知的三个面积加减得出.  
    var area_cdb = area_cda + area_abc - area_abd ;  
    if (  area_cda * area_cdb >= 0 ) {  
        return false;  
    }  
  
    //计算交点坐标  
    var t = area_cda / ( area_abd- area_abc );  
    var dx= t*(b[0] - a[0]),  
        dy= t*(b[1] - a[1]);  
    return { x: a[0] + dx , y: a[1] + dy };  
}

鉴于手机上性能有限, 可以先用两个矩形相交来简单判断一下, 只有两个矩形相交的情况下再做线是否和多边形上边相交的判断.

最后, 附上项目高清二维码, 欢迎大家体验:

技术图片

本文转载于:猿2048→https://www.mk2048.com/blog/blog.php?id=h1jj2aiciib






以上是关于H5中优化碰撞检测的主要内容,如果未能解决你的问题,请参考以下文章

2D空间中使用Quadtree四叉树进行碰撞检测优化

四叉树优化碰撞检测

[译]2D空间中使用四叉树Quadtree进行碰撞检测优化

碰撞检测

在发生碰撞之前检测到碰撞

UE4最简化碰撞检测