For a new game I’m working on, I need some 2D “physics” that work in discrete time and discrete space. In other words: every object consists of one or more blocks aligned to a square grid, and time advances in turn-based steps. If you’re thinking of Sokoban, you’ve got the idea:
But unlike Sokoban, there can be multiple actors applying forces, and forces are transferred between objects too. It turns out that this is complicated!
Here is an example situation. The black arrow shows an external force being applied to the red box, which causes it to push all the other boxes along.
These are the rules I want the system to obey:
Rule 1: Objects move in response to forces
A force is described as just a direction, and is considered “infinitely strong” (but not so strong it can push objects into walls). This means that the mass of objects is irrelevant.
There is also an implicit “friction” that brings objects to rest at the end of the timestep. If we want them to keep moving, we have to keep applying a force to them.
The red box moves due to the force, but the orange box is being pushed into the wall and stays put:
Forces can cancel each other out:
And they can add up:
Rule 2: Forces are transferred from objects onto other objects
If object A pushes into B, B pushes into C, and C can move freely ahead, then all three will move. We’ve already seen an example of this at the start of this article.
Conversely, if anything is blocked, the entire chain of movement cannot happen:
Rule 3: During a time step, an object can move at most 1 axis-aligned square
Rotation does not exist in this world, even though this long object would happily rotate in real life:
Movement by more than one square is not possible, even if multiple forces act in the same direction:
Rule 4: Resolve ambiguities sensibly
There are many cases in which these rules do not give rise to a single, unique solution. In those cases, the system should do something sensible and deterministic.
For example, if both a horizontal and a vertical force are applied to an object, and both could result in movement, we have two possible outcomes, neither better than the other. (Remember, diagonal movement is forbidden.)
Either horizontal movement wins, and there is no way for the orange object to move forwards:
Or vertical movement wins, and the red object has no way to move:
A similar situation occurs when two objects want to move into the same space simultaneously — we arbitrarily gave precedence to the orange object in the example below:
Rule 5: No overlap during animation
This is not a valid solution:
Even though the “before” and “after” states are valid, and sensibly follow from the forces, the resulting animation shows the objects overlapping. Instead, the red object should wait for its turn, which might come in the next timestep:
Note that this rule makes the situation ambiguous, so it’s also fine if the red object gets to move first:
Also note that overlaps during animations are only an issue when the movement is orthogonal (left/right vs. up/down). If both objects move along the same line, we’re fine:
This post laid out some of the basic rules I want my physics system to obey. In next week’s post, we’ll take a stab at writing an algorithm to implement these rules, and discover that it’s not as easy as it seems!