【发布时间】:2012-03-17 18:13:14
【问题描述】:
我这里有很多代码,但是比较简单。
这都是来自不同类的所有 sn-ps,所有引用都是正确的,但我想我在某处犯了一个基于数学的错误,我找不到它。它总是在 y 轴上发现一个像素之前的碰撞。我还没有尝试过使用不同的 X 轴位置,但它似乎可以通过它旁边的块。
结构“mapSection”只包含两个Vector2s-左上块和左下块坐标。
tileManager.def_ts 是默认的 tile 宽度和高度 (32)。播放器的尺寸为 32x64。
toWorldSpace 函数现在除了返回之外什么都不做,所以这不是问题。
当我说块坐标时,我的意思是块在图块数组中的哪个索引(例如 0、0 是第一个块,0、1 是 Y 轴上的第二个块,1、3 是第一个块在X轴和Y轴上的3,我不是指实际像素。)
来自磁贴引擎类:
public mapSection toMapMinMax(Vector2 position, Vector2 size)
{
position = toWorldSpace(position);
position.X = (float)Math.Floor(position.X / tileManager.def_ts);
position.Y = (float)Math.Floor(position.Y / tileManager.def_ts);
size.X = (float)Math.Floor(size.X / tileManager.def_ts);
size.Y = (float)Math.Floor(size.Y / tileManager.def_ts);
return new mapSection(position, position + size);
}
public bool collision(Vector2 screenPosition, Vector2 size)
{
mapSection mapCollisionPossibilities = toMapMinMax(screenPosition, size);
for (int y = (int)mapCollisionPossibilities.topLeft.Y; y <= mapCollisionPossibilities.bottomRight.Y; y++)
{
for (int x = (int)mapCollisionPossibilities.topLeft.X; x <= mapCollisionPossibilities.bottomRight.X; x++)
{
if (x >= 0 && y >= 0 && y < tiles.Count && x < tiles[y].Count)
{
if (tileManager.tileTypes[tiles[y][x]].collideable == true)
{
return true;
}
}
}
}
return false;
}
这是播放器类的代码:
if (!tEngine.collision(position + new Vector2(0, 1), new Vector2(32, 64)))
{
position.Y += 1;
}
我添加了“Vector2(0, 1)”,因为我想看看在更下方的像素是否存在碰撞;这样他就会跌倒,直到撞到什么东西。它现在非常基本,但它只是为了测试碰撞引擎,它不起作用。
有错误的图片。你可以看到播放器的像素太高了。
图中“X:”为X轴左上块坐标,“X2:”为X轴右下块坐标,与“Y:”和“Y2:”相同,除了Y 轴。直接从 mapSection 中读取。
如果有人能注意到为什么会发生这种情况,我们将不胜感激。
谢谢。
如果您无法理解代码的任何部分,请在 cmets 中发布,我会很乐意解释,或者如果您认为我在这篇文章的某些方面过于不具体。
【问题讨论】:
-
这个问题本质上只是视觉问题,还是数字也相差 1?这可能是由许多原因引起的,包括图形图像有额外的行、不减去 1 的高度计算、应该是
-
toMapMinMax 会过早返回下一个图块一个像素,这可能是一个舍入问题。随着 Y 值的增加,您需要逐步执行 toMapMinMax,并确认它每次都返回正确的图块坐标。
-
在 toMapMinMax 中,您可能应该在执行计算之前对位置和大小进行舍入,方法是转换为整数或使用 Math.Round
-
您的碰撞代码和绘制代码必须采用不同的舍入方式。即使您的碰撞代码关闭了一个像素,您也不会注意到您的绘制代码是否也关闭了。要么你碰撞得太快,要么你画得太高了。 (可能)
-
“我只在位置上加 1”浮点数不保证那么准确。例如,您可以添加 18 + 1,得到 18.99999999999。 Math.Floor 会将其变为 18,而您的绘制代码可能会绘制为 19。
标签: c# xna collision-detection