|
| 1 | +--- |
| 2 | +tags: physics, box2d |
| 3 | +title: Box2D Material Properties Tuning |
| 4 | +brief: Tune Box2D density, friction, and restitution from script using Box2D V2 legacy and Box2D V3. |
| 5 | +author: Defold Foundation |
| 6 | +scripts: box2d_material_tuning_v3.script, box2d_material_tuning_v2.script |
| 7 | +thumbnail: thumbnail.webp |
| 8 | +--- |
| 9 | + |
| 10 | +This example compares three dynamic balls whose Box2D material properties are tuned from script. It works with both Box2D V2 legacy and Box2D V3 by attaching one script for each backend. Each script checks `b2d.get_version()` during `init()` and becomes a no-op when the other backend is active. |
| 11 | + |
| 12 | +Click or tap the window to reset the balls and watch the comparison again. |
| 13 | + |
| 14 | +## What You'll Learn |
| 15 | + |
| 16 | +* How to get a Box2D body from a Defold collision object |
| 17 | +* How to detect the active Box2D version with `b2d.get_version()` |
| 18 | +* How to tune density, friction, and restitution through the V2 fixture API |
| 19 | +* How to tune density, friction, and restitution through the V3 shape API |
| 20 | +* How to switch the project between Box2D V2 and V3 with app manifests |
| 21 | + |
| 22 | +## Setup |
| 23 | + |
| 24 | +The collection contains three spawner game objects, one for each material: Ice, Rubber, and Gold. Each spawner has both backend scripts, a label, and a local factory component named `ball_factory`. |
| 25 | + |
| 26 | +All three factories point at `/example/ball.go`, a shared prototype with one sprite and one dynamic circle collision object. The active script creates a ball at the spawner's position, tints the spawned sprite, applies the material settings, and gives it a starting velocity and spin from the spawner's script properties. |
| 27 | + |
| 28 | +The material comparison comes from per-instance script property overrides: |
| 29 | + |
| 30 | +<kbd>Ice</kbd> |
| 31 | +: Low friction and low restitution, so the ball slides along the ramp. |
| 32 | + |
| 33 | +<kbd>Rubber</kbd> |
| 34 | +: Medium friction and high restitution, so the ball bounces more. |
| 35 | + |
| 36 | +<kbd>Gold</kbd> |
| 37 | +: High density, high friction, and low restitution, so the ball feels heavier and settles quickly. |
| 38 | + |
| 39 | +The static scene is built from white walls, and three colored ramps. |
| 40 | + |
| 41 | + |
| 42 | + |
| 43 | +The `game.project` of this example is configured to build with `/box2d_v3.appmanifest` by default. To test V2 locally after downloading the example, change `Native Extensions -> App Manifest` in `game.project` to `/box2d_v2.appmanifest`. |
| 44 | + |
| 45 | + |
| 46 | + |
| 47 | +## How It Works |
| 48 | + |
| 49 | +Both scripts read `b2d.get_version()` once. `box2d_material_tuning_v2.script` only continues when the major version is 2, while `box2d_material_tuning_v3.script` only continues when the major version is 3. |
| 50 | + |
| 51 | +`go.property()` exposes the material settings on each script instance. The Ice, Rubber, and Gold spawners use the same scripts, but each spawner overrides density, friction, restitution, velocity, spin, tint, and material name in the collection. |
| 52 | + |
| 53 | +`b2d.get_body()` returns the Box2D body owned by the spawned ball's collision object. The active script then updates the ball with the backend-specific material API. |
| 54 | + |
| 55 | +There is a significant difference between Box2D V2 legacy and Box2D V3. |
| 56 | + |
| 57 | +In Box2D V2 legacy, collision geometry and material properties are attached to a body through fixtures. The V2 script reads the first fixture with `b2d.body.get_fixtures()` and uses `b2d.fixture.set_density()`, `b2d.fixture.set_friction()`, and `b2d.fixture.set_restitution()` to tune the ball. When setting density, the script asks Box2D to update the body mass from the new value. |
| 58 | + |
| 59 | +In Box2D V3, the script uses the shape API instead of the V2 fixture API. It reads the first shape with `b2d.body.get_shapes()` and uses `b2d.shape.set_density()`, `b2d.shape.set_friction()`, and `b2d.shape.set_restitution()`. After changing density, it calls `b2d.body.reset_mass_data()` so the body mass reflects the new density immediately. |
| 60 | + |
| 61 | +After applying the values, each script reads them back and shows them on the label attached to the same spawner. Clicking or tapping makes each active spawner delete its current ball, spawn a fresh one from its own factory, and reapply its material settings for the current backend. |
0 commit comments