Physics drawing components
Draw four physics shapes and move a custom kinematic collider.
APIs demonstrated
Section titled “APIs demonstrated”- PhysicsShape2D from
@pibbl/core/physics/2d - Capsule2D from
@pibbl/core/physics/2d - Segment2D from
@pibbl/core/physics/2d - Chain2D from
@pibbl/core/physics/2d - kinematicBody2D from
@pibbl/core/physics/2d - withPhysicsShape2D from
@pibbl/core/physics/2d - PibblPhysicsKinematicBody2DOptions from
@pibbl/core/physics/2d - PibblPhysicsKinematicTarget2D from
@pibbl/core/physics/2d - PibblPhysicsAttachment2D from
@pibbl/core/physics/2d - PibblPhysicsBodyAttachment2D from
@pibbl/core/physics/2d - PibblPhysicsColliderAttachment2D from
@pibbl/core/physics/2d - PibblPhysicsPrimitiveProps2D from
@pibbl/core/physics/2d - PibblPhysics2DPropExtension from
@pibbl/core - PhysicsShape2DProps from
@pibbl/core/physics/2d - PhysicsShape2DStyle from
@pibbl/core/physics/2d - Capsule2DProps from
@pibbl/core/physics/2d - Capsule2DStyle from
@pibbl/core/physics/2d - Segment2DProps from
@pibbl/core/physics/2d - Segment2DStyle from
@pibbl/core/physics/2d - Chain2DProps from
@pibbl/core/physics/2d - Chain2DStyle from
@pibbl/core/physics/2d
Complete example
Section titled “Complete example”Plain source. Run as a browser module after the document body exists. TSX uses jsx: "react-jsx" and jsxImportSource: "@pibbl/core".
import { Group, pibbl, definePrimitive, signal, type PibblPhysics2DPropExtension, type SystemStyle } from '@pibbl/core';import { Capsule2D, Chain2D, PhysicsShape2D, PhysicsWorld2D, Segment2D, boxShape2D, collider2D, kinematicBody2D, withPhysicsShape2D, type Capsule2DProps, type Capsule2DStyle, type Chain2DProps, type Chain2DStyle, type PibblPhysicsAttachment2D, type PibblPhysicsBodyAttachment2D, type PibblPhysicsColliderAttachment2D, type PibblPhysicsKinematicBody2DOptions, type PibblPhysicsKinematicTarget2D, type PibblPhysicsPrimitiveProps2D, type PibblPhysicsVector2, type PhysicsShape2DProps, type PhysicsShape2DStyle, type Segment2DProps, type Segment2DStyle,} from '@pibbl/core/physics/2d';
const canvas = document.createElement('canvas');canvas.width = 360;canvas.height = 200;document.body.append(canvas);
const capsuleStyle: Capsule2DStyle = { start: [20, 40], end: [95, 40], radius: 12, fill: '#0f766e',};const segmentStyle: Segment2DStyle = { start: [20, 85], end: [115, 85], stroke: '#be123c', strokeWidth: 4,};const chainStyle: Chain2DStyle = { points: [[20, 125], [80, 145], [135, 125]], radius: 3, stroke: '#1d4ed8', strokeWidth: 2,};const shapeStyle: PhysicsShape2DStyle = { shape: boxShape2D({ width: 34, height: 26, center: [185, 130] }), fill: '#f59e0b',};const decorative: PibblPhysicsPrimitiveProps2D = { pointerEvents: 'none' };const capsuleProps: Capsule2DProps = decorative;const segmentProps: Segment2DProps = decorative;const chainProps: Chain2DProps = decorative;const shapeProps: PhysicsShape2DProps = decorative;
interface DiamondStyle extends SystemStyle { readonly size: number }const RawDiamond = definePrimitive<{}, DiamondStyle>((_props, style, context) => { const half = style.size / 2; context.beginPath(); context.moveTo(0, -half); context.lineTo(half, 0); context.lineTo(0, half); context.lineTo(-half, 0); context.closePath(); context.fillStyle = '#7c3aed'; context.fill();});const Diamond = withPhysicsShape2D(RawDiamond, { resolveShape: (style: Readonly<DiamondStyle>) => boxShape2D({ width: style.size, height: style.size }),});
const position = signal<PibblPhysicsVector2>([260, 70]);const target: PibblPhysicsKinematicTarget2D = { position };const kinematicOptions: PibblPhysicsKinematicBody2DOptions = { target, collider: false };const bodyAttachment: PibblPhysicsBodyAttachment2D = kinematicBody2D(kinematicOptions);const colliderAttachment: PibblPhysicsColliderAttachment2D = collider2D({ tag: 'moving-diamond' });const attachment: PibblPhysicsAttachment2D = colliderAttachment;const diamondPhysics: PibblPhysics2DPropExtension = { physics: attachment };
function MovingDiamond() { const [x, y] = position.get(); return <Group physics={bodyAttachment} style={{ translateX: x, translateY: y }}> <Diamond {...diamondPhysics} style={{ size: 28 }} /> </Group>;}
const controller = pibbl(canvas, <PhysicsWorld2D gravity={[0, 0]}> <Capsule2D {...capsuleProps} style={capsuleStyle} /> <Segment2D {...segmentProps} style={segmentStyle} /> <Chain2D {...chainProps} style={chainStyle} /> <PhysicsShape2D {...shapeProps} style={shapeStyle} /> <MovingDiamond /> </PhysicsWorld2D>,);
const button = document.createElement('button');button.textContent = 'Move diamond';button.addEventListener('click', () => { position.set([position.get()[0] === 260 ? 300 : 260, 70]);});document.body.append(button);window.addEventListener('pagehide', () => controller.dispose(), { once: true });Usage notes
Section titled “Usage notes”- The derived primitive supplies collider geometry through a pure shape resolver.
Documentation version
Section titled “Documentation version”Documentation built with @pibbl/core 0.0.2, revision 2dccb19. ALPHA — NOT FOR PRODUCTION USE.