最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
HTML怎么做canvas碰撞检测_HTML canvas碰撞检测算法方法全面解析
时间:2026-07-25 10:51:49 编辑:袖梨 来源:一聚教程网
应使用AABB算法进行Canvas矩形碰撞检测,而非getBoundingClientRect();因后者受transform、滚动、iframe影响易偏移,需手动校正且易出错,而AABB直接基于Canvas坐标系的x、y等属性计算,稳定可靠。
矩形碰撞检测用 AABB 判断,别直接比 getBoundingClientRect()
Canvas 里做矩形碰撞,最常用也最稳的是轴对齐边界框(AABB)算法,不是靠 getBoundingClientRect() 拿 DOM 坐标——那玩意儿快是快,但一遇上 transform、滚动、iframe 就偏移失真,得手动校正,反而容易出错。
你该直接用 Canvas 坐标系下的对象属性:每个矩形有 x、y、、<code>height,判断逻辑就一行:
function isRectCollision(a, b) { return !(a.x + a.width <= b.x || b.x + b.width <= a.x || a.y + a.height <= b.y || b.y + b.height <= a.y);}
- 这个写法本质是“找分离轴”:只要水平或垂直方向完全分离,就不碰撞
- 避免用
a.x 这类正向条件,容易漏掉等号边界(比如刚好贴边时误判) - 所有坐标必须统一在 Canvas 画布坐标系下,别混用 CSS 像素或视口坐标
圆形碰撞别调 Math.hypot(),手算 dx*dx + dy*dy 更安全
两个圆是否碰撞,只看圆心距离是否小于半径和。但 Math.hypot(dx, dy) 在旧版 Safari 和部分 Electron 环境里不支持,而且开方本身有浮点误差和性能开销。
直接平方比较,既快又稳:
立即学习“前端免费学习笔记(深入)”;
function isCircleCollision(a, b) { const dx = a.x - b.x; const dy = a.y - b.y; const rSum = a.radius + b.radius; return dx * dx + dy * dy < rSum * rSum;}
- 注意:这里用的是
<而不是<=,因为“刚好相切”通常不算碰撞(除非你的游戏逻辑明确需要) - 如果对象带旋转,
radius不能直接取渲染尺寸——得用原始定义半径,否则缩放后会误判 - 圆形适合子弹、球体、头像徽章这类中心对称物体,不适合长条状角色
矩形和圆形混合碰撞,关键在找“矩形上离圆心最近的点”
比如小球撞墙、角色撞箱子,不能套用纯矩形或纯圆形逻辑。核心是:先求圆心在矩形边界上的投影点(即“最近点”),再测该点到圆心的距离是否 ≤ 半径。
function isAABBCircleCollision(rect, circle) { const clampedX = Math.max(rect.x, Math.min(circle.x, rect.x + rect.width)); const clampedY = Math.max(rect.y, Math.min(circle.y, rect.y + rect.height)); const dx = circle.x - clampedX; const dy = circle.y - clampedY; return dx * dx + dy * dy <= circle.radius * circle.radius;}
-
clampedX/Y是把圆心 x/y “拉回”矩形范围的结果:在内就是圆心本身,在外就是对应边上的垂足 - 这个算法天然覆盖三种情况:圆心在矩形内、在边上、在角外——不用分 case 写
- 别忘了矩形坐标必须是 Canvas 坐标系下的,且未被
scale()或translate()影响;如果用了 canvas 变换,得先反向变换圆心坐标
像素级碰撞要防跨域,且只读交集区域
当你要检测带透明边缘的角色图、不规则地形贴图是否真正“像素相触”,就得走 getImageData()。但它有两个硬限制:一是跨域图片会触发 canvas 污染(SecurityError),二是全图读取太慢。
- 解决跨域:服务端加
CORS头,或前端加载时设img.crossOrigin = 'anonymous' - 别用
ctx.getImageData(0, 0, canvas.width, canvas.height)—— 一次读几 MB 图像数据,帧率直接崩 - 只读两物体包围盒的交集区域:
ctx.getImageData(x, y, width, height),其中x/y/width/height是交集矩形的 Canvas 坐标 - 遍历时跳过 alpha === 0 的像素,只比非透明通道;若两个对象在交集区都有非透明像素,才算碰撞
这一步几乎总是性能瓶颈,上线前务必用 console.time() 测真实耗时——尤其在低端 Android 设备上,10×10 像素交集都可能卡顿。
相关文章
- 苹果折叠屏爆料汇总:售价超两万,比例阔折叠 07-30
- 纪念碑谷3 纪念碑谷3手游玩法详解与体验评测 07-30
- 晴空双子金卡阵容推荐 晴空双子高性价比氪金养成指南 07-30
- 大周列国志全新派系系统 07-30
- 兔小萌世界甜系小房间搭建指南 兔小萌世界高颜值甜系房间布置全流程详解 07-30
- 大周列国志全新剧本包西汉剧本包 07-30