component

package
v0.16.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 4, 2026 License: LGPL-3.0 Imports: 8 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ActiveContacts

type ActiveContacts struct {
	Pairs []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 (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 (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       []Vec2  `json:"vertices,omitempty"`
	ChainPoints    []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"`
}

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 (convex polygon, respect backend limits)
  • 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)

func (ColliderShape) FromProto added in v0.15.0

func (ColliderShape) ToProto added in v0.15.0

func (ColliderShape) Validate

func (s ColliderShape) Validate() error

Validate checks for NaN/Inf in all float fields and a valid ShapeType tag.

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 (ContactPairEntry) ToProto added in v0.15.0

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 []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 (e.g. snapshot recovery), missing fields are defaulted to their Box2D values automatically via a custom UnmarshalJSON. Explicitly serialized false values are preserved exactly.

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 (PhysicsBody2D) MarshalWire added in v0.15.0

func (c PhysicsBody2D) MarshalWire() []byte

func (PhysicsBody2D) Name

func (PhysicsBody2D) Name() string

Name returns the ECS component name.

func (PhysicsBody2D) ProtoDescriptor added in v0.16.4

func (c PhysicsBody2D) ProtoDescriptor() protoreflect.MessageDescriptor

func (PhysicsBody2D) ToProto added in v0.15.0

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 (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 (PhysicsSingletonTag) ToProto added in v0.15.0

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 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

type Transform2D struct {
	Position Vec2    `json:"position"`
	Rotation float64 `json:"rotation"`
}

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 (Transform2D) MarshalWire added in v0.15.0

func (c Transform2D) MarshalWire() []byte

func (Transform2D) Name

func (Transform2D) Name() string

Name returns the ECS component name.

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

type Vec2 struct {
	X float64 `json:"x"`
	Y float64 `json:"y"`
}

Vec2 is a 2D vector in world space, used by physics-facing components and APIs.

func (Vec2) FromProto added in v0.15.0

func (c Vec2) FromProto(p *pbcomponent.Vec2) Vec2

func (Vec2) ToProto added in v0.15.0

func (c Vec2) ToProto() *pbcomponent.Vec2

type Velocity2D

type Velocity2D struct {
	Linear  Vec2    `json:"linear"`
	Angular float64 `json:"angular"`
}

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) Name

func (Velocity2D) Name() string

Name returns the ECS component name.

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL