or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

bodies-shapes.mdconstraints.mdgeometry.mdindex.mdphysics-world.mdutilities.mdvisualization.md
tile.json

tessl/pypi-pymunk

Pymunk is a easy-to-use pythonic 2D physics library built on Munk2D

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
pypipkg:pypi/pymunk@7.1.x

To install, run

npx @tessl/cli install tessl/pypi-pymunk@7.1.0

index.mddocs/

Pymunk - Python 2D Physics Library

Pymunk is a easy-to-use pythonic 2D physics library that provides a complete interface to the Chipmunk2D physics engine. It enables developers to create realistic physics simulations with rigid bodies, collisions, constraints, and forces for games, simulations, and educational physics demonstrations.

Package Information

Package Name: pymunk
Version: 7.1.0
License: MIT
Homepage: https://www.pymunk.org
Repository: https://github.com/viblo/pymunk

Installation

pip install pymunk

Dependencies

  • Python: 3.9+
  • Chipmunk2D: Included (forked as Munk2D)
  • CFFI: For C library bindings
  • Optional: pygame, pyglet, matplotlib (for visualization utilities)

Core Imports

import pymunk

# Core simulation classes
from pymunk import Space, Body, Shape

# Shape types
from pymunk import Circle, Poly, Segment

# Utility classes  
from pymunk import Vec2d, BB, Transform, ShapeFilter

# Physics information
from pymunk import Arbiter, ContactPoint, ContactPointSet
from pymunk import PointQueryInfo, SegmentQueryInfo, ShapeQueryInfo

# Debug visualization
from pymunk import SpaceDebugDrawOptions

# Constraint/joint classes (from pymunk.constraints)
from pymunk.constraints import (
    PinJoint, SlideJoint, PivotJoint, GrooveJoint,
    DampedSpring, DampedRotarySpring, RotaryLimitJoint,
    RatchetJoint, GearJoint, SimpleMotor
)

# Utility modules
import pymunk.pygame_util   # Pygame integration
import pymunk.pyglet_util   # Pyglet integration 
import pymunk.matplotlib_util  # Matplotlib integration
import pymunk.autogeometry  # Automatic geometry generation
import pymunk.util          # Geometry and math utilities
import pymunk.batch         # High-performance batch operations

Basic Usage

Creating a Simple Physics World

import pymunk

# Create the physics space
space = pymunk.Space()
space.gravity = (0, -981)  # Earth gravity (pixels/s²)

# Create a static ground body
ground_body = pymunk.Body(body_type=pymunk.Body.STATIC)
ground_shape = pymunk.Segment(ground_body, (0, 0), (800, 0), 5)
ground_shape.friction = 0.7
space.add(ground_body, ground_shape)

# Create a dynamic falling ball
ball_mass = 10
ball_radius = 20
ball_moment = pymunk.moment_for_circle(ball_mass, 0, ball_radius)
ball_body = pymunk.Body(ball_mass, ball_moment)
ball_body.position = 400, 600
ball_shape = pymunk.Circle(ball_body, ball_radius)
ball_shape.friction = 0.7
ball_shape.elasticity = 0.8  # Bounciness
space.add(ball_body, ball_shape)

# Run the simulation
dt = 1/60.0  # 60 FPS
for i in range(600):  # 10 seconds
    space.step(dt)
    print(f"Ball position: {ball_body.position}")

Physics Constraints Example

import pymunk

space = pymunk.Space()
space.gravity = (0, -981)

# Create two bodies connected by a pin joint
body1 = pymunk.Body(10, pymunk.moment_for_circle(10, 0, 20))
body1.position = 100, 300
shape1 = pymunk.Circle(body1, 20)

body2 = pymunk.Body(10, pymunk.moment_for_circle(10, 0, 20))  
body2.position = 200, 300
shape2 = pymunk.Circle(body2, 20)

# Connect with a pin joint (rigid connection)
pin = pymunk.PinJoint(body1, body2, (0, 0), (0, 0))

# Add a spring between them
spring = pymunk.DampedSpring(
    body1, body2, (0, 0), (0, 0), 
    rest_length=50, stiffness=1000, damping=50
)

space.add(body1, shape1, body2, shape2, pin, spring)

Collision Detection and Callbacks

import pymunk

def collision_handler(arbiter, space, data):
    """Handle collision between two shapes"""
    print(f"Collision! Impulse: {arbiter.total_impulse}")
    return True  # Process the collision normally

space = pymunk.Space()

# Set collision handler for specific collision types
space.add_collision_handler(1, 2).begin = collision_handler

# Create shapes with collision types
ball1 = pymunk.Circle(body1, 20)
ball1.collision_type = 1

ball2 = pymunk.Circle(body2, 20) 
ball2.collision_type = 2

space.add(body1, ball1, body2, ball2)

Architecture

Pymunk follows a clean object-oriented design with the following core components:

Space - The Physics World

The Space class represents the physics simulation world that contains and manages all physical objects. It handles collision detection, constraint solving, and time stepping.

Key Responsibilities:

  • Managing bodies, shapes, and constraints
  • Running collision detection algorithms
  • Solving constraint equations
  • Integrating physics over time
  • Providing spatial queries

Bodies - Physical Objects

The Body class represents rigid objects with mass, position, velocity, and rotation. Bodies can be:

  • Dynamic: Affected by forces and collisions
  • Kinematic: Controlled by user code
  • Static: Never move (for terrain/walls)

Shapes - Collision Geometry

Shape classes (Circle, Poly, Segment) define the collision boundaries and material properties of bodies:

  • Handle collision detection
  • Define material properties (friction, elasticity)
  • Provide mass/inertia calculation
  • Support sensors (collision detection without response)

Constraints - Connections Between Bodies

Constraint classes define relationships between bodies:

  • Joints: Pin joints, pivot joints, slide joints
  • Springs: Linear and rotary springs with damping
  • Motors: Velocity and position control
  • Limits: Restrict motion ranges

Utility Classes

Supporting classes for common operations:

  • Vec2d: 2D vector math with operator overloading
  • Transform: 2D affine transformations
  • BB: Axis-aligned bounding boxes
  • ShapeFilter: Collision filtering system

Capabilities

Physics World Management

Complete control over physics simulation parameters and object lifecycles.

# Space configuration
space.iterations = 10      # Solver iterations per step
space.gravity = (0, -981)  # Global gravity vector  
space.damping = 0.999      # Global velocity damping
space.sleep_time_threshold = 0.5  # Time before objects sleep
space.collision_slop = 0.1 # Collision overlap tolerance

# Object management
space.add(body, shape, constraint)     # Add objects
space.remove(shape)                    # Remove objects
space.step(dt)                         # Advance simulation

# Spatial queries
hits = space.point_query((100, 200), 0, pymunk.ShapeFilter())
hit = space.point_query_nearest((100, 200), 0, pymunk.ShapeFilter())
hits = space.segment_query((0, 0), (100, 100), 0, pymunk.ShapeFilter())

→ See Physics World Documentation

Bodies and Shapes

Flexible rigid body dynamics with multiple shape types and material properties.

# Body types and creation
body = pymunk.Body(mass=10, moment=pymunk.moment_for_circle(10, 0, 25))
kinematic_body = pymunk.Body(body_type=pymunk.Body.KINEMATIC)
static_body = space.static_body  # Built-in static body

# Shape creation with materials
circle = pymunk.Circle(body, radius=25, offset=(0, 10))
circle.friction = 0.7
circle.elasticity = 0.95
circle.density = 1.0

poly = pymunk.Poly(body, vertices=[(0,0), (50,0), (50,50), (0,50)])
segment = pymunk.Segment(body, (0, 0), (100, 0), radius=5)

# Force and impulse application
body.apply_force_at_world_point((1000, 0), (100, 100))
body.apply_impulse_at_local_point((500, 0), (0, 0))

→ See Bodies and Shapes Documentation

Physics Constraints

Rich set of constraint types for connecting bodies with realistic joint behavior.

# Joint constraints
pin = pymunk.PinJoint(body_a, body_b, anchor_a=(0, 0), anchor_b=(0, 0))
pivot = pymunk.PivotJoint(body_a, body_b, pivot_point=(100, 100))
slide = pymunk.SlideJoint(body_a, body_b, anchor_a, anchor_b, min_dist=10, max_dist=50)
groove = pymunk.GrooveJoint(body_a, body_b, groove_a=(0,0), groove_b=(100,0), anchor_b=(0,0))

# Spring constraints
spring = pymunk.DampedSpring(
    body_a, body_b, anchor_a=(0, 0), anchor_b=(0, 0),
    rest_length=100, stiffness=500, damping=20
)
rotary_spring = pymunk.DampedRotarySpring(
    body_a, body_b, rest_angle=0, stiffness=1000, damping=50  
)

# Motor constraints
motor = pymunk.SimpleMotor(body_a, body_b, rate=math.pi)
gear = pymunk.GearJoint(body_a, body_b, phase=0, ratio=2.0)

→ See Constraints Documentation

Mathematical Utilities

Comprehensive 2D math utilities with intuitive vector operations and geometric calculations.

# Vector operations
v1 = pymunk.Vec2d(10, 20)
v2 = pymunk.Vec2d(5, 15)
result = v1 + v2                    # Vector addition
length = abs(v1)                    # Vector magnitude  
unit = v1.normalized()              # Unit vector
rotated = v1.rotated(math.pi/2)     # Rotate vector

# Bounding boxes  
bb = pymunk.BB(left=0, bottom=0, right=100, top=100)
center = bb.center()                # Get center point
area = bb.area()                    # Calculate area
expanded = bb.expand(pymunk.Vec2d(10, 10))  # Expand by vector

# Transformations
transform = pymunk.Transform.rotation(math.pi/4)  # 45° rotation
translated = transform.translated(100, 50)        # Add translation
point = transform @ pymunk.Vec2d(10, 10)          # Apply to point

→ See Utilities Documentation

Debug Visualization

Built-in debug drawing support for popular graphics libraries with customizable rendering options.

# Pygame debug drawing
import pygame
import pymunk.pygame_util

screen = pygame.display.set_mode((800, 600))
draw_options = pymunk.pygame_util.DrawOptions(screen)
space.debug_draw(draw_options)

# Pyglet debug drawing  
import pyglet
import pymunk.pyglet_util

draw_options = pymunk.pyglet_util.DrawOptions()
with draw_options:
    space.debug_draw(draw_options)

# Matplotlib debug drawing
import matplotlib.pyplot as plt
import pymunk.matplotlib_util

fig, ax = plt.subplots()
draw_options = pymunk.matplotlib_util.DrawOptions(ax)
space.debug_draw(draw_options)
plt.show()

# Custom debug options
draw_options.shape_outline_color = pymunk.SpaceDebugColor(1, 0, 0, 1)  # Red
draw_options.collision_point_color = pymunk.SpaceDebugColor(0, 1, 0, 1)  # Green

→ See Visualization Documentation

Geometry Processing

Advanced geometry utilities for automatic shape generation, convex decomposition, and marching squares.

import pymunk.autogeometry
import pymunk.util

# Automatic geometry processing
points = [(0,0), (100,0), (100,100), (50,150), (0,100)]
simplified = pymunk.autogeometry.simplify_curves(points, tolerance=5.0)
convex_hull = pymunk.autogeometry.to_convex_hull(points, tolerance=1.0)
convex_parts = pymunk.autogeometry.convex_decomposition(points, tolerance=1.0)

# Marching squares for bitmap to geometry conversion
def sample_func(point):
    """Sample function returning 1.0 for solid, 0.0 for empty"""
    x, y = point
    return 1.0 if (x-50)**2 + (y-50)**2 < 25**2 else 0.0

polylines = pymunk.autogeometry.march_soft(
    pymunk.BB(0, 0, 100, 100), 20, 20, 0.5, sample_func
)

# Utility geometry functions
is_convex = pymunk.util.is_convex(points)
area = pymunk.util.calc_area(points)  
centroid = pymunk.util.calc_center(points)
triangles = pymunk.util.triangulate(points)

→ See Geometry Documentation

Physics Calculation Functions

Pymunk provides convenience functions for calculating mass properties and areas of common shapes. These are essential for setting up bodies with proper physics properties.

Moment of Inertia Calculations

def moment_for_circle(
    mass: float, 
    inner_radius: float, 
    outer_radius: float, 
    offset: tuple[float, float] = (0, 0)
) -> float:
    """
    Calculate the moment of inertia for a hollow circle.
    
    A solid circle has an inner radius of 0.
    
    Args:
        mass: Mass of the shape
        inner_radius: Inner radius (0 for solid circle)
        outer_radius: Outer radius
        offset: Offset from body center of gravity
        
    Returns:
        Moment of inertia value
        
    Example:
        # Solid circle
        moment = pymunk.moment_for_circle(10, 0, 25)
        
        # Hollow circle (ring)
        moment = pymunk.moment_for_circle(10, 20, 25)
    """

def moment_for_segment(
    mass: float, 
    a: tuple[float, float], 
    b: tuple[float, float], 
    radius: float
) -> float:
    """
    Calculate the moment of inertia for a line segment.
    
    The endpoints a and b are relative to the body.
    
    Args:
        mass: Mass of the shape
        a: First endpoint
        b: Second endpoint
        radius: Thickness radius
        
    Returns:
        Moment of inertia value
    """

def moment_for_box(mass: float, size: tuple[float, float]) -> float:
    """
    Calculate the moment of inertia for a solid box centered on the body.
    
    Args:
        mass: Mass of the shape
        size: (width, height) of the box
        
    Returns:
        Moment of inertia value
        
    Example:
        moment = pymunk.moment_for_box(10, (50, 30))
    """

def moment_for_poly(
    mass: float,
    vertices: Sequence[tuple[float, float]],
    offset: tuple[float, float] = (0, 0),
    radius: float = 0
) -> float:
    """
    Calculate the moment of inertia for a solid polygon shape.
    
    Assumes the polygon center of gravity is at its centroid.
    The offset is added to each vertex.
    
    Args:
        mass: Mass of the shape
        vertices: List of vertices
        offset: Offset added to each vertex
        radius: Corner rounding radius
        
    Returns:
        Moment of inertia value
    """

Area Calculations

def area_for_circle(inner_radius: float, outer_radius: float) -> float:
    """
    Calculate area of a hollow circle.
    
    Args:
        inner_radius: Inner radius (0 for solid circle)
        outer_radius: Outer radius
        
    Returns:
        Area of the circle
    """

def area_for_segment(
    a: tuple[float, float], 
    b: tuple[float, float], 
    radius: float
) -> float:
    """
    Calculate area of a beveled segment.
    
    Will always be zero if radius is zero.
    
    Args:
        a: First endpoint
        b: Second endpoint
        radius: Thickness radius
        
    Returns:
        Area of the segment
    """

def area_for_poly(
    vertices: Sequence[tuple[float, float]], 
    radius: float = 0
) -> float:
    """
    Calculate signed area of a polygon shape.
    
    Returns a negative number for polygons with clockwise winding.
    
    Args:
        vertices: List of vertices
        radius: Corner rounding radius
        
    Returns:
        Signed area of the polygon
    """

Empty Callback Function

def empty_callback(*args, **kwargs) -> None:
    """
    A default empty callback function.
    
    Can be used to reset a collision callback to its original empty
    function. More efficient than defining your own empty function.
    """

Version Information

Pymunk provides version information for both the Python library and the underlying Chipmunk2D physics engine.

Version Properties

version: str
"""
The release version of this Pymunk installation.

Valid only if Pymunk was installed from a source or binary
distribution (i.e. not in a checked-out copy from git).

Example:
    import pymunk
    print(pymunk.version)  # "7.1.0"
"""

chipmunk_version: str  
"""
The Chipmunk2D version used with this Pymunk version.

This property shows the actual version when you import Pymunk.

The string format is: <cpVersionString>-<github_commit>
where cpVersionString is the version string set by Chipmunk2D 
and the git commit hash corresponds to the specific chipmunk 
source from github.com/viblo/Chipmunk2D included with Pymunk.

Example:
    import pymunk
    print(pymunk.chipmunk_version)  # "7.0.3-ade7ed72849e60289eefb7a41e79ae6322fefaf3"
"""

Usage Example

import pymunk

# Get version information
print(f"Pymunk version: {pymunk.version}")
print(f"Chipmunk version: {pymunk.chipmunk_version}")

# Version compatibility checking
def check_version_compatibility():
    """Check if current Pymunk version meets minimum requirements"""
    required_version = "7.0.0"
    current_version = pymunk.version
    
    # Simple string comparison (works for semantic versioning)
    if current_version >= required_version:
        print(f"✓ Pymunk {current_version} meets requirement (>= {required_version})")
        return True
    else:
        print(f"✗ Pymunk {current_version} does not meet requirement (>= {required_version})")
        return False

check_version_compatibility()

Error Handling

Pymunk uses standard Python exceptions and provides detailed error messages for common issues:

  • ValueError: Invalid parameters or constraints
  • RuntimeError: Physics engine errors or invalid operations
  • AttributeError: Accessing properties on freed objects

Thread Safety

  • Spaces can be created with threading support: Space(threaded=True)
  • Individual objects are not thread-safe
  • Use appropriate locking when accessing objects from multiple threads
  • Threading not available on Windows platform

Performance Tips

  • Use Space.use_spatial_hash() for large numbers of objects
  • Prefer static bodies for terrain and immovable objects
  • Use batch operations from pymunk.batch for large datasets
  • Set appropriate Space.iterations for stability vs. performance trade-offs
  • Use sensors for non-physical collision detection
  • Consider object sleeping for inactive bodies

This comprehensive physics library provides all the tools needed for realistic 2D physics simulations with an intuitive Python interface that abstracts the underlying C physics engine complexity while maintaining high performance and flexibility.