« Back to tutorial listing

— Sprite Atlas Tutorial —
Part 3: Creating the atlas meta data

Note: this tutorial assumes knowledge of C, as well as prior tutorials.

Introduction

In the previous two tutorials, we gathered the details of the images we wanted to add to our atlas, and ran through the process of actually creating it. The final step is to output the meta data, so the atlas can be used by games and applications that require it. We'll be outputting the details of the added images as a JSON array, since the format is easy to read and understand, and is well supported. Using some C code written by Dave Gamble, we can easily marshall our data into JSON (and read it back later). Extract the archive, run cmake CMakeLists.txt, followed by make, and then run it with ./gen03. You'll now see both the atlas.png and an atlas.json file. Open up the JSON file and take a look at the contents. You'll find it matches what was added to the atlas.

Inspecting the code

Outputting the meta data of the atlas is very easy, thanks for Dave's code. After adding the cJSON.h header to our own atlasGen.h, we can call the CJSON functions. All this is done in main. The first thing we want to do is create a JSON array:


rootJSON = cJSON_CreateArray();

Simple enough. Now we need to add the details of the images themselves. Within the main for-loop, after we've added the image to the atlas, we want to create a JSON object, and add the details of the image to it.


entryJSON = cJSON_CreateObject();

cJSON_AddStringToObject(entryJSON, "filename", images[i].filename);
cJSON_AddNumberToObject(entryJSON, "x", dest.x);
cJSON_AddNumberToObject(entryJSON, "y", dest.y);
cJSON_AddNumberToObject(entryJSON, "w", dest.w);
cJSON_AddNumberToObject(entryJSON, "h", dest.h);
cJSON_AddNumberToObject(entryJSON, "rotated", rotated);

The first thing we do is create the JSON object by calling cJSON_CreateObject. With that done, we want to add the image's filename, by calling cJSON_AddStringToObject. The key of the string is "filename", with the value being the image filename itself. Next, we want to add the coordinates where the image resides on the atlas (its x, y, w, and h values). We can do this by calling cJSON_AddNumberToObject, and specifying the appropriate key and value. We also want to add the rotated value (which will either be a 0 or 1) to the object.

The above will create a JSON object that will resemble the following:

{
	"filename": "gfx/tall/long.png",
	"x": 0,
	"y": 0,
	"w": 34,
	"h": 128,
	"rotated": 0
}

As you can see, working with cJSON makes things very easy. With all the image data added to the object, we need only add it to the main JSON array. This is a single function call using cJSON_AddItemToArray, passing in the rootJSON variable as the array we wish to use and the entryJSON as the object we want to add:


cJSON_AddItemToArray(rootJSON, entryJSON);

This is done for all the valid images in the atlas (we don't want to add images that we failed to add to the atlas, for whatever reason). When we have completed looping through the images and creating the JSON object, the last thing we need to do is save the data. Once again, cJSON makes this very easy. A call to cJSON_Print, passing in the rootJSON reference, will return use a char array with the nicely formatted JSON:


out = cJSON_Print(rootJSON);

We then just need to save this data by writing it to a file, using the standard C IO calls:


fp = fopen("atlas.json", "wb");
fprintf(fp, "%s", out);
fclose(fp);

Opening the atlas.json file, we'll see we've got data like this:

[{
	"filename":	"gfx/tall/long.png",
	"x":	0,
	"y":	0,
	"w":	34,
	"h":	128,
	"rotated":	0
}, {
	"filename":	"gfx/misc/pinkTextured.png",
	"x":	35,
	"y":	0,
	"w":	121,
	"h":	123,
	"rotated":	0
}, {
	"filename":	"gfx/cubes/bigGrey.png",
	"x":	157,
	"y":	0,
	"w":	62,
	"h":	63,
	"rotated":	0
}, {
	"filename":	"gfx/cubes/bigGreen.png",
	"x":	0,
	"y":	129,
	"w":	62,
	"h":	63,
	"rotated":	0
}, {
...

The very final thing we need to do is clean up the memory we used. We can delete the JSON array and all its child objects with one call to cJSON_Delete, passing in the rootJSON variable. We also need to free the char array that was created when we printed it out, with a call to free.


cJSON_Delete(rootJSON);

free(out);

There we have it, a basic sprite atlas generator! The nice thing about this generator is that since the output is JSON, it's very flexible and can be used in a variety of places. In the next tutorial, we'll look into how we can use the atlas in an SDL application.

Purchase

The source code for all parts of this tutorial (including assets) is available for purchase:

From itch.io

It is also available as part of the SDL2 tutorial bundle:

Desktop site