“等一下,我碰!”——常见的 2D 碰撞检测
在2D游戏开发中,”碰撞检测”(Collision Detection)是决定游戏交互真实性的核心技术。无论是角色跳跃踩踏平台、子弹击中敌人,还是道具拾取,都离不开精准的碰撞判断。本文将系统梳理2D碰撞检测的核心方法,从基础几何检测到高级优化策略,为开发者提供完整的技术解决方案。
一、基础几何碰撞检测
1. 轴对齐包围盒(AABB)
AABB(Axis-Aligned Bounding Box)是最简单高效的检测方式,通过比较两个矩形的边界坐标实现:
def aabb_check(box1, box2):return (box1.x < box2.x + box2.width andbox1.x + box1.width > box2.x andbox1.y < box2.y + box2.height andbox1.y + box1.height > box2.y)
适用场景:规则形状物体(如方块角色、平台)的快速检测
优势:计算量小(仅需4次比较),适合移动设备
局限:无法处理旋转物体,紧密贴合度低
2. 圆形碰撞检测
基于圆心距离与半径和的比较:
import mathdef circle_collision(circle1, circle2):dx = circle1.x - circle2.xdy = circle1.y - circle2.ydistance = math.sqrt(dx*dx + dy*dy)return distance < (circle1.radius + circle2.radius)
适用场景:球形物体(如弹球、粒子效果)
优势:天然支持旋转物体,计算效率高
优化技巧:可省略平方根计算,直接比较距离平方
3. 分离轴定理(SAT)
处理凸多边形碰撞的核心算法,通过检测所有可能的分离轴实现:
def project_polygon(axis, vertices):min_proj = max_proj = dot(axis, vertices[0])for vertex in vertices[1:]:proj = dot(axis, vertex)min_proj = min(min_proj, proj)max_proj = max(max_proj, proj)return min_proj, max_projdef sat_check(poly1, poly2):edges = get_edges(poly1) + get_edges(poly2)for edge in edges:axis = perpendicular(edge)proj1 = project_polygon(axis, poly1.vertices)proj2 = project_polygon(axis, poly2.vertices)if not overlaps(proj1, proj2):return Falsereturn True
适用场景:任意凸多边形(如不规则地形、斜坡)
关键点:需检测所有边对应的法线轴,计算量较大
优化方向:提前终止检测(发现分离轴立即返回)
二、高级检测技术
1. 像素级碰撞检测
通过逐像素比较实现最高精度检测,常用方法包括:
- 颜色键检测:为碰撞区域设置特定颜色
-
Alpha通道检测:利用透明度信息判断碰撞
# 伪代码示例def pixel_perfect_collision(sprite1, sprite2):# 获取两个精灵的位图数据bitmap1 = sprite1.get_bitmap()bitmap2 = sprite2.get_bitmap()# 计算重叠区域overlap_area = calculate_overlap(sprite1, sprite2)# 遍历重叠像素for x in range(overlap_area.width):for y in range(overlap_area.height):if (bitmap1.get_pixel(x,y).alpha > 0 andbitmap2.get_pixel(x,y).alpha > 0):return Truereturn False
适用场景:不规则形状(如复杂角色、特效)
性能优化: - 结合粗检测阶段(先用AABB筛选)
- 使用位掩码加速像素比较
- 限制检测频率(如每3帧检测一次)
2. 空间分区技术
解决大量物体检测时的性能问题:
- 网格分区:将场景划分为固定大小网格
-
四叉树:递归分割空间,动态适应物体分布
class QuadTreeNode:def __init__(self, boundary, capacity):self.boundary = boundary # 节点边界self.capacity = capacity # 最大容量self.points = [] # 存储的物体self.divided = False # 是否已分割self.children = None # 子节点def insert(self, point):if not self.boundary.contains(point):return Falseif len(self.points) < self.capacity:self.points.append(point)return Trueelse:if not self.divided:self.subdivide()return (self.children[0].insert(point) orself.children[1].insert(point) orself.children[2].insert(point) orself.children[3].insert(point))
选择建议:
- 静态场景:网格分区(实现简单)
- 动态场景:四叉树(自适应性强)
- 物体分布不均:空间哈希(内存效率高)
三、碰撞响应处理
检测到碰撞后,需要正确处理物体间的相互作用:
1. 位置修正
当物体穿透时,需将其移回合法位置:
def resolve_penetration(obj1, obj2, penetration):# 计算修正方向(从obj1指向obj2的法线)correction = penetration.normalized() * (penetration.length() * 0.5)obj1.position -= correctionobj2.position += correction
关键参数:
- 穿透深度(penetration depth)
- 修正比例(通常取50%-100%)
- 最大修正次数(防止无限循环)
2. 物理响应
实现弹性碰撞效果:
def elastic_collision(obj1, obj2):# 计算相对速度velocity_diff = obj1.velocity - obj2.velocity# 计算法线方向的速度分量dot_product = dot(velocity_diff, normal)# 计算冲量(使用恢复系数e)e = 0.8 # 弹性系数impulse = (1 + e) * dot_product / (1/obj1.mass + 1/obj2.mass)# 应用冲量obj1.velocity -= (impulse / obj1.mass) * normalobj2.velocity += (impulse / obj2.mass) * normal
物理参数:
- 质量(mass)
- 恢复系数(0=完全非弹性,1=完全弹性)
- 摩擦系数(可选)
四、性能优化策略
1. 检测阶段划分
采用”粗检测→细检测”的多阶段流程:
1. 空间分区筛选(四叉树/网格)2. 包围盒检测(AABB/圆形)3. 精确形状检测(SAT/像素级)4. 碰撞响应处理
效果:可减少90%以上的冗余计算
2. 缓存优化
- 预计算物体几何信息(如多边形法线)
- 复用计算结果(如连续帧间的边界框)
- 使用对象池管理检测数据
3. 并行计算
- 多线程处理独立物体的检测
- GPU加速像素级检测(使用Compute Shader)
- SIMD指令优化向量计算
五、实用建议
-
选择合适的检测精度:根据游戏类型平衡精度与性能(如休闲游戏可用AABB,动作游戏需SAT)
-
分层检测体系:建立”世界→区域→物体”的检测层级,减少无效比较
-
调试可视化:实现碰撞边界渲染功能,便于快速定位检测问题
# 调试渲染示例(使用Pygame)def draw_debug(screen, objects):for obj in objects:if obj.show_debug:# 绘制AABBpygame.draw.rect(screen, RED, obj.aabb, 1)# 绘制法线(SAT用)if hasattr(obj, 'normals'):for normal in obj.normals:end_point = (obj.center.x + normal.x*20,obj.center.y + normal.y*20)pygame.draw.line(screen, GREEN, obj.center, end_point, 2)
-
性能监控:实时统计检测耗时,设置性能预警阈值
-
工具链建设:开发自动化测试用例,覆盖各种碰撞场景
结语
2D碰撞检测是游戏物理系统的基石,其实现质量直接影响游戏体验。开发者应根据项目需求,灵活组合基础检测方法与高级优化技术。建议从AABB开始实现,逐步增加复杂度,同时建立完善的调试和性能监控体系。随着游戏复杂度的提升,空间分区和并行计算将成为关键优化手段。掌握这些技术后,开发者将能创造出更具沉浸感和物理真实性的2D游戏世界。