Introduction
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...
So:
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.
Indeed:
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:
010205404000000102054040010001020540400200
And since it's a long hexadedimal data stream, we can save that as a binary file from Python.
Great!
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:
model|animation|direction|height|width|x|y|
Or, using a hex-representation of the uint8_t (8 bit) data type:
00|00|00|00|00|00|00
And without pipes:
00000000000000
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).