我创建了一个可以操纵球的项目。我有些问题不知道怎么解决。我正在使用处理。
在我的项目中,圆相互碰撞。在这一点上,为了检查对象是否相互碰撞,我检查了所有的对象,这是非常欠优化。我想通过创建一个netforcircu类来改进这一点,在这个类中,我将对象放在一起,只比较那些靠得很近的对象。我的主要问题是,如果圆在网格的不同部分有一个圆心,那么在网格中插入对象是不起作用的。另外,如果窗口大小改变,我也不知道如何改变网格大小。
void checkForCollision()
{
for (int i = 0; i<cir.size() -1; i++)
{
for (int j = i + 1; j<cir.size(); j++)
{
//calculating distance between object
PVector lengthFrom_i_to_j= PVector.sub( cir.get(j).point, cir.get(i).point);
float oldDist = lengthFrom_i_to_j.mag();
float min_dyst = cir.get(j).radius + cir.get(i).radius;
//checking for collision
if (oldDist <= min_dyst)
{
collision(cir.get(i), cir.get(j), oldDist, min_dyst, lengthFrom_i_to_j);
}
}
}
}
void collision(Circum con1, Circum con2, float dist_, float min_, PVector lock)
{
float u1, u2, distance = dist_, min_dyst = min_;
//static collision
float distanceCorrection = (min_dyst-distance)/2.0;
PVector correctionVector = lock.normalize().mult(distanceCorrection);
con2.point.add(correctionVector);
con1.point.sub(correctionVector);
//dynamic collision
// Defining the X axis
PVector dirX = lock.copy();
dirX.normalize();
// Defining the Y axis
PVector dirY = new PVector(dirX.y, -dirX.x);
// X coordinates of velocities
float vx1 = dirX.dot(con1.velocity);
float vx2 = dirX.dot(con2.velocity);
// Y coordinates of velocities
float vy1 = dirY.dot(con1.velocity);
float vy2 = dirY.dot(con2.velocity);
// Applying the collision to X coordinates
u1 = (2 * vx2 * con2.mass + vx1 * (con1.mass - con2.mass)) / (con1.mass + con2.mass);
u2 = (2 * vx1 * con1.mass + vx2 * (con2.mass - con1.mass)) / (con1.mass + con2.mass);
// Turning velocities back into vectors
PVector vel1 = PVector.mult(dirX, u1);
PVector vel2 = PVector.mult(dirX, u2);
vel1.add(PVector.mult(dirY, vy1));
vel2.add(PVector.mult(dirY, vy2));
con1.velocity = vel1;
con2.velocity = vel2;
}
class NetForCircum {
int cell = 8;
PVector size = new PVector(0, 0);
IntList[][] objectsInCell = new IntList[cell][cell];
NetForCircum(ArrayList<Circum> cir)
{
size.x = width/cell;
size.y = height/cell;
for (int i = 0; i<cell; i++)
{
for (int j = 0; j<cell; j++)
{
objectsInCell[i][j] = new IntList();
}
}
for (int i = 0; i<cir.size() - 1; i++)
{
float pozLeft = cir.get(i).point.x - cir.get(i).radius, pozRight = cir.get(i).point.x + cir.get(i).radius, pozUp = cir.get(i).point.y - cir.get(i).radius, pozDown = cir.get(i).point.y + cir.get(i).radius;
for (int j = 1; j<=cell; j++)
{
for (int k = 1; k<=cell; k++)
{
float curentSizeX = size.x * j, curentSizeY = size.y * k, previousSizeX = size.x * (j - 1), previousSizeY = size.y * (k - 1);
if ((pozLeft>previousSizeX && pozRight<curentSizeX && pozUp>previousSizeY && pozDown<curentSizeY) || (cir.get(i).point.x>previousSizeX && cir.get(i).point.x<curentSizeX && cir.get(i).point.y>previousSizeY && cir.get(i).point.y<curentSizeY))
{
cir.get(i).cellNumber.add(new PVector(j, k));
cir.get(i).cellBorderX.set(previousSizeX, curentSizeX);
cir.get(i).cellBorderY.set(previousSizeY, curentSizeY);
objectsInCell[j-1][k-1].append(i);
}
}
}
}
}
}
2条答案
按热度按时间1u4esq0p1#
除了@rabbid76的优秀答案之外,我还建议避免两次循环(例如检查i和j,然后检查j和i):
很多年前,我从基思·彼得的《让事情在动作脚本中移动》中学到了这一点,在这本书中,每一点表现都很重要。还要注意如何只访问一次对象属性,并将其缓存到局部变量中以供重用。这是另一个习惯,因为访问actionscript(或javascript)虚拟机中的嵌套数据(getter)代价高昂。java虚拟机可能效率更高一些,这可能不是必需的。
我还强烈建议将优化放在最后,并使用visualvm等分析工具来确定要优化的内容。你所指出的是一个很好的候选人,但可能还有其他地方需要研究。从最慢的开始,剩下的你可能需要触摸。
例如,基于pastebin代码,圆和线的渲染看起来有点慢。你可以考虑使用
PShape
/createShape(ELLIPSE)
以及“处理>示例>演示>性能”中的粒子示例wxclj1h52#
一种廉价的优化方法是比较距离的平方,而不是距离。为了计算欧氏距离,需要平方根:
即使在今天的计算机上,计算平方根也是非常昂贵的。对于距离的平方,不需要平方根:
使用
magSq()
而不是mag()
把它和min_dyst*min_dyst
而不是min_dyst
: