How to Sync PixiJS Sprites with Matter.js
Synchronizing PixiJS sprites with Matter.js rigid bodies allows you to leverage Matter.js for accurate 2D physics simulation while using PixiJS for high-performance WebGL rendering. Because Matter.js calculates motion and collision data headlessly without drawing graphics, you must manually bind each visual sprite's position and rotation properties to its corresponding physics body inside an active rendering loop.
1. Align the Sprite Anchor Point
By default, PixiJS positions and rotates sprites relative to their
top-left corner (0, 0). In contrast, Matter.js defines a
body's position and rotation around its center of mass. To ensure the
sprite visually aligns with the physics body during movement and
rotation, set the sprite's anchor to its center:
sprite.anchor.set(0.5);2. Associate the Sprite with the Body
To update pairs efficiently, establish a direct reference between each Matter.js body and its corresponding PixiJS sprite. The simplest method is attaching the sprite directly to the body object:
const body = Matter.Bodies.rectangle(x, y, width, height);
const sprite = PIXI.Sprite.from('texture.png');
sprite.anchor.set(0.5);
// Link the sprite to the body
body.plugin = { sprite: sprite };
Matter.Composite.add(engine.world, body);
app.stage.addChild(sprite);Alternatively, you can maintain an array of paired references:
const physicsPairs = [];
physicsPairs.push({ body, sprite });3. Update Position and Rotation in the Render Loop
Inside the PixiJS ticker or your main
requestAnimationFrame loop, update the physics engine
first, then transfer the calculated coordinates and rotation angles from
the Matter.js body to the PixiJS sprite.
app.ticker.add(() => {
// 1. Advance the physics engine
Matter.Engine.update(engine, app.ticker.deltaMS);
// 2. Sync properties for each paired object
for (const pair of physicsPairs) {
pair.sprite.position.x = pair.body.position.x;
pair.sprite.position.y = pair.body.position.y;
pair.sprite.rotation = pair.body.angle;
}
});Complete Implementation Example
import * as PIXI from 'pixi.js';
import Matter from 'matter-js';
// Setup PixiJS Application
const app = new PIXI.Application({ width: 800, height: 600 });
document.body.appendChild(app.view);
// Setup Matter.js Engine
const engine = Matter.Engine.create();
const world = engine.world;
// Create a Matter.js Box Body
const boxBody = Matter.Bodies.rectangle(400, 100, 60, 60, { restitution: 0.8 });
const groundBody = Matter.Bodies.rectangle(400, 580, 810, 40, { isStatic: true });
Matter.Composite.add(world, [boxBody, groundBody]);
// Create PixiJS Sprites
const boxSprite = PIXI.Sprite.from(PIXI.Texture.WHITE);
boxSprite.width = 60;
boxSprite.height = 60;
boxSprite.tint = 0xff0000;
boxSprite.anchor.set(0.5);
app.stage.addChild(boxSprite);
// Animation Loop
app.ticker.add(() => {
Matter.Engine.update(engine, app.ticker.deltaMS);
// Synchronize coordinates and rotation
boxSprite.position.set(boxBody.position.x, boxBody.position.y);
boxSprite.rotation = boxBody.angle;
});