Box2D: What the C17 Rewrite Means for a 2D Physics Engine
Box2D is a 2D physics engine for games
At a glance
- What is it?
- Box2D is a 2D rigid body physics engine for games, now written in portable C17 with a data-oriented design. This review covers what it solves, how the v3 API works, how to build it, and where it stops being the right tool.
- Who is it for?
- Adopt Box2D if you are writing a game in C, C++, Swift, or Zig and want a solver you can read and rebuild from source; the MIT license and the C17 core make that straightforward. Do not adopt it if you need a scripting-language physics layer out of the box, or if you expect pull requests to be merged.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 5 days ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 27, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Who Box2D is for, and the problem it removes
Box2D simulates rigid bodies in two dimensions: it takes shapes, masses, and joints, and produces positions and rotations over time. The README lists what that covers in practice: continuous collision detection, contact events, convex polygons, capsules, circles, rounded polygons, segments and chains, multiple shapes per body, collision filtering, ray casts, shape casts, overlap queries, and a sensor system. On the dynamics side it names a soft step rigid body solver, island based sleep, and revolute, prismatic, distance, mouse, weld, and wheel joints with limits, motors, springs, and friction.
The audience is game developers who would otherwise write that solver themselves. A platformer that needs a crate to slide down a slope, a top-down game with stacked objects, a character controller that must not tunnel through a wall at high speed: each of those is a collision and constraint problem, not a rendering problem. Box2D is the layer between your game logic and the arithmetic.
The design leans toward large piles of bodies. The README uses exactly that phrase under System, alongside data-oriented design, portable C17, and multithreading and SIMD. That is a statement about where the effort went: not into a friendly object model, but into memory layout and parallelism. If your scene has ten bodies, you will not notice. If it has ten thousand, you will.
How the v3 C API actually works
The API is handle based, not pointer based. You create a world with b2CreateWorld, which takes a b2WorldDef obtained from b2DefaultWorldDef. You then create bodies and attach shapes, and step the world each frame. The README's Zig example shows the pattern in three lines: get a default world definition, set gravity, create the world.
var world_def = box2d.b2DefaultWorldDef();
world_def.gravity.y = 9.8;
const world_id = box2d.b2CreateWorld(&world_def);Two things follow from that shape. First, definitions are value types you fill in and pass by address, so defaults matter and you should start from b2DefaultWorldDef rather than a zeroed struct. Second, the world is referred to by an ID. The Swift example in the README shows the same call from a different language, with the note that C structs are passed as inout arguments using &:
import box2d
var worldDef = b2DefaultWorldDef()
let worldId = b2CreateWorld(&worldDef)The engine's step is where the work happens. The feature list names a soft step solver, continuous physics for fast translations and rotations, and island based sleep. Islands are groups of bodies connected by contacts or joints; sleeping an island skips its simulation until something wakes it. That is the mechanism behind the performance claim for large piles, and it is also why a body that should be moving can appear frozen if it was never woken.
Collision detection is separate from the solver in the feature list: contact events, sensors, and the query family (ray casts, shape casts, overlap queries) are the read side. If you only need to know what is under a cursor, you do not need to build a simulation at all.
Building Box2D and creating a first world
The README's build instructions start with two prerequisites: install CMake and install git, and ensure both run from the command line. The recommended path is CMake presets, which the README says give one build flow on every platform and are picked up automatically by Visual Studio, VS Code, and CLion.
On Linux, the preset flow is two commands. The README adds that the presets use the default native toolchain (Make on Linux), so no specific compiler version is required.
cmake --preset linux-release
cmake --build --preset linux-releaseOn Windows the equivalent pair is cmake --preset windows followed by cmake --build --preset windows-release, and on macOS cmake --preset macos followed by cmake --build --preset macos-release. There is also a plain path that installs the library and a pkg-config file:
mkdir build
cd build
cmake ..
cmake --build . --config Release
cmake --install .The README notes the install step might need sudo. After installing, pkg-config --modversion box2d reports the installed version and pkg-config --cflags --libs box2d gives the build flags. If you are not using pkg-config, the headers live in include/ and the sources in src/ at the top level of the repository.
For a first run, the samples app is the shortest route. Any preset builds it, and it doubles as the replay viewer. On Linux you launch it as build/bin/samples. The README lists sample files such as samples/container.c, samples/car.cpp, and samples/sample_character.cpp, so the sample set covers stacking, vehicles, and character movement rather than only a spinning box.
Zig and Swift users have first-class paths. Zig fetches the dependency with zig fetch --save git+https://github.com/erincatto/box2d and imports it in build.zig through b.dependency("box2d", .{}), then addImport("box2d", box2d_dep.module("box2d")). Swift adds the package from "main" in Package.swift and imports the C API directly.
The trade-offs in a data-oriented C17 engine
The move to C17 with an ID-based API is the most consequential thing about v3, and it cuts both ways. Handles let the engine move bodies around in memory without invalidating your references, which is what makes the multithreading and SIMD work possible. The README states that Box2D uses SSE2 and Neon (AArch64) SIMD math and that this can be disabled by defining BOX2D_DISABLE_SIMD. The cost is that you no longer hold a pointer to a body and call methods on it. You hold an ID and call functions. Code written against v2 does not compile against v3, which is why the repository ships docs/migration.md.
The build requirements are stricter than the feature list suggests. The README says you need a compiler that supports C17 to build the library, and a compiler that supports C++20 to build the samples. Those are two different toolchains in one project. If your team is pinned to an older MSVC or an embedded C99 compiler, the library itself is out of reach until you upgrade, regardless of how small your game is.
Determinism is not addressed in the README. That silence matters, because a common reason to pick a 2D physics engine is lockstep networking or replays, and neither works without reproducible results across machines. The engine does ship a replay viewer for .b2rec recordings, with docs/recording.md describing how to make one, and the README warns that debug build presets are not recommended for the replay viewer. A recording format is not the same as a cross-platform determinism guarantee, and the README does not make that guarantee.
The contribution policy is unusual and worth reading before you plan around it. The README says: "Please do not submit pull requests. Instead, please file an issue for bugs or feature requests." Support is directed to the Discord server. If your organization requires upstream patches to be merged, this project does not work that way. The README also states that LLMs are used in unit tests, the samples app, migration between Box2D and Box3D, build configuration, code reviews, and benchmarking, and that elsewhere all code is developed and written by the author.
When Box2D is the wrong choice
Box2D is a 2D rigid body engine. It is not a 3D engine, and the README's mention of Box3D as a migration target is a reminder that the two are separate codebases. If your game needs depth, you are on the wrong project.
It is also not a scripting-language library. The README's external bindings list is explicitly labeled unsupported: Beef bindings, C++ bindings, and a WASM port are linked under the heading "External ports, wrappers, and bindings (unsupported)". Nothing in the repository promises those bindings track the v3 API or receive fixes. If your engine is in C# or JavaScript, you are depending on a third party's maintenance schedule, not on this project's.
The third case is the one people miss: if you need a few simple collisions, a full solver is overhead. A platformer with axis-aligned tiles and no rotation can use swept AABB checks in less code than it takes to set up a world, define bodies, and wire up contact events. Box2D earns its place when bodies rotate, stack, and constrain each other.
Finally, the samples are not a framework. They are built with OpenGL, GLFW, and imgui per the README, and they exist to demonstrate features and performance. You get a library and a viewer, not a scene graph, an asset pipeline, or an editor.
How Box2D compares to a component-based physics layer
The clearest alternative in the same problem space is a physics integration that ships inside a game engine, where bodies are components attached to entities rather than IDs managed by a standalone library. The difference is architectural, not cosmetic. In a component model, the engine owns the world, the step, and the transform hierarchy, so a physics body and its render transform are the same object and you never write synchronization code. Box2D owns only the simulation. You keep your own representation of every object and copy positions out after each step, and you decide when to step and with what timestep.
That separation is the point. It means Box2D does not care what renders your scene, and the README's samples use OpenGL with GLFW to prove it. It also means the integration work is yours. There is no editor to place a collider, no inspector to tune friction, and no automatic transform sync.
The second meaningful difference is language surface. Engine-integrated physics is usually reached through the engine's scripting language. Box2D's supported surfaces are C, Swift, and Zig, per the README's build sections, plus the unsupported binding list. If your team writes gameplay in a scripting language, you are choosing between an engine integration and a wrapper that the README does not support.
Licence, maintenance, and the cost of upgrading
Box2D is developed by Erin Catto and uses the MIT license, per the README. MIT is permissive: it allows use in closed-source products, and the practical obligation is retaining the copyright and permission notice. That is a summary of what the license identifier means, not legal advice; your counsel should confirm how it applies to your distribution.
The repository is not archived, and the last push was on 2026-09-16. Recent releases are v3.1.1 on 2025-06-04, v3.1.0 on 2025-04-20, and v3.0.0 on 2024-08-12. The gap between v3.0.0 and v3.1.0 is roughly eight months, and v3.1.1 followed about six weeks later, so patch releases do arrive between the larger jumps.
Upgrade cost depends on which version you are on. Coming from v2, the API change is the entire task, and the repository provides docs/migration.md for it. Coming from v3.0.0 to v3.1.x, the version numbers suggest a minor and a patch release, but the README does not document what changed between them and does not describe a rollback procedure. Check the release notes for the specific version before upgrading a shipped title.
The contribution policy affects upgrade cost in a way that is easy to overlook. Because pull requests are not accepted, a bug that affects your project cannot be fixed by you upstream. You can file an issue, or you can carry a local patch. Either way, the patch is yours to rebase on every version bump, and the README does not describe a supported mechanism for that.
Editorial conclusion
Adopt Box2D if you are writing a game in C, C++, Swift, or Zig and want a solver you can read and rebuild from source; the MIT license and the C17 core make that straightforward. Do not adopt it if you need a scripting-language physics layer out of the box, or if you expect pull requests to be merged. Before committing, verify that your toolchain has a C17 compiler and a C++20 compiler for the samples, and check the migration guide at docs/migration.md if you have v2 code, because the v3 API changed.
Frequently asked questions
What is Box2D used for?
It is a 2D physics engine for games, per the README. It handles collision detection, rigid body simulation, joints, and queries such as ray casts and overlap tests.
Is Box2D C or C++?
The library is written in portable C17, and the README says you need a compiler that supports C17 to build it. The samples require a compiler that supports C++20.
Is Box2D free?
Yes. Box2D is developed by Erin Catto and uses the MIT license, according to the README.
How do I install Box2D?
Install CMake and git, then use the CMake presets for your platform, or run cmake, cmake --build . --config Release, and cmake --install . from a build directory. The README notes the install step might need sudo and that a pkg-config file is installed with it.
Is Box2D deterministic?
The README does not state a determinism guarantee. It documents a replay viewer for .b2rec recordings and points to docs/recording.md for how to make a recording, which is a separate matter from reproducible results across machines.
Is Box2D open source?
Yes. Box2D is developed by Erin Catto and uses the MIT license, per the README.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/erincatto-box2d)