Slow Rush Studios logo,
    depicting an apprehensive-looking snail rushing forward

Slow Rush Studios

◂  Particles, for real this time
News index
Designing a Magic System  ▸

Playing Nice with Moving Bodies

Contents

This week, atoms finally play nice with moving bodies thanks to last week's particles.

That means you can fling a moving body into water and the water makes a little wave, and moving bodies & players don't have their movement blocked by falling sand anymore! (Oh, also, atom movement is vaguely plausible again, unlike last week - yay!)

There was a lot of fiddling to get this all somewhat working, so let's get our feet wet.

Debug log console

If I printed out all the code responsible for moving atoms, it'd have about the same page count as the average curriculum-mandated book for a 3rd grader - it's far too big to run it all in my head for more than one atom at a time.

So to find bugs in it, I do what programmers call "print line debugging": whenever anything happens, it writes a message to a log. Then when things go wrong, I read the logs to work out what happened to & figure out what programming mistake I made.

Screenshot of a large amount of mostly inscrutable output
Example logs for two particles for one logic update. The other 60ish particles are another 600+ lines... and you can mentally multiply that by another 60 updates per second to get the output per second of gameplay.

Reading this output is tricky because usually I am focused on specifically why one atom behaved oddly, and updates for it are many screens of log lines apart. Yet I also need the other atoms' logs to understand where they were, deduce the update order of atoms (a topic for another time), etc - so I can't fully turn off their logs.

So I made a little in-game debug console that lets me filter the logs for a play session down to just a particular atom:

Debug log console in action; I can click the frame or debug ID columns to time travel to that frame or filter for that atom

It's integrated with last week's time travel feature so that it only shows log entries up to the current point in time, and I can click a frame number on the left to time travel & see what the game looked like at that point in time. While I was at it, I also accidentally made the game better at handling high volumes of log output.1 2

Better atom movement

Using the debug log console, I fixed the "atoms are drifting to the right as if by wind" bug (a stupid rounding error on my part), so atom movement is now sane-ish again:

When I shoot sand atoms ~45 degrees from upwards and they hit the roof, they no longer drift uncontrollably to the right!

Atoms still lose too much horizontal velocity when they hit the roof, but it's better!

I also made bouncing for solid materials a bit better; here are some "bricks" bouncing in a very un-brick-like fashion:

Yes, I know bricks don't bounce this much in real life.

Again, the bouncing isn't perfect, but I'm not sure yet whether "perfectly physically accurate" collisions and bouncing will actually matter in the game.

Moving body water splashes, powered by particles

With particles that move sanely (from last week) and atoms that also move sanely, I also finally made moving bodies splash water around:

When a moving body tries to occupy a spot taken by a water atom, it gets turned into a particle and flung into the air.

The flinging is pretty naive because it always flings particles in the direction of "up plus the horizontal velocity of the (particular point on the) body that hit the water". This looks good as long as water is flat but can look a little odd when the water is moving horizontally:

Here the water is moving right and the moving body hits it at twice the speed the water moves. You wouldn't expect the water to move upwards at all: it should just be flung further to the right. But again, it might not matter for the game in practice - we shall see.

The body also isn't slowed down by the water yet, and also can't be buoyed by the water. The former is easy to fix (apply a force to the body at the point that is displacing the water) but I'm still thinking about how to do the latter without making performance drop off a cliff.

Moving bodies get crushed by atoms even less

So if a water atom gets flung out of the way, we can just do the same with sand atoms that are in the way, right?

Unfortunately not, unless you want to create quicksand: it would make the moving body sink into a sand pile. That's why we create fixed colliders for the sand instead; we want the body to be stopped by the sand.

But when sand is falling, it's terrible to have a body bouncing off a single (or many) grains of falling sand, and even worse to have a single grain of sand crush a body into the ground.

One fix is to say that movable atoms with velocity greater than 0 are excluded from fixed collider generation - but in practice this doesn't work because some of the atom movement code occasionally overrides the velocity (that's how sand moves diagonally sometimes).

And last week I tried a quick semi-fix that said "if an atom moved in its last update, then it can't be a collider". But if you have a whole group of atoms in the air then the ones at the top sometimes are stationary for a bit, as they wait for the atoms below them to move - and having them block moving bodies still feels bad.

Grounding atoms

To fix this, I dreamed up an algorithm which I call "Grounding":

Then, only Grounded atoms contribute to the collider generation, which means that falling atoms will never create colliders, and atoms that aren't Grounded can just be flung out of the way as particles.

Diagram showing grounding algorithm in action
Example with sand: the red atoms are ungrounded because at least one possible destination (orange arrow) is ungrounded.

The catch is that an atom that's on top of a moving body needs to also count as being Grounded, otherwise a pile of sand that's resting on a moving body wouldn't generate a collider, which means that a second body hitting that pile of sand would go straight through it.

However, colliders are generated from simplified shapes roughly based on the atoms - so atoms that rest on a moving body can create colliders that intersect with the moving body and cause it to wobble weirdly:

Here you can see various points where sand atoms resting on the moving body cause it to get pushed down strangely

Semi-grounding

I experimented with allowing some space around the colliders, but that caused some odd gaps.

So instead I introduced a Semi-Grounded state: an atom is Semi-Grounded if one of the places it could move to is currently occupied by a moving body.

Atoms that are grounded via Semi-Grounded atoms are themselves (regular) Grounded, so a Semi-Grounded atom basically means "an atom that's resting stably on a moving body".

Diagram showing semi-grounding
Here you can see a moving body in light blue (along with the positions it occupies) and the Semi-Grounded atoms sitting on top of it in dark blue.

Having that distinction allows treating them differently:

The last piece of the puzzle is accounting for movement of the body itself: if a body is moving quickly, then we shouldn't treat any atoms as being semi-grounded via that body.3

Results

After all that, body and atom interaction is much more reasonable:

Dropping atoms on bodies and moving bodies into atoms works as you'd expect now. Previously, bodies with sand on it would have been pinned in place immovably, and dropping atoms on bodies would push the bodies through the floor!

It still glitches out a little in some circumstances (but hey, so does Noita's implementation!), and there's a bit of tuning left to do for atoms that get flung out of the way to make it look a bit more realistic.

Here's a zoomed in demo, with a Grounding debug visualization turned on:

Bright green atoms are fully Grounded and purple atoms are Semi-grounded.

Still to do

There's one big remaining glitch that's really easy to trigger:

If you enclose a moving body completely in sand, it will almost immediately 'explode out' and fling sand everywhere. (The red lines are a debug overlay showing the collider generated for the sand - see below)

What's happening?

  1. The collider generation algorithm I'm using doesn't support holes in colliders, so as soon as all the sand around the body is grounded, the created collider has no hole in it.
  2. The body physics engine says "oh no, this body is inside a fixed collider, let's move it the hell out!"
  3. The atom simulation says "woah this body is moving quickly, let's make sure no atoms are grounded via it!"
  4. All the atoms that were sitting on top of the body get removed4 from the collider.
  5. The body physics engine sees a big empty space to move the body into.
  6. ... which causes all the atoms to be flung out of the way of the moving body.

So in theory, fixing #1 should fix this. In theory.

Oh, and the other big thing is that none of what I talked about today is actually implemented for the "player" yet, so you can't jump into water and have it splash, nor push falling sand out of the way (though at least falling sand doesn't block you moving anymore). So I should fix that too.

Playable web build‎

Press 4 for sand drawing, 5 for water drawing, B for body drawing, G for body grabbing, then use left click to do those things.

Click to focus, then play with keyboard and mouse. No mobile support! Give feedback.

1

Technical details for making lots of logging statements not slow down the game quite as much:

Keeping high fidelity logs around uses up a lot of memory, so despite the speed improvements I still turn the default log level down for web builds.

2

Yes we have proper footnotes on Slow Rush now! At some point I'd like to make it so you can click them and they render in a little popover bubble like waitbutwhy does. Baby steps :)

3

Otherwise a body moving upwards that collides with a falling block of atoms would cause the 1st row of atoms to be Semi-grounded, the second row to be fully Grounded, and that row would create a collider which the moving body would bounce off!

4

Technically the atoms don't get removed from the collider - the collider just is recreated without them.

◂  Particles, for real this time
News index
Designing a Magic System  ▸