大疆面试:“你是如何实现碰撞检测的?”
前记
因为在简历中的项目提到了 对拖拽元素进行边界检测,从而派生出了这道面试题,因为当时只注重实现的结果加上项目的久远,在提到这个问题的时候一时间没有很好的组织出答案,所以想写下这篇文章来重新组织自己的思路和语言。
AABB碰撞检测
因为在我的项目中拖拽的元素都是矩形形状的元素,所以在项目中我封装了一个 AABB碰撞检测函数。
- 比较官方的解释: AABB碰撞检测是一种用于检测两个物体或图形是否相交的碰撞算法。AABB表示轴对齐的边界框,也称为包围盒,它是一个坐标轴平行的矩形框,完全包围住一个物体或图像。
- 我的直接理解:
- demo 代码
function checkAABBCollision(rectA, rectB) {
// 检查矩形A的边界
let leftA = rectA.x;
let rightA = rectA.x + rectA.width;
let topA = rectA.y;
let bottomA = rectA.y + rectA.height;
// 检查矩形B的边界
let leftB = rectB.x;
let rightB = rectB.x + rectB.width;
let topB = rectB.y;
let bottomB = rectB.y + rectB.height;
// 判断是否相交
if (leftA < rightB && rightA > leftB && topA < bottomB && bottomA > topB) {
return true; // 碰撞发生
} else {
return false; // 无碰撞
}
}
接受两个矩形对象 rectA 和 rectB 作为参数。每个矩形对象都有x,y,width和height属性,分别表示矩形的左上角坐标、宽度和高度。
函数内部,使用矩形的边界值来判断两个矩形是否相交:
- 矩形A的右边界 > 矩形B的左边界
- 矩形A的左边界 < 矩形B的右边界
- 矩形A的底边界 > 矩形B的顶边界
- 矩形A的顶边界 < 矩形B的底边界
同时满足 -> 两个矩形相交(即碰撞)
我在项目中的使用
我做的这个项目是使用vue3实现的一个可视化拖拽编辑器,接下来说一下我在项目中是如何实现拖拽元素的过程中动态进行碰撞检测的:
:style根据数据的变化动态地设置元素样式- 封装拖拽事件函数拿到变化的数据
- 将拿到的数据进行AABB碰撞检测
- 如果碰撞即边框变为红色
注意
- 使用的时候要注意坐标数据的响应式是否丢失
- 拖拽事件函数的正确封装
- 因为的拖拽的过程中可能会比较频繁触发(碰撞的时机),可以使用防抖、节流进行性能优化
- 后面还需要考虑其他情况的碰撞,还要优化矩形坐标的存储方式,所以这是一个半成品