GameMaker: Optimal text shadows

Time to time people come up with strange, slow-ish methods for drawing text with shadows in GameMaker. This is a tutorial about how to achieve the best effect without any of those struggles.

For this tutorial, aside of GameMaker, you'll need two programs:

  • BmFont: A free and open-source bitmap font generator.
  • BmFontToGMX: A tool of mine for converting BMFont' fonts into GMS-compatible formats.

Once both are installed, open BMFont, and configure the font settings as per guide on BmFontToGMX page (or import settings from the file provided in

Then, you'll want to change font settings for your case.

On "Font Settings", set the font, size, style, and "rasterization options". The later affect how font will be output, and you can tweak this until the font looks as crisp/smooth as you want (accept changes and press V to preview the font).

On "Export Options", you need two things:

  • Tweak "padding" to extend far enough for your desired shadow settings.
    For example, if you want shadow to extend 5 pixels outwards and be shown at offset (1, 2), you'd want to set top=(5-2)=3, left=(5-1)=4, right=(5+1)=6, bottom=(5+2)=7.
    Here I'm doing a 5px shadow at 1,1 offset so the padding is set to left=4,top=4,right=6,bottom=6.
  • Tweak the "Width" and "Height" to be 2N (128, 256, 512, 1024, ...) values that are large enough for you font to fit onto a single "page" when previewing (title showing "1/1").

Once all is done and your font fits into one page on preview, export two copies of it - one is going to be the font' color, and other is going to be the font' shadow. I'm going to name them fnt_test0 (shadow) and fnt_test1 (color) accordingly.

Now, it's time to add the shadow. If you are using Paint.NET, you can use this plugin for "Filters - Object - Drop Shadow". Most other editors have a built-in effect for shadows. In worst case, you can simply apply "guassian blur" for shadow blurring and move the image around for shadow offset.

If you are using the linked PDN plugin, you would change the settings as intended, before finally changing the color to white and unticking "keep original image".

The result should look like following:

Next, you would convert both fonts to GMS fonts by dragging the .fnt files onto BmFontToGMX executable inside the "bin" directory.

Then, you would import both fonts into your GMS projects by dragging files onto the GameMaker: Studio window with the project open.

So now to the actual trick - to draw text with a shadow, you set the font to blurry/shadowy one and color to shadow' color, draw the text once (producing a shadow), then set the font to regular one and color to text' color, and draw it at the same location to produce text on top of shadow.

For example, for the post' demo I made this simple script:

/// test_text_shadow(x, y, text)
var _x = argument0;
var _y = argument1;
var s = argument2;
var c = draw_get_color();
// draw shadow:
draw_text(_x, _y, s);
// draw color:
draw_text(_x, _y, s);

Allowing to do

test_text_shadow(room_width/2, room_height/2, "Hello World!");

To produce the text with a fancy shadow as shown in the beggining of the post:

Additional notes:

  • If you are calculating/applying the shadow' offset programmatically, you can keep even padding on all sides of the font when exporting.
  • The same approach can be used for outlines, glow, and numerous other text effects.
  • You can use Littera (with fnt export format) instead of BMFont, but only with pack methods 6/7.

You can also download the Sample GMZ with the resulting fonts and script from this tutorial if you like.

Related posts:

2 thoughts on “GameMaker: Optimal text shadows

  1. unless i’ve gotten something wrong, it looks like bmfont only converts existing fonts into usable textures. is there any way to create a new [pixel] font from scratch?

    • Indeed, it is for rendering generally-vector fonts.

      If you have a pixel font, you could just add it as a sprite and use font_add_sprite\font_add_sprite_ext to convert it to a font when the game’s running.

Leave a Reply

Your email address will not be published. Required fields are marked *