Fluid / gas flow mechanics.

  • I'm trying to simulate fluid / gas mechanics in an array. The centre of the array has a large value, topped up to max constantly and I want it to spread out from that point.

    My first attempt was to run through the array and on each square, test the 4 neighbouring squares to see if they're lower. If they are, the final value of the square + lower neighbours is averaged out, so e.g If this square has 1000 fluid, one neighbouring square has zero (others are higher so ignored), then this square and the lower neighbour now have 500 each.

    This sort of works and does have the advantage that the values 'flow' through the array and around objects. But it also has 2 problems.

    Firstly, if I just run through the array with a foreach, it goes top-to-bottom/left-to-right and there's an obvious bias in certain directions.

    Secondly, and more fatally, some of the outside edges never receive anything, even if I use standard values with lots of decimal places. They don't even receive a tiny fraction. So somewhere along the way, the math obviously balances out and the flow is no longer pushing 'forwards'.

    One solution that I can think of in my head is to even out every square that's connected, all at the same time. Problem is, working out which squares are connected would probably require some sort of searching algorithm and I don't know how that would work. Plus that would lose the 'flow' feel, which I like.

    Any ideas?

  • My guess on the outside squares is that, because there aren't squares to one (or two) sides, the math is breaking down and they aren't receiving anything. You mention your code is testing all 4 neighbors for a given square, but the edge pieces only have 3 neighbors, and the corners only have 2. Without being able to look at your code, I might guess that something's breaking there.

    Also, to avoid the bias issues you're talking about, fluid simulations typically work in "passes", from what I understand. They don't modify the array values one-by-one, but calculate the ENTIRE array and then use those results. I don't know if they'd use 2 arrays or a 3D array with the Z-axis representing the "current" and "next" values for each square. Typically these simulations are using something more advanced than just averaging two squares, though. They'll use something like Navier-Stokes, which involves a bit of calculus, but is pretty easy to find example code for in any language (even javascript!)

    An example web-app using that method is at https://www.esimov.com/experiments/javascript/fluid-solver-mono/. That guy has a link to his blog where he talks about coding it, as well, so you may be able to get an idea of the method used there.

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • I don't think that's the issue with the edge squares, because with C3, if there is nothing on a condition, it just skips the condition. So my code first counts any squares which have a lower amount than 'this' square, then averages them out. That works the same on an edge square.

    But yes, it does look like it requires some kind of entire-map calculation and my method probably isn't going to work, even if I 'correct' it. I'll take a look at the ideas you suggested and some pre-existing code. Thanks.

  • The navier stokes equation is how this is usually done. There are some javascript versions. This may be a bit much but it also might give you some ideas.


  • Thanks. I think the full equations are unnecessarily complex for my needs. I think my method has two main issues, firstly, I need to take a snapshot of the grid before any calculations and use those values, as suggested. Secondly, averaging out the squares is probably why it eventually locks up, because outer squares pass values back inwards as those inner squares start to empty out. So I think it ends up in a kind of equilibrium. So it probably needs to be weighted somehow so that the source doesn't empty to the level of the destination, so that it should keep 'flowing' in that direction. I'll play around with it, thanks for the ideas.

  • Got this working in the end. Definitely needs a copy of the values to use during the loop and the rest was just fiddling around with C3 arrays, which are super-fiddling imo :)


Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)