如何解决扫描 AABB 与 2D 中的线段
近一个星期以来,我一直在尝试启动并运行扫掠碰撞检测,但我终其一生都无法让它发挥作用。我想尝试对线段移动 AABB,看看它是否以及何时发生碰撞。
下面有一个关于这个链接的答案: https://gamedev.stackexchange.com/questions/29479/swept-aabb-vs-line-segment-2d/30220#30220?newreg=95e000808fe74acdbd7a6b7d1d4b3a05
我已将其翻译成 Go,它将运行游戏服务器并需要此逻辑:
func SweepRectLine(rectX,rectY,rectW,rectH,rectHSpeed,rectVSpeed,lineX1,lineY1,lineX2,lineY2 float64) (bool,float64) {
outVel := [2]float64{}
// hitnormal := [2]float64{}
lineNX,lineNY := lineX2-lineX1,lineY2-lineY1
// lineMinX,lineMaxX,lineMinY,lineMaxY := math.Min(lineX1,lineX2),math.Max(lineX1,math.Min(lineY1,lineY2),math.Max(lineY1,lineY2)
var lineMinX,lineMaxY float64
if lineNX > 0 {
lineMinX,lineMaxX = lineX1,lineX2
} else {
lineMinX,lineMaxX = lineX2,lineX1
}
if lineNY > 0 {
lineMinY,lineMaxY = lineY1,lineY2
} else {
lineMinY,lineMaxY = lineY2,lineY1
}
r := (rectW/2)*math.Abs(lineNX) + (rectH/2)*math.Abs(lineNY) //radius to Line
BoxProj := (lineX1-rectX)*lineNX + (lineY1-rectY)*lineNY
velProj := rectHSpeed*lineNX + rectVSpeed*lineNY
if velProj < 0 {
r *= -1
}
hitTime := math.Max((BoxProj-r)/velProj,0)
outTime := math.Min((BoxProj+r)/velProj,1)
// log.Println("start",hitTime,outTime)
rectXMax,rectXMin := rectX+rectW/2,rectX-rectW/2
if rectHSpeed < 0 { // left
if rectXMax < lineMinX {
return false,0
}
hitTime = math.Max((lineMaxX-rectXMin)/rectHSpeed,hitTime)
outTime = math.Min((lineMinX-rectXMax)/rectHSpeed,outTime)
} else if rectHSpeed > 0 { // right
if rectXMin > lineMaxX {
return false,0
}
hitTime = math.Max((lineMinX-rectXMax)/rectHSpeed,hitTime)
outTime = math.Min((lineMaxX-rectXMin)/rectHSpeed,outTime)
// log.Println("right",outTime)
} else {
if lineMinX > rectXMax || lineMaxX < rectXMin {
return false,0
}
}
if hitTime > outTime {
return false,0
}
rectYMax,rectYMin := rectY+rectH/2,rectY-rectH/2
if rectVSpeed < 0 { // up
if rectYMax < lineMinY {
return false,0
}
hitTime = math.Max((lineMaxY-rectYMin)/rectVSpeed,hitTime)
outTime = math.Min((lineMinY-rectYMax)/rectVSpeed,outTime)
} else if rectVSpeed > 0 { // down
if rectYMin > lineMaxY {
return false,0
}
hitTime = math.Max((lineMinY-rectYMax)/rectVSpeed,hitTime)
outTime = math.Min((lineMaxY-rectYMin)/rectVSpeed,outTime)
} else {
if lineMinY > rectYMax || lineMaxY < rectYMin {
return false,0
}
outVel[0] = rectHSpeed * hitTime
outVel[1] = rectVSpeed * hitTime
return true,hitTime
}
我还在此处提供了一个带有可执行 UI 的 Gist:https://gist.github.com/KidLinus/3f847c46b0e6dc1addac7252d9cb54ab
我一生都无法弄清楚所有类变量代表什么。我认为其中一些是 Unity 原生的,但这只是猜测。我已经弄清楚了该范围是所述方向上宽度/高度的一半。 “line.n”代表什么是任何人的猜测,我假设它的方向并且不知道它是否被标准化。还有一些死变量就在那里。
我很乐意帮助您完成 Go 中的实现。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。