如何确定矩形的哪一边与圆碰撞

在你指出这个问题还有其他答案之前,我已经查看了这个问题或类似问题的大多数其他答案,但我还没有找到我需要的解决方案。

基本上我想要做的就是当圆/球与矩形碰撞时,我想确定这个碰撞发生在矩形的哪一侧。 我想找到这个,以便我可以强制执行更逼真的物理,例如,如果球击中矩形的顶部,只反过来它的Y速度……而不是两者。

我已经尝试比较球和矩形的X和Y位置,甚至是它们两个边界框的位置……测试即使球的底部与矩形顶部相交……使用’if ball .boundingBox.Bottom> = rectangle.boundingBox.Top’。

我已经附上了一张照片,以显示我想要实现的目标…以防它有点混乱,因为它不详细……如果球从一侧进来,那么看起来像v的红色是路径,我希望撞击时的运动以相反的方式行进,但这取决于矩形的一侧,关于球的速度的哪个部分我将不得不改变……

仅供参考我也看过矢量标准化…我之前没有使用过它原谅我如果可以用这个来解决…

感谢v.much阅读

编辑,因为我匆忙,我使用了不同的图像……这仍然显示了我想要实现的行为,因为图上显示的物理是我希望球在与另一个碰撞时表现的行为双方……链接到图片: http : //codeincomplete.com/posts/2011/6/12/collision_detection_in_breakout/bounce2.v283.png

此代码可能比您需要的更全面,并且可以根据您的需要进行重构,但它是一个完整的答案,并且可以灵活地使用移动边界矩形和移动圆圈。

这是一个图形,为代码正在做的事情提供视觉帮助。 红色圆圈与黑色矩形相交。 可视化穿过对角的两条假想线。 如果您知道圆圈所在的2条线中的每条线的哪一侧,则可以推断出碰撞的边缘。

在此处输入图像描述

首先声明类范围私有成员

Rectangle CollisionBoxRect; Rectangle circleRect; Dictionary corners; 

在您移动圆圈并设置其位置和潜在相交框位置后的更新中,它会进行基本检查,以查看圆的边界矩形是否与块的边界矩形有关。 如果是这样的话,那么它会根据圆圈碰撞的矩形的哪一侧以适当的碰撞法线改变球的速度。

 if (CollisionBoxRect.Intersects(circleRect)) { ballVelocity = Vector2.Reflect(ballVelocity, GetCollisionNormal(CollisionBoxRect)); } 

以下方法支持获得正确的一方(实际上是正常的)。 如果它们永远不会改变,那么其中一些方法可以在初始化阶段完成一次(如获取角点方法);

 private Vector2 GetCollisionNormal(Rectangle boxBeingIntersected) { getCorners(boxBeingIntersected); bool isAboveAC = isOnUpperSideOfLine(corners["bottomRight"], corners["topLeft"], getBallCenter()); bool isAboveDB = isOnUpperSideOfLine( corners["topRight"], corners["bottomLeft"], getBallCenter()); if (isAboveAC) { if (isAboveDB) { //top edge has intersected return -Vector2.UnitY; } else { //right edge intersected return Vector2.UnitX; } } else { if (isAboveDB) { //left edge has intersected return -Vector2.UnitX; } else { //bottom edge intersected return Vector2.UnitY; } } } 

 public bool isOnUpperSideOfLine(Vector2 corner1, Vector2 oppositeCorner, Vector2 ballCenter) { return ((oppositeCorner.X - corner1.X) * (ballCenter.Y - corner1.Y) - (oppositeCorner.Y - corner1.Y) * (ballCenter.X - corner1.X)) > 0; } 

 private Vector2 getBallCenter() { return new Vector2(circleRect.Location.X + circleRect.Width / 2, circleRect.Location.Y + circleRect.Height / 2); } 

 private void getCorners(Rectangle boxToGetFrom) { corners.Clear(); Vector2 tl = new Vector2(boxToGetFrom.X, boxToGetFrom.Y); Vector2 tr = new Vector2(boxToGetFrom.X + boxToGetFrom.Width, boxToGetFrom.Y); Vector2 br = new Vector2(boxToGetFrom.X + boxToGetFrom.Width, boxToGetFrom.Y + boxToGetFrom.Height); Vector2 bl = new Vector2(boxToGetFrom.X, boxToGetFrom.Y + boxToGetFrom.Height); corners.Add("topLeft", tl); corners.Add("topRight", tr); corners.Add("bottomRight", br); corners.Add("bottomLeft", bl); }