0
# Pymunk - Python 2D Physics Library
1
2
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.
3
4
## Package Information
5
6
**Package Name:** `pymunk`
7
**Version:** 7.1.0
8
**License:** MIT
9
**Homepage:** https://www.pymunk.org
10
**Repository:** https://github.com/viblo/pymunk
11
12
### Installation
13
14
```bash
15
pip install pymunk
16
```
17
18
### Dependencies
19
20
- **Python:** 3.9+
21
- **Chipmunk2D:** Included (forked as Munk2D)
22
- **CFFI:** For C library bindings
23
- **Optional:** pygame, pyglet, matplotlib (for visualization utilities)
24
25
## Core Imports
26
27
```python { .api }
28
import pymunk
29
30
# Core simulation classes
31
from pymunk import Space, Body, Shape
32
33
# Shape types
34
from pymunk import Circle, Poly, Segment
35
36
# Utility classes
37
from pymunk import Vec2d, BB, Transform, ShapeFilter
38
39
# Physics information
40
from pymunk import Arbiter, ContactPoint, ContactPointSet
41
from pymunk import PointQueryInfo, SegmentQueryInfo, ShapeQueryInfo
42
43
# Debug visualization
44
from pymunk import SpaceDebugDrawOptions
45
46
# Constraint/joint classes (from pymunk.constraints)
47
from pymunk.constraints import (
48
PinJoint, SlideJoint, PivotJoint, GrooveJoint,
49
DampedSpring, DampedRotarySpring, RotaryLimitJoint,
50
RatchetJoint, GearJoint, SimpleMotor
51
)
52
53
# Utility modules
54
import pymunk.pygame_util # Pygame integration
55
import pymunk.pyglet_util # Pyglet integration
56
import pymunk.matplotlib_util # Matplotlib integration
57
import pymunk.autogeometry # Automatic geometry generation
58
import pymunk.util # Geometry and math utilities
59
import pymunk.batch # High-performance batch operations
60
```
61
62
## Basic Usage
63
64
### Creating a Simple Physics World
65
66
```python { .api }
67
import pymunk
68
69
# Create the physics space
70
space = pymunk.Space()
71
space.gravity = (0, -981) # Earth gravity (pixels/s²)
72
73
# Create a static ground body
74
ground_body = pymunk.Body(body_type=pymunk.Body.STATIC)
75
ground_shape = pymunk.Segment(ground_body, (0, 0), (800, 0), 5)
76
ground_shape.friction = 0.7
77
space.add(ground_body, ground_shape)
78
79
# Create a dynamic falling ball
80
ball_mass = 10
81
ball_radius = 20
82
ball_moment = pymunk.moment_for_circle(ball_mass, 0, ball_radius)
83
ball_body = pymunk.Body(ball_mass, ball_moment)
84
ball_body.position = 400, 600
85
ball_shape = pymunk.Circle(ball_body, ball_radius)
86
ball_shape.friction = 0.7
87
ball_shape.elasticity = 0.8 # Bounciness
88
space.add(ball_body, ball_shape)
89
90
# Run the simulation
91
dt = 1/60.0 # 60 FPS
92
for i in range(600): # 10 seconds
93
space.step(dt)
94
print(f"Ball position: {ball_body.position}")
95
```
96
97
### Physics Constraints Example
98
99
```python { .api }
100
import pymunk
101
102
space = pymunk.Space()
103
space.gravity = (0, -981)
104
105
# Create two bodies connected by a pin joint
106
body1 = pymunk.Body(10, pymunk.moment_for_circle(10, 0, 20))
107
body1.position = 100, 300
108
shape1 = pymunk.Circle(body1, 20)
109
110
body2 = pymunk.Body(10, pymunk.moment_for_circle(10, 0, 20))
111
body2.position = 200, 300
112
shape2 = pymunk.Circle(body2, 20)
113
114
# Connect with a pin joint (rigid connection)
115
pin = pymunk.PinJoint(body1, body2, (0, 0), (0, 0))
116
117
# Add a spring between them
118
spring = pymunk.DampedSpring(
119
body1, body2, (0, 0), (0, 0),
120
rest_length=50, stiffness=1000, damping=50
121
)
122
123
space.add(body1, shape1, body2, shape2, pin, spring)
124
```
125
126
### Collision Detection and Callbacks
127
128
```python { .api }
129
import pymunk
130
131
def collision_handler(arbiter, space, data):
132
"""Handle collision between two shapes"""
133
print(f"Collision! Impulse: {arbiter.total_impulse}")
134
return True # Process the collision normally
135
136
space = pymunk.Space()
137
138
# Set collision handler for specific collision types
139
space.add_collision_handler(1, 2).begin = collision_handler
140
141
# Create shapes with collision types
142
ball1 = pymunk.Circle(body1, 20)
143
ball1.collision_type = 1
144
145
ball2 = pymunk.Circle(body2, 20)
146
ball2.collision_type = 2
147
148
space.add(body1, ball1, body2, ball2)
149
```
150
151
## Architecture
152
153
Pymunk follows a clean object-oriented design with the following core components:
154
155
### Space - The Physics World
156
The `Space` class represents the physics simulation world that contains and manages all physical objects. It handles collision detection, constraint solving, and time stepping.
157
158
**Key Responsibilities:**
159
- Managing bodies, shapes, and constraints
160
- Running collision detection algorithms
161
- Solving constraint equations
162
- Integrating physics over time
163
- Providing spatial queries
164
165
### Bodies - Physical Objects
166
The `Body` class represents rigid objects with mass, position, velocity, and rotation. Bodies can be:
167
- **Dynamic**: Affected by forces and collisions
168
- **Kinematic**: Controlled by user code
169
- **Static**: Never move (for terrain/walls)
170
171
### Shapes - Collision Geometry
172
Shape classes (`Circle`, `Poly`, `Segment`) define the collision boundaries and material properties of bodies:
173
- Handle collision detection
174
- Define material properties (friction, elasticity)
175
- Provide mass/inertia calculation
176
- Support sensors (collision detection without response)
177
178
### Constraints - Connections Between Bodies
179
Constraint classes define relationships between bodies:
180
- **Joints**: Pin joints, pivot joints, slide joints
181
- **Springs**: Linear and rotary springs with damping
182
- **Motors**: Velocity and position control
183
- **Limits**: Restrict motion ranges
184
185
### Utility Classes
186
Supporting classes for common operations:
187
- **Vec2d**: 2D vector math with operator overloading
188
- **Transform**: 2D affine transformations
189
- **BB**: Axis-aligned bounding boxes
190
- **ShapeFilter**: Collision filtering system
191
192
## Capabilities
193
194
### Physics World Management
195
Complete control over physics simulation parameters and object lifecycles.
196
197
```python { .api }
198
# Space configuration
199
space.iterations = 10 # Solver iterations per step
200
space.gravity = (0, -981) # Global gravity vector
201
space.damping = 0.999 # Global velocity damping
202
space.sleep_time_threshold = 0.5 # Time before objects sleep
203
space.collision_slop = 0.1 # Collision overlap tolerance
204
205
# Object management
206
space.add(body, shape, constraint) # Add objects
207
space.remove(shape) # Remove objects
208
space.step(dt) # Advance simulation
209
210
# Spatial queries
211
hits = space.point_query((100, 200), 0, pymunk.ShapeFilter())
212
hit = space.point_query_nearest((100, 200), 0, pymunk.ShapeFilter())
213
hits = space.segment_query((0, 0), (100, 100), 0, pymunk.ShapeFilter())
214
```
215
216
[→ See Physics World Documentation](physics-world.md)
217
218
### Bodies and Shapes
219
Flexible rigid body dynamics with multiple shape types and material properties.
220
221
```python { .api }
222
# Body types and creation
223
body = pymunk.Body(mass=10, moment=pymunk.moment_for_circle(10, 0, 25))
224
kinematic_body = pymunk.Body(body_type=pymunk.Body.KINEMATIC)
225
static_body = space.static_body # Built-in static body
226
227
# Shape creation with materials
228
circle = pymunk.Circle(body, radius=25, offset=(0, 10))
229
circle.friction = 0.7
230
circle.elasticity = 0.95
231
circle.density = 1.0
232
233
poly = pymunk.Poly(body, vertices=[(0,0), (50,0), (50,50), (0,50)])
234
segment = pymunk.Segment(body, (0, 0), (100, 0), radius=5)
235
236
# Force and impulse application
237
body.apply_force_at_world_point((1000, 0), (100, 100))
238
body.apply_impulse_at_local_point((500, 0), (0, 0))
239
```
240
241
[→ See Bodies and Shapes Documentation](bodies-shapes.md)
242
243
### Physics Constraints
244
Rich set of constraint types for connecting bodies with realistic joint behavior.
245
246
```python { .api }
247
# Joint constraints
248
pin = pymunk.PinJoint(body_a, body_b, anchor_a=(0, 0), anchor_b=(0, 0))
249
pivot = pymunk.PivotJoint(body_a, body_b, pivot_point=(100, 100))
250
slide = pymunk.SlideJoint(body_a, body_b, anchor_a, anchor_b, min_dist=10, max_dist=50)
251
groove = pymunk.GrooveJoint(body_a, body_b, groove_a=(0,0), groove_b=(100,0), anchor_b=(0,0))
252
253
# Spring constraints
254
spring = pymunk.DampedSpring(
255
body_a, body_b, anchor_a=(0, 0), anchor_b=(0, 0),
256
rest_length=100, stiffness=500, damping=20
257
)
258
rotary_spring = pymunk.DampedRotarySpring(
259
body_a, body_b, rest_angle=0, stiffness=1000, damping=50
260
)
261
262
# Motor constraints
263
motor = pymunk.SimpleMotor(body_a, body_b, rate=math.pi)
264
gear = pymunk.GearJoint(body_a, body_b, phase=0, ratio=2.0)
265
```
266
267
[→ See Constraints Documentation](constraints.md)
268
269
### Mathematical Utilities
270
Comprehensive 2D math utilities with intuitive vector operations and geometric calculations.
271
272
```python { .api }
273
# Vector operations
274
v1 = pymunk.Vec2d(10, 20)
275
v2 = pymunk.Vec2d(5, 15)
276
result = v1 + v2 # Vector addition
277
length = abs(v1) # Vector magnitude
278
unit = v1.normalized() # Unit vector
279
rotated = v1.rotated(math.pi/2) # Rotate vector
280
281
# Bounding boxes
282
bb = pymunk.BB(left=0, bottom=0, right=100, top=100)
283
center = bb.center() # Get center point
284
area = bb.area() # Calculate area
285
expanded = bb.expand(pymunk.Vec2d(10, 10)) # Expand by vector
286
287
# Transformations
288
transform = pymunk.Transform.rotation(math.pi/4) # 45° rotation
289
translated = transform.translated(100, 50) # Add translation
290
point = transform @ pymunk.Vec2d(10, 10) # Apply to point
291
```
292
293
[→ See Utilities Documentation](utilities.md)
294
295
### Debug Visualization
296
Built-in debug drawing support for popular graphics libraries with customizable rendering options.
297
298
```python { .api }
299
# Pygame debug drawing
300
import pygame
301
import pymunk.pygame_util
302
303
screen = pygame.display.set_mode((800, 600))
304
draw_options = pymunk.pygame_util.DrawOptions(screen)
305
space.debug_draw(draw_options)
306
307
# Pyglet debug drawing
308
import pyglet
309
import pymunk.pyglet_util
310
311
draw_options = pymunk.pyglet_util.DrawOptions()
312
with draw_options:
313
space.debug_draw(draw_options)
314
315
# Matplotlib debug drawing
316
import matplotlib.pyplot as plt
317
import pymunk.matplotlib_util
318
319
fig, ax = plt.subplots()
320
draw_options = pymunk.matplotlib_util.DrawOptions(ax)
321
space.debug_draw(draw_options)
322
plt.show()
323
324
# Custom debug options
325
draw_options.shape_outline_color = pymunk.SpaceDebugColor(1, 0, 0, 1) # Red
326
draw_options.collision_point_color = pymunk.SpaceDebugColor(0, 1, 0, 1) # Green
327
```
328
329
[→ See Visualization Documentation](visualization.md)
330
331
### Geometry Processing
332
Advanced geometry utilities for automatic shape generation, convex decomposition, and marching squares.
333
334
```python { .api }
335
import pymunk.autogeometry
336
import pymunk.util
337
338
# Automatic geometry processing
339
points = [(0,0), (100,0), (100,100), (50,150), (0,100)]
340
simplified = pymunk.autogeometry.simplify_curves(points, tolerance=5.0)
341
convex_hull = pymunk.autogeometry.to_convex_hull(points, tolerance=1.0)
342
convex_parts = pymunk.autogeometry.convex_decomposition(points, tolerance=1.0)
343
344
# Marching squares for bitmap to geometry conversion
345
def sample_func(point):
346
"""Sample function returning 1.0 for solid, 0.0 for empty"""
347
x, y = point
348
return 1.0 if (x-50)**2 + (y-50)**2 < 25**2 else 0.0
349
350
polylines = pymunk.autogeometry.march_soft(
351
pymunk.BB(0, 0, 100, 100), 20, 20, 0.5, sample_func
352
)
353
354
# Utility geometry functions
355
is_convex = pymunk.util.is_convex(points)
356
area = pymunk.util.calc_area(points)
357
centroid = pymunk.util.calc_center(points)
358
triangles = pymunk.util.triangulate(points)
359
```
360
361
[→ See Geometry Documentation](geometry.md)
362
363
## Physics Calculation Functions
364
365
Pymunk provides convenience functions for calculating mass properties and areas of common shapes. These are essential for setting up bodies with proper physics properties.
366
367
### Moment of Inertia Calculations
368
369
```python { .api }
370
def moment_for_circle(
371
mass: float,
372
inner_radius: float,
373
outer_radius: float,
374
offset: tuple[float, float] = (0, 0)
375
) -> float:
376
"""
377
Calculate the moment of inertia for a hollow circle.
378
379
A solid circle has an inner radius of 0.
380
381
Args:
382
mass: Mass of the shape
383
inner_radius: Inner radius (0 for solid circle)
384
outer_radius: Outer radius
385
offset: Offset from body center of gravity
386
387
Returns:
388
Moment of inertia value
389
390
Example:
391
# Solid circle
392
moment = pymunk.moment_for_circle(10, 0, 25)
393
394
# Hollow circle (ring)
395
moment = pymunk.moment_for_circle(10, 20, 25)
396
"""
397
398
def moment_for_segment(
399
mass: float,
400
a: tuple[float, float],
401
b: tuple[float, float],
402
radius: float
403
) -> float:
404
"""
405
Calculate the moment of inertia for a line segment.
406
407
The endpoints a and b are relative to the body.
408
409
Args:
410
mass: Mass of the shape
411
a: First endpoint
412
b: Second endpoint
413
radius: Thickness radius
414
415
Returns:
416
Moment of inertia value
417
"""
418
419
def moment_for_box(mass: float, size: tuple[float, float]) -> float:
420
"""
421
Calculate the moment of inertia for a solid box centered on the body.
422
423
Args:
424
mass: Mass of the shape
425
size: (width, height) of the box
426
427
Returns:
428
Moment of inertia value
429
430
Example:
431
moment = pymunk.moment_for_box(10, (50, 30))
432
"""
433
434
def moment_for_poly(
435
mass: float,
436
vertices: Sequence[tuple[float, float]],
437
offset: tuple[float, float] = (0, 0),
438
radius: float = 0
439
) -> float:
440
"""
441
Calculate the moment of inertia for a solid polygon shape.
442
443
Assumes the polygon center of gravity is at its centroid.
444
The offset is added to each vertex.
445
446
Args:
447
mass: Mass of the shape
448
vertices: List of vertices
449
offset: Offset added to each vertex
450
radius: Corner rounding radius
451
452
Returns:
453
Moment of inertia value
454
"""
455
```
456
457
### Area Calculations
458
459
```python { .api }
460
def area_for_circle(inner_radius: float, outer_radius: float) -> float:
461
"""
462
Calculate area of a hollow circle.
463
464
Args:
465
inner_radius: Inner radius (0 for solid circle)
466
outer_radius: Outer radius
467
468
Returns:
469
Area of the circle
470
"""
471
472
def area_for_segment(
473
a: tuple[float, float],
474
b: tuple[float, float],
475
radius: float
476
) -> float:
477
"""
478
Calculate area of a beveled segment.
479
480
Will always be zero if radius is zero.
481
482
Args:
483
a: First endpoint
484
b: Second endpoint
485
radius: Thickness radius
486
487
Returns:
488
Area of the segment
489
"""
490
491
def area_for_poly(
492
vertices: Sequence[tuple[float, float]],
493
radius: float = 0
494
) -> float:
495
"""
496
Calculate signed area of a polygon shape.
497
498
Returns a negative number for polygons with clockwise winding.
499
500
Args:
501
vertices: List of vertices
502
radius: Corner rounding radius
503
504
Returns:
505
Signed area of the polygon
506
"""
507
```
508
509
### Empty Callback Function
510
511
```python { .api }
512
def empty_callback(*args, **kwargs) -> None:
513
"""
514
A default empty callback function.
515
516
Can be used to reset a collision callback to its original empty
517
function. More efficient than defining your own empty function.
518
"""
519
```
520
521
## Version Information
522
523
Pymunk provides version information for both the Python library and the underlying Chipmunk2D physics engine.
524
525
### Version Properties
526
527
```python { .api }
528
version: str
529
"""
530
The release version of this Pymunk installation.
531
532
Valid only if Pymunk was installed from a source or binary
533
distribution (i.e. not in a checked-out copy from git).
534
535
Example:
536
import pymunk
537
print(pymunk.version) # "7.1.0"
538
"""
539
540
chipmunk_version: str
541
"""
542
The Chipmunk2D version used with this Pymunk version.
543
544
This property shows the actual version when you import Pymunk.
545
546
The string format is: <cpVersionString>-<github_commit>
547
where cpVersionString is the version string set by Chipmunk2D
548
and the git commit hash corresponds to the specific chipmunk
549
source from github.com/viblo/Chipmunk2D included with Pymunk.
550
551
Example:
552
import pymunk
553
print(pymunk.chipmunk_version) # "7.0.3-ade7ed72849e60289eefb7a41e79ae6322fefaf3"
554
"""
555
```
556
557
### Usage Example
558
559
```python { .api }
560
import pymunk
561
562
# Get version information
563
print(f"Pymunk version: {pymunk.version}")
564
print(f"Chipmunk version: {pymunk.chipmunk_version}")
565
566
# Version compatibility checking
567
def check_version_compatibility():
568
"""Check if current Pymunk version meets minimum requirements"""
569
required_version = "7.0.0"
570
current_version = pymunk.version
571
572
# Simple string comparison (works for semantic versioning)
573
if current_version >= required_version:
574
print(f"✓ Pymunk {current_version} meets requirement (>= {required_version})")
575
return True
576
else:
577
print(f"✗ Pymunk {current_version} does not meet requirement (>= {required_version})")
578
return False
579
580
check_version_compatibility()
581
```
582
583
## Error Handling
584
585
Pymunk uses standard Python exceptions and provides detailed error messages for common issues:
586
587
- **ValueError**: Invalid parameters or constraints
588
- **RuntimeError**: Physics engine errors or invalid operations
589
- **AttributeError**: Accessing properties on freed objects
590
591
## Thread Safety
592
593
- Spaces can be created with threading support: `Space(threaded=True)`
594
- Individual objects are not thread-safe
595
- Use appropriate locking when accessing objects from multiple threads
596
- Threading not available on Windows platform
597
598
## Performance Tips
599
600
- Use `Space.use_spatial_hash()` for large numbers of objects
601
- Prefer static bodies for terrain and immovable objects
602
- Use batch operations from `pymunk.batch` for large datasets
603
- Set appropriate `Space.iterations` for stability vs. performance trade-offs
604
- Use sensors for non-physical collision detection
605
- Consider object sleeping for inactive bodies
606
607
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.