更新; -将 j=0 更改为 j=i 允许多达 700 个具有平滑帧速率的粒子
我正在尝试用数百个粒子模拟 2D 水,这些粒子的 Vector2 声明了它们的位置,Vector2 声明了它们的速度。
当谈到碰撞检测时,我的程序不喜欢超过 450 个粒子,尽管只使用毕达哥拉斯定理。
下面是主类中的碰撞检测;
for (int i = 0; i < particleList.Count; i++)
{
for (int j = 0; j < particleList.Count; j++)
{
if (distanceBetween(particleList[i].position, particleList[j].position) < reactDistance)
{
if (particleList[i].position.X > particleList[j].position.X) //x axis
{
particleList[i].velocity.X += repelSpeed;
particleList[j].velocity.X -= repelSpeed;
particleList[i].position.X -= attractSpeed;
particleList[j].position.X += attractSpeed;
}
else
{
particleList[i].velocity.X -= repelSpeed;
particleList[j].velocity.X += repelSpeed;
particleList[i].position.X += attractSpeed;
particleList[j].position.X -= attractSpeed;
}
if (particleList[i].position.Y > particleList[j].position.Y) //y axis
{
particleList[i].velocity.Y += repelSpeed;
particleList[j].velocity.Y -= repelSpeed;
particleList[i].position.Y -= attractSpeed;
particleList[j].position.Y += attractSpeed;
}
else
{
particleList[i].velocity.Y -= repelSpeed;
particleList[j].velocity.Y += repelSpeed;
particleList[i].position.Y += attractSpeed;
particleList[j].position.Y -= attractSpeed;
}
}
}
}
这里是 distanceBetween(v1, v2) 方法;
public float distanceBetween(Vector2 a, Vector2 b)
{
float xDist, yDist, distTo;
if (a.X > b.X) //x axis
{
xDist = a.X - b.X;
}
else
{
xDist = b.X - a.X;
}
if (a.Y > b.Y) //y axis
{
yDist = a.Y - b.Y;
}
else
{
yDist = b.Y - a.Y;
}
distTo = (float)(Math.Sqrt((xDist * xDist) + (yDist * yDist)));
return distTo;
}
Vector2.Distance(v1, v2) 不会产生明显的性能变化。
如果您想知道 attractSpeed 究竟是做什么的;这是我尝试收集水的糟糕尝试。我不确定该怎么做。
最终我想要这样的东西:http://grantkot.com/MPM/Liquid.html
最佳答案
虽然有一些性能方面可以改进,但最终,粒子的存储将使任何努力相形见绌。
您的算法是 O(n^2)
,对于每个粒子,您再次遍历整个粒子列表。对于 n = 700
,这是循环的 700*700 = 490000
执行。此外,许多粒子 i
的检查过于频繁。如果您在 j=i
处开始内部循环,您将获得明显的加速。
然而,这在我看来只是一个创可贴。您应该研究更有效的粒子存储方式,即 Quadtree .
此外,不是为每个距离计算 sqrt,而是将您比较的距离平方:
distTo = (xDist * xDist) + (yDist * yDist);
...
if(distanceBetween(particleList[i].position, particleList[j].position) < reactDistance * reactDistance)
您甚至可以在循环之前预先计算它,这样您就不会每次都有这样的开销。
关于c# - 2D 粒子引擎无法处理超过 450 个粒子。为什么? (新华社),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19743520/