Skip to content

Text

TextComponent is for free-positioned text on a render layer — a debug HUD overlay, a diegetic floor label, a one-off world-space string that should zoom and rotate with the camera. It’s Transform-synced like a sprite, serializable, and takes a style object that mirrors CSS font properties.

import { TextComponent } from "@yagejs/renderer";
entity.add(new Transform());
entity.add(
new TextComponent({
text: "DEBUG",
layer: "debug",
anchor: { x: 0.5, y: 0 },
style: {
fontFamily: "ui-monospace, monospace",
fontSize: 14,
fill: 0xf8fafc,
fontWeight: "bold",
},
}),
);

Update at runtime with setText() / setStyle(), or tweak tint and alpha directly.

For most “text on screen” cases — HUD cards, score readouts with a backdrop, dialog boxes, nameplates above an enemy, floating damage numbers that should stay axis-aligned at any zoom — UIPanel + UIText from @yagejs/ui is the right answer. You get flexbox layout (padding, gap, alignment), a styled background fill, and child stacking, all of which TextComponent deliberately doesn’t try to provide.

Specifically:

  • Text widget with layout / padding / backdropUIPanel + UIText.
  • Entity-tracked text that stays constant-size at any zoom (nameplates, damage numbers, interaction prompts) → ScreenFollow + UIPanel({ positioning: "transform" }).
  • Free string with no layout, that should follow camera transforms (diegetic floor label, debug overlay, world-pinned billboard text) → TextComponent.

Thin wrapper: the style option forwards as-is to pixi’s TextStyleOptions — full set of CSS-style font properties available (fontFamily, fontSize, fontWeight, fontStyle, fill, letterSpacing, lineHeight, dropShadow, etc.). .text is the underlying pixi Text instance (or BitmapText when bitmap is set). See the pixi Text guide and TextStyle reference for every available option.

Canvas-rasterised Text is bilinear-sampled by the GPU, so it goes blurry the moment it’s drawn at a non-integer scale — a zoomed pixel-art camera, a 4× upscale — on a non-Retina display. BitmapText draws pre-baked glyph quads instead, so it stays crisp. Set the bitmap option (works on TextComponent and UIText alike):

// Zero-config: bake a dynamic bitmap font from this text's own style.
new TextComponent({
text: "SCORE",
bitmap: true,
style: { fontFamily: "monospace", fontSize: 12 },
});
// Render with an installed / loaded bitmap font by name. `size`
// overrides the glyph size.
new TextComponent({ text: "READY", bitmap: { font: "PressStart", size: 16 } });

To bake a bitmap atlas from a .ttf at runtime, use installBitmapFont — it loads the font and returns a name you hand straight to bitmap: { font }:

import { installBitmapFont, TextComponent } from "@yagejs/renderer";
const font = await installBitmapFont("fonts/PressStart2P.ttf", {
name: "PressStart",
size: 16, // glyph bake size (default 32)
resolution: 2, // keeps glyphs crisp when upscaled (default 2)
});
entity.add(new TextComponent({ text: "READY", bitmap: { font } }));

For a pre-built BMFont (.fnt/.xml + atlas), preload the bitmapFont("fonts/x.fnt") handle through a scene’s preload and pass the fontFamily declared in the descriptor as bitmap: { font }. Bitmap text honours the same Yoga word-wrap / truncate behaviour as canvas text inside a UIPanel.

In Pixi v8, resolution is a Text constructor option, not a TextStyle property. Setting TextStyle.defaultTextStyle.resolution does nothing — text stays rasterised at resolution 1 and blurs when scaled. There’s no global toggle; pass resolution per text:

new TextComponent({ text: "HUD", resolution: window.devicePixelRatio });

resolution is ignored when bitmap is set — a bitmap font’s resolution is fixed when its atlas is baked (installBitmapFont({ resolution })). For genuinely pixel-perfect text at any zoom, prefer bitmap over chasing canvas resolution.