好吧,今天我决定尝试进一步优化我的磁贴引擎的碰撞检测代码。
这就是我所做的:
Circle类检查范围内是否有点。如果有,则检查播放器和磁贴之间的冲突。
代码:
int tileWidth = 128;
int tileHeight = 128;
int[,] Layer3 = { 1, 1, 1, etc... };
int tileMapWidth = Layer3.GetLength(1);
int tileMapHeight = Layer3.GetLength(0);
Rectangle tile, tile2;
for (int x = 0; x < tileMapWidth; x++)
{
for (int y = 0; y < tileMapHeight; y++)
{
int wallIndex = Layer3[y, x];
if (wallIndex == 1) //Full-sized Tile Collision (128 x 128)
{
if (collisionCircle.Contains(new Vector2(x * tileWidth + (tileWidth / 2) + (int)Player.camera.Position.X,
y * tileHeight + (tileHeight / 2) + (int)Player.camera.Position.Y))) //+ tile / 2 is for centering the point
{
tile = new Rectangle(x * tileWidth + (int)Player.camera.Position.X, y * tileHeight + (int)Player.camera.Position.Y, tileWidth, tileHeight);
Collide(tile);
}
}
}
}
这将检查整个第3层是否有&#34; 1&#34;。如果有,请指定矩形,如果点位于碰撞半径内,则检查碰撞。
另外,我检查了这段代码(使用绘制方法),我知道它正常工作,至少是行为。
我添加了大约120,000(32 x 3888)个磁贴,试图让它延迟,在代码之前,它稍微滞后了。但是在我添加代码后,它更加滞后。
我认为,因为它只检查半径范围内的瓷砖(点)之间的碰撞,它甚至不会远程滞后,但事实并非如此......
关于如何优化这一点的任何帮助/想法都会很棒。
非常感谢, Shyy
编辑:
Cirlce.Contains()代码:
public bool Contains(Vector2 Point)
{
return ((Point - position).Length() <= radius);
}
我使用了一个圆圈,因为我听说它比使用矩形更快。
答案 0 :(得分:1)
另一种可能的优化是代替
return ((Point - position).Length() <= radius);
使用
return ((Point - position).LengthSquared() <= radius * radius);
这更快,因为Vector2.Length()
必须执行昂贵的平方根操作。 Vector2.LengthSquared()
不必执行那么慢的操作。半径必须与自身相乘,以考虑矢量平方的长度。
听起来你正在尝试确定哪些瓷砖不需要用来与玩家发生碰撞。您可以做的另一个优化是,如果(X = 5,Y = 5)的图块位于播放器的上方和左侧,则您不需要在(X = 4,Y = 4)处检查图块。类似地,如果(X = 5,Y = 5)低于和向右,则(X = 6,Y = 6)也保证太远。尝试确定何时通过播放器,不再需要检查碰撞。
答案 1 :(得分:0)
我建议仅在屏幕上的可见平铺上循环,以使用移动偏移检查碰撞。 我会尝试一些东西......
for x as integer = 0 + offSetX to tilesInWidth + offSetX
for y as integer = 0 + offSetY to tilesInHeight + offSetY
if player.insideCircle(player.position, radius) '
object = layer(y,x);
if player.collideWith(object) then Collide()
end if
next
next