gpt4 book ai didi

java - 有效地绘制大量粒子

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:02:55 25 4
gpt4 key购买 nike

我写了一个粒子系统小程序;目前我正在创建并分别绘制每个粒子。(这里是代码)

BufferedImage backbuffer;
Graphics2D g2d;

public void init(){
backbuffer = new BufferedImage(WIDTH,HEIGHT,BufferedImage.TYPE_INT_RGB);
g2d = backbuffer.createGraphics();
setSize(WIDTH, HEIGHT);

//creates the particles
for (int i = 0; i < AMOUNTPARTICLES; i++) {
prtl[i] = new particleO();
prtl[i].setX(rand.nextInt(STARTX));
prtl[i].setY(rand.nextInt(STARTY));
prtl[i].setVel(rand.nextInt(MAXSPEED)+1);
prtl[i].setFAngle(Math.toRadians(rand.nextInt(ANGLESPREAD)));

}

//other code
}



public void update(Graphics g) {

g2d.setTransform(identity);

//set background
g2d.setPaint(BGCOLOUR);
g2d.fillRect(0,0,getSize().width,getSize().height);
drawp();
paint(g);
}


public void drawp() {

for (int n = 0; n < AMOUNTPARTICLES; n++) {

if (prtl[n].getAlive()==true){
g2d.setTransform(identity);
g2d.translate(prtl[n].getX(), prtl[n].getY());
g2d.setColor(prtl[n].getColor());

g2d.fill(prtl[n].getShape());


}
}

}

它的性能还不错,我可以用 20,000 个粒子获得大约 40FPS(尽管我有一台不错的笔记本电脑)。但是在我添加了碰撞检测之后(见下文),这个数字直线下降到不到 2000,

public void particleUpdate(){
for (int i = 0; i < AMOUNTPARTICLES; i++) {
//other update code (posx, posy, angle etc etc)

for (int j = 0; j < AMOUNTPARTICLES; j++) {

if (i!=j && prtl[j].getAlive()==true){

if(hasCollided(i, j)){
prtl[i].setcolor(Color.BLACK);
prtl[j].setcolor(Color.BLACK);
}
}
}

public boolean hasCollided(int prt1, int prt2){

double dx = prtl[prt1].getX() - prtl[prt2].getX();
double dy = prtl[prt1].getY() - prtl[prt2].getY();
int edges = prtl[prt1].getRadius() + prtl[prt2].getRadius();

double distance = Math.sqrt( (dx*dx) + (dy*dy) );
return (distance <= edges);


}

我已经搜索了很多将粒子绘制到屏幕上的更好方法,但这些示例要么让我感到困惑,要么不适用。

我正在进行大量计算(太多)。但我想不出其他方法,欢迎提出建议。

最佳答案

首先,添加诸如碰撞检测之类的东西总是需要大量内存。但是,让我们看看您的碰撞检测算法

public void particleUpdate(){
for (int i = 0; i < AMOUNTPARTICLES; i++) {
//other update code (posx, posy, angle etc etc)

for (int j = 0; j < AMOUNTPARTICLES; j++) {

if (i!=j && prtl[j].getAlive()==true){

if(hasCollided(i, j)){
prtl[i].setcolor(Color.BLACK);
prtl[j].setcolor(Color.BLACK);
}
}
}

假设只有 2 个粒子,1 和 2。您将按顺序检查1,11,22,12,2

事实是,在这种情况下,您真的只需要检查 1 对 2。如果 1 击中 2,则 2 也将击中 1。因此请更改之前测试过的 for 循环跳过,并为此更改相同的数字。

public void particleUpdate(){
for (int i = 0; i < AMOUNTPARTICLES; i++) {
//other update code (posx, posy, angle etc etc)

for (int j = i+1; j < AMOUNTPARTICLES; j++) {

我注意到的另一件事是您进行了 sqrt 操作,但只是为了与看起来像静态数字的内容进行比较。如果你删除它,并将它与数字的平方进行比较,你会得到很大的改进,尤其是对于你经常做的事情。

    double distance_squared = ( (dx*dx) + (dy*dy) );
return (distance <= edges*edges);

继续寻找这样的改进。然后您可能会仔细查看其他选项,例如使用不同的类、线程等,这些都可能会改进系统。但是请确保先在可以优化的地方优化代码。这是我会尝试的其他事情的列表,大致按顺序排列。

  1. 在 i 进入视野后计算任何其他东西之前,先检查一下粒子 i 是否还活着。
  2. 快速浏览两对,如果它们很接近,甚至不会费心去详细检查。一种简单的方法是先检测它们是否在 x 和 y 维度内,然后再进行 sqrt 操作。始终先进行成本最低的测试,然后再进行复杂的测试。
  3. 查看您的代码,看看您是否真的使用了所有计算出的值,或者您是否能够以某种方式减少操作次数。
  4. 也许您可以定期对图像进行粗略的聚类,然后仅细化通过初始聚类一段时间的对象,然后执行粗略的聚类算法。
  5. 您可以线程化碰撞检测。但是,如果您打算这样做,您应该只对检查进行线程化以查看是否发生了碰撞,并在所有这些线程完成后,更新 View 上的对象。
  6. 研究替代架构,这可能会加快速度。

关于java - 有效地绘制大量粒子,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13521368/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com