How Does Friction Affect Contacting Surfaces in Planck.js?
This article provides a quick overview of how friction operates between contacting surfaces in Planck.js, a 2D physics engine for JavaScript games. It explains the mechanics behind friction simulation, how friction coefficients are calculated and combined when two fixtures collide, and how developers can manipulate these values to achieve realistic physical behavior in their applications.
Understanding Friction in Planck.js
In Planck.js (which is a JavaScript port of the Box2D physics engine), friction is a force that resists the relative lateral motion of two contacting surfaces. Its primary purpose is to simulate the natural roughness of real-world materials, causing sliding objects to slow down and allowing objects to roll or grip each other without infinitely sliding.
Friction in Planck.js is simulated using Coulomb friction, which means the frictional force is proportional to the normal force (the force pushing the two surfaces together).
The Friction Coefficient
Every fixture (Fixture) in Planck.js has a friction
property, typically defined via its FixtureDef during
creation.
- Value Range: The friction coefficient is usually a
value between
0.0and1.0. - 0.0: Represents a perfectly frictionless surface (like perfectly smooth ice).
- 1.0 or higher: Represents a highly high-friction surface (like sandpaper or rubber). Note that while values above 1.0 are mathematically valid and allowed, the friction force will scale dramatically.
How Contact Friction is Calculated
When two fixtures collide, Planck.js must determine a single, unified friction value for the contact point. It does this by combining the friction coefficients of both interacting fixtures using a geometric mean formula:
\[\mu = \sqrt{\mu_1 \times \mu_2}\]
Where:
- \(\mu\) is the final contact friction coefficient.
- \(\mu_1\) is the friction coefficient of the first fixture.
- \(\mu_2\) is the friction coefficient of the second fixture.
This specific formula ensures that if even one of the surfaces has a
friction coefficient of 0.0, the resulting contact will be
completely frictionless, mimicking real-world logic (e.g., if you put a
rough block on frictionless ice, it will still slide flawlessly).
Modifying Friction Dynamically
While you set the initial friction value when configuring a fixture, Planck.js allows you to override this behavior dynamically during gameplay. This is particularly useful for mechanics like ice patches, oil slicks, or speed-boosting conveyor belts.
To change friction on the fly, you can listen to contact events using a contact listener:
- Intercept the collision in the
BeginContactorPreSolvelifecycle hooks. - Access the
Contactobject. - Use the
setFriction()method to manually inject a new friction coefficient for that specific frame’s physics calculation.
Note: Changes made via
setFriction()inPreSolveonly persist for the current time step. If you want a permanent change for that ongoing contact, you must set it during everyPreSolvestep until the contact ends.