【发布时间】:2016-11-25 14:24:09
【问题描述】:
我为我正在开发的游戏编写了一个碰撞检测系统,但我遇到了一个奇怪的故障,偶尔会有射弹穿过玩家或散布在整个关卡中的墙壁。因为射弹可以以任意角度发射,所以我将每个射弹的边界框分解为多个较小的边界框,然后根据射弹在空间中的旋转围绕纹理中心旋转这些边界框。出于某种原因,有时长矛射弹会穿过玩家或墙壁,即使其他人不会。
我使用以下方法来确定纹理的旋转并平移边界框:
public double RotateToFaceTarget()
{
double rotation = Math.Atan2((double)_direction.Y, (double)_direction.X);
return rotation;
}
public List<BoundingBox> TranslateBoundingBox(List<BoundingBox> box, double rotation)
{
List<BoundingBox> newBounds = new List<BoundingBox>();
foreach (BoundingBox b in box)
{
Vector2 boundsOrigin = new Vector2(b.Pos.X + b.Size.X / 2, b.Pos.Y + b.Size.Y / 2);
Vector2 texOrigin = new Vector2(_pos.X + _texture.Width / 2, _pos.Y + _texture.Height / 2);
Vector2 newPosBasedOnOrigin = Vector2.Transform(boundsOrigin - texOrigin, Matrix.CreateRotationZ((float)rotation)) + boundsOrigin;
newBounds.Add(new BoundingBox(newPosBasedOnOrigin, b.Size));
}
return newBounds;
}
_direction 是通过从目标位置减去弹丸的位置并归一化来计算的。我使用这种方法来确定弹丸是否与另一个实体发生碰撞:
public bool ProjectileCollision(Entity e, Projectile entity2)
{
if (entity2.CanCollide)
{
foreach(GameObject.BoundingBox b in entity2.BoundingBox)
{
foreach(GameObject.BoundingBox b2 in e.BoundingBox)
{
if (b2.Intersect(b) && (entity2.IgnoredEntities.Contains(e.Type) == false))
{
entity2.IsActive = false;
e.Health -= entity2.Damage;
return true;
}
return false;
}
}
return false;
}
return false;
}
这是我的边界框相交方法:
public bool Intersect(BoundingBox intersected)
{
if ((_pos.Y < intersected.Pos.Y + intersected.Size.Y) && (_pos.Y + _size.Y > intersected.Pos.Y) && (_pos.X + _size.X > intersected.Pos.X) && (_pos.X < intersected.Pos.X + intersected.Size.X))
{ return true; }
return false;
}
编辑:在进一步的测试中,如果玩家基于左上角击中,弹丸似乎总是会检测到击中(现在我查看了我的相交代码,这很有意义)。还有其他方法可以重写我的 Intersect 方法以使用比左上角更准确的东西吗?
EDIT2:我为某些对象绘制了碰撞箱,这是我抓住长矛穿过玩家的一个实例:
玩家是较大的粉红色方块。 hitboxes 没有被正确翻译,但它不应该只是停止工作,对于某些人而不是其他人,对吧?
【问题讨论】:
-
这有时发生在我身上。弹丸的速度是否大于目标的宽度?如果是这样,它可能会在更新循环期间“跳过”。
-
玩家的hitbox为32x32,弹丸的速度最大为15。
-
我能想到一些情况,它跳跃 15 像素会导致它跳过合法的点击,而不是正面,这解释了为什么这种行为有时只会发生。我的直接想法是将要检查的位置拆分为旧位置和新位置的一些切片(例如 10 个),如果要比较的两个事物大致彼此靠近。然后使用 those- 检查弹丸是否会通过
-
它似乎最常发生在大约 45 度(+- 大约 10)的角度,这可以解释这个问题。关于如何解决这个问题的任何建议?
-
在进一步的测试中,如果玩家基于左上角击中,弹丸似乎总是会检测到击中(现在我查看了我的相交代码,这很有意义)。还有其他方法可以重写我的 Intersect 方法以使用比左上角更准确的东西吗?
标签: c# xna monogame bounding-box