如何检测轴对齐的两个矩形是否碰撞(适配Minecraft区域坐标场景)
问题核心原因
你之前的两个方案失效,核心是两个共性问题:
- 没有对
Region的坐标做归一化处理:你无法保证aX一定小于bX、aY一定小于bY,直接用原始的aX/bX/aY/bY做判断,会出现逻辑颠倒的情况,尤其坐标支持负数的场景下问题更明显。 Rectangle方案的宽高计算逻辑完全错误:使用Math.abs做减法会抹掉坐标的正负属性,很容易得到负的宽高值,而Rectangle构造函数传入负宽高时会默认将宽高置为0,自然无法正确判断碰撞。
正确实现方案
方案1:纯逻辑实现(无需依赖AWT包,推荐)
public boolean doesCollide(Region other) { // 归一化当前区域的坐标范围 int thisMinX = Math.min((int) aX, (int) bX); int thisMaxX = Math.max((int) aX, (int) bX); int thisMinY = Math.min((int) aY, (int) bY); int thisMaxY = Math.max((int) aY, (int) bY); // 归一化待比对区域的坐标范围 int otherMinX = Math.min((int) other.aX, (int) other.bX); int otherMaxX = Math.max((int) other.aX, (int) other.bX); int otherMinY = Math.min((int) other.aY, (int) other.bY); int otherMaxY = Math.max((int) other.aY, (int) other.bY); // 轴对齐矩形碰撞判断:X轴和Y轴同时存在重叠即判定为碰撞 return thisMinX < otherMaxX && thisMaxX > otherMinX && thisMinY < otherMaxY && thisMaxY > otherMinY; }
如果业务要求区域边界接触就算碰撞,把判断里的<改为<=、>改为>=即可。
方案2:正确使用java.awt.Rectangle实现
public boolean doesCollide(Region other) { // 计算当前区域的合法参数 int thisMinX = Math.min((int) aX, (int) bX); int thisMinY = Math.min((int) aY, (int) bY); int thisWidth = Math.max((int) aX, (int) bX) - thisMinX; int thisHeight = Math.max((int) aY, (int) bY) - thisMinY; Rectangle thisRectangle = new Rectangle(thisMinX, thisMinY, thisWidth, thisHeight); // 计算待比对区域的合法参数 int otherMinX = Math.min((int) other.aX, (int) other.bX); int otherMinY = Math.min((int) other.aY, (int) other.bY); int otherWidth = Math.max((int) other.aX, (int) other.bX) - otherMinX; int otherHeight = Math.max((int) other.aY, (int) other.bY) - otherMinY; Rectangle otherRectangle = new Rectangle(otherMinX, otherMinY, otherWidth, otherHeight); return thisRectangle.intersects(otherRectangle); }
内容的提问来源于stack exchange,提问作者Jan Herzog
相关产品推荐
相关产品推荐

