JS游戏碰撞检测技巧与4种常用算法
时间:2025-06-25 12:58:09 276浏览 收藏
小伙伴们有没有觉得学习文章很有意思?有意思就对了!今天就给大家带来《JS游戏碰撞检测方法及4种常用算法》,以下内容将会涉及到,若是在学习中对其中部分知识点有疑问,或许看了本文就能帮到你!
碰撞检测算法对游戏的真实感、流畅度和可玩性至关重要。1. 它确保玩家操作反馈准确,避免误判影响体验;2. 常见算法包括AABB(性能高但精度低)、圆形检测(适用于近似圆形物体)、SAT(高精度适用于凸多边形)、像素级检测(精度最高但计算量大);3. 选择算法需根据游戏类型、物体形状、性能与精度需求综合判断,常采用混合策略提升效率。
游戏碰撞检测,简单来说,就是判断游戏中不同的物体是不是“撞”到了一起。实现方式有很多,选择哪种取决于你的游戏类型、性能需求和精度要求。

游戏开发中,碰撞检测是核心环节。

为什么碰撞检测算法如此重要?
碰撞检测不仅仅是“撞没撞到”那么简单。它直接影响到游戏的真实感、流畅度和可玩性。想象一下,如果你的角色明明躲开了敌人的攻击,游戏却判定你受到了伤害,或者明明应该击中的目标却穿过去了,那游戏体验肯定会大打折扣。选择合适的碰撞检测算法,能让你的游戏世界更加真实、可信,从而提升玩家的沉浸感。
碰撞检测算法一:AABB碰撞检测(Axis-Aligned Bounding Box)
AABB碰撞检测,顾名思义,就是使用轴对齐的包围盒来进行碰撞检测。简单来说,就是用一个矩形(在3D中是长方体)来包裹住游戏中的物体。这种方法的优点是计算简单、速度快,非常适合对性能要求高的游戏。

实现原理:
判断两个AABB是否相交,只需要判断它们在每个轴上的投影是否都相交即可。例如,在2D游戏中,只需要判断两个矩形在X轴和Y轴上的投影是否都相交。
JS代码示例:
function aabbCollision(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 ); } // 使用示例 const rect1 = { x: 10, y: 10, width: 50, height: 50 }; const rect2 = { x: 60, y: 10, width: 50, height: 50 }; if (aabbCollision(rect1, rect2)) { console.log("AABB Collision detected!"); }
适用场景:
- 性能要求高的2D游戏,例如横版过关、射击游戏等。
- 作为复杂碰撞检测的第一步,快速排除掉大部分不可能发生碰撞的物体。
局限性:
- 精度较低,对于不规则形状的物体,AABB会包含很多空白区域,导致误判。
- 无法处理旋转后的物体,需要实时更新AABB的坐标,增加了计算量。
碰撞检测算法二:圆形碰撞检测
圆形碰撞检测,顾名思义,就是用圆形来包裹住游戏中的物体。这种方法比AABB更精确一些,但计算量也稍大。
实现原理:
判断两个圆形是否相交,只需要判断它们圆心之间的距离是否小于等于它们的半径之和即可。
JS代码示例:
function circleCollision(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; } // 使用示例 const circle1 = { x: 10, y: 10, radius: 25 }; const circle2 = { x: 60, y: 10, radius: 25 }; if (circleCollision(circle1, circle2)) { console.log("Circle Collision detected!"); }
适用场景:
- 需要一定精度的2D游戏,例如弹幕游戏、台球游戏等。
- 物体形状接近圆形的游戏。
局限性:
- 对于形状差异较大的物体,圆形包围盒的精度仍然不够。
- 无法处理旋转后的物体,需要实时更新圆心的坐标,增加了计算量。
碰撞检测算法三:分离轴定理(SAT,Separating Axis Theorem)
分离轴定理是一种更高级的碰撞检测算法,可以用于检测任意凸多边形之间的碰撞。它基于一个简单的原理:如果两个凸多边形不相交,那么一定存在一条直线,将它们完全分开。
实现原理:
对于两个凸多边形,我们需要找到所有可能的分离轴(通常是多边形的边的法线方向),然后判断这两个多边形在每个分离轴上的投影是否相交。如果存在一个分离轴,使得它们的投影不相交,那么这两个多边形就一定不相交。
JS代码示例:
(由于SAT算法较为复杂,这里只提供一个简化的示例,不包含所有优化和特殊情况处理)
function projectPolygon(polygon, axis) { let min = Infinity; let max = -Infinity; for (const vertex of polygon) { const projection = vertex.x * axis.x + vertex.y * axis.y; min = Math.min(min, projection); max = Math.max(max, projection); } return { min, max }; } function isSeparatingAxis(polygon1, polygon2, axis) { const projection1 = projectPolygon(polygon1, axis); const projection2 = projectPolygon(polygon2, axis); return projection1.max < projection2.min || projection2.max < projection1.min; } function satCollision(polygon1, polygon2) { // 获取所有可能的分离轴(这里简化为只考虑两个多边形的边的法线) const axes = []; for (let i = 0; i < polygon1.length; i++) { const p1 = polygon1[i]; const p2 = polygon1[(i + 1) % polygon1.length]; const axis = { x: p2.y - p1.y, y: p1.x - p2.x }; // 法线方向 axes.push(axis); } for (let i = 0; i < polygon2.length; i++) { const p1 = polygon2[i]; const p2 = polygon2[(i + 1) % polygon2.length]; const axis = { x: p2.y - p1.y, y: p1.x - p2.x }; // 法线方向 axes.push(axis); } // 判断是否存在分离轴 for (const axis of axes) { if (isSeparatingAxis(polygon1, polygon2, axis)) { return false; // 存在分离轴,不相交 } } return true; // 不存在分离轴,相交 } // 使用示例 const polygon1 = [{ x: 10, y: 10 }, { x: 60, y: 10 }, { x: 60, y: 60 }, { x: 10, y: 60 }]; const polygon2 = [{ x: 40, y: 40 }, { x: 90, y: 40 }, { x: 90, y: 90 }, { x: 40, y: 90 }]; if (satCollision(polygon1, polygon2)) { console.log("SAT Collision detected!"); }
适用场景:
- 需要高精度碰撞检测的2D游戏。
- 物体形状不规则,且需要处理旋转的情况。
局限性:
- 计算量较大,不适合对性能要求极高的游戏。
- 只能处理凸多边形,对于凹多边形需要进行分解。
碰撞检测算法四:像素级碰撞检测
像素级碰撞检测是最精确的碰撞检测算法,它可以精确到每个像素的级别。但是,它的计算量也是最大的,通常只用于对精度要求极高的特殊情况。
实现原理:
判断两个物体是否相交,需要遍历它们重叠区域的每个像素,判断是否有像素重叠。
JS代码示例:
(像素级碰撞检测通常需要操作图像数据,这里只提供一个伪代码示例)
function pixelCollision(image1, image2, x1, y1, x2, y2) { // 获取两个图像的重叠区域 const overlapXStart = Math.max(x1, x2); const overlapYStart = Math.max(y1, y2); const overlapXEnd = Math.min(x1 + image1.width, x2 + image2.width); const overlapYEnd = Math.min(y1 + image1.height, y2 + image2.height); // 遍历重叠区域的每个像素 for (let x = overlapXStart; x < overlapXEnd; x++) { for (let y = overlapYStart; y < overlapYEnd; y++) { // 获取两个图像在当前像素位置的颜色值 const color1 = getImagePixel(image1, x - x1, y - y1); const color2 = getImagePixel(image2, x - x2, y - y2); // 判断是否有像素重叠(例如,判断alpha值是否都大于0) if (color1.alpha > 0 && color2.alpha > 0) { return true; // 像素重叠,发生碰撞 } } } return false; // 没有像素重叠,没有发生碰撞 } // 使用示例 // 需要先加载图像数据 const image1 = loadImage("image1.png"); const image2 = loadImage("image2.png"); image1.onload = () => { image2.onload = () => { if (pixelCollision(image1, image2, 10, 10, 40, 40)) { console.log("Pixel Collision detected!"); } }; };
适用场景:
- 需要极高精度碰撞检测的特殊情况,例如子弹击中敌人的精确位置。
- 处理不规则形状的物体。
局限性:
- 计算量极大,不适合大量物体的碰撞检测。
- 需要操作图像数据,实现较为复杂。
如何选择合适的碰撞检测算法?
选择合适的碰撞检测算法,需要综合考虑以下因素:
- 游戏类型: 不同类型的游戏对碰撞检测的精度和性能要求不同。
- 物体形状: 规则形状的物体可以使用简单的AABB或圆形碰撞检测,不规则形状的物体可以使用SAT或像素级碰撞检测。
- 性能需求: 对性能要求高的游戏,应该选择计算简单的AABB或圆形碰撞检测。
- 精度要求: 对精度要求高的游戏,应该选择SAT或像素级碰撞检测。
通常,我们会采用一种混合策略,例如先使用AABB进行粗略的碰撞检测,排除掉大部分不可能发生碰撞的物体,然后再使用更精确的算法对剩余的物体进行碰撞检测。
碰撞检测的优化技巧
除了选择合适的碰撞检测算法,还可以使用一些优化技巧来提高碰撞检测的效率:
- 空间划分: 将游戏世界划分为多个区域,只对相邻区域的物体进行碰撞检测。常用的空间划分方法有网格划分、四叉树、八叉树等。
- 碰撞分组: 将游戏中的物体分为不同的组,只对可能发生碰撞的组进行碰撞检测。例如,可以将玩家、敌人、子弹分为不同的组。
- 减少碰撞检测的频率: 不需要每帧都进行碰撞检测,可以降低碰撞检测的频率,例如每隔几帧进行一次碰撞检测。
掌握这些碰撞检测算法和优化技巧,可以帮助你开发出更加真实、流畅、有趣的游戏。
以上就是本文的全部内容了,是否有顺利帮助你解决问题?若是能给你带来学习上的帮助,请大家多多支持golang学习网!更多关于文章的相关知识,也可关注golang学习网公众号。
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
105 收藏
-
393 收藏
-
385 收藏
-
329 收藏
-
456 收藏
-
333 收藏
-
295 收藏
-
497 收藏
-
309 收藏
-
373 收藏
-
432 收藏
-
331 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 508次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 484次学习