This is the game @Niarkou and I made for Ludum Dare 45 in 72 hours.
Ludum Dare entry page · GitHub source code
A few warnings about this version:
- the ball does nothing
- the cave is not implemented
- there is no reward for watering the plants
- there is no reward for the riddle
- there is a large empty area at the east
We want to work on the game and improve the story when the Ludum Dare voting period is over. Hope you already enjoy it as it is now, though!
When saving to .p8.png, PICO-8 flattens the #include directives. But it does not do that with the HTML exports, resulting in broken exports:
Is there an option I may be missing?
Ludum Dare entry for this game
Grandma is on yet another quest to find her beloved Cookie and save a few other stray cats on her way.
Controls: arrows to move, Z to shoot
This is a rogue-like game project by @Niarkou and me. We started it for Ludum Dare 44 and ran out of time, but we will continue working on it!
It may be a side effect of fixing the peek4() CPU cycle exploit, but now all “adjusted” functions seem to cost the same as if they were standard Lua API calls.
The following program used to run at 21.6% CPU on 0.1.11f. Now on 0.1.12b it runs at 64.5% CPU!
function _draw() cls() local i = 0 for j = 0,10000 do i = bxor(j, shl(i, 3)) end print(tostr(stat(1)*100).."% cpu", 2, 2) end |
It’s now possible to include .lua files, but PICO-8 seems to be very confused when they have CRLF line terminators, reporting syntax errors at weird locations.
Note that including .p8 files with CRLF line endings works just fine, but not if they have an UTF-8 BOM ( @Niarkou reported this a while ago: https://www.lexaloffle.com/bbs/?tid=31617). To summarise:
- .p8 with UTF-8 BOM: fail
- .p8 with CRLF: OK
- .lua with UTF-8 BOM: OK
- .lua with CRLF: fail
It’s not unusual to have CRLF line endings, even unwillingly; for instance, if I push a .lua file to Git from a Linux box (with LF line endings) then pull the file on Windows, by default it magically gets CRLF line endings. This can be configured but it may confuse users.
The function peek4() does not properly check its number of arguments, so calling it with no arguments will cost zero cycles. Combined with any other function that costs fewer cycles than its number of arguments, such as shl(), this can be exploited to reclaim CPU cycles.
Here is a function that reclaims n cycles:
function reclaim(n) for i=0,n/5 do shl(peek4(),peek4())shl(peek4(),peek4()) shl(peek4(),peek4())shl(peek4(),peek4()) shl(peek4(),peek4())shl(peek4(),peek4()) end end |
I do not know to what extent this can be exploited, but here is an example.
The following program runs at 15 FPS:
function _draw() for y=0,127 do m=3+rnd() for x=0,127 do pset(x,y,(x+7)*m%5) end end print(stat(7).." fps",1,1,7) end |
But this one runs at 30 FPS:
function _draw() for y=0,127 do m=3+rnd() for x=0,127 do pset(x,y,(x+7)*m%5) end reclaim(200) end print(stat(7).." fps",1,1,7) end |
106 frames of animation, compressed and embedded in the cart (half in the code, half in the gfx segment).
I have started measuring function costs precisely, because I like accurate things. It’s all on the wiki but not fully complete.
Here are a few funny things I already learned:
- <code>x^.5</code> costs 16 cycles, whereas <code>sqrt(x)</code> costs 27
- <code>x^4</code> costs 8 cycles, but <code>x*x*x*x</code> only costs 3
Some of these, such as clipped <code>circ()</code>, are pretty tricky to measure, I hope someone can help!
Edit: removed claim about shl() because that function behaves a bit differently.
Just a work in progress. The parser is not perfect but it needs a lot of work.
This code does not work (unexpected symbol near 'then'):
if (x == "\\") then print(x) end
But this works OK:
bs = "\\" if (x == bs) then print(x) end
Your kittens are in danger! How could they survive in such a crazy world?
You must return them home safely. Select the color of the kittens you wish to call and they will follow you everywhere.
Controls:
- Navigation and player controls: arrows
- Call your kittens: X
- Validation and jump: Z or W
This is the entry for Ludum Dare 43 we made with @Niarkou.
This is my entry for #TweetTweetJam: an unfinished shooter, in about 530 characters of code.
Left/right to move, X to shoot.
It has music and SFX and many things but no actual gameplay.
Jam entry page: https://itch.io/jam/tweettweetjam/rate/331412
I noticed that if there is a file named "splash.png" in PICO-8’s directory, it will be displayed at launch before the boot sequence. This also works with cartridges exported as binary.
My love Niarkou and I made this for Ludum Dare in 72 hours!
Objectives: Feed your cats by filling their bowls. The more they eat, the more points you get! But too many cats and you will run out of space.
Controls:
- Pause: P or Enter
- Navigation / Player controls: ◀ ▲▼ ▶
- Menu validation / Take something / Pour something into the bowl: W / Z
- Throw away something: X
LDJam link: https://ldjam.com/events/ludum-dare/42/cat-lady-simulator
I was working on this a while ago and haven’t found much time for it lately, but I thought it could be interesting to some people. It is a fork of Lua that implements the PICO-8 dialect.
Why?
If you know how to embed Lua somewhere, then there are chances that you can embed PICO-8 compatible Lua instead! I use it for an unfinished toy emulator project.
Features
- short if syntax (on one line)
- short print syntax (? at the beginning of a line)
- compound assignment operators: += /= etc.
- C style not equal operator: !=
- C++ style comments with //
- fixed-point arithmetic with overflows, infinity etc.
- the PICO-8 math library (shr, atan2, flr etc.)
- binary literals: 0b1001001.10010
- works in Windows and Linux, and probably in OS X too
How?
The usual approach to the language extensions is through code parsing and patching. For instance, replacing all occurrences of <something>+=<blah> with <something>=<something>+(<blah>). This is what PICO-8 itself does, which is why it still has the occasional weird parsing issues (you can write x=0y=1 but not x+=0y=1). My approach is to implement these extensions in the Lua parser instead, which is elegant, more robust, and gives better error reporting.
Where?
It’s on GitHub: https://github.com/samhocevar/z8lua
Example
Here is a z8lua session in my terminal; you can see familiar PICO-8 syntax in here:
We made this game over the weekend as some practice for Ludum Dare. It is named after one of our cats.
Controls: left/right to move, X to fire.
I was working on this during Ludum Dare 39 (4 months ago) but never got the courage to finish it… maybe one day!
Made for Ludum Dare. It’s 2 minutes before the deadline, I need some sleep now.
A mini adventure game.
This cartridge extensively abuses Lua memory, lossy zlib compression, data-stored-in-code, and dget to render a 600×252 image with pixel-perfect scrolling. This is more a tech demo but I ended up doing a full mini game for Ludum Dare 37.
I’ll write a postmortem to explain all the hacks.
This function abuses Unicode and ANSI color codes to output a screenshot of the current screen to a text terminal such as xterm. You can record the PICO-8 rendering and replay it using “cat”! You can run PICO-8 over ssh! You can be anything you want.
I also set up a telnet service demonstrating the feature:
telnet lol.pm 12345
Here is how it looks like; this is PICO-8 (small window) launched from GNOME Terminal (large window) just after screenshot() was called:
And here is the code:
pico-8 cartridge // http://www.pico-8.com version 8 __lua__ -- screenshot to console -- by sam hocevar function screenshot() local l={ 16, 17, 89, 29, 131, 240, 251, 230, 197, 214, 220, 47, 39, 103, 211, 223 } local e="\027[" printh(e.."?25l") -- hide cursor for y=0,63 do local ofg,obg=-1,-1 local s=e..(y+1)..";1\072" -- uppercase h for x=0,127 do fg,bg,ch=pget(x,y*2),pget(x,y*2+1),"\226\150\128" if bg>fg then fg,bg,ch=bg,fg,"\226\150\132" end if fg!=ofg or bg!=obg then s=s..e local t="" if (bg!=obg) s,t=s.."48;5;"..l[bg+1],";" if (fg!=ofg) s=s..t.."38;5;"..l[fg+1] s=s.."m" end s=s..ch ofg,obg=fg,bg end printh(s..e.."0m"..e.."\075") -- uppercase k end printh(e.."?25h") -- show cursor end |
The terminal must be UTF-8 and 256-color aware, so this will probably work in most Linux and OS X terminals. On Windows I could test it successfully with the MSYS2 terminal.
View Older Posts