Made a sample platformer, mostly to show how to do things like collisions, camera, jump buffering, and slopes. I wrote this to be clear rather than to save tokens, and it has no real gameplay to keep the core of the engine as clear as possible.
The code for this cart can also be found on github and is MIT licensed.
- Movement and jumping
- Collision checking and resolution
- Jump buffering
- Platforming camera
Quick pseudo 3D worldmap skew effect meant to emulate something like Final Fantasy 6's overworld. The way this works is it copies the screen to the spritesheet after rendering the map, then goes through from top to bottom taking skewh rows and drawing them using sspr, adding 2 pixels more to the width every time. The skewh value defaults to 4.
Left/down decreases skewh (minimum of 1), up/right increases skewh (maximum of 16), and the buttons toggle the skewing on and off.
Hi, I just released Depicofier, which converts PICO-8's syntax to regular Lua syntax. I looked at a couple existing solutions but they didn't work for me, so I made this. It's open source under the MIT license on Github.
It should be feature complete, but if I missed anything please let me know.
Converts/translates PICO-8 style Lua syntax to standard clean Lua syntax. Download the latest release here.
This tool uses a publicly available and well-tested Lua language grammar to parse PICO-8 source code, so that any enhanced or special syntax or shorthand will only be converted where it should be.
If you like this tool please consider kicking me a dollar on Patreon.
Depicofier.exe [inFile] [outFile] Or to output source to console: Depicofier.exe [inFile] -print Switches: -strict Print warnings for Lua syntax not found in Pico 8 such as binary operators, integer division, and bitwise shifts
I know pcall isn't part of pico 8, which means you can't do regular Lua exception handling. I noticed though that coroutines swallow errors, and can return the error message. So I leveraged that to create a C#/Java style try catch finally function.
function try(t,c,f) local co=cocreate(t) local s,m=true while s and costatus(co)!="dead" do s,m=coresume(co) if not s then c(m) end end if f then f() end end cls() try(function() print("hi ") --print("hi " .. nil) end, function(e) print("an error occurred:\n"..e) end, function() print("finally") end)
To use just use it like above. The finally function is optional, so most people will probably use it like this:
try(function() -- code end, function(e) -- exception handler end)
Enjoy, and if you like it feel free to kick a buck to my Patreon.
I've created a two-cart application that uses two carts, and has two options:
- Use cstore to store data from the main cart into the 2nd cart, then finish the program
- Use reload to load data from the 2nd cart to the main cart
When I bundle both carts using a binary export, the cstore function creates a file named the same as the filename I passed to the cstore function. E.g. I use "cstore(0,0,4,"exporttest_data.p8")" and in AppData\Roaming\pico-8\cstore a file named that shows up, and it has the correct data in it. But when I restart the program and reload from the cart, it only shows the data of the cart as it was when it was bundled into a binary export.
When I don't bundle the 2nd cart, a file called "__(null).p8" appears in the cstore folder, with the correct data, although the program still doesn't appear to be able to read it.
Since there is a cstore folder and p8 carts are being created there I assume cstore is supposed to work in binary exports, but I'm pretty sure given the malformed "__(null).p8" file that there's a bug with it. I've added the main cartridge for testing.
And here's the code:
cls() done=false while not done do if btn(4) then poke(0,8) poke(1,7) poke(2,6) poke(3,5) cstore(0,0,4,"exporttest_data.p8") done=true elseif btn(5) then poke(0,0) poke(0,0) poke(0,0) poke(0,0) reload(0,0,4,"exporttest_data.p8") print(peek(0)) print(peek(1)) print(peek(2)) print(peek(3)) done=true while btn() == 0 do flip() end end flip() end
Generates a random star system on load. Sometimes it generates one without a nebula at all so you may need to Cmd/Ctrl+R to reset if that happens.
My first Pico 8 cart on the BBS. This is a cart that generates a procgen starfield with nebulae, that you can scroll through (256x256 pixel size).
The big technical achievement is the nebula. I used fractal noise with smoothing to generate the data, where every point is a 2x2 pixel area. After that I stored every row of colors as runs containing the byte length for that color and the color data. When drawing the screen I go through the runs of color, using memset to fill in the pixels which makes the dithering pretty easy, doing two rows of pixels on screen at the same time by flipping the pattern for odd numbered rows.
The really tricky part was the scrolling, particularly in the X direction, because the patterns break if the camera X coordinate is odd and not even. To fix that I draw it as if it were 1 pixel to the left with the pattern flipped, then take the last 2x2 pixel area for a run, and copy the next run's right side pattern into the right side of the 2x2 area. That fixes the one pixel offset without too much of a performance penalty. I didn't fix artifacts along the edges of the screen and instead just lazy draw a black rectangle over it.
I also used a monochrome hue ramp for this because it lets me do some other cool effects, like the blinking stars. The little one pixel stars also dim when they go behind the nebula, and dim more when behind the purple sections.
Finally I wanted to add random noise like described in the linked article, but with scrolling I couldn't really forego cls(). What I wound up doing was trying to add a few random points every frame to a table, and only keeping the last 200, removing the oldest at the start of the table first, as well as removing any that are offscreen.
All in all I'm really happy with how this turned out. :D