Version 2.0 --New system with much-improved ease-of-use and flexibility in one tiny, 74-token function!
With Pico-8's small spritesheet, many game makers who want a nice title screen are forced to either give up valuable sprite space for a custom-drawn logo, or use a tiny one and zoom in so it but looks very pixelated. Occasionally, someone will use a more advanced method to store images, such as Zep's PX9 or dw817's compression programs. These work well, but the minimum cost of 1000+ characters and 280+ tokens for decompression plus prite sheet rewriting, and/or screen-filling compressed strings can be overkill for many projects, so I came up with my own alternatives.
Version 1.0 encodes logos as 1bpp images into 7 bit-per-character strings, then renders graphical features such as shadows, color gradients, and outlines in real time, without using the sprite sheet. A logo drawing function built with it takes between 85-130 tokens and achieves high levels of compression, though it's limited only to logos, and large ones with outlines can use ~50% of cpu cycles at 30fps.
Version 2.0 uses a version of Run-Length-Encoding (RLE) to compress full-color graphics into strings. It's based on this system here, originally devised by @spellcaster, but I was able to shrink the core functionality down to a fraction of the size and token count while adding a few new features. Like version 1.0 it doesn't use the sprite sheet at all and can handle images of any pixel dimensions. It offers a slightly less compact data footprint, but is far simpler to use, uses less CPU, and can handle any kind of graphics you want. There are 3 versions:
- Core version --the one demonstrated in the cart (74 tokens)
- Version with pre-conversion of strings to tables (104 tokens, lowers CPU usage about 40% further on average --could be useful for 60fps games)
- Version with pre-conversion and real-time vertical and horizontal flipping (161 tokens)
Both 1.0 and 2.0 include instructions to encode your own logos or images, but version 2.0 is much simpler to use, just import or paste an image into the top left corner of the spritesheet, specify its size in pixels, run the cartridge, and follow the icons to encode the image and output a compressed string.
I'm not currently using poke because after experimenting with it, I didn't have much success. I want to preserve full animation and rendering capabilites, and as I currently understand it, transferring the image onto the screen via pokes would require either limiting output to simple static screens, or coding more complex logic I don't understand very well. Please feel free to correct my ignorance.
As for the bitwise shift operators, I haven't used that kind of operation yet, but I'll definitely look into it.
--Edit: Okay, I used the <<operator, and it does give a performance boost where it's used, but since my current method only deals with bitwise operations in the initial setup stage, it doesn't make a noticeable difference in general cpu usage. I'll have to think if there's a better way to leverage that. I did notice the initial decoding of bits into pixels was rather slow, that's why my current method copies values to a table and renders from that, otherwise the whole thing just wouldn't have been viable.
There's actually a converter built in to the cart. Just follow the directions in the tab marked "String encoder function" to set it up, then press down in the main program to enter "create new logo" mode to encode the string and paste it to the clipboard.
Been re-assessing my code and I've found a way to cut the cpu load for basic outlined logos by approximately half by incorporating that procedure into the init function, just takes a few tokens more on average. Ones like the PullFrog logo with larger diameter circular outlines and/or ones that surround a shadow will still have to work the current way. I'll try to get a revised version uploaded soon.
I'm trying to understand the conversion logic, but my knowledge of LUA and Pico8 seem to fall short here...
-- seems like you're reseting to 0 each bit of your result, basically preparing your matrix as empty/all-black
g[n\7] = 0
--I'm guessing here's where's the pixel get's summed up if it's white
(where "n" is a value from 0 to width*height...basically the pixel 'index')
Where I'm seriously lost (in both cases) is that "\" operator, never seen that before and can't get my head or googling skills around it...
Any help would be much appreciated ^^
edit: I'm actually building an automation tool for this and have everything pretty much ready to start doing some magic, except for the image-2-string conversion itself =F
The "\"operator just means the same thing as flr(/), and allows easy addressing of rows. As for your other questions, the place where you see the table value being set to zero is for the table that temporarily holds the values that will be encoded as string characters, since you can't add to a nil value. For the image buffer table generated by the init function, I'm not setting every blank value to zero, just keeping them as nil unless I want to write a pixel value there, as this saves a few tokens in the decoding logic. Lastly, the code snippet with the exponent just sequentially sets each bit in a string character to 1 if the corresponding pixel is white.
I'll be uploading a version 1.1 with improved performance and a couple new features, probably within a couple days, hopefully it won't require a big rewrite of your new tool.
Yeah, I do need to update this, sorry about that, been busy. I had a version 1.1 that added a few features and increased general performance, but then I came upon an alternate way of making things work that isn't quiiite as space-efficient, but takes even less CPU and is way simpler to use, more versatile, and takes fewer tokens on average, so I've been wondering if I should just upload that as a version 2.0 instead.
What a surprise to stumble across this while browsing the bbs and find my game's logo in it. Real nice considering the logo takes up a whole graphics tab.
This could prove useful for one of my upcoming projects, and I'd also like to see that version 1.1/2.0 you mentioned.
[Please log in to post a comment]