Skip to content

How to use sprite sheets with GameMaker

Joachim Grill
Last updated:
GitHub
How to use sprite sheets with GameMaker

In this tutorial you are going to learn:

  • How to pack sprite strips and grids with TexturePacker, and import them into GameMaker
  • How to pack your sprites tightly, so they need less memory
  • How to load a packed sheet as a GameMaker texture group, where the sprites become regular sprite assets
  • How to load a packed sheet with a loader script, for HTML5 and older GameMaker versions

The complete tutorial project is available on GitHub.

Which method should I use?

TexturePacker offers four ways to get your sprites into GameMaker. They differ in what you end up with on the GameMaker side — animation frames of a single sprite, or a set of independent sprite assets — and in which GameMaker versions and targets support them.

MethodGameMakerSprites becomeNotes
Sprite strip / gridany versionframes of one spritea single animation of equally sized sprite frames
Texture group format2024.14 or newerregular sprite assetsthe recommended route; not on HTML5 / GX.games
Loader script formatany versiondrawn by a scriptworks everywhere; sprites can be rotated on the sprite sheet for a better pack rate

If you are on GameMaker 2024.14 or newer and don't build for HTML5, use the texture group format: it packs your sprites tightly and gives you normal sprite assets to work with. Use the loader script format when you need HTML5, an older GameMaker, or the tighter packing that rotated sprites allow.

Install TexturePacker

With TexturePacker you can easily create sprite sheets for GameMaker. Download TexturePacker, it is available for macOS, Windows and Linux. You can test it within a 7-day trial period before purchasing a license:

Create a sprite strip

Start TexturePacker and drop the sprites that should be packed onto TexturePacker's main window. You can also drop folders, TexturePacker will automatically scan them for image files and add them to the sheet.

Make sure that no Framework is selected ("Choose Data Format" button must be displayed). Otherwise, click on the button and choose "Sprite sheet only".

Create sprite strip with TexturePacker
  1. After dropping your animation sprites on TexturePacker, in the center view a preview of the packed sprite sheet is displayed.
  2. Use the folder icon to open a file selector and set the file name for the packed Texture file.
  3. Select algorithm Grid / Strip. TexturePacker will pack the sprites in alphabetical order from left to right, until the maximum texture size is reached.
  4. Export sprite sheet will save the sprite sheet texture on disk.

Please make sure that the texture file name has a _stripN suffix. The number N tells GameMaker the number of frames in which the strip should be split during import.

Import sprite strip in GameMaker

In GameMaker simply drop the sprite sheet on the Sprites folder of the Asset Browser:

Import sprite strip in GameMaker

GameMaker automatically imports the sprite sheet and opens the sprite editor. At the bottom of the sprite editor window you can see the individual sprite frames in which the sheet has been split, according to the file name suffix.

If you've changed the sprite sheet, use the Import button to re-import the new sprite sheet.

Pack sprites with grid layout

In TexturePacker's Grid / Strip mode, sprites are packed as a strip from left to right until the maximum texture width is reached. Then a new line of sprites is started, and the sprites are placed on a grid:

Create a grid layout with TexturePacker

Of course, you can increase the Max size of the texture to get all sprites packed as a strip. But in this section we will learn how to import a sprite sheet with grid layout.

First, don't add a _stripN suffix to the sprite sheet's file name, because we don't want GameMaker to split the sheet automatically.

Import sprite sheet with grid layout in GameMaker

After importing the sprite sheet in GameMaker, click on Edit Image in the sprite editor. Then select Convert to Frames from the Image menu:

Split sprite sheet with GameMaker

To split the sheet in sprite frames you have to enter...

  • the total number of sprite frames
  • the sprites per row
  • the size of a sprite frame

On the right side of the window a preview of the sprite frames is displayed.

With the Horizontal / Vertical Cell Offset the top-left corner of the grid can be set. To extract the "betty-run-left" sprites in our example, we skip the first column and row by setting the cell offsets to 1 and reduce the number of frames to 5:

Split sprite sheet with additional offset

Drawbacks

... of the strip/grid layout as described above:

  • Equal sized frames:
    All cells of a strip or grid have the same size. If your sprites differ in size, a lot of space is wasted.

  • Only a convenient solution for animations:
    All sprites of a sprite sheet are grouped in one GameMaker Sprite as animation frames. But individual sprites of the sheet cannot be accessed independently, and they cannot be referenced by name.

  • Sprite sheets are re-packed:
    When a sprite strip sheet is imported and split by GameMaker, the individual sprite images are saved in your project directory. The sheet image is no longer needed after importing it. During the build, the sprites are packed on internal sprite sheets, which are squared and have a "power-of-two" size (e.g. 2048x2048). This size constraint often wastes memory due to unused texture space.

  • Texture embedding:
    For some platforms, GameMaker embeds the internally generated sprite sheets in the executable. For large games, the executable will get very big. If memory, address space, or loader performance is limited, this might be a problem.

Create a tightly packed sprite sheet

With TexturePacker you can pack your sprites more tightly than using a grid layout. The sprite name and the position on the sprite sheet are written to a JSON data file.

TexturePacker offers two data formats for GameMaker. They differ in how you load the sheet at runtime:

  • Texture group format — GameMaker builds a native texture group from the sheet and you access the sprites as regular Sprite assets. Needs GameMaker 2024.14 or newer.
  • Loader script format — a small helper script draws the sprites straight from the sheet. Works with every GameMaker version and on HTML5.

TexturePacker provides a large number of packer options to reduce the size of the resulting sprite sheets, whichever format you choose:

  • Sprite sheet size need not be squared or power-of-two.
  • Texture image can be saved with reduced color space to optimize file size.

Here's a comparison of the sprite sheets GameMaker would generate internally (when using individual sprites or sprite strip/grids) vs packed with TexturePacker:

packed with GameMaker
2048 x 2048, RGBA8888 PNG
2472 kB (on disk)

Sprite sheet internally generated by GameMaker

packed with TexturePacker
2002 x 1692, 8-bit indexed PNG
196 kB (on disk)

Sprite sheet generated with TexturePacker

Texture group format

GameMaker's texturegroup_add() builds a texture group from an external sprite sheet at runtime — in GameMaker 2024.14 or newer, and not on HTML5 or GX.games. The sprites become regular sprite assets: GameMaker animates them for you, and you can use image_index and draw_self() as with any other sprite. No helper script is required.

  1. Select GameMaker (texturegroup) as Framework
  2. Specify the file name for the Data file. By default, the Texture file will be saved in the same directory.
  3. Choose MaxRects as Algorithm. Rotation is not available for this format — the GameMaker texture group format cannot store rotated sprites, so TexturePacker does not offer a rotation option here.
Export a GameMaker texture group with TexturePacker

Animations are detected automatically, so walk/0001.png … walk/0016.png become a single 16-frame sprite instead of 16 separate ones. You can turn that off with Auto-detect animations in the Advanced settings, and set the playback speed with Frame speed (fps) — it defaults to 30, the demo project uses 12.

Publish into the datafiles folder

Publish the data file and the texture into the datafiles folder of your GameMaker project — any subfolder is fine. datafiles is GameMaker's fixed Included Files root, and its content becomes the working directory at runtime, so datafiles/spritesheets/cityscene-texturegroup.json is loaded as "spritesheets/cityscene-texturegroup.json".

GameMaker lists both files in the Included Files panel:

GameMaker: Included files

Load the sprite sheet

Loading takes four lines, and no script needs to be added to your project. Put them in the Create event of a controller object — oScene in our example — and create the objects that use the sprites right after, so the sheet is loaded before anything looks a sprite up:

var _buf  = buffer_load("spritesheets/cityscene-texturegroup.json");
var _json = json_parse(buffer_read(_buf, buffer_text));
buffer_delete(_buf);
texturegroup_add("cityscene", _json.textures, { sprites: _json.sprites });

instance_create_layer(1400, 850, "Player", oPlayerTextureGroup);

Read the buffer with buffer_text — the data file is plain text without a NUL terminator.

TexturePacker reduces the file names to valid identifiers: capguy/walk/0001.png becomes capguy_walk when it is part of a detected animation, or capguy_walk_0001 when it is a single image. Assign such a sprite in the object that uses it — oPlayerTextureGroup in our example — and GameMaker plays the animation for you, with no Draw event and no manual frame counting:

sprite_index = asset_get_index("capguy_turn");

Release the texture group when it is no longer needed, for example in the cleanup event. texturegroup_add() raises a fatal error if a group with that name already exists.

texturegroup_delete("cityscene");

Advantages

  • The sprites are regular sprite assets — image_index and draw_self() both work.
  • GameMaker plays the animations; you don't implement frame timing yourself.
  • No loader script in your project.
  • Trimming and 9-patch borders (which become nine-slice data) are carried over from TexturePacker automatically. Pivot points carry over too, and become the sprite origin, but only when TexturePacker's write pivot points setting is enabled.

Drawbacks

  • Requires GameMaker 2024.14 or newer (including LTS 2026), and does not work on HTML5 or GX.games.
  • Sprites cannot be rotated on the sheet, so the packing is slightly less tight than with the loader script format.
  • These sprites only exist at runtime, once texturegroup_add() has run: there is no Asset Browser entry to browse or drag into a room, and the only way to reach one is asset_get_index().

Loader script format

Use this format when you build for HTML5 or GX.games, when you target a GameMaker older than 2024.14.

  1. Select GameMaker (loader script) as Framework
  2. Specify the file name for the Data file. By default, the Texture file will be saved in the same directory.
  3. Choose MaxRects as Algorithm.
Pack sprite sheet with TexturePacker's MaxRects algorithm

Add the generated sprite sheet and data file into the datafiles folder, following the same folder placement described above.

To load the sprite sheet, add the following script from our GitHub example repository to your project:

SpriteSheetLoader.gml

The script provides two methods, the first one is used to load the JSON data file and the texture image. You can call it in the creation code of your room or scene, and store the handle in a global variable:

global.atlas_cityscene = tp_load_texture_atlas("spritesheets/cityscene.json");

To draw a sprite from the atlas, use the following function:

tp_draw_sprite_from_atlas(global.atlas_cityscene, "Background.png", 0, 0);
...

tp_draw_sprite_from_atlas(global.atlas_cityscene, "capguy/walk/0001.png", x, y);

The function also accepts optional scale and rotation parameters: tp_draw_sprite_from_atlas(atlas, name, x, y, scale_x = 1, scale_y = 1, angle = 0).

If the atlas is no longer needed, it should be released to avoid memory leaks. This can be done in the cleanup event handler:

tp_release_texture_atlas(global.atlas_cityscene);

For a demo application please check out this GitHub repository. It displays a scene background and an animated player character:

Screenshot of demo app

Advantages

  • Works with every GameMaker version and on every target, including HTML5 and GX.games.
  • TexturePacker can rotate sprites for improved pack ratios — the texture group format cannot do this.

Drawbacks

Loading external sprite sheets at runtime also comes with some drawbacks:

  • Since the sprites of the sprite sheet are not accessible as Sprite objects in GameMaker, they cannot be added to a layer via drag-and-drop.
  • The sprite sheet loader cannot add multiple animation frames to one sprite object, that's why animations must be implemented manually. However, as demonstrated in our GitHub example, this is quite simple.