Python Turtle三角形海龟碰撞检测:distance函数未考虑形状尺寸
Turtle海龟重叠检测解决方案
针对你遇到的distance()仅计算海龟中心距离、无法识别图形边缘重叠的问题,提供两种可行方案:
一、快速外接圆碰撞检测
适合对精度要求不高的场景,通过计算海龟图形的外接圆半径,判断两圆是否相交(中心距离小于两半径之和)。
代码示例
import turtle att = turtle.Turtle() dif = turtle.Turtle() dif.shape("triangle") dif.color("red") dif.shapesize(stretch_wid=2, stretch_len=2) reference = att.heading() startpoint = att.position() dif_pos = dif.position() Aod = turtle.Turtle() Aod.penup() Aod.color("green") Aod.shape("triangle") Aod.shapesize(stretch_wid=15, stretch_len=15) Aod.setheading(reference + 180) Aod.goto(startpoint) Aod.forward(-170) # 计算海龟的碰撞外接圆半径 def get_collision_radius(t): # 默认海龟基准形状的中心到顶点距离约为10像素 base_radius = 10 # 取宽/长缩放的最大值作为实际缩放倍数 scale = max(t.shapesize()[0], t.shapesize()[1]) return base_radius * scale aod_radius = get_collision_radius(Aod) dif_radius = get_collision_radius(dif) current_distance = Aod.distance(dif) if current_distance < (aod_radius + dif_radius): print(f"当前距离: {current_distance}") print("检测到重叠/碰撞") else: print(f"当前距离: {current_distance}") print("无重叠")
二、精确三角形碰撞检测(分离轴定理)
针对三角形海龟,通过获取图形的实际顶点坐标,使用分离轴定理判断两个三角形是否相交,能准确识别边缘接触的情况。
代码示例
import turtle import math # 获取海龟在世界坐标系中的形状顶点 def get_world_vertices(t): poly = t.get_shapepoly() stretch_wid, stretch_len, _, _ = t.shapesize() x0, y0 = t.position() heading_rad = math.radians(t.heading()) cos_h = math.cos(heading_rad) sin_h = math.sin(heading_rad) vertices = [] for x, y in poly: # 缩放坐标:x对应朝向方向缩放,y对应垂直朝向方向缩放 scaled_x = x * stretch_len scaled_y = y * stretch_wid # 旋转坐标适配海龟朝向 rotated_x = scaled_x * cos_h - scaled_y * sin_h rotated_y = scaled_x * sin_h + scaled_y * cos_h # 平移到海龟当前位置 world_x = rotated_x + x0 world_y = rotated_y + y0 vertices.append((world_x, world_y)) return vertices # 分离轴定理判断两个三角形是否相交 def triangles_intersect(tri1, tri2): # 获取边的法向量作为分离轴 def edge_normal(pt1, pt2): dx = pt2[0] - pt1[0] dy = pt2[1] - pt1[1] return (-dy, dx) # 将点集投影到轴上,返回极值 def project(points, axis): min_proj = max_proj = points[0][0] * axis[0] + points[0][1] * axis[1] for p in points[1:]: proj = p[0] * axis[0] + p[1] * axis[1] if proj < min_proj: min_proj = proj if proj > max_proj: max_proj = proj return min_proj, max_proj # 判断两个投影区间是否重叠 def overlap(min1, max1, min2, max2): return not (max1 < min2 or max2 < min1) # 收集所有需要检测的分离轴 axes = [] for i in range(3): axes.append(edge_normal(tri1[i], tri1[(i+1)%3])) axes.append(edge_normal(tri2[i], tri2[(i+1)%3])) # 检查每个轴,若存在分离轴则不相交 for axis in axes: min1, max1 = project(tri1, axis) min2, max2 = project(tri2, axis) if not overlap(min1, max1, min2, max2): return False return True # 测试逻辑 att = turtle.Turtle() dif = turtle.Turtle() dif.shape("triangle") dif.color("red") dif.shapesize(stretch_wid=2, stretch_len=2) reference = att.heading() startpoint = att.position() Aod = turtle.Turtle() Aod.penup() Aod.color("green") Aod.shape("triangle") Aod.shapesize(stretch_wid=15, stretch_len=15) Aod.setheading(reference + 180) Aod.goto(startpoint) Aod.forward(-170) # 获取两个海龟的三角形顶点 aod_tri = get_world_vertices(Aod) dif_tri = get_world_vertices(dif) if triangles_intersect(aod_tri, dif_tri): print("检测到三角形重叠") else: print("无三角形重叠") turtle.done()
方案说明
- 外接圆方案代码简洁、计算快,适合实时性要求高的场景;
- 分离轴定理方案精度高,能准确识别边缘接触,但计算量稍大,适合需要精确碰撞判断的场景。
内容的提问来源于stack exchange,提问作者Stefano Menicocci
相关产品推荐
相关产品推荐

