简述

这是一种模拟粒子移动以及粒子交互的方式,在游戏 Noita 中使用了此方式来模拟沙子及其它粒子,在这儿可以找到在线示例。

开始

此模拟方式的本质是一个元胞自动机,每个粒子按照特定规则更新。

在此示例中,演示了在 2D 空间中的模拟情况。在此将世界视为一个二维网格,每个网格都可以包含一个粒子,可以使用二维矩阵来表示它。

可以使用如下结构体来表示粒子:

struct Particle {
  uint8_t type;
  uint8_t density;
  vec2 velocity;
  bool isLiquids;
  bool updated;
  ...
}

为了实现过程,需要遍历网格并更新:

for (int y = 0; y < elements.height; y++) {
  for (int x = 0; x < elements.width; x++) {
    Particle p = & elements[x][y];
    if (p.updated) continue;
    if (p.type == 0) continue;
    if (p.type == TYPE_SAND) emulateSand(x, y);
    ...
  }
}

粒子

沙子:规则

sand_rule

水:规则

优化

在每次更新中迭代整个网格性能较低,为了解决此问题,可将世界分成若干小块,并根据需要激活/更新更新块