当前位置:首页 > JavaScript

js实现碰撞

2026-01-30 10:56:12JavaScript

检测矩形碰撞

使用矩形边界框检测碰撞是最简单的方法。假设两个矩形的位置和尺寸已知,可以通过比较它们的边界来判断是否重叠。

function checkRectCollision(rect1, rect2) {
  return (
    rect1.x < rect2.x + rect2.width &&
    rect1.x + rect1.width > rect2.x &&
    rect1.y < rect2.y + rect2.height &&
    rect1.y + rect1.height > rect2.y
  );
}

检测圆形碰撞

对于圆形物体,通过比较两圆圆心距离与半径之和来判断碰撞。

js实现碰撞

function checkCircleCollision(circle1, circle2) {
  const dx = circle1.x - circle2.x;
  const dy = circle1.y - circle2.y;
  const distance = Math.sqrt(dx * dx + dy * dy);
  return distance < circle1.radius + circle2.radius;
}

像素级碰撞检测

更精确的方法是使用像素级检测,适合不规则形状物体。HTML5 Canvas提供了getImageData方法可以获取像素数据。

function checkPixelCollision(ctx1, ctx2, x1, y1, x2, y2) {
  const data1 = ctx1.getImageData(x1, y1, width, height).data;
  const data2 = ctx2.getImageData(x2, y2, width, height).data;

  for (let i = 0; i < data1.length; i += 4) {
    if (data1[i+3] > 0 && data2[i+3] > 0) {
      return true;
    }
  }
  return false;
}

分离轴定理(SAT)

对于凸多边形之间的碰撞检测,分离轴定理是最可靠的方法。需要检查所有边的法向量作为潜在分离轴。

js实现碰撞

function projectPolygon(axis, polygon) {
  let min = Infinity;
  let max = -Infinity;

  for (const point of polygon.points) {
    const proj = point.x * axis.x + point.y * axis.y;
    min = Math.min(min, proj);
    max = Math.max(max, proj);
  }

  return {min, max};
}

function checkSATCollision(poly1, poly2) {
  const axes = [...poly1.edges, ...poly2.edges].map(edge => {
    return {x: -edge.y, y: edge.x}; // 法向量
  });

  for (const axis of axes) {
    const proj1 = projectPolygon(axis, poly1);
    const proj2 = projectPolygon(axis, poly2);

    if (proj1.max < proj2.min || proj2.max < proj1.min) {
      return false;
    }
  }
  return true;
}

性能优化建议

对于大量物体的碰撞检测,应使用空间分割技术如四叉树或网格来减少检测次数。四叉树将空间递归划分为四个区域,只检测同一区域或相邻区域内的物体。

class Quadtree {
  constructor(bounds, capacity) {
    this.bounds = bounds;
    this.capacity = capacity;
    this.objects = [];
    this.divided = false;
  }

  insert(obj) {
    if (!this.bounds.contains(obj)) return false;

    if (this.objects.length < this.capacity) {
      this.objects.push(obj);
      return true;
    }

    if (!this.divided) this.subdivide();

    return (this.northeast.insert(obj) || 
            this.northwest.insert(obj) ||
            this.southeast.insert(obj) || 
            this.southwest.insert(obj));
  }

  query(range, found) {
    if (!this.bounds.intersects(range)) return found;

    for (const obj of this.objects) {
      if (range.contains(obj)) found.push(obj);
    }

    if (this.divided) {
      this.northeast.query(range, found);
      this.northwest.query(range, found);
      this.southeast.query(range, found);
      this.southwest.query(range, found);
    }

    return found;
  }
}

物理引擎集成

对于复杂场景,建议使用成熟的物理引擎如Matter.js或Box2D。这些引擎提供了完整的碰撞检测和物理模拟功能。

// 使用Matter.js示例
const engine = Matter.Engine.create();
const boxA = Matter.Bodies.rectangle(400, 200, 80, 80);
const boxB = Matter.Bodies.rectangle(450, 50, 80, 80);
Matter.Composite.add(engine.world, [boxA, boxB]);

Matter.Events.on(engine, 'collisionStart', (event) => {
  const pairs = event.pairs;
  pairs.forEach(pair => {
    console.log('碰撞发生在:', pair.bodyA, pair.bodyB);
  });
});

标签: js
分享给朋友:

相关文章

js 实现倒计时

js 实现倒计时

实现倒计时的基本方法 使用 JavaScript 实现倒计时可以通过 setInterval 或 setTimeout 结合日期计算来完成。以下是两种常见实现方式。 使用 setInterval 实…

js实现换肤

js实现换肤

使用CSS变量实现换肤 通过CSS变量可以轻松实现主题切换功能。CSS变量在根元素中定义,通过JavaScript动态修改这些变量值。 :root { --primary-color: #349…

js实现瀑布流

js实现瀑布流

实现瀑布流布局 瀑布流布局是一种常见的网页布局方式,常用于图片展示、商品列表等场景。以下是使用 JavaScript 实现瀑布流布局的几种方法。 纯 JavaScript 实现 通过计算元素的位置和…

js实现vr

js实现vr

使用WebXR API实现VR体验 WebXR是浏览器中实现VR和AR体验的标准API,它取代了早期的WebVR。现代浏览器如Chrome、Edge和Firefox已支持WebXR。 // 初始化W…

vue实现js休眠

vue实现js休眠

实现 JavaScript 休眠的方法 在 Vue 中实现 JavaScript 休眠(延迟执行)可以通过以下方式实现。由于 JavaScript 本身没有内置的 sleep 函数,通常使用 Prom…

js怎么实现异步

js怎么实现异步

异步实现方法 JavaScript中实现异步操作主要通过以下几种方式: Promise Promise是ES6引入的异步解决方案,用于处理异步操作的成功或失败状态。 const promise…