Documentation
¶
Index ¶
- Constants
- type ActiveContacts
- func (c ActiveContacts) FromProto(p *pbcomponent.ActiveContacts) ActiveContacts
- func (c ActiveContacts) MarshalWire() []byte
- func (ActiveContacts) Name() string
- func (c ActiveContacts) ProtoDescriptor() protoreflect.MessageDescriptor
- func (c ActiveContacts) ToProto() *pbcomponent.ActiveContacts
- func (c ActiveContacts) UnmarshalWire(data []byte) (any, error)
- type BodyType
- type ColliderShape
- type ContactPairEntry
- type PhysicsBody2D
- func (c PhysicsBody2D) FromProto(p *pbcomponent.PhysicsBody2D) PhysicsBody2D
- func (c PhysicsBody2D) MarshalWire() []byte
- func (PhysicsBody2D) Name() string
- func (c PhysicsBody2D) ProtoDescriptor() protoreflect.MessageDescriptor
- func (c PhysicsBody2D) ToProto() *pbcomponent.PhysicsBody2D
- func (p *PhysicsBody2D) UnmarshalJSON(data []byte) error
- func (c PhysicsBody2D) UnmarshalWire(data []byte) (any, error)
- func (p PhysicsBody2D) Validate() error
- type PhysicsSingletonTag
- func (c PhysicsSingletonTag) FromProto(p *pbcomponent.PhysicsSingletonTag) PhysicsSingletonTag
- func (c PhysicsSingletonTag) MarshalWire() []byte
- func (PhysicsSingletonTag) Name() string
- func (c PhysicsSingletonTag) ProtoDescriptor() protoreflect.MessageDescriptor
- func (c PhysicsSingletonTag) ToProto() *pbcomponent.PhysicsSingletonTag
- func (c PhysicsSingletonTag) UnmarshalWire(data []byte) (any, error)
- type ShapeType
- type Transform2D
- func (c Transform2D) FromProto(p *pbcomponent.Transform2D) Transform2D
- func (c Transform2D) MarshalWire() []byte
- func (Transform2D) Name() string
- func (c Transform2D) ProtoDescriptor() protoreflect.MessageDescriptor
- func (c Transform2D) ToProto() *pbcomponent.Transform2D
- func (c Transform2D) UnmarshalWire(data []byte) (any, error)
- func (t Transform2D) Validate() error
- type Vec2
- type Velocity2D
- func (c Velocity2D) FromProto(p *pbcomponent.Velocity2D) Velocity2D
- func (c Velocity2D) MarshalWire() []byte
- func (Velocity2D) Name() string
- func (c Velocity2D) ProtoDescriptor() protoreflect.MessageDescriptor
- func (c Velocity2D) ToProto() *pbcomponent.Velocity2D
- func (c Velocity2D) UnmarshalWire(data []byte) (any, error)
- func (v Velocity2D) Validate() error
Constants ¶
const MaxPolygonVertices = box2d.MaxPolygonVertices
MaxPolygonVertices is the most vertices a ShapeTypeConvexPolygon collider can carry. It is box2d.MaxPolygonVertices, the bound the engine itself compiles in, so ColliderShape.Vertices is sized to exactly what Box2D can accept and the two can never drift apart.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ActiveContacts ¶
type ActiveContacts struct {
Pairs immutable.Slice[ContactPairEntry] `json:"pairs"`
}
ActiveContacts persists which contact pairs have had Begin emitted (and not yet End). After a rebuild, the physics step diffs this against Box2D's live contact list to emit correct Begin/End events without duplicates or missed ends.
func (ActiveContacts) FromProto ¶ added in v0.15.0
func (c ActiveContacts) FromProto(p *pbcomponent.ActiveContacts) ActiveContacts
func (ActiveContacts) MarshalWire ¶ added in v0.15.0
func (c ActiveContacts) MarshalWire() []byte
func (ActiveContacts) Name ¶
func (ActiveContacts) Name() string
func (ActiveContacts) ProtoDescriptor ¶ added in v0.16.4
func (c ActiveContacts) ProtoDescriptor() protoreflect.MessageDescriptor
func (ActiveContacts) ToProto ¶ added in v0.15.0
func (c ActiveContacts) ToProto() *pbcomponent.ActiveContacts
func (ActiveContacts) UnmarshalWire ¶ added in v0.15.0
func (c ActiveContacts) UnmarshalWire(data []byte) (any, error)
type BodyType ¶
type BodyType uint8
BodyType selects how the rigid body participates in the simulation.
const ( // BodyTypeStatic is immovable world geometry; zero velocity; does not respond to forces. BodyTypeStatic BodyType = iota + 1 // BodyTypeDynamic is fully simulated: forces, collisions, and integration apply. BodyTypeDynamic // BodyTypeKinematic is moved by setting velocity from gameplay; Box2D integrates velocity // into position each step. Does not respond to forces but can push dynamic bodies on // contact. Post-step writeback keeps ECS in sync with Box2D's integrated position. BodyTypeKinematic // BodyTypeManual is for gameplay-driven entities that use Box2D only for contact detection. // Under the hood it creates a kinematic body, but post-step writeback is skipped: ECS owns // position and velocity, and the reconciler pushes ECS values into Box2D each tick. // Use this for characters, enemies, and other entities where gameplay code (input handling, // AI, pathfinding) computes position directly. // // Box2D collision rules apply: manual bodies generate contacts with dynamic bodies only, // not with static or other kinematic/manual bodies. BodyTypeManual )
type ColliderShape ¶
type ColliderShape struct {
ShapeType ShapeType `json:"shape_type"`
LocalOffset Vec2 `json:"local_offset"`
LocalRotation float64 `json:"local_rotation"`
IsSensor bool `json:"is_sensor"`
// Geometry (use fields matching ShapeType).
Radius float64 `json:"radius,omitempty"`
HalfExtents Vec2 `json:"half_extents,omitempty"`
Vertices [MaxPolygonVertices]Vec2 `json:"vertices,omitempty"`
ChainPoints immutable.Slice[Vec2] `json:"chain_points,omitempty"`
EdgeVertices [2]Vec2 `json:"edge_vertices,omitempty"`
CapsuleCenter1 Vec2 `json:"capsule_center1,omitempty"`
CapsuleCenter2 Vec2 `json:"capsule_center2,omitempty"`
// Material and per-shape collision filtering (fixture-level in Box2D).
Friction float64 `json:"friction"`
Restitution float64 `json:"restitution"`
Density float64 `json:"density"`
CategoryBits uint64 `json:"category_bits"`
MaskBits uint64 `json:"mask_bits"`
GroupIndex int32 `json:"group_index,omitempty"`
// VertexCount says how many of Vertices' slots are live. It sits at the bottom, away from the
// geometry it belongs to, because the generator numbers proto fields by declaration order and
// the schema rule is append-only: putting it next to Vertices would renumber every field after
// it and silently misread every ColliderShape in an existing snapshot.
VertexCount int `json:"vertex_count,omitempty"`
}
ColliderShape is one child shape inside a compound PhysicsBody2D.
Each entry has its own local transform, sensor flag, material, and collision filter (category, mask, group). Geometry fields are a tagged-union style: only the fields that match ShapeType are used.
- ShapeTypeCircle → Radius
- ShapeTypeBox → HalfExtents (half-width on X, half-height on Y, axis-aligned before LocalOffset/LocalRotation)
- ShapeTypeConvexPolygon → Vertices and VertexCount (convex polygon; see WithVertices)
- ShapeTypeStaticChain → ChainPoints (open polyline in local space)
- ShapeTypeStaticChainLoop → ChainPoints (closed loop in local space)
- ShapeTypeEdge → EdgeVertices (exactly 2 points in local space)
- ShapeTypeCapsule → CapsuleCenter1, CapsuleCenter2, Radius (two semicircles connected by a rectangle)
A polygon has a bound Box2D fixes at MaxPolygonVertices, so Vertices is a fixed array stored inline and VertexCount says how many of its slots are live — the same shape box2d.Polygon uses. A chain has no such bound, so ChainPoints is an immutable.Slice: it travels as the same repeated field a []Vec2 would, and its backing array cannot be indexed or resliced. Its derivations (With, Filter, ...) still write through to the world's column, so always Set the component after one.
ChainPoints encodes as a plain JSON array ("chain_points": [{"x":0,"y":0}, ...]), so a hand-written payload can carry one; snapshots still travel as protobuf via MarshalWire.
func (ColliderShape) FromProto ¶ added in v0.15.0
func (c ColliderShape) FromProto(p *pbcomponent.ColliderShape) ColliderShape
func (ColliderShape) PolygonVertices ¶ added in v0.16.8
func (s ColliderShape) PolygonVertices() []Vec2
PolygonVertices returns the live convex-polygon vertices, i.e. Vertices[:VertexCount]. It returns nil when VertexCount is out of range, which Validate reports as an error.
func (ColliderShape) ToProto ¶ added in v0.15.0
func (c ColliderShape) ToProto() *pbcomponent.ColliderShape
func (ColliderShape) Validate ¶
func (s ColliderShape) Validate() error
Validate checks for NaN/Inf in all float fields, a VertexCount within the polygon bound, and a valid ShapeType tag.
func (ColliderShape) WithVertices ¶ added in v0.16.8
func (s ColliderShape) WithVertices(vertices ...Vec2) ColliderShape
WithVertices returns a copy of s carrying vertices as its convex-polygon geometry, with VertexCount set to match. Slots past VertexCount are zeroed, so a shape reused with fewer vertices carries no leftovers from the longer one.
type ContactPairEntry ¶
type ContactPairEntry struct {
EntityA cardinal.EntityID `json:"a"`
ShapeIndexA int `json:"sa"`
EntityB cardinal.EntityID `json:"b"`
ShapeIndexB int `json:"sb"`
IsSensor bool `json:"sensor"`
// Fixture filters for normalized EntityA/B (recovery End / trigger vs contact routing).
// Omitempty keeps older snapshots valid.
FilterACategoryBits uint64 `json:"fa_cat,omitempty"`
FilterAMaskBits uint64 `json:"fa_mask,omitempty"`
FilterAGroupIndex int32 `json:"fa_grp,omitempty"`
FilterBCategoryBits uint64 `json:"fb_cat,omitempty"`
FilterBMaskBits uint64 `json:"fb_mask,omitempty"`
FilterBGroupIndex int32 `json:"fb_grp,omitempty"`
}
ContactPairEntry is one active contact pair tracked by the physics engine. Entries are normalized: EntityA < EntityB (or if equal, ShapeIndexA <= ShapeIndexB).
func (ContactPairEntry) FromProto ¶ added in v0.15.0
func (c ContactPairEntry) FromProto(p *pbcomponent.ContactPairEntry) ContactPairEntry
func (ContactPairEntry) ToProto ¶ added in v0.15.0
func (c ContactPairEntry) ToProto() *pbcomponent.ContactPairEntry
type PhysicsBody2D ¶
type PhysicsBody2D struct {
BodyType BodyType `json:"body_type"`
LinearDamping float64 `json:"linear_damping"`
AngularDamping float64 `json:"angular_damping"`
GravityScale float64 `json:"gravity_scale"`
Active bool `json:"active"`
Awake bool `json:"awake"`
SleepingAllowed bool `json:"sleeping_allowed"`
Bullet bool `json:"bullet"`
FixedRotation bool `json:"fixed_rotation"`
Shapes immutable.Slice[ColliderShape] `json:"shapes"`
}
PhysicsBody2D holds simulation parameters for a rigid body and its collider shapes.
BodyType selects static vs dynamic vs kinematic behavior. LinearDamping and AngularDamping are simulation damping coefficients. GravityScale multiplies the world's gravity vector for this body; world gravity itself is runtime configuration, not a component field.
Body flags ¶
Active controls whether the body participates in the simulation at all. An inactive body has no contacts, no collisions, and is effectively removed from Box2D without destroying it. Set Active=false to temporarily disable an entity's physics (e.g. a dormant trap).
Awake controls whether the body is currently awake in the simulation. Setting Awake=true wakes a sleeping body; Box2D may put it back to sleep on subsequent ticks if nothing disturbs it and SleepingAllowed is true. The plugin mirrors solver sleep state back into this field after each step, and wakes the body when you change another param without touching Awake. A rebuild (snapshot restore, Plugin.Reset) wakes bodies that had active contacts; others keep their Awake value.
SleepingAllowed controls whether Box2D is permitted to put the body to sleep when it comes to rest. When false, the body stays awake indefinitely.
Note: Box2D v3 processes sensors in a separate overlap pass that runs regardless of body sleep state (only disabled bodies are skipped). Sensor contacts are not affected by sleeping.
Bullet enables continuous collision detection (CCD) for fast-moving dynamic bodies to prevent tunneling through thin geometry. Has a performance cost; only enable for projectiles or similarly fast objects.
FixedRotation prevents the body from rotating in response to torques or collisions. Useful for top-down characters that should not spin.
Shapes ¶
Shapes holds the compound collider description. Cardinal allows one instance per component type per entity, so compound colliders are modeled as multiple ColliderShape entries. Shape identity (v1): index i in Shapes identifies fixture slot i.
Defaults ¶
Box2D defaults Active, Awake, and SleepingAllowed to true and GravityScale to 1. Use NewPhysicsBody2D to create a PhysicsBody2D with these defaults set correctly. Bare struct literals leave bool fields at false and GravityScale at 0, which produces an inactive, sleeping body with no gravity — almost never what you want.
When deserializing from JSON, missing fields are defaulted to their Box2D values automatically via a custom UnmarshalJSON. Explicitly serialized false values are preserved exactly. Snapshots go through MarshalWire/UnmarshalWire (protobuf) rather than JSON: JSON is for hand-written payloads and for logging, not for round-tripping a body the world is holding. (A Slice field such as Shapes or ColliderShape.ChainPoints encodes as a plain JSON array — see immutable.Slice.)
Bullet and FixedRotation default to false (off), matching Box2D defaults.
Post-step writeback ¶
Writeback applies to dynamic and kinematic bodies: position, rotation, velocity and Awake. Static and manual bodies are not written back.
func NewPhysicsBody2D ¶
func NewPhysicsBody2D(bodyType BodyType, shapes ...ColliderShape) PhysicsBody2D
NewPhysicsBody2D returns a PhysicsBody2D with the given body type, Box2D-compatible defaults (Active=true, Awake=true, SleepingAllowed=true, GravityScale=1), and the provided shapes.
func (PhysicsBody2D) FromProto ¶ added in v0.15.0
func (c PhysicsBody2D) FromProto(p *pbcomponent.PhysicsBody2D) PhysicsBody2D
func (PhysicsBody2D) MarshalWire ¶ added in v0.15.0
func (c PhysicsBody2D) MarshalWire() []byte
func (PhysicsBody2D) ProtoDescriptor ¶ added in v0.16.4
func (c PhysicsBody2D) ProtoDescriptor() protoreflect.MessageDescriptor
func (PhysicsBody2D) ToProto ¶ added in v0.15.0
func (c PhysicsBody2D) ToProto() *pbcomponent.PhysicsBody2D
func (*PhysicsBody2D) UnmarshalJSON ¶
func (p *PhysicsBody2D) UnmarshalJSON(data []byte) error
UnmarshalJSON decodes a PhysicsBody2D from JSON, applying Box2D-compatible defaults for fields missing from the payload. This handles old snapshots that predate the body flags (Active, Awake, SleepingAllowed default to true; GravityScale defaults to 1) while preserving explicitly serialized values including false.
func (PhysicsBody2D) UnmarshalWire ¶ added in v0.15.0
func (c PhysicsBody2D) UnmarshalWire(data []byte) (any, error)
func (PhysicsBody2D) Validate ¶
func (p PhysicsBody2D) Validate() error
Validate guards against NaN/Inf in float fields, an invalid body type tag, and invalid shapes.
type PhysicsSingletonTag ¶
type PhysicsSingletonTag struct{}
PhysicsSingletonTag marks the single entity that holds physics plugin state (ActiveContacts).
func (PhysicsSingletonTag) FromProto ¶ added in v0.15.0
func (c PhysicsSingletonTag) FromProto(p *pbcomponent.PhysicsSingletonTag) PhysicsSingletonTag
func (PhysicsSingletonTag) MarshalWire ¶ added in v0.15.0
func (c PhysicsSingletonTag) MarshalWire() []byte
func (PhysicsSingletonTag) Name ¶
func (PhysicsSingletonTag) Name() string
func (PhysicsSingletonTag) ProtoDescriptor ¶ added in v0.16.4
func (c PhysicsSingletonTag) ProtoDescriptor() protoreflect.MessageDescriptor
func (PhysicsSingletonTag) ToProto ¶ added in v0.15.0
func (c PhysicsSingletonTag) ToProto() *pbcomponent.PhysicsSingletonTag
func (PhysicsSingletonTag) UnmarshalWire ¶ added in v0.15.0
func (c PhysicsSingletonTag) UnmarshalWire(data []byte) (any, error)
type ShapeType ¶
type ShapeType uint8
ShapeType selects which geometry fields in ColliderShape are valid.
Callers must set ShapeType consistently with the populated geometry fields. Box2D validates geometry internally (convexity, vertex count, welding) and will panic on invalid input. This is caught during development.
const ( // ShapeTypeCircle uses Radius; fixture is a circle in the shape's local frame. ShapeTypeCircle ShapeType = iota + 1 // ShapeTypeBox uses HalfExtents (half-width, half-height) for an axis-aligned box in the // shape's local frame before applying LocalOffset/LocalRotation. ShapeTypeBox // ShapeTypeConvexPolygon uses the first VertexCount entries of Vertices as a convex polygon // in the shape's local frame. ShapeTypeConvexPolygon // ShapeTypeStaticChain uses ChainPoints for open chain segments (static or kinematic // bodies only; not for dynamic bodies which require mass). ShapeTypeStaticChain // ShapeTypeStaticChainLoop uses ChainPoints for closed chain loops (static or kinematic // bodies only; not for dynamic bodies). Unlike ShapeTypeStaticChain, the last vertex // automatically connects back to the first, creating a sealed boundary. ShapeTypeStaticChainLoop // ShapeTypeEdge uses EdgeVertices (exactly 2 points) for a single line segment // (static or kinematic bodies only). Lighter than a 2-point chain for isolated barriers // or triggers. ShapeTypeEdge // ShapeTypeCapsule uses CapsuleCenter1, CapsuleCenter2, and Radius; fixture is a capsule // (two semicircles connected by a rectangle) in the shape's local frame. ShapeTypeCapsule )
type Transform2D ¶
Transform2D is the authoritative world-space pose of an entity.
Position is the world-space origin of the body transform. Rotation is the world-space orientation in radians (see package doc for handedness and sign).
func (Transform2D) FromProto ¶ added in v0.15.0
func (c Transform2D) FromProto(p *pbcomponent.Transform2D) Transform2D
func (Transform2D) MarshalWire ¶ added in v0.15.0
func (c Transform2D) MarshalWire() []byte
func (Transform2D) ProtoDescriptor ¶ added in v0.16.4
func (c Transform2D) ProtoDescriptor() protoreflect.MessageDescriptor
func (Transform2D) ToProto ¶ added in v0.15.0
func (c Transform2D) ToProto() *pbcomponent.Transform2D
func (Transform2D) UnmarshalWire ¶ added in v0.15.0
func (c Transform2D) UnmarshalWire(data []byte) (any, error)
func (Transform2D) Validate ¶
func (t Transform2D) Validate() error
Validate checks that the transform uses finite scalars only.
type Vec2 ¶
Vec2 is a 2D vector in world space, used by physics-facing components and APIs.
func (Vec2) ToProto ¶ added in v0.15.0
func (c Vec2) ToProto() *pbcomponent.Vec2
type Velocity2D ¶
Velocity2D is the authoritative linear and angular motion state.
Linear is world-space linear velocity. Angular is angular velocity in radians per second about the axis perpendicular to the XY plane (required for rotating rigid bodies and oriented colliders).
func (Velocity2D) FromProto ¶ added in v0.15.0
func (c Velocity2D) FromProto(p *pbcomponent.Velocity2D) Velocity2D
func (Velocity2D) MarshalWire ¶ added in v0.15.0
func (c Velocity2D) MarshalWire() []byte
func (Velocity2D) ProtoDescriptor ¶ added in v0.16.4
func (c Velocity2D) ProtoDescriptor() protoreflect.MessageDescriptor
func (Velocity2D) ToProto ¶ added in v0.15.0
func (c Velocity2D) ToProto() *pbcomponent.Velocity2D
func (Velocity2D) UnmarshalWire ¶ added in v0.15.0
func (c Velocity2D) UnmarshalWire(data []byte) (any, error)
func (Velocity2D) Validate ¶
func (v Velocity2D) Validate() error
Validate checks that linear and angular velocity are finite.