JavaScript 分离轴碰撞检测教程
一、引言
在游戏开发或物理仿真中,碰撞检测是非常重要的功能之一。本篇文章将教你如何使用 JavaScript 实现“分离轴碰撞检测”算法。它是一种高效、广泛应用于2D物体之间碰撞检测的算法。接下来,我们将通过分步过程深入分析。
二、整体流程
在实现分离轴碰撞检测之前,我们首先了解实现的步骤。下表展示了整个流程:
| 步骤 | 描述 |
|---|---|
| 1. 确定碰撞的形状 | 确定将要检测的物体的形状(如矩形、圆等) |
| 2. 提取顶点 | 从每个形状中提取出它的顶点坐标 |
| 3. 计算法向量 | 为每一条边计算法向量,以确定分离轴 |
| 4. 投影坐标 | 将所有顶点投影到分离轴上 |
| 5. 检查重叠 | 检查在每个投影上的重叠情况,以判断是否发生碰撞 |
| 6. 返回结果 | 返回碰撞检测的结果 |
三、详细步骤解析
步骤 1: 确定碰撞的形状
首先,我们需要确定要检测的形状。这里我们以两个矩形为例。
步骤 2: 提取顶点
我们需要提取出矩形的四个顶点。
function getVertices(rect) {
return [
{ x: rect.x, y: rect.y }, // 左上角
{ x: rect.x + rect.width, y: rect.y }, // 右上角
{ x: rect.x + rect.width, y: rect.y + rect.height }, // 右下角
{ x: rect.x, y: rect.y + rect.height } // 左下角
];
}
注释:该函数返回一个矩形的四个顶点坐标。
步骤 3: 计算法向量
通过获取每一条边的法向量,以下是计算法向量的代码:
function getNormalEdges(vertices) {
let edges = [];
for (let i = 0; i < vertices.length; i++) {
const nextIndex = (i + 1) % vertices.length; // 获取下一个顶点索引
const edge = {
x: vertices[nextIndex].x - vertices[i].x,
y: vertices[nextIndex].y - vertices[i].y
};
// 计算法向量
edges.push({ x: -edge.y, y: edge.x });
}
return edges;
}
注释:此函数接收一个顶点数组,获取每一条边,并计算法向量。
步骤 4: 投影坐标
对每个顶点进行投影,以确定它在法向量上的位置。
function projectVertices(vertices, axis) {
let min = Infinity, max = -Infinity;
for (let vertex of vertices) {
const projection = (vertex.x * axis.x + vertex.y * axis.y);
min = Math.min(min, projection);
max = Math.max(max, projection);
}
return { min, max };
}
注释:函数将顶点投影到给定轴上,并返回投影的最小值和最大值。
步骤 5: 检查重叠
我们需要检查两个形状的投影是否重叠。
function overlapOnAxis(proj1, proj2) {
return !(proj1.max < proj2.min || proj2.max < proj1.min);
}
注释:此函数判断两个投影区间是否重叠。
步骤 6: 返回结果
最后,我们将上述步骤组合到一起,形成完整的碰撞检测函数。
function isColliding(rect1, rect2) {
const vertices1 = getVertices(rect1);
const vertices2 = getVertices(rect2);
const edges1 = getNormalEdges(vertices1);
const edges2 = getNormalEdges(vertices2);
for (const edge of [...edges1, ...edges2]) {
const projection1 = projectVertices(vertices1, edge);
const projection2 = projectVertices(vertices2, edge);
if (!overlapOnAxis(projection1, projection2)) {
return false; // 没有发生碰撞
}
}
return true; // 发生了碰撞
}
注释:这是整个碰撞检测的实现,判断两个矩形是否碰撞。
四、关系图
在编写代码的过程中,我们可以通过简单的 ER 图理解不同组成部分的关系:
erDiagram
RECTANGLE {
STRING id
FLOAT x
FLOAT y
FLOAT width
FLOAT height
}
COLLISION {
STRING rect1_id
STRING rect2_id
BOOLEAN isColliding
}
五、饼状图
为了更好地理解碰撞检测的应用,我们可以用饼状图表示不同形状的碰撞检测结果分布:
pie
title 碰撞检测结果分布
"无碰撞": 70
"发生碰撞": 30
六、结尾
通过上述步骤,我们完全实现了利用 JavaScript 进行分离轴碰撞检测的方法。这种方法简单而高效,被广泛应用于2D游戏开发和物理引擎中。希望这篇文章能为你提供一个良好的开始,鼓励你进一步探索碰撞检测和物理模拟的更深层次内容。祝你在编程的道路上越走越远!
















