【问题标题】:Collision handling in a JavaScript/canvas particle systemJavaScript/canvas 粒子系统中的碰撞处理
【发布时间】:2013-10-15 06:49:42
【问题描述】:

我在 JavaScript 中有一个基本的粒子系统(使用画布进行渲染),我正在尝试找到处理粒子之间碰撞的最佳方法。粒子系统可以以相当不错的 FPS 处理大约 70,000 个粒子。

它由一个包含每个 Particle 对象的数组组成。 每个 Particle 对象包含 3 个 Vector 对象(一个用于位移、速度和加速度),其中包含一个 x 和一个 y 变量。 在每一帧之前,加速度矢量应用于速度矢量,速度矢量应用于每个粒子对象的位移矢量。 然后渲染器遍历每个粒子,然后在每个位移向量的位置绘制一个 1x1 像素的正方形。

粒子系统也有“磁场”,它可以使粒子加速朝向/远离给定点。

我尝试对每个粒子应用“磁场”,但用于获取每个粒子的更新加速度矢量的计算效率太低,而且这种方法大大降低了 FPS。

下面是我用来重新计算粒子加速度矢量的代码,相对于附近的磁场(这个函数在每一帧之前调用):

Particle.prototype.submitToFields = function (fields) {
    // our starting acceleration this frame
    var totalAccelerationX = 0;
    var totalAccelerationY = 0;

    // for each passed field
    for (var i = 0; i < fields.length; i++) {
        var field = fields[i];

        // find the distance between the particle and the field
        var vectorX = field.point.x - this.point.x;
        var vectorY = field.point.y - this.point.y;

        // calculate the force via MAGIC and HIGH SCHOOL SCIENCE!
        var force = field.mass / Math.pow(vectorX*vectorX+vectorY*vectorY,1.5);

        // add to the total acceleration the force adjusted by distance
        totalAccelerationX += vectorX * force;
        totalAccelerationY += vectorY * force;
    }

    // update our particle's acceleration
    this.acceleration = new Vector(totalAccelerationX, totalAccelerationY);
}

很明显,为什么上述方法会大幅降低性能 - 每添加一个新粒子,计算次数就会呈指数增长。

是否有另一种粒子碰撞检测方法对数千个粒子具有良好的性能?这些方法是否适用于我当前的对象结构?

【问题讨论】:

  • 粒子系统本身就非常消耗资源,如果你另外对 70k+ 粒子进行碰撞检测,恐怕 JavaScript 对你没有多大帮助。即使使用宏观优化(在这种情况下可能很重要),您也会看到性能问题。通常,这些东西是使用低级代码(汇编程序或 c/c++)结合硬件加速 3D 卡制作的 - 有时必须渲染一些东西(这在专业视频世界中是正常的)。您可以评估是否愿意在粒子数量上做出妥协,我认为这是最好的机会..
  • 如果可能的话,我建议你为我们提供一个我们可以玩的小提琴并进行一些优化,我们可以从那里看到结果(即使它会根据硬件配置而变化) )

标签: javascript canvas physics physics-engine particle-system


【解决方案1】:

不要在这里创建一个新的向量。这意味着您每帧创建 70 000 个新向量。只需更改向量值:

this.acceleration.x = totalAccelerationX; // or : this.acceleration[0] = totalAccelerationX;
this.acceleration.y = totalAccelerationY; // or : this.acceleration[1] = totalAccelerationY;

如果它没有足够的帮助,您将不得不使用 WebWorker。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    相关资源
    最近更新 更多