So, for the past couple of weeks, I've been working on a falling sand simulation inspired by games such as The Powder Toy, Noita, and Sandspiel. I've been making it in Love2D and I'm please with what I got so far. The simulation can handle 59k particles at 60FPS however pretty much anything over that amount will cause the FPS to plummet so I've been thinking of other ways to optimize it.
The way my simulation works is that I have a large table that contains numbers. These numbers refer to an index inside a table which contains particle data. The particle data is structured as:
Name, Color(table containing 4 values, r,g,b,a), Update logic function, Color variation modifier (0 = no color variation between particles)
I've got the options for optimization narrowed down to a pretty small list:
- Spatialhashing/Quadtree - splitting the screen into a grid and only updating cells with particles in it
- GPU simulation - Moving simulation logic to the GPU
- Multithreading - Moving simulation logic to separate CPU threads
The downsides of all of these are as follow:
Spatialhashing/Quadtree - There are no unique identifiers for the particles themselves as they're only stored in the table as the index for their data so it's hard to have a reference that can be added/removed when needed
GPU simulation - I'm not good with shader code and there are no good ways to do GPU code in Love2D that's purely computational.
Multithreading - Similar to GPU simulation, I'm not knowledgable when it comes to multithreading nor do I have any idea of how to parallelize my simulation code.
Some information about how to multithread a falling sand physics simulation comes from the devs of Noita, where they split the world into chunks and updated each on a different thread in a checkerboard pattern (to make ensure that pixels weren't being updated by multiple threads at the same time). They also had 'dirty rects' which showed which particles needed updating which is similar to spatial hashing.
However, the talk the noita dev did just showed what they did, rather than how they did it. Since I lack a lot of knowledge in these fields, I don't really have much to go on for implementing them.
My code is open source and viewable on github. You'll need the latest version of Love2D to run it:
https://github.com/BradBath/Sand (either drag the Sand-master folder on the love2D executable or open the folder in VSCode and use the Love2D plugin to run it via LALT+L)
If anyone has any ideas I could implement some of these optimizations, or has any other ideas for optimization, I'd love to hear them. Thanks!