likes
comments
collection
share

canvas小游戏离不开的几种碰撞检测

作者站长头像
站长
· 阅读数 43

在这篇文章中,我将介绍一些基本的碰撞检测方法,包括矩形碰撞检测圆形碰撞检测多边形碰撞检测

一、矩形碰撞检测

矩形碰撞检测是最简单的方法。可以通过判断两个矩形是否有重叠部分来确定是否发生碰撞。如果两个矩形有任何一个边重叠,就可以判断发生了碰撞。

1.1 运行效果

当然是先看运行效果图啦,只有这样,大家才能直观感受!

canvas小游戏离不开的几种碰撞检测

1.2 代码实现

实现矩形碰撞检测的方法很简单,只需要比较两个矩形的位置和大小即可。

    /**
     * 矩形碰撞检测
     * @param {Object} rect1 矩形1的信息,包含x、y坐标、宽度和高度
     * @param {Object} rect2 矩形2的信息,包含x、y坐标、宽度和高度
     * @returns {Boolean} 是否碰撞
     */
    function rectCollide(rect1, rect2) {
      // 如果矩形1的右边界大于等于矩形2的左边界,且矩形1的左边界小于等于矩形2的右边界,且矩形1的下边界大于等于矩形2的上边界,且矩形1的上边界小于等于矩形2的下边界,说明两个矩形有重叠部分,发生了碰撞
      if (rect1.x + rect1.width >= rect2.x &&
          rect1.x <= rect2.x + rect2.width &&
          rect1.y + rect1.height >= rect2.y &&
          rect1.y <= rect2.y + rect2.height) {
        return true;
      }
      // 否则,说明两个矩形没有重叠部分,没有发生碰撞
      return false;
    }

矩形碰撞检测的优点是速度快,可以在游戏中广泛应用。但是,它的缺点也很明显:只能检测矩形之间的碰撞,对于其他形状的物体无法进行检测。

二、圆形碰撞检测

圆形碰撞检测是通过判断两个圆形是否相交来判断是否碰撞。用勾股定理来计算两个圆形的距离,如果距离小于两个圆形半径之和,则发生碰撞。

2.1 运行效果

接着,我们在实现圆形碰撞代码前,先看下运行的效果。

canvas小游戏离不开的几种碰撞检测

2.2 代码实现:

圆形碰撞检测的实现方法是比较简单的,只需要计算两个圆形的距离即可。

    /**
     * 圆形碰撞检测
     * @param {Object} circle1 圆形1的信息,包含x、y坐标和半径
     * @param {Object} circle2 圆形2的信息,包含x、y坐标和半径
     * @returns {Boolean} 是否碰撞
     */
    function circleCollide(circle1, circle2) {
      var dx = circle1.x - circle2.x;
      var dy = circle1.y - circle2.y;
      var distance = Math.sqrt(dx * dx + dy * dy);
      if (distance < circle1.radius + circle2.radius) {
        return true;
      }
      return false;
    }

dxdy 分别表示两个圆形中心点在x轴和y轴上的距离,distance 表示两个圆形中心点之间的距离。如果 distance 小于两个圆形半径之和,就说明发生了碰撞,函数返回 true。否则,函数返回 false

圆形碰撞检测的优点是可以检测任意形状的物体,而且相对于多边形碰撞检测来说,计算量较小,速度较快。但是,对于不规则的物体,圆形碰撞检测的精度可能不够高。

三、多边形碰撞检测

多边形碰撞检测是一种更复杂的方法,通过判断两个多边形是否相交来判断是否碰撞。这种方法需要计算多边形的每个边和另一个多边形的每个边是否相交,比较繁琐。

3.1 运行效果

接着,我们在实现多边形碰撞代码前,先看下运行的效果。

canvas小游戏离不开的几种碰撞检测

3.2 代码实现

多边形碰撞检测的实现方法比较复杂,需要用到向量和投影等数学知识。

/**
 * 多边形碰撞检测
 * @param {Array} poly1 多边形1的顶点数组,数组中每个元素包含x和y坐标
 * @param {Array} poly2 多边形2的顶点数组,数组中每个元素包含x和y坐标
 * @returns {Boolean} 是否碰撞
 */
function polygonCollide(poly1, poly2) {
  let polygons = [poly1, poly2];
  let minA, maxA, projected, i, j;

  for (i = 0; i < polygons.length; i++) {
    // 循环遍历多边形的所有边
    let polygon = polygons[i];
    for (j = 0; j < polygon.length; j++) {
      let next = j + 1;
      if (next === polygon.length) {
        next = 0;
      }
      let p1 = polygon[j];
      let p2 = polygon[next];
      // 计算当前边的法向量
      let normal = { x: p2.y - p1.y, y: -(p2.x - p1.x) };

      // 投影多边形1和多边形2到法向量上,得到最小值和最大值
      projected = projectPolygon(normal, poly1);
      minA = projected.min;
      maxA = projected.max;
      projected = projectPolygon(normal, poly2);
      if (projected.min > maxA || projected.max < minA) {
        return false;
      }
    }
  }

  return true;
}

/**
 * 投影多边形到法向量上,得到最小值和最大值
 * @param {Object} axis 投影的法向量,包含x和y坐标
 * @param {Array} polygon 多边形的顶点数组,数组中每个元素包含x和y坐标
 * @returns {Object} 包含最小值和最大值的对象
 */
function projectPolygon(axis, polygon) {
  let min = dotProduct(axis, polygon[0]);
  let max = min;
  for (let i = 1; i < polygon.length; i++) {
    let dotProductValue = dotProduct(axis, polygon[i]);
    if (dotProductValue < min) {
      min = dotProductValue;
    } else if (dotProductValue > max) {
      max = dotProductValue;
    }
  }
  return { min: min, max: max };
}

/**
 * 计算两个向量的点积
 * @param {Object} a 向量a,包含x和y坐标
 * @param {Object} b 向量b,包含x和y坐标
 * @returns {Number} 点积的结果
 */
function dotProduct(a, b) {
  return a.x * b.x + a.y * b.y;
}

polygonCollide() 函数可以判断两个多边形是否相交,projectPolygon() 函数用来投影多边形到法向量上,得到多边形在法向量上的最小值和最大值,dotProduct() 函数用来计算两个向量的点积。 多边形碰撞检测的优点是可以检测任意形状的物体,精度较高。但是,计算量比较大,速度相对较慢。

四、写在文末

Canvas游戏中常用的三种碰撞检测方法:矩形碰撞检测圆形碰撞检测多边形碰撞检测。每种方法都有自己独特的优点和缺点,应该根据实际需要选择合适的方法。在选择碰撞检测方法时,还需要考虑性能因素,以保证游戏的流畅性和稳定性。

转载自:https://juejin.cn/post/7236337121911636005
评论
请登录