Text & Fonts

You may want to display Text in your game, this can be achieved with the Text, Font, and SpriteFont.

Font or SpriteFont or HTML?

Excalibur currently supports 2 different types of text out of the box. We generally recommend using HTML where you can for UI, because it's really good at that!

  1. Font which will source a CSS loaded font from the browser
  2. SpriteFont which will source an image to source glyphs for text

You should use a SpriteFont when you really care about how the look and feel of the glyphs. For example, if you have a pixel art game and not having anti-aliased text is important to you you should use a SpriteFont. If you specifically don't want blurry text at lower game resolutions you should use a SpriteFont.

You should use a Font if you want to leverage CSS fonts and want smoothed text or emojis to display. Font works best at higher game resolutions.

Text

Text is a raster graphic that can be used to draw text to the screen, all of the normal things that can be done with rasters and graphics can be done with text.

Text supports both normal OS/web fonts and Sprite fonts.

Example

var text = new ex.Text({
  text: 'This is raster text ❤️',
  font: new ex.Font({ size: 30 }),
})

Text is a prebuilt Graphic that can be used to draw text to the screen. Multiple lines of text are supported.

const game = new ex.Engine({...});
const text = new ex.Text({
    text: 'Some Text Drawn Here\nNext line'
});

const actor = new ex.Actor({
    pos: ex.vec(100, 100)
});
actor.graphics.use(text);

game.currentScene.add(actor);

Text also supports word wrapping, this can be done by setting the maxWidth property on the text options.

const text = new ex.Text({
    text: 'Some Text Drawn Here\nNext line'
    maxWidth: 200 // pixels
});

Labels

Labels are a batteries included Actors with Text built and font built in.

const label = new ex.Label({
  text: 'Some text',
  pos: ex.vec(100, 100),
  font: new ex.Font({
    family: 'impact',
    size: 24,
    unit: ex.FontUnit.Px,
  }),
})

Font

A Font is a traditional system or loaded web font.

Possible font options

export interface FontOptions {
  size?: number
  unit?: FontUnit
  family?: string
  style?: FontStyle
  bold?: boolean
  textAlign?: TextAlign
  baseAlign?: BaseAlign
  direction?: Direction
  shadow?: {
    blur?: number
    offset?: Vector
    color?: Color
  }
}
var text = new ex.Text({
  text: 'This is raster text ❤️',
  font: new ex.Font({
    size: 30,
    unit: FontUnit.Px,
    family: 'sans-serif',
    style: FontStyle.Normal,
    bold: false,
    textAlign: TextAlign.Left,
    baseAlign: BaseAlign.Alphabetic,
    direction: Direction.LeftToRight,
    shadow: {
      blur: 2,
      offset: ex.Vec(2, 2),
      color: ex.Color.Black,
    };
  })
});

It is recommended you load any font important to your game and not rely on any pre-installed system fonts, those will be different from computer to computer.

For example the google fonts loader is a common way to do this.

<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
  href="https://fonts.googleapis.com/css2?family=Roboto:wght@100&display=swap"
  rel="stylesheet"
/>
const font = new ex.Font({
  family: 'Roboto',
  size: 24,
  unit: ex.FontUnit.Px,
})

One potential issue with using web fonts is they won't render correctly until loaded see article for details.

async function waitForFontLoad(font, timeout = 2000, interval = 100) {
  return new Promise((resolve, reject) => {
    // repeatedly poll check
    const poller = setInterval(async () => {
      try {
        await document.fonts.load(font);
      } catch (err) {
        reject(err);
      }
      if (document.fonts.check(font)) {
        clearInterval(poller);
        resolve(true);
      }
    }, interval);
    setTimeout(() => clearInterval(poller), timeout);
  });
}

// Load font before game start
await waitForFontLoad('24px Roboto');

const game = new ex.Engine({...})
await game.start();

SpriteFont

Sometimes you want to use a custom font based on a sprite sheet of character glyphs

Custom pixel art glyphs
const image = new ex.ImageSource('./path/to/sprite-font.png')

const spriteSheet = SpriteSheet.fromImageSource({
  image: image,
  grid: {
    rows: 3,
    columns: 16,
    spriteWidth: 16,
    spriteHeight: 16,
  },
})

const spriteFont = new SpriteFont({
  alphabet: '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ,!\'&."?-()+ ',
  caseInsensitive: true,
  spriteSheet: spriteSheet,
  spacing: -6,
})

const text = new ex.Text({
  text: 'some text with a sprite font!',
  font: spriteFont,
})

SpriteFont

Sometimes you want to use text of your own creation from a spritesheet,

const spriteFontSheet = ex.SpriteSheet.fromImageSource({
  image: spriteFontImage,
  grid: {
    rows: 3,
    columns: 16,
    spriteWidth: 16,
    spriteHeight: 16
  }
});

const spriteFont = new ex.SpriteFont({
    alphabet: '0123456789abcdefghijklmnopqrstuvwxyz,!\'&."?- ',
    caseInsensitive: true,
    spriteSheet: spriteFontSheet
  });
});

const text = new ex.Text({
  text: 'This is sprite font text!!',
  font: spriteFont
});