As it is: I'm still trying my hand at game programming at a fairly low level. My current puzzle is creating spritesheets of character animations and importing them in to the engine I'm writing in C. The images come from Blender, I wrote a Python script that takes the individual rendered frames and copies them onto a 1024x1024 .png file. So: For every frame I write I know:
- The model name
- The animation name (walk, run, etc.)
- The direction (north, northeast, etc.)
- The frame width and height
- The frame's position on the new sprite sheet (x, y)
My needs for the entity data were more complicated and I made a super basic json importer, but I figured with the flatness of this data I could do something a little better here.
The Python Part
My first thought was a pipe-separated list of values to be read by the engine:
player|walk|north|64|64|0|0 player|walk|north|64|64|64|0 player|walk|north|64|64|128|0
and so on
But I got self-conscious about all of those strings, and was like, I could keep a file in common with the C and Python code to hold the string tokens, so now it's:
player = 1 animation = 2 direction = 5 1|2|5|64|64|0|0 1|2|5|64|64|64|0 1|2|5|64|64|128|0
Which is definitely smaller, but technically, I'm still using strings. And there's the pipe separator to deal with.
I could pad the numbers and get rid of the pipes, but it's still a string. Unless I can somehow save this as a binary file instead of a text file...
In Python I convert the integer data into hex, so 1 becomes, well, 1. But 10 is now A and 11 is B and 16 is, well, 10.
If I can store each number in two hex characters, that gives me plenty of space to work with. Except for the coordinates, which will definitely go above 256, but I could just save the panel numbers and multiply that by the width or height to get the right place on the image.
Now we have hexadedimal strings:
01020540400000 01020540400100 01020540400200
(which is kind of a terrible example, since there aren't any of the A-F characters)
and we really don't need the newlines there either, since this data is totally fixed width:
And since it's a long hexadedimal data stream, we can save that as a binary file from Python.
Size-wize, for those 3 entries:
data.txt: 87 bytes (the original data with pipes and names) data.bin: 22 bytes (the binarified hex data)
Almost a 75% savings! But that's not even the neat part...
So what does that mean from C? (the neat part)
The thing about C is it has data structures, which are made up of contiguous memory. So if I have, say, a structure that has:
uint8_t model; uint8_t animation; uint8_t direction; uint8_t height; uint8_t width; uint8_t x; uint8_t y;
It's going to take up a fixed amount of memory, and each field will be neighbors. So if you were to separate these into pipes, you'd get something like:
Or, using a hex-representation of the uint8_t (8 bit) data type:
And without pipes:
Which, I hope, should look somewhat familiar.
Now all that's left is reading that data in from a file and doing some stuff with it. The structure of my animation data in the game is a bunch of linked lists, so my goal here was to read in to a defined data structure and then iterate over that creating the real animation data I need (and linking it within the larger structure).