Pixi.js TilingSprite Texture Repeating and Scrolling

This article explains how to use the TilingSprite class in Pixi.js to create repeating texture patterns and infinite scrolling backgrounds. You will learn how to instantiate a TilingSprite, control the scale of the repeated pattern, and animate the texture coordinates to achieve a seamless scrolling effect.

Understanding TilingSprite

In Pixi.js, a standard Sprite stretches or squishes its texture to fit its dimensions. A TilingSprite, however, repeats (tiles) the texture to fill its defined width and height. This makes it the ideal tool for creating repeating background patterns, infinite side-scroller backgrounds, or repeating terrain in games.

Creating a TilingSprite

To create a TilingSprite, you need a texture, a target width, and a target height.

import * as PIXI from 'pixi.js';

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

// Load the texture
const texture = await PIXI.Assets.load('path/to/pattern.png');

// Create the TilingSprite (texture, width, height)
const tilingSprite = new PIXI.TilingSprite({
    texture: texture,
    width: app.screen.width,
    height: app.screen.height
});

app.stage.addChild(tilingSprite);

Controlling the Texture Scale

By default, the texture is drawn at its original resolution. If you want to scale the repeating pattern inside the sprite without changing the sprite’s actual width and height, use the tileScale property.

// Scale the repeating pattern to 50% of its original size
tilingSprite.tileScale.set(0.5, 0.5);

// Scale the pattern independently on the X and Y axes
tilingSprite.tileScale.x = 0.8;
tilingSprite.tileScale.y = 1.2;

Implementing Texture Scrolling

To create a scrolling effect, you must manipulate the tilePosition property. This property offsets the starting point of the repeating texture. By updating this offset inside the Pixi.js animation ticker, you create a continuous, infinite scroll.

// Set an initial offset
tilingSprite.tilePosition.set(0, 0);

// Update the position in the game loop
app.ticker.add((ticker) => {
    // Scroll horizontally to the left
    tilingSprite.tilePosition.x -= 2 * ticker.deltaTime;

    // Scroll vertically downwards
    tilingSprite.tilePosition.y += 1 * ticker.deltaTime;
});

Because the texture repeats infinitely inside the TilingSprite boundaries, modifying tilePosition will never run out of image data, resulting in a smooth and lightweight scrolling performance.