It's September so it's back to school season -- for game developers too!

I started working on some new enemies and wasn't happy with how little control I had over their locomotion. I really wanted them to move using nothing but forces and torques1, but I could not get a handle on rotating them precisely using just torque. Enemies move through the world by path finding, generating a sequence of way points, rotating and moving towards each one in turn. Getting the rotating part right is what I went back to math class for.

I need a function that takes a physics body and a target angle and computes the torque that would cause the body to rotate and stop exactly at the target angle. Reading the relevant Matter.js source code and reviewing geometric series2 I got something that worked!

/**
 * @param {Matter.Body} body
 * @param {number} targetAngle
 */
function torqueToAngle(body, targetAngle) {
  const deltaAngle = targetAngle - body.angle
  const F = 1 - body.frictionAir
  const S2 = physics.STEP * physics.STEP // the physics loop time step, 1 / 60s
  return (deltaAngle * (1 - F) - body.angularVelocity) * (body.inertia / S2)
}

That is mathematically accurate but the body rotates slowly, at a speed determined by its physical properties (inertia and air friction3). To be able to control the rotation speed I am trying something... sketchy. I temporarily increase the air friction by multiplying it by impulse before computing torque, which gives us faster rotation. This goes on until velocity dips below arrive, after which we reset air friction to its original value and compute and apply torque again which gets us to land on the target angle perfectly.

I do not expect this to work in the game. Fiddling with air friction will have ripple effects and will mess up how the body moves as well as rotates. This is a good jumping off point to get a handle on the math, but needs work to become a viable non-sketchy solution

Click anywhere to start rotating the capsule towards the mouse. The line turns gray during rotation (when air friction is set artificially high) and then back to white when the capsule has arrived. impulse and arrive can be modified in the top right corner and there's a readout of relevant numbers in the bottom left.

Full thing here. Not fun, just lots of math!

I generally need to think with my fingers and having access to a quick reloading development cycle with line gizmos is a godsend to working through math problems. This is still the same game codebase as before, just with the main loop commented out and replaced with this physics widget.


  1. The orca cheats a bit here -- rotation is done using trigonometry, not physics, but I think for the player character having mathematically perfect controls is OK. Plus I really like how the orca feels. ↩︎

  2. And doing some honest-to-god pen-and-paper math! Like before computers! ↩︎

  3. This is what Matter.js calls it because they assume a side-view simulation with gravity, but we've disabled gravity to achieve a top-view simulation, and air friction is what acts to slow rotation and movement over time. ↩︎