Box2D: Low-level bindings to the Box2D physics engine

[ library, physics ] [ Propose Tags ] [ Report a vulnerability ]

Low-level FFI bindings to Box2D, Erin Catto's 2D rigid-body physics engine. The engine's C sources (v3.2.0, MIT licensed) are bundled and compiled with the package, so no system library is needed.

Each module follows one part of the C API, and each wrapper's documentation names the function it binds. See the README for an example and the rules on callbacks and object lifetimes.


[Skip to Readme]

Modules

[Last Documentation]

  • Box2D
    • Box2D.Base
    • Box2D.Body
    • Box2D.Callbacks
    • Box2D.Chain
    • Box2D.Collision
    • Box2D.Contact
    • Box2D.DebugDraw
    • Box2D.Distance
    • Box2D.DistanceJoint
    • Box2D.DynamicTree
    • Box2D.Events
    • Box2D.Extra
    • Box2D.FilterJoint
    • Box2D.Geometry
    • Box2D.Id
    • Box2D.Internal
      • Box2D.Internal.DrawClosure
    • Box2D.Joint
    • Box2D.MathFunctions
    • Box2D.MathTypes
    • Box2D.MotorJoint
    • Box2D.Mover
    • Box2D.MoverJoint
    • Box2D.PogoJoint
    • Box2D.PrismaticJoint
    • Box2D.Recording
    • Box2D.Replay
    • Box2D.RevoluteJoint
    • Box2D.Shape
    • Box2D.Tags
    • Box2D.UserData
    • Box2D.WeldJoint
    • Box2D.WheelJoint
    • Box2D.World

Flags

Manual Flags

NameDescriptionDefault
assertions

Keep the engine's internal assertions. A failed one stops the process with a trap.

Disabled
double-precision

Store world positions as doubles (the engine's large world mode). Every package in a build shares this setting.

Disabled

Use -f <flag> to enable a flag, or -f -<flag> to disable that flag. More info

Downloads

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees

Candidates

  • No Candidates
Versions [RSS] 0.1.0.0, 0.1.1.0
Change log CHANGELOG.md
Dependencies base (>=4.16 && <5), vector (>=0.13 && <0.14) [details]
Tested with ghc ==9.10.3
License BSD-3-Clause AND MIT[multiple license files]
Copyright 2026 IC Rainbow
Author IC Rainbow
Maintainer aenor.realm@gmail.com
Uploaded by AlexanderBondarenko at 2026-11-14T21:49:59Z
Category Physics
Source repo head: git clone https://gitlab.com/dpwiz/box-nd
Distributions
Downloads 3 total (3 in the last 30 days)
Rating (no votes yet) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs pending
Build status unknown [no reports yet]

Readme for Box2D-0.1.1.0

[back to package description]

Box2D

Low-level Haskell bindings to Box2D, Erin Catto's 2D rigid-body physics engine.

The engine's C sources (v3.2.0, MIT licensed) are bundled and compiled with the package. You need a C compiler, but no system library.

The bindings stay close to the C API: b2World_Step is Box2D.World.step, and each wrapper's documentation names the function it binds. Most modules are generated from the engine headers by boxnd-gen, in the source repository.

Example

{-# LANGUAGE PatternSynonyms #-}

module Main (main) where

import Control.Monad (replicateM_)

import Box2D.Body (BodyDef (..), defaultBodyDef, pattern DynamicBody)
import Box2D.Body qualified as Body
import Box2D.Geometry (Circle (..))
import Box2D.MathTypes (Pos (..), Vec2 (..), vec2Zero)
import Box2D.Shape (defaultShapeDef)
import Box2D.Shape qualified as Shape
import Box2D.World (WorldDef (..), defaultWorldDef)
import Box2D.World qualified as World

main :: IO ()
main = do
  worldDef <- defaultWorldDef
  world <- World.create worldDef{gravity = Vec2 0 (-10)}

  bodyDef <- defaultBodyDef
  ball <- Body.create world bodyDef{type_ = DynamicBody, position = Pos 0 10}
  shapeDef <- defaultShapeDef
  _ <- Shape.createCircle ball shapeDef (Circle vec2Zero 0.5)

  replicateM_ 60 (World.step world (1 / 60) 4)
  Body.getPosition ball >>= print

  World.destroy world

Modules

The modules are designed for qualified import.

Area Modules
Simulation World, Body, Shape, Chain, Contact, Events
Joints Joint, DistanceJoint, FilterJoint, MotorJoint, MoverJoint, PogoJoint, PrismaticJoint, RevoluteJoint, WeldJoint, WheelJoint
Geometry and queries Geometry, Collision, Distance, DynamicTree, Mover
Callbacks and drawing Callbacks, DebugDraw
Recording Recording, Replay
Foundation Id, MathTypes, MathFunctions, Base, UserData, Extra, Tags

Box2D.Internal and its submodule are exposed, but may change in any release.

Things to know

  • Start from the defaults. Create definitions with default*Def and update the fields you need, rather than building them from scratch. They carry an initialization marker, which the engine checks when assertions is on.
  • World positions are Pos. The engine takes and returns Pos for places in the world and WorldTransform for a full pose, while directions, velocities and shape geometry stay Vec2. MathTypes.toPos, toVec2, subPos and offsetPos convert between them.
  • Enums are open. They are newtypes over CInt with pattern synonyms, and the engine can hand back a value with no name here, so include a wildcard when you case on one.
  • Worlds are not thread-safe. Create, step and destroy them from one thread at a time, and never create or destroy two worlds at once: the world table is global. Callbacks.withThreadPoolTaskSystem runs the engine's internal work in parallel.
  • Callback lifetimes. The with* functions in Box2D.Callbacks free their callback when the action ends, so anything holding it, a world included, must be finished by then. Callbacks may run on the engine's worker threads.
  • Exceptions in callbacks. Draw callbacks are trapped and rethrown by Callbacks.draw. An exception escaping any other callback stops the process, because it cannot unwind through C frames.
  • Events are copied. Box2D.Events copies each event buffer into a vector that is safe to keep. The raw buffers from Box2D.World are only valid until the next step.

Build flags

assertions (off by default) keeps the engine's internal assertions. They catch invalid arguments and corrupted state, stopping the process with a trap (SIGILL on x86-64), and only with this flag does Base.setAssertCallback ever fire. Turn it on while developing, for example with stack build --flag Box2D:assertions.

double-precision (off by default) builds the engine's large world mode, which stores world positions as doubles so they stay accurate far from the origin. Pos then holds Double instead of Float, and everything else stays Float. Code that builds positions from literals and the MathTypes helpers compiles either way. Every package in a build shares this setting.

Run stack clean Box2D before changing either flag on an already-built package. A flag change does not rebuild the C objects or preprocessed modules, so without a clean the old setting silently stays in effect.

Limits

  • x86-64 and AArch64 only: ids cross the FFI as machine words, which relies on those calling conventions.
  • Built and tested on Linux x86-64 with GHC 9.10.3.