npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@newkrok/nape-pixi

v0.1.0

Published

PixiJS v8 renderer integration for @newkrok/nape-js — body-sprite binding, interpolation, debug draw, worker bridge.

Downloads

147

Readme

@newkrok/nape-pixi

PixiJS v8 renderer integration for @newkrok/nape-js. Keeps PIXI display objects in sync with nape bodies, handles smooth rendering under variable frame rates, provides an on-demand debug overlay, and gives you the plumbing to run physics off-thread in a Web Worker.

Status: 0.1.0-alpha — API is stable. Pending first npm release.

  • Zero bundled dependencies — pixi.js and @newkrok/nape-js are peer deps.
  • Pure structural types: nothing in src/ imports pixi.js at runtime, so you can swap in mocks or headless-render against plain objects.
  • Tree-shakeable. Roughly 10 KB minified ESM, 17 KB d.ts.
  • TypeScript-first, TSDoc on every public export.

Install

npm install @newkrok/nape-pixi @newkrok/nape-js pixi.js

Quickstart

import { Application, Graphics } from "pixi.js";
import { Space, Body, BodyType, Circle, Vec2 } from "@newkrok/nape-js";
import { BodySpriteBinding, FixedStepper } from "@newkrok/nape-pixi";

const app = new Application();
await app.init({ width: 800, height: 600 });
document.body.appendChild(app.canvas);

const space = new Space(new Vec2(0, 400));
const ball = new Body(BodyType.DYNAMIC, new Vec2(400, 50));
ball.shapes.add(new Circle(20));
ball.space = space;

const gfx = new Graphics().circle(0, 0, 20).fill(0x58a6ff);
app.stage.addChild(gfx);

const stepper = new FixedStepper({ hz: 60 });
const binding = new BodySpriteBinding({ stepper });
binding.bind(ball, gfx);

let last = performance.now();
app.ticker.add(() => {
  const now = performance.now();
  const alpha = stepper.step(space, (now - last) / 1000);
  last = now;
  binding.update(alpha);
});

Examples

Self-contained reference code lives in ./examples:

| File | What it shows | | ------------------------------------------------ | ------------------------------------------------------- | | 01-basic.ts | Naive space.stepbinding.update() each frame. | | 02-interpolation.ts | FixedStepper + render-interpolation alpha. | | 03-worker-main.ts + 03-worker.ts | Physics in a Web Worker via WorkerBridge. |

API

BodySpriteBinding

Map nape Body instances to PIXI display targets. Writes x, y, rotation each update(). Supports body-local { offsetX, offsetY } (rotates with the body), re-binding, auto-cleanup on space removal, and optional sub-step interpolation via a FixedStepper.

const binding = new BodySpriteBinding({ stepper });   // stepper is optional
binding.bind(body, sprite);
binding.bind(body, sprite, { offsetX: 4, offsetY: 0 });
binding.update(alpha);                                 // alpha is ignored without a stepper
binding.unbind(body);
binding.dispose();

Without a stepper, alpha is ignored and update() always writes the current body state. With a stepper, the binding subscribes to onBeforeStep to snapshot previous state, and update(alpha) lerps (shortest-path angle, including across ±π).

FixedStepper

Fixed-timestep driver with accumulator, spiral-of-death guard, and before/after hooks.

const stepper = new FixedStepper({
  hz: 60,                // fixed step rate
  maxStepsPerFrame: 5,   // cap catch-up steps
  velocityIterations: 10,
  positionIterations: 10,
});

// once per render frame
const alpha = stepper.step(space, deltaSec);  // runs 0..N steps, returns [0, 1)

Hooks:

const unsub = stepper.onBeforeStep((space) => { /* snapshot, input sample */ });
stepper.onAfterStep((space, dt) => { /* post-step logic */ });
unsub();

PixiDebugDraw

One-line debug overlay. Exposes a PIXI.Container you add to your stage; caches one Graphics per body, rebuilds geometry only on showOutlines flips.

import * as PIXI from "pixi.js";
import { PixiDebugDraw } from "@newkrok/nape-pixi";

const debug = new PixiDebugDraw({ pixi: PIXI });
app.stage.addChild(debug.container);

app.ticker.add(() => {
  space.step(1 / 60);
  debug.render(space);
});

// Toggles — live
debug.drawShapes = true;
debug.drawConstraints = true;
debug.showOutlines = false;

Supports Circle, Polygon, Capsule. Constraint lines are drawn for any joint carrying body1 + body2 (PivotJoint, DistanceJoint, WeldJoint, …). Colour policy: colorResolver override → static colour → sleeping colour → palette (cycled by insertion order).

WorkerBridge + transform protocol

Protocol for shuttling body transforms between a physics worker and the main thread. The library does not ship a worker script — you write it — but provides everything else.

// Main thread
import { WorkerBridge, createTransformsBuffer } from "@newkrok/nape-pixi";

const alloc = createTransformsBuffer(1024);
const worker = new Worker(new URL("./physics-worker.ts", import.meta.url),
  { type: "module" });
const bridge = new WorkerBridge({ worker, transforms: alloc.transforms });

worker.postMessage({
  type: "init",
  buffer: alloc.isShared ? alloc.buffer : null,
  maxBodies: 1024,
});
await bridge.ready;

for (let i = 0; i < sprites.length; i++) bridge.setSprite(i, sprites[i]);

app.ticker.add(() => bridge.applyTransforms());
// Worker
import { Space } from "@newkrok/nape-js";
import { writeTransforms } from "@newkrok/nape-pixi";

// ... on "init", build your Space and wire `transforms`
setInterval(() => {
  const t0 = performance.now();
  space.step(1 / 60);
  writeTransforms(space, transforms, maxBodies, performance.now() - t0);
  self.postMessage({ type: "frame" });   // + transforms copy when non-shared
}, 1000 / 60);

Buffer layout (Float32Array, little-endian):

| Offset | Meaning | | -------------- | ------------------------------------------- | | 0 | Body count written this frame | | 1 | space.timeStamp at write | | 2 | Step cost (ms) measured by the worker | | 3 + i*3 … +2 | Body i: x, y, rotation |

Slots correspond to space.bodies iteration order — append-only flows give stable mappings; if you remove bodies from the middle, re-assign sprite slots accordingly.

createTransformsBuffer() allocates a SharedArrayBuffer when the runtime allows it (cross-origin-isolated contexts with COOP/COEP headers) and falls back to a plain ArrayBuffer otherwise.

Migrating from docs/renderers/pixijs-adapter.js

The engine's demo site bundles a PIXI adapter (PixiJSAdapter) that is demo-runner specific — it entangles attach/detach lifecycle, a 2D HUD overlay, a worker-transform path, and per-body colour conventions from userData._colorIdx / _color. @newkrok/nape-pixi replaces the reusable pieces and drops the demo-only ones.

| PixiJSAdapter feature | Equivalent in @newkrok/nape-pixi | | ---------------------------------- | ------------------------------------------------------ | | attach(container, W, H) | You own the Application. The debug draw exposes its own PIXI.Container. | | Per-body Graphics + transform sync | BodySpriteBinding (for your sprites) or PixiDebugDraw (for diagnostics). | | renderFromTransforms(...) | WorkerBridge.applyTransforms(). | | setOutlines(show) | debug.showOutlines = show. | | userData._colorIdx / _color | colorResolver(body) => number \| null option. | | 2D HUD overlay (getOverlayCtx) | Out of scope — draw your own canvas / PIXI.Text. |

The visual output matches: same default palette, same default alphas, same circle/polygon/capsule geometry.

License

MIT © Istvan Krisztian Somoracz