Anyone else disappointed by the lack of double (and triple) buffering? It all comes to just having a larger framebuffer for faster graphics operations. A lot of special effects and filters can only be implemented fast and correct using more video ram.
The only other thread I could find on the subject is:
https://www.lexaloffle.com/bbs/?tid=2853
I've used the Lua array method, but it's notably slower than video operations.
I guess this is just a hard limitation so one doesn't sink too much time in chasing these sort of thiings, like having too many colors / channels of sound?
I think Pico-8 does use double-buffering internally to avoid tearing—note the function called flip()—but it's true you can't access the "back buffer." If you need to store and manipulate the current screen buffer, you could always memcpy() into sprite storage, or else a block of memory from halfway into sfx through user data.
I've never run into a situation where this becomes a real limitation—but what specific effect are you trying to achieve?
An example is a dark screen with a circle as a clipping mask surrounding the player (to suggest a light / lantern in the dark).
Normally, I would draw my normal screen on screen A and draw a circle on screen B and then OR-operate them (or loop over the pixels to do that myself when there is no OR operation) to the final buffer. Easy and fast.
However, since this is not possible in Pico-8, I need to draw my normal screen and then use 4 black borders to make the 4 edges (or perhaps use the API "clip" command). Then, for the corners, I need to calculate the pixels of the circle myself and fill the outer space of the circle. Or perhaps draw a circle with the "circle" command in a unused color and then fill the outer space, which is not ideal either.
Just one example where the result is possible, it's just more of a hassle.
If you get into the 80s-esque Pico-8 way of thinking about graphics programming, there's a faster way to do this kind of masking/blending-- you can do it by copying to sprite memory, palette shifting, and blitting it back to the screen. There are a couple of threads going on this very subject:
https://www.lexaloffle.com/bbs/?tid=28635
https://www.lexaloffle.com/bbs/?pid=33799#p33799
The spirit of the Pico-8 community is similar to that of the demoscene, I think—it's less about modern convenience and more about pushing the limits of a very specific imaginary 1980s console. (And obviously there are now many accessible game development platforms out there that also take advantage of modern graphics capabilities—GameMaker, Unity, etc.)
Thanks a lot mate, that makes for an interesting read!
I think I'll stick with one of my solutions since I don't want to sacrifice sprite memory. :) The section where I'm using it doesn't require speed so that's ok.
I also programmed in the 80s but mostly learned on the 90s Amiga - I already had 1 MB of shared RAM by then. ;)
Cool, hope it helps!
Also (and apologies if you've tried this already) you can use a technique similar to the OR method you described, as long as the mask is somewhat smaller than the screen size. You would draw your mask to the screen in an initialization phase, then copy it to user data memory (an empty block that starts at 0x4300 and runs for 6192 bytes). If the "transparent" value of your mask is color 15, you could loop through the area you want to mask with something like this:
poke(screenAddr,band(peek(maskAddr),peek(screenAddr))) |
which would mask two pixels at once since there are two pixels packed into every byte. (Obviously this assumes your mask is of an even size and aligned to an even screen X coordinate--otherwise things get a little more complicated.)
[Please log in to post a comment]