Keel’s physics components are pure ECS data — they carry no pymunk or pybullet objects themselves. TheDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/VKSFY/keel/llms.txt
Use this file to discover all available pages before exploring further.
Physics2D and Physics3D bridges read these fields on every Phase.POST_UPDATE tick, create or update the underlying simulation objects, advance the solver, and write results back into Transform2D / Transform3D. You describe what you want; the bridge makes it happen.
Enums
BodyType
Shared by 2D and 3D.BodyType is an IntEnum, so BodyType.STATIC == 1 is True and raw integer literals work everywhere.
| Value | Int | Description |
|---|---|---|
BodyType.DYNAMIC | 0 | Affected by gravity, forces, and impulses. Collides with everything. Emits CollisionEvent2D / CollisionEvent3D. |
BodyType.STATIC | 1 | Immovable. Emits collision events when a dynamic body touches it. Does not emit events against kinematic bodies (pymunk limitation). |
BodyType.KINEMATIC | 2 | Moved manually via Physics2D.set_velocity / set_position. Does not emit CollisionEvent2D against another kinematic or static body. Use DYNAMIC for entities that must detect mutual collisions. |
ShapeType2D
Selects the pymunk shape built for aCollider2D.
| Value | Int | Active fields |
|---|---|---|
ShapeType2D.CIRCLE | 0 | radius |
ShapeType2D.BOX | 1 | width, height |
ShapeType2D.SEGMENT | 2 | width (segment half-length × 2, thickness = 1 px) |
ShapeType3D
Selects the pybullet collision shape built for aCollider3D.
| Value | Int | Active fields |
|---|---|---|
ShapeType3D.SPHERE | 0 | radius |
ShapeType3D.BOX | 1 | size_x, size_y, size_z |
ShapeType3D.CAPSULE | 2 | radius, size_y (total height) |
ShapeType3D.MESH | 3 | mesh_id (index into MeshRegistry) |
2D Components
RigidBody2D
RigidBody2D carries the mass, moment of inertia, velocity, angular velocity, and simulation mode for a 2D entity. It must appear alongside Transform2D and Collider2D on the same entity — missing any one of the three causes the entity to be skipped with a RuntimeWarning.
Fields
Mass in grams (pymunk uses centimeter-gram-second units when gravity is
−980.0). Only meaningful for DYNAMIC bodies. STATIC and KINEMATIC bodies ignore this field.Moment of inertia. When
0.0, Physics2D auto-computes an appropriate moment from the collider shape and mass. Set explicitly only if you need non-standard rotational behavior.Initial (or externally set) linear velocity along X in pixels per second. Updated each frame by
sync_from_physics.Initial (or externally set) linear velocity along Y in pixels per second.
Angular velocity in radians per second. Positive = counterclockwise.
Linear velocity damping coefficient passed to pymunk.
0.0 is no damping; values closer to 1.0 create strong air resistance. Note: pymunk’s damping is per-body, not per-space.Simulation mode. Use
keel.BodyType.DYNAMIC (0), keel.BodyType.STATIC (1), or keel.BodyType.KINEMATIC (2). Raw integers are accepted because BodyType is an IntEnum.Collider2D
Collider2D defines the collision shape attached to the pymunk body. Which size fields are used depends on shape_type.
Fields
Selects the pymunk shape:
ShapeType2D.CIRCLE (0), ShapeType2D.BOX (1), or ShapeType2D.SEGMENT (2).Width for
BOX shapes, or the full length for SEGMENT shapes (the half-length is width / 2). Ignored for CIRCLE.Height for
BOX shapes. Ignored for CIRCLE and SEGMENT.Radius for
CIRCLE shapes. Ignored for BOX and SEGMENT.Surface friction coefficient. Overridden by
PhysicsMaterial2D if apply_material was called on this entity. Typical range [0.0, 1.0].Bounciness / restitution.
0.0 = no bounce, 1.0 = perfectly elastic. Overridden by PhysicsMaterial2D if applied.When
True, the shape is a trigger zone — it detects overlap and emits CollisionEvent2D but does not physically resolve the contact. Bodies pass through the sensor.Bitmask identifying which collision category this shape belongs to. Used with
mask_bits to implement selective collision layers.Bitmask of categories this shape collides with. A contact fires only when
(A.category_bits & B.mask_bits) != 0 and (B.category_bits & A.mask_bits) != 0.3D Components
RigidBody3D
RigidBody3D is the 3D analogue of RigidBody2D, backed by pybullet’s DIRECT-mode rigid body. All three linear and angular velocity components are present.
Fields
Mass in kilograms (pybullet uses SI units when gravity is
−9.81). Only meaningful for DYNAMIC bodies.Linear velocity along X in meters per second. Updated each frame by
sync_from_physics.Linear velocity along Y in meters per second.
Linear velocity along Z in meters per second.
Angular velocity around X in radians per second.
Angular velocity around Y in radians per second.
Angular velocity around Z in radians per second.
Linear damping fraction per second (pybullet
linearDamping). 0.0 = none.Angular damping fraction per second (pybullet
angularDamping). 0.0 = none.Simulation mode. Same
BodyType enum as 2D: DYNAMIC (0), STATIC (1), KINEMATIC (2).Collider3D
Collider3D defines the pybullet collision shape. The MESH shape type uses a triangle mesh from the MeshRegistry.
Fields
Selects the pybullet collision shape:
SPHERE (0), BOX (1), CAPSULE (2), MESH (3).Half-extent along X for
BOX shapes. The full box width is 2 × size_x. Ignored for other shape types.Half-extent along Y for
BOX, or total height for CAPSULE.Half-extent along Z for
BOX shapes.Radius for
SPHERE and CAPSULE shapes.Surface friction coefficient passed to pybullet’s
lateralFriction. Typical range [0.0, 1.0].Bounciness passed to pybullet’s
restitution. 0.0 = no bounce, 1.0 = perfectly elastic.MeshRegistry ID to use when shape_type == ShapeType3D.MESH. The mesh must already be registered before the entity is synced to physics.Collision Events
CollisionEvent2D
Emitted byPhysics2D every tick that two collidable shapes are in contact.
Entity ID of the first participant.
Entity ID of the second participant.
X component of the contact normal (pointing from B toward A).
0.0 for sensor contacts.Y component of the contact normal.
0.0 for sensor contacts.Magnitude of the impulse applied to resolve the contact.
0.0 for sensor contacts.CollisionEvent3D
Emitted byPhysics3D every tick that two pybullet bodies report a contact point.
Entity ID of the first participant.
Entity ID of the second participant.
X coordinate of the contact point in world space.
Y coordinate of the contact point.
Z coordinate of the contact point.
X component of the contact normal.
Y component of the contact normal.
Z component of the contact normal.
PhysicsMaterial2D
PhysicsMaterial2D is a reusable preset that overrides a Collider2D component’s friction and elasticity at body-creation time. Apply it with keel.apply_material(world, entity_id, material) immediately after spawning and flushing the entity.
Built-in presets
| Preset | friction | elasticity |
|---|---|---|
PhysicsMaterial2D.DEFAULT | 0.50 | 0.30 |
PhysicsMaterial2D.BOUNCY | 0.30 | 0.90 |
PhysicsMaterial2D.ICE | 0.05 | 0.10 |
PhysicsMaterial2D.RUBBER | 0.90 | 0.80 |
PhysicsMaterial2D.WOOD | 0.60 | 0.20 |
PhysicsMaterial2D.METAL | 0.30 | 0.10 |
