JS/HTML5游戏碰撞检测:圆形包围盒算法详解
本文详解JavaScript与HTML5游戏中常用的圆形包围盒碰撞检测算法。通过比较两圆圆心距离平方与半径之和的平方,避免开方运算以提升性能。文章提供核心检测函数及完整Canvas示例代码,适用于需要高效处理大量物体碰撞的游戏场景。
圆形包围盒碰撞检测概述
本文详细介绍JavaScript与HTML5游戏中广泛使用的碰撞检测技术,重点解析包围盒检测算法。内容旨在为开发者提供实用的参考方案。
物体碰撞的本质是判断几何体是否发生重叠。由于实际游戏对象的形状复杂多样,直接对边缘进行精确碰撞检测的计算成本极高。特别是在网络游戏环境中,服务器需同时处理成千上万甚至数十万在线用户的交互,若进行高精度检测,即便大型服务器也可能因计算过载而崩溃。因此,在无需极致精度的场景下,通常采用包围盒算法,即将物体简化为包含其内部的多边形区域,以此降低计算复杂度。
基于上述原理,开发中常选用结构最简单的多边形作为包围体,例如圆形和矩形。
圆形包围盒算法实现原理
首先介绍圆形包围盒算法的实现方式。该算法利用圆形包裹游戏物体,检测时仅需判断两个圆形是否相交。判断过程相对直观:假设圆A的坐标为(x1, y1),半径为r1;圆B的坐标为(x2, y2),半径为r2。若满足不等式(y2−y1)²+(x2−x1)²≤(r1+r2)²,则判定两圆发生碰撞。这实质上是判断圆心间距是否小于两圆半径之和。由于计算距离涉及开方运算,效率较低,因此优化方案是直接比较距离的平方与半径之和的平方。

核心代码与完整示例
核心检测逻辑如下:
function hitTest( source, target ) {
/* 源物体和目标物体都包含 x, y 以及 width, height */
return !(
Math.pow((source.x - target.x),2) + Math.pow((source.y - target.y),2) > Math.pow((source.r + target.r),2)
);
}
完整的运行示例代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<meta charset="UTF-8">
<title>盒包围碰撞算法-圆形</title>
<style>
#stage {
border: 1px solid lightgray;
}
</style>
</head>
<body>
<h1>是否碰撞:<span class="hitTest">否</span></h1>
<canvas id="stage"></canvas>
</body>
<script>
window.onload = function () {
var stage = document.querySelector('#stage'),
ctx = stage.getContext('2d');
stage.width = 400;
stage.height = 400;
document.onkeydown = function (event) {
var e = event || window.event || arguments.callee.caller.arguments[0];
//根据地图数组碰撞将测
switch (e.keyCode) {
case 37:
console.log("Left");
if (balls[0].x > 0) {
balls[0].x -= 2;
}
break;
case 38:
console.log("Top");
if (balls[0].y > 0) {
balls[0].y -= 2;
}
break;
case 39:
console.log("Right");
if (balls[0].x < stage.width) {
balls[0].x += 2;
}
break;
case 40:
console.log("Bottom");
if (balls[0].y < stage.height) {
balls[0].y += 2;
}
break;
default:
return false;
}
};
stage.addEventListener('click', function (event) {
var x = event.clientX - stage.getBoundingClientRect().left;
var y = event.clientY - stage.getBoundingClientRect().top;
balls[0].x = x - balls[0].r/2;
balls[0].y = y - balls[0].r/2;
});
var player = {
x: stage.width / 2 - 20,
y: stage.height / 2 - 20,
r: 40,
c: "red"
},balls = [];
balls.push(player);
for (var i = 0; i < 10; i++) {
var ball = {
x: 60 * i,
y: 60 * i,
r: 40,
c: "blue"
};
balls.push(ball);
}
function createBall(x, y, r, c) {
ctx.beginPath();
ctx.fillStyle = c;
ctx.arc(x, y, r, 0, Math.PI*2);
ctx.fill();
}
function hitTest( source, target ) {
/* 源物体和目标物体都包含 x, y 以及 width, height */
return !(
Math.pow((source.x - target.x),2) + Math.pow((source.y - target.y),2) > Math.pow((source.r + target.r),2)
);
}
function update() {
ctx.globalAlpha=1;
ctx.clearRect(0, 0, 400, 400);
document.querySelector('.hitTest').innerHTML = "否";
for (var i = 1, len = balls.length; i < len; i++) {
createBall(balls[i].x, balls[i].y, balls[i].r, balls[i].c);
var flag = hitTest(balls[0],balls[i]);
if(flag){
document.querySelector('.hitTest').innerHTML = "是";
ctx.globalAlpha=0.5;
}
}
createBall(balls[0].x, balls[0].y, balls[0].r, balls[0].c);
requestAnimationFrame(update);
}
update();
};
</script>
</html>
可使用在线HTML/CSS/JavaScript代码运行工具:http://tools.jb51.net/code/HtmlJsRun 对上述代码进行测试,运行结果如图所示:

相关源代码托管于GitHub:https://github.com/krapnikkk/JS-gameMathematics
如需了解更多JavaScript相关知识,可参考本站专题:《JavaScript数学运算用法总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript数组操作技巧总结》、《JavaScript排序算法总结》、《JavaScript遍历算法与技巧总结》、《JavaScript查找算法技巧总结》及《JavaScript错误与调试技巧总结》。
希望本文所述内容能对您的JavaScript程序设计工作提供帮助。
JS动态构建复杂嵌套JSON对象的方法
2026-11-05 15:41:52
JS负数取余为什么是负数?详解余数与模运算区别
2026-11-05 13:34:41
JS 解压出现乱码或报错怎么解决?
2026-11-05 12:32:38
JS 中 startsWith、indexOf 与正则判断字符串前缀的对比
2026-11-04 22:19:43
JS解析Excel后怎么将数据转换为JSON格式
2026-11-04 20:58:28
