A while back, RhythmLynx posted a couple lowercase fonts that tried to use as little sprite space as possible. I had a lot of fun trying to pack the characters into overlapping regions on the sprite sheet to use even less sprite space.
But, recently I had an idea to skip the sprite sheet entirely and define each character as binary data that can be stored as a number in a table. This is the result. Press z to swap between demo text and a reference guide. The reference guide is stored on the sprite sheet, but is not used for the lowercase print function.
Some explanation hidden...
A number in pico-8 is stored in 32 bits (4 bytes), something like this:
0 0000000 00000000 00000000 00000000 ^ ^^^^^^^ ^^^^^^^^ ^^^^^^^^ ^^^^^^^^ | | integer part | | decimal part | | negative sign
In hexadecimal, the integer and decimal parts are separated by a period, just like in base 10.
a = 30.25 b = 0x1e.4 assert(a==b)
In Short Text, each character is laid out on a 4x8 grid. Each column is then treated as a byte and joined together into a number. For example, the letter "b" looks like this, where . is a blank pixel and # is a used pixel:
#... #... ##.. #.#. ##.. .... .... ....
Converted to binary, starting from the bottom right and working up then left, we turn this into...
00000000 00001000 00010100 00011111
which, in hexadecimal, is written as 0x0008.141f, roughly 8.079.
So, we build a table that assigns this number to B.
... chars\["b"\] = 0x0008.141f ...
Then, when we want to draw b, we just check each bit in that number and draw the ones that are set onto the screen.
Even though this method can store 4x8 characters, I only needed a 3x7 space for this font. I originally had a method that allowed me to store two characters per number, but the extra tokens necessary to handle the multi-letter storage outweighed the tokens gained by shortening the array.
The final approach is more flexible and could be used to swap in any custom font, maybe even m7kenji's kana font.
Small Text also allows you to force a default character by inserting a backslash before the character. Be careful: the backslash also has to be escaped, so your string has to look like "\e" to draw a capital E.
Ha, from 2 sprites to 0! This is really cool, it's especially nice that you can easily drop capitals in wherever you want. Reference guide is very useful too, good explanation. I'm curious what your method for storing two characters per number is?
dw817: I like where your font is going!
RhythLymx: Each of these characters (with one exception) is actually only 3x5 pixels. Some happen to be positioned higher or lower than others. Storing 3x5 pixels takes 15 bits, and one more bit indicates whether to start drawing from the top line or shifted down two pixels. That's 16 bits per character, so you can fit exactly two characters per lua number. The exception I mentioned is "j", which is six pixels high. This could be redrawn to fit into a 3x5 box, but I originally just had a special exception that could treat that character as 2x7 instead of 3x5.
I played around and ended up with a bunch more fonts. Use up/down to switch font. Use z to switch between the sample text and reference mode.
I only made letters, but numbers and symbols can be easily added.
And here's the utility that I used to figure out the data for each character.
- Open this cart in pico-8.
- Draw the characters you want into the sprite sheet. Each character occupies half of a sprite (4x8 pixels).
- Run the cart to see the hex values for each character. Cycle through each row of sprites with the up/down arrows.
- Take a screenshot or something to save the hex values.
- In the font box cart (or your own cart with these font libraries), set a string variable containing all the characters in your font.
- Make a table with the hex values of each character. Make sure the order of the character table matches the order of the letter string.
[Please log in to post a comment]