Log In  
Follow
RealShadowCaster

@notehead
Here's a thread to discuss a collab.

you can see the mode in action here :
https://www.lexaloffle.com/bbs/?pid=139583#p

and some explanations about it here
https://www.lexaloffle.com/bbs/?pid=139595#p

In the example, the modded game was already in 128l x 64c 16 colors mode, but if you want 64 x 64, it's possible to draw in the top half of the screen in 64l x 64c, then set the screen as sprite source with a poke and stretch the screen with sspr for a visual 64 x 64 32 colors mode, even if it's technically 128 x 64 with doubled lines behind the scene.

A lot is possible : you could use regular 16 colors sprites, and use some flags to know which of the 32 colors to use for the sprite, or you could use 5bpp full 32colors sprites, but this would cost 1 line of sprite for the 5th bit per 4 lines of sprites.

the drawing primitives like line or circl won't be directly working, but it's not too hard to re-implement them using clip and the originals, essentially drawing twice, one in each vertical half of the screen.

3 comments



Early alpha attempt to make a hexagonal version of the Mora Jai puzzle boxes from Blue Prince.
There's a single puzzle at the moment, but every color is implemented.
Instead of left clicking the tiles to play normally, you can right click a tile to change its color (rudimentary level edit), or right click outside the puzzle to randomly color the 7 tiles.
Feedback (or even level sceenshots) very welcome.

Cart #mora_jai_hex-0 | 2026-07-23 | Code ▽ | Embed ▽ | No License

0 comments



I tried to see how many prime numbers I could make pico8 compute before running out of memory, and I'm a bit surprised by the result.

The highest computed prime is 821647, witch is the 65537th prime.
The out of memory error occurs on the t[i]=i line, when trying to add it to the computed array of primes.
Just before the error, memory usage is at 1305KiB/2048KiB, around 64%.

Ideas ?

The code

cls()
t={}
i=2>>16
cpt=0
while(i>0) do
 if (t[i]) then
   -- i is not prime
   p=t[i]
   t[i]=nil
   n=i
   repeat
    n+=p
   until not t[n]
   if (n>0) t[n]=p
   i+=1>>16
 else
   -- i is prime
   cpt+=1>>16
   print("\#0"..tostr(i,0x2)..
         "("..tostr(cpt,0x2)..")"..stat(0)

         ,0,0)
   t[i]=i
 end
end

In cart form

Cart #gusozanode-0 | 2026-06-22 | Code ▽ | Embed ▽ | No License

0 comments



I'm trying to make a pico-8 piet interpreter.
https://esolangs.org/wiki/Piet
It can't be an exact interpreter for the simple reason that piet uses an image as its code and the 20 valid pixel colors are not in the pico-8 palette, but something similar using the 20 of the 32 pico-8 colors might be possible.
The 16 colors max per screen can be overcome with the 64 x 128 32 colors mode, but my struggle is to find what colors to use.

In piet, aside from black that is used as a wall and white as a do nothing, colors are organizes in a 6 hues times 3 lightnesses. Each color has no special meaning, but the difference in hue and lightness between adjacent pixels is what defines opcodes.

We can't simply match to nearest in pico-8, but another 3 times 6 organization might make sense.

Suggestions anyone ?

1
3 comments



Just released cart based on a recent numberphile video.
The cart generates cool images based on original settings and pixel read/write.
https://www.lexaloffle.com/bbs/?tid=157045
Because every pixel counts for the final image, I used the pause menu and menuitem for the parameter input interface... And spent much more time on that than on the rest of the code.
Retrospectively, I should have done the computations on the sprite sheet instead of directly on screen.
Because generating an image takes a few seconds and I didn't want to deal with lag, coroutines, or CPU monitoring, I used imperative coding instead of the usual _init _draw _update event way of coding.
That made the image generation part much simpler, but completely messed up the pause menu :
the items where properly shown, but the associated functions were never called.
Turns out that pico-8 was waiting for a call to flip() that never came before launching the pause menu functions. I added a few calls to flip(), but strange things were happening if multiple pauses and calls occurred between two calls of flip().

[ Continue Reading.. ]

1
0 comments



Cart #red_and_black_knights-0 | 2026-05-25 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
2


Pico-8 implementation of the leapers on a spiral discovered by Jonas Karlson and mentioned in the two following numberphile videos :
https://www.youtube.com/watch?v=UiX4CFIiegM
https://www.youtube.com/watch?v=VgmDuBCayPw

Choose your own (up to 5) leaper pieces and share your own discoveries.

2
0 comments



I'm currently working on the Celeste part of the Balloon mod and I'd like suggestion about how to color Madeline :

Balloon uses the standard pico-8 palette, except for color 15 that is replaced by a dark blue, mostly for water effects.
Because Madeline's skin uses color 15, she's blue (da be dee da be daaaa) at the moment.

On the screen shot, I could have set display palette entry 15 to 15 because there is no onscreen water, and on screens with water, there's always (I think) an unused color depending on her environment, but the unused color varies.
I could draw the screen, set 15 transparent, draw Madeline, scan every pixel of the screen to find an unused index, then add Madeline's sprite with draw entry 15 set to the unused color and draw palette entry number found unusused as 15, but that might take a lot of CPU (full read and handling of pixels one by one).
So I'm wondering if anyone has a better idea. (brown skin Madeline would require no extra code for example).

[ Continue Reading.. ]

2 comments



Cart #noolld8-3 | 2026-04-07 | Code ▽ | Embed ▽ | No License
12


mods
Flip OK
Big OK
Soap OK
Celeste NOK

12
5 comments



Cart #dedayegeju-0 | 2026-03-27 | Code ▽ | Embed ▽ | No License
1


Very early WIP implementation of the TAPA puzzle.
Game rules :
Shade some empty cells black to create a single connected wall. Numbers in a cell indicate the length of consecutive shaded blocks in the neighboring cells. If there is more than one number in a cell, then there must be at least one white (unshaded) cell between the black cell groups. Cells with numbers cannot be shaded, and the shaded cells cannot form a 2×2 square anywhere in the grid.

Single level (not by me) at the moment, and no validity check.
Mouse only at the moment.
Happy about the mouse controls (left click for black and right click dot, with clear effect if tried on an already marked tile), but not with the visuals. Help welcome regarding that.

1
0 comments



Pico-8 has a nice poke to adjust the map width, but you unfortunately can't use the built in map editor to conveniently take advantage of it.
I wonder if someone already rebuilt the sprite and map editor of pico-8 in pico-8, so I could tweak it to add map width support without starting from scratch.
Another feature I'd like to add is usage of the range 128-255 tiles+flags for the 4sceen x 8 screen maps, so you can use the extra range as flipped versions of the 0-127 range.

1
0 comments



Officially, you can't use multiple data storage one one program.
This feels mostly true, but very similar in spirit to statements like "pico-8 has 16 colors".

"cartdata() can only be called once per program", is already less restrictive :
You could have a game that uses 3 save slots, each with a different cartdata ID because each save requires most or all of the 256 bytes of a cartdata storage, and let the player choose his slot at start of the program. You'd only ever call cartdata once per game session, but would have three storage slots used in one program.
This would still not be great because you can't display any info about the slots before loading them so the player would have to blindly load a slot, see if it's the save he intended to use, and reset the game if he made a mistake.

Could we do that programmatically ? Turns out that yes, we can :
extcmd("reset")
Does reset the cart. Problem is, how do we remember what the previously viewed storage was, or what we were doing before triggering the reset ?

[ Continue Reading.. ]

8
1 comment



SSPR sandbox

According to the documentation, sspr is pretty self explanatory :

QUOTE

SSPR(SX, SY, SW, SH, DX, DY, [DW, DH], [FLIP_X], [FLIP_Y]]
Stretch a rectangle of the sprite sheet (sx, sy, sw, sh) to a destination rectangle on the screen (dx, dy, dw, dh). In both cases, the x and y values are coordinates (in pixels) of the rectangle's top left corner, with a width of w, h.
Colour 0 drawn as transparent by default (see PALT())
dw, dh defaults to sw, sh
When FLIP_X is TRUE, flip horizontally.
When FLIP_Y is TRUE, flip vertically.

END OF QUOTE

So I was pretty surprised to see an upside down sprite while debugging, when I knew I wasn't even using the flip parameters anywhere.
Things are pretty normal as long as the coordinates are in the 0-127 range and the sizes in the 1-128.
What happens otherwise is unclear, so I wrote this little test cart. (image in the sprite sheet by Freds72)

Cart #sspr_sandbox-0 | 2025-04-17 | Code ▽ | Embed ▽ | No License
2

[ Continue Reading.. ]

2
0 comments



User @taxicomics started a thread compiling fades and transitions code snippets https://www.lexaloffle.com/bbs/?tid=148256

I though I'd add my screen dissolve effect, base on a 14 bit variation of the xorshift algorithm
https://en.wikipedia.org/wiki/Xorshift

The shift parameters used are >>3 <<1 >>4 . It's not good as a random generator, but that's a property I don't care about in this context, and amongst the many triplets that give the maximum cycle length needed to progressively blacken every screen pixel, it's the easiest to remember : 314 is the start of pi and 14 is the number of bits.

It works as expected for the first 2/3 of the screen, but after that, the CPU load goes over 100%, and the frame skips makes the animation end in awful looking flicker :

function fade(progress)
 pset(0,0,0)
 local s=1
 while progress>0 do
  s^^=s\8
  s^^=s<<1
  s&=0x3fff
  s^^=s\16
  pset(s\128,s%128,0) 

[ [size=16][color=#ffaabb] [ Continue Reading.. ] [/color][/size] ](/bbs/?pid=165609#p)
1
6 comments



To ping a user in a post, you usually just type @ directly followed by their user name.
This sometimes fails if the user has special characters in their name.
For example, to ping @Peter Mosevich that has a space in his user name (how are you buddy ? any new pico-8 cart or puzzlescript in preparation ?), you can use @ then { then the user name with the space, then }.
This has worked for me so far, but today, I tried to ping a user (cat-8) that has a minus sign in his user name, and I ended up pinging user cat instead (sorry).
Does anyone know how to properly ping such a user ?

1
3 comments



While looking at an empty project in the built-in pico-8, I thought about the default map/sprite options available without extra code.

There are the two classic approaches :
1) use the shared map/sprite area for sprites.
We get 256 tiles with 8bit flags, and a map 2 screens tall and 8 screens wide.

2) use the shared area for map.
We get 128 tiles, and a 4 screen tall and 8 screens wide map.

We can also use a hybrid of the two, where the bottom of the shared space is used for sprites, while keeping the map rectangular...

Option 1 is efficient, IE every bit counts, while option 2 is pretty wasteful :
in the map, every tile index is in the 0-127 range, but still uses one byte. That's 12.5% of the map data forced to be zero.
Flags for tiles 128-255 are also unused...

What if these unused spaces had had significance ?
For example, the tiles 128-255 could have been a horizontal mirrors of the tiles 0-127.
Maybe instead, two of the flags of each tile in the 128-255 range could be used as horizontal and vertical mirror ? That would save a few tiles, but in tile sets, you often have the 4 versions (normal, HFLIP VFLIP H&VFLIP), or even eight if 90° rotation is also needed.

[ Continue Reading.. ]

1
2 comments



@pancelor, @rupees,

Pancelor suggested in Beam's thread to start a new thread for technical discussion in order not to clutter the game's thread. I fully agree with the idea and I'm sorry for cluttering.

Here's what Pancelor wrote :

  • you can replace the body of get_random_bird_name() with this: return del(bird_names,rnd(bird_names)) or "♥"
  • you can replace p.velocity_x=p.velocity_x+i_xp.acceleration with p.velocity_x+=i_xp.acceleration, etc
  • you should be able to remove tfnsplit altogether, by saying things like a,b,c,d=unpack_split"1,2" (which does the same thing as a,b,c,d=1,2,nil,nil. this one will probably take some more explanation)

End of Quote

About the 3rd point :
when doing a multi assignation, it still works if the number of elements does not match :
a,b,c=1,2,3,4
a is 1, b is 2, c is 3, 4 is discarded.
a,b,c=1,2
a is 1, b is 2, c is nil ([NIL] when printed.)

Now a word about what is considered true and false in LUA :

[ Continue Reading.. ]

1
4 comments



I was browsing the _ENV content, hoping to find the modulo and integer division function exposed (no luck) with this quickly written cart (not even alphabetic sorting)

Cart #kiyejamose-0 | 2024-12-09 | Code ▽ | Embed ▽ | No License
1

Amongst the unknowns to me, there is a mysterious radio() function.
I tried to call it with different parameters, and only got [nil],0 as return values.
Does anyone know more about that ?

1
0 comments



One of the games I used to play the most was populous.
While some of my friends could play it with beautiful graphics on their amiga or atari ST :

I was playing on a slow TO-16 PC compatible with CGA graphics and a monochrome green screen. You can't even find an online picture of a setting that bad for this game, the closest I could find online was color CGA that is actually almost as bad looking as the green version.

Despite the visuals, I was hooked and somehow managed to finish the game (level 400 something), using every possible trick available. (save scumming so the "random" swamps would always spawn under the enemy's knights feet, abusing the bad AI when possible (enemy flood that insta-kill every single enemy unit was the most memorable), using a bug that allowed to raise the terrain to level 1 on levels where it was disabled...).
Despite all that, after level 400, the building speed of the computer was just insane : he would add a block every frame (around 4 times per second on my crappy PC), making enemy progressing absolutely overwhelming.

[ Continue Reading.. ]

13
7 comments



Hello everyone, I'm thinking about de-making Xblast, a linux clone of bomberman that allows up to 6 players at the same time.
Here's a early WIP screenshot :

What I'm worried about now is the 6 players local game play.
On paper, Pico-8 has native support of up to 8 controllers.
I wrote a simple cart that just highlights in red the active buttons of the 8 controllers.
Could anyone confirm that this actually works for up to six controllers before I go further into the dev ?
I'm a bit worried as I've never encountered a pico8 game that plays with more than two controllers at the same time so far.
If you get it it to highlight buttons of players 3 to 7, could you please tell me how you set it up ?

Cart #zuhapiheku-0 | 2024-10-11 | Code ▽ | Embed ▽ | No License

0 comments



One of the simple examples in the LUA documentation for metamethods is to implement set logic on tables.
s1+s2 returns a new set that is the union of the two by defining __add, s1*s2 returns the intersection thanks to __mul, so far so good.
There is also the very useful __index and __newindex to handle reads and writes to unassigned indexes of the table, but the very important assignation metamethod at table level seem to silently not exist, as if it were of no use.

when I do
set1=set2
followed by
set2=set2+{new_elem}

I most certainly didn't mean for set1 to be changed.

There's of course plenty ow ways to force the behavior I wanted :
set1=set2+{}
would work.
We could define a set_copy function
set1=set_copy(s2)

But there seem to be no way to override the assignation behavior, like we would redefine the = operator of a class in C++ for example.

Could someone please shed some light on the subject ? What is the reason behind this omission ?

[ Continue Reading.. ]

3 comments





Top    Load More Posts ->