Pymunk
Pymunk is an easy-to-use pythonic 2D physics library designed for games, demos, and simulations. It is built on top of Munk2D, a fork of the robust Chipmunk2D C physics library. First released in 2007, Pymunk remains actively developed and maintained, with its current version being 7.2.0, and has a regular release cadence with several updates per year.
Common errors
-
AttributeError: 'Space' object has no attribute 'add_collision_handler'
cause Attempting to use the `add_collision_handler` method, which was removed in Pymunk 7.0.0.fixUpdate collision handling code to use `space.on_collision()` instead. Refer to the Pymunk 7.0.0 changelog for migration details. -
Pymunk polygon vertices not correct / Polygon appears as a square instead of the intended shape
cause Attempting to create a `Poly` shape with concave vertices. Pymunk automatically creates a convex hull, simplifying the shape.fixSplit any concave polygon definitions into multiple convex polygons. Attach all resulting convex shapes to the same `Body`. -
Objects pass through each other without colliding (object tunneling)
cause Objects are moving too fast, causing them to completely traverse other objects between discrete physics steps.fixReduce the `dt` (time step) passed to `space.step()`, potentially calling `space.step()` multiple times per rendering frame. For projectile-like objects, use `space.segment_query()` for accurate hit detection. -
AttributeError: /usr/lib/python3.x/site-packages/pymunk/libchipmunk64.so: undefined symbol: cpInitChipmunk (or similar linking errors)
cause This error, common in older versions or when installing from source, indicates a problem with Pymunk finding or linking to the underlying Chipmunk C library.fixEnsure you are using `pip install pymunk` which typically provides pre-built binary wheels including Chipmunk. If installing from source, make sure Chipmunk (or Munk2D) is correctly compiled and linked. Check Pymunk's documentation for specific build requirements on your platform.
Warnings
- breaking Pymunk 7.0.0 introduced significant breaking changes to collision handling. The `Space.add_collision_handler()` method and the `CollisionHandler` object were removed.
- breaking In Pymunk 7.0.0, methods like `Space.add()` and `Space.remove()` no longer accept lists or tuples of objects.
- breaking Pymunk 6.0.0 dropped support for Python 2.x and required Python 3.6 or newer. Additionally, the `Vec2d` vector class was completely overhauled to be an immutable `NamedTuple` subclass with a streamlined API.
- gotcha Pymunk's underlying Chipmunk library does not directly support concave polygons for collision detection due to performance and complexity. When a concave polygon is provided, Pymunk will attempt to create a convex hull, potentially resulting in an unexpected shape.
- gotcha Fast-moving objects can 'tunnel' through other objects if they move too quickly during a single physics step (`space.step()`), causing collisions to be missed.
- gotcha Unstable simulations (e.g., objects 'blowing up' or moving illogically) can occur with certain physics configurations.
Install
-
pip install pymunk
Imports
- pymunk
import pymunk
- Space
from pymunk import Space
- Body
from pymunk import Body
- Shape (e.g., Circle, Poly, Segment)
from pymunk.shapes import Circle, Poly, Segment
- Vec2d
some_vector_var = [x, y]
from pymunk import Vec2d
Quickstart
import pymunk
# 1. Create a Space (the simulation world)
space = pymunk.Space()
space.gravity = 0, -981 # Set gravity (e.g., 9.81 m/s^2 downwards)
# 2. Create a Body (the physical object)
mass = 1
moment = pymunk.moment_for_circle(mass, 0, 10) # Moment of inertia for a circle
body = pymunk.Body(mass, moment)
body.position = 50, 150 # Initial position of the body
# 3. Create a Shape (for collision detection) and attach to the Body
circle_shape = pymunk.Circle(body, 10) # 10 is radius
circle_shape.friction = 0.7
circle_shape.elasticity = 0.9
# 4. Create a static ground for the ball to land on
ground_shape = pymunk.Segment(space.static_body, (0, 0), (200, 0), 5) # From (0,0) to (200,0) with radius 5
ground_shape.friction = 0.7
ground_shape.elasticity = 0.9
ground_shape.color = (0, 0, 0, 255)
# 5. Add the Body and Shape to the Space
space.add(body, circle_shape, ground_shape)
# 6. Simulate the physics
print(f"Initial position: {body.position}")
for i in range(100): # Run 100 steps of the simulation
space.step(1 / 60.0) # Advance the simulation by 1/60th of a second
if i % 10 == 0:
print(f"Step {i}: Position: {body.position}")
print(f"Final position: {body.position}")