Log In  
:: Unfold ::

Cart #gb_tileart-0 | 2023-08-11 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

P#132947 2023-08-11 00:06

:: Unfold ::

Cart #gb_chain-0 | 2023-08-09 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

I enjoy the idea of lists. I really like how through code we can create pointers to pointers (or in PICO-8's case, reference to reference). I like experimenting with different simple structures in code and seeing how I can produce different kinds of little graphical effects with them.

This is similar to my Procedural Fire cart, as well as its sister cart, the Cool Sonar Effect. These two carts humor the idea of a command queue, where each entry in the queue is a function which should be called.

Anyway, this cart utilizes singly-linked lists to store string data. There are a few commands which were produced to create a tiny linked-list API. The functions are as follows:

-- link node
-- d: data
-- n: next node (if necessary)
function link(d,n)
    local l={
    return l

-- loop through all nodes
-- in the chain and call f(d)
-- on the data inside.
function loop(l,f)
    while l!=nil do

-- count the size of the list
-- starting with link l
-- (this will hang forever
-- if the list is circular)
function count(l)
    if (l==nil) return 0
    local c=0
    while l do
    return c

-- get the data for the list.
-- if data is provided, also set
-- the data before returning
function data(l,d)
    if d then l.data=d end
    return l.data

-- get the next link for the
-- list. if the next link is
-- provided set the next link
-- before returning
function next(l,n)
    if n then l.next=n end
    return l.next

The example code of the cart is:

-- example

-- clear to dark blue

-- sample text to use
sss="hello world !! "
-- starting node (nil)
-- tile x and y
-- flip flag
-- create a new list with
-- each node containing a
-- character of the sample
-- string. we do this backwards.
for i=#sss,1,-1 do

    ?l.data,tx*4,ty*8,rnd()>0.5 and 15 or 2
    if next(l)==nil then
    if (tx>=32) tx=0 ty+=1
    if (ty>=16) ty=0
    if btn(❎) or btn(πŸ…ΎοΈ) then
        fp=not fp
    if (fp==true) then

Notice how in the example code, the characters in the string are added backwards. This is similar to stacking paper, or any kind of stack, really. We have access to only the top item in the stack, and if we want to read it from first to last, we have to add the items in backwards. The link command asks for a reference to the previous link, and returns itself. When used like xxx=link(sub(sss,i,i),xxx) we are storing the most recent link in xxx.

Singly-linked lists (stacks) are not quite as flexible as doubly-linked lists. We cannot read backwards from a stack. Once the topmost item has been removed, we don't have any way to reference it. But, sometimes you don't need that ability. In this example, there isn't even a container object keeping track of things.

One of the more interesting commands of this set is loop(). It asks for the first link, and also a function which will work on each link, starting with the one provided. This can allow you to iterate through each link and do whatever you'd like with its data!

for i=1,10 do

  -- prints 9 to 0 on each line

You can even do things like neat mathematical models like the Fibonacci sequence

-- if we go over 23 there
-- will be overflow
for i=1,23 do
  -- fill stack with 23 0's

-- fill the sequence
  if data(l)==0 then
    if next(l) and next(next(l)) then
      data(next(next(l)), data(l)+data(next(l)))

-- read the sequence
P#132889 2023-08-09 01:55 ( Edited 2023-08-09 02:12)

:: Unfold ::

Cart #gb_squeeb-1 | 2023-08-06 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

For lack of a better title.
Inspired by Hologram Plasma by cheesemug.

P#132777 2023-08-06 01:57

:: Unfold ::

Cart #gb_static-0 | 2023-07-15 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

O/X = select random palette

Made in like 20 minutes because I wasn't sure if Pico-8 was fast enough to handle a lot of PSETs. Turns out it's more than capable :).

P#131984 2023-07-15 03:07

:: Unfold ::
-- serial
st2=";",quote="\"",sp=" ",nl=
local b=tonum(a)local c=tostr(b)
return a==c,b end;srl.strisbool=
function(a)if a=="true"then
return true,true elseif a==
"false"then return true,false
end;return false,nil end;
srl.trim=function(a)local d=0;
local e=0;local f;for g=1,#a do
f=sub(a,g,g)if not(f==" "or f==
"\n")then if d==0 then d=g;e=g
else e=g end end end;return sub
local a="{"local i=""for g,j in
pairs(h)do a=a..tostr(g).."="i=
type(j)if i=="number"then a=a..
tostr(j)elseif i=="string"then
a=a..j elseif i=="boolean"then
a=a..(j and"true"or"false")
elseif i=="table"then a=a..srl.
tostr(j)elseif i=="function"then
a=a.."(f)"else a=a.."(r)"end;a=a
..";"end;a=a.."}"return a end;
srl.fromstr=function(a,k)k=k or
1;local l={}local m=""local n=""
local o=false;local p=""local q=
""local r=srl.sts.open;local
g=1;while g<=#a do m=sub(a,g,g)
if r==srl.sts.open then if m==
srl.tok.open then r=srl.sts.key
end elseif r==srl.sts.key then
if m==srl.tok.close then return
l,g+k-1 elseif m==srl.tok.ass
then if#n>0 then n=srl.trim(n)
p=n;n=""r=srl.sts.value end
elseif m==srl.tok.st1 or m==srl.
tok.st2 then if#n>0 then n=n..m
end elseif m==" " or m==
"\n" or m=="\t" then if#n>0 then n=n
..m end else n=n..m end elseif
r==srl.sts.value then if m==srl.
tok.open then if#n==0 then l[p],
elseif m==srl.tok.close then n=n
..m elseif m==srl.tok.ass then n
=n..m elseif m==srl.tok.st1 or m
==srl.tok.st2 then if#n>0 then q
=srl.trim(n)local s,t=srl.
strisnum(q)local u,v=srl.
strisbool(q)if s then q=t
elseif u then q=v end;n=""l[p]=
q end;r=srl.sts.key elseif m==
srl.tok.sp or m==srl.tok.nl then
if#n>0 then n=n..m end else n=n..
m end end;g=g+1 end;return l end

s = srl.tostr(t) :: Converts a table to a string
t = srl.fromstr(s) :: Converts a string back to a table.

Formatting and Differences:

  • Strings aren't quoted. The parser will trim any whitespace before and after.
  • Strings that look like numbers will always be turned to numbers.
  • Strings that look like booleans will always be turned to booleans.
  • The input string must have an opening and closing curly bracket.
  • You must include a comma or semicolon after every entry, including the last one.
    • The exception to the rule is the very last closing bracket.
  • nil will be the string "nil" and not actual nil.
  • Keys are always strings.


  a = 10;
  b = 20;
  c = {
    d = 12.34;
    e = some string;
    f = false;
    g = { 
      h = true;

It's roughly 600 tokens, and could use further optimization.
But, it works! Now you can store game data in a string, which
costs only one token!

P#131764 2023-07-09 00:24 ( Edited 2023-07-09 01:50)

:: Unfold ::

Cart #gb_fountain-1 | 2023-01-01 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

This is a little example of using layered sprites to create the illusion of liquids which adhere to each other.

If you happen to keep particles close to each other, the illusion becomes much more convincing. Below, I'm only setting the initial velocity of each new particle close together:

Cart #gb_fountain-2 | 2023-01-01 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

P#123400 2023-01-01 02:08 ( Edited 2023-01-01 02:22)

:: Unfold ::

Cart #gb_hellmod-0 | 2022-12-05 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

This is "Hellmod" which is a heavily modified version of the cartridge Four Giga Boss Fights by Guerragames. This was just something I tinkered around with in my spare time. It's not 100% polished. The original game doesn't have a license, so I don't mind taking this down if he has a problem with it.

There's some notable changes from the original:

  • You can hold your angle by holding the Z button (O on consoles). Your speed is reduced significantly if your power meter is empty.
  • The power meter is now hidden and is instead indicated with the color of the bullets fired from your weapon.
  • You can 'overcharge' your power by not using any super bullets (holding X) in which your bullets will turn red and do additional damage for being patient.
  • "Ripping the wings" off of a boss by destroying all of its bullet/laser nodes before killing it will fill your power meter to max (not overcharged). This will also cause the angel to lose its will to live, and you can purge it in a single shot afterwards. This is more difficult with later stages.
  • The ships in the original game were replaced with fantasy weapons, and your hitbox has been changed to look like a little player character.
  • The music was removed and replaced with an eerie drone like sound to hammer in that feeling that you're fighting solo with a giant demonic angel.
  • The lives were changed to look like heart icons.
  • The bosses (angels) only have one set of colors now: red and black.
  • Bosses have way more health now, but now hitting their wings does a small amount of damage to them. They are stronger, but so are you.
  • Death is punishing, and you will lose all of your power when you die. So, try not to.


P#121856 2022-12-05 15:36 ( Edited 2022-12-05 15:49)

:: Unfold ::

Cart #gb_curlygame-5 | 2022-10-11 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

Based on Rainbow Curve by Adekto


  • pressing down will only work once per item get
  • added sfx for safety turning (pressing down)


  • created speed option in menu (1x or 2x speed)


  • added palette swapping (O or X)
  • changed player sprite


  • changed number font
  • changed item got sprite


  • up key now toggles direction
  • down key cannot be repeated if held down


  • initial release
P#118774 2022-10-08 08:25 ( Edited 2022-10-11 04:19)

:: Unfold ::

Cart #gb_dadday_2022-1 | 2022-06-19 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

edit 1: topleft cards were incorrect (changed to 8-7 pair)

music is Startropics (NES) - Town Theme

P#113353 2022-06-19 12:56 ( Edited 2022-06-19 13:01)

:: Unfold ::

Cart #gb_momday_22-2 | 2022-05-08 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

VER 0: Initial release
VER 1: Fixed shading under left M
VER 2: Date said 2020, changed to 2022

P#111532 2022-05-08 21:57 ( Edited 2022-05-08 23:27)

:: Unfold ::

It seems that I am no longer able to release a sustained note in playback in the SFX editor using the 'A' key. A colleague on the Discord server mentioned:

"Checking old versions on my hard drive, it releases the sample in 0.2.0i and doesn't in 0.2.4"

The functionality stopped for me a couple versions ago, personally.

Operating System: Linux Mint 19.3
PICO-8 Version: 0.2.4b

Is this a bug, or a revoked feature?
Thanks in advance.

  • Goober
P#107640 2022-02-25 16:02 ( Edited 2022-02-25 16:03)

:: Unfold ::

Cart #gb_vampkill-0 | 2022-02-20 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

P#107315 2022-02-20 08:34

:: Unfold ::

Cart #zelda1_dungeon_2021_10_17-0 | 2021-10-17 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

P#98785 2021-10-17 12:03

:: Unfold ::

Cart #gb_zelda1_dng-0 | 2021-10-13 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

Press X to add/remove the low health beeping sound which layers on top of one of the music channels. I have many memories of hearing it that way, so I added it in, haha.

Edit - This was created with respect to this post from earlier:

P#98560 2021-10-13 01:24 ( Edited 2021-10-13 01:37)

:: Unfold ::

Cart #ndarwyi-0 | 2021-03-03 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

P#88446 2021-03-03 13:55

:: Unfold ::

Cart #procedural_fire-0 | 2021-02-26 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

P#88203 2021-02-26 15:13

:: Unfold ::

Cart #ch_func_demo-0 | 2021-02-26 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

I was thinking of ways to decouple code flow from a standard procedural design and more towards what I call a chaining queue. Basically, the queue starts off with a single function. This function would then add itself with some modified parameters to the call queue via a table {func, args...}. This would closely resemble JavaScript's setTimeout() function.

This demo only uses a 1:1 call (it calls itself once, and that's it), meaning that the queue will never overfill.

I ended up making some really cool-looking color demo accidentally!

P#88200 2021-02-26 13:48

:: Unfold ::

Cart #sonic2_emeraldhillzone_2-0 | 2020-12-18 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

P#85548 2020-12-18 07:32 ( Edited 2020-12-18 07:35)

:: Unfold ::

Cart #wip_ma_20200905-0 | 2020-09-05 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

Just in time for GBJAM8.
I had to remove the breakable pots to conserve tokens.
I am literally at 8192 tokens even after making even more optimizations!
I had to add the key and door to exit the stage.

P#81517 2020-09-05 11:31

:: Unfold ::

Cart #wip_ma_20200902-2 | 2020-09-03 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

Hey again. Goober here.

This revision has me REALLY looking in every little nook and cranny I can find
to get precious tokens. I've had to resort to utilizing SECRET SPECIAL tricks
to making sure I can load as much data as possible while not using very many
tokens at all. In the beginning of my code I've created a special function:

-- handy token-saving function
glb     =_𝘦𝘯𝘷
function vars(...)
    local a={...}
    local b=split(a[1],",")
    local c=2
    for i in all(b) do

Pair this with one of my modules - the dialog module, for example:


This will allow me to assign multiple global variables while saving about 1/3
of the tokens. A lot of data is being converted to strings in order to save
more and more tokens. Data which doesn't need to be written to very often
may also be stored together in strings, but I haven't really gotten to that
point yet.

What will PROBABLY happen is that I'll start looking into using peek/poke
for reading and writing data. One of the problems with using poke, though, is
that each call to this is 4 tokens. [poke ( offset , value]. The ending brace
doesn't count. Peeking is about the same. Even with shorthand peeking, it takes
four tokens to assign a value.

But, there are some features added to this version!

  • When attacking and killing bats, their spheara (currency is souls) is sucked
    in by the magic lantern. When the lantern takes the soul, it glows bright for
    a split second.

  • It's now possible to die. While it's not possible to be hurt by the bats
    right now (fixed this), you can die from spikes or falling into the water at the bottom of
    the stage. This results in a neat effect! Also, when you die, a password is
    displayed. While this password doesn't serve any purpose right now, I'm planning
    on allowing players to input their password upon startup.

  • You still can't end the level yet. The key actor has not yet been implemented.
    Because I'm out of tokens right now, I'll need to save some more before I can
    implement this. It's in the works!

I think that's it for now. See ya!

~ Goober

P#81473 2020-09-03 11:04 ( Edited 2020-09-03 12:05)

View Older Posts
Follow Lexaloffle:          
Generated 2023-11-29 22:09:23 | 0.083s | Q:82