如何解决二维 AABB 碰撞解决多角问题 C#
我已经研究了几天,但似乎无法做到完美。我正在制作一个自上而下的程序生成冒险游戏,我的碰撞解决系统有一些不足之处。
问题:
尝试在 2 个通常不允许您进入的碰撞箱之间移动,如果您正在对角移动,则可以进入,这可能导致无限循环,其中碰撞永远不会从碰撞解决列表中删除(罕见),或暂时允许您在实体碰撞箱内自由走动(最常见的效果)。
奇怪的部分是其他角落情况正确解决,即如果没有间隙,您不会剪辑,并且您可以沿着任何固体hitBox向任何方向滑动而不会“抓住”或任何东西,如果旁边有2彼此。 事实上这似乎只发生在你试图通过的间隙比你的hitBox小一个像素时,所以我猜发生的是当碰撞在帧的开头,只有 2 个碰撞箱中的一个被添加,当它解决时,它会将您推入另一个。我不知道如何解决这个问题,因此非常感谢您的帮助。
演示问题的视频:
public void Collide(float newX,float newY,List<GameObject> colObj,int seed,GraphicsDeviceManager graphics,Player p) {
//newx is intermediatePosition + float value of controller left stick X
//newy " " Y
//colObj is a list of gameobjects that are collidable that are within a certain distance to the player (possible collisions)
var fr = new Rectangle((int)Math.Round(newX) + p.bbofsx,(int)Math.Round(newY) + p.bbofsy,p.boundingBox.Width,p.boundingBox.Height);
for (int i = 0; i < colObj.Count; i++) {
if (fr.Intersects(colObj[i].boundingBox)) {
colObj[i].distancetoPlayer = (int)AABB.GetdistanceSquared(fr,colObj[i].boundingBox);
p.collisionsToResolve.Add(colObj[i]);
}
}
//order list
p.collisionsToResolve = p.collisionsToResolve.OrderBy(o => o.distancetoPlayer).ToList();
for (int w = 0; w < p.collisionsToResolve.Count; w++) {
//overworld collision code
var side = AABB.GetCollisionSide(p.boundingBox,p.collisionsToResolve[w].boundingBox,new Vector2((float)Math.Round(newX) - p.worldPosition.X,(float)Math.Round(newY) - p.worldPosition.Y));
switch (side) {
case CollisionSide.Left:
while (fr.Intersects(p.collisionsToResolve[w].boundingBox)) {
newX--;
p.intermediateWorldPosition.X = p.worldPosition.X;
fr = new Rectangle(p.boundingBox.X + (int)((float)Math.Round(newX) - p.worldPosition.X),p.boundingBox.Y + (int)((float)Math.Round(newY) - p.worldPosition.Y),p.boundingBox.Height);
}
break;
case CollisionSide.Right:
while (fr.Intersects(p.collisionsToResolve[w].boundingBox)) {
newX++;
p.intermediateWorldPosition.X = p.worldPosition.X;
fr = new Rectangle(p.boundingBox.X + (int)((float)Math.Round(newX) - p.worldPosition.X),p.boundingBox.Height);
}
break;
case CollisionSide.Top:
while (fr.Intersects(p.collisionsToResolve[w].boundingBox)) {
newY--;
p.intermediateWorldPosition.Y = p.worldPosition.Y;
fr = new Rectangle(p.boundingBox.X + (int)((float)Math.Round(newX) - p.worldPosition.X),p.boundingBox.Height);
}
break;
case CollisionSide.Bottom:
while (fr.Intersects(p.collisionsToResolve[w].boundingBox)) {
newY++;
p.intermediateWorldPosition.Y = p.worldPosition.Y;
fr = new Rectangle(p.boundingBox.X + (int)((float)Math.Round(newX) - p.worldPosition.X),p.boundingBox.Height);
}
break;
}
p.UpdateBoundingBox();
for (int i = 0; i < colObj.Count; i++) {
if (fr.Intersects(colObj[i].boundingBox)) {
p.collisionsToResolve.RemoveAt(w);
colObj[i].distancetoPlayer = (int)AABB.GetdistanceSquared(p.boundingBox,colObj[i].boundingBox);
p.collisionsToResolve.Add(colObj[i]);
p.collisionsToResolve = p.collisionsToResolve.OrderBy(o => o.distancetoPlayer).ToList();
w = 0;
}
}
var done = true;
for (int i = 0; i < p.collisionsToResolve.Count; i++) {
if (fr.Intersects(p.collisionsToResolve[i].boundingBox)) {
done = false;
break;
}
}
if (done) {
break;
}
}
//move player and update bounding Box
p.worldPosition.X = (float)Math.Round(newX);
p.worldPosition.Y = (float)Math.Round(newY);
p.UpdateBoundingBox();
}
解决方法
如果这对其他人有帮助,我想出了解决它的方法,而不是尝试解决新位置(x 和 y)的碰撞,首先解决新的 x 位置,然后是 y 位置(或反之亦然)。您可以根据 2 个边界框的位置动态选择首先解析哪个轴。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。