(Note: I already pushed it a few days ago, but I deleted it by accident^^)
Hello,
Just programmed a simple "Menu Manager" and I thought, it can be useful for others. :)
It presents a way to write your own Menu, moving a cursor with Arrow-Keys (Up/Down), select an Entry (X) and call a Function.
The Sourcecode is well documented.
EXAMPLE
menu={} function menu.update() --Copy from Cartridge function menu.draw() --Copy from Cartridge function _update() menu.update() end function _draw() menu.draw() end function entry_one() cls() print("entry one selected!") end function entry_two() cls() print("entry two selected!") end function entry_x() cls() print("entry x selected!") end cls() menu.entries = { "text entry one", entry_one, "text entry two", entry_two, "text entry x", entry_x} cursor(26,40) menu.start() |
The fact you can read and write PICO-8 GPIO values from the web wrapper is awesome - it means you can do things like emit vibrations according to game state, change the site theme to match different in-game levels, or maybe even develop a brand new input scheme.
However the API for reading these values is a bit basic... PICO-8 writes GPIO values to an array, and it's up to you, the developer to check those values periodically to see if they're different. What if you could just tell JavaScript to let you know whenever the GPIO pins get updated with new values?
Voilà:
var gpio = getP8Gpio(); var unsubscribe = gpio.subscribe(function(indices) { console.log( 'New values at indices ' + indices.join(', ') + ': ' + indices.map(function(i) { return gpio[i]; }).join(', ') ); }); // unsubscribe later if you want... unsubscribe(); |
This uses JavaScript setters under the hood to watch each index in the array, which means the watching part is shoved into a native background thread (== faster!). No need to write once-a-frame JS iterator loops or anything like that. Whenever PICO-8 writes to the GPIO array, you get notified immediately.
Of course you can also write back to the GPIO array:
gpio[3] = 255; gpio[4] = 0; |


Any pico-8 game I play (my own or downloaded) seems to have some noticeable input lag in the standalone client (a delay between when a key is pressed and when the game responds). This doesn't happen with other games on my computer, so I know it's not a video delay issue. Is this an issue that anyone else has noticed, and if so is there a fix for it?



I want my web export to support mobile. But if you're like me, you might find the API for controlling touch button inputs from a web page a bit esoteric, and not super easy to read/write. Why not write a tiny API wrapper that makes this much easier?
If you have a page that looks like this:
<!-- ... cart stuff --> <button id="left"> < </button> <button id="right"> > </button> <button id="up"> /\ </button> <button id="down"> \/ </button> <button id="o"> O </button> <button id="x"> X </button> <! -- ... --> |
Include this in your page...
(function() { var __btns = {}; function update_btns(playerIndex) { pico8_buttons[playerIndex] = Object.keys(__btns[playerIndex]).reduce(function(val, btn) { return val | (__btns[playerIndex][btn] ? Math.pow(2, btn) : 0); }, 0); } function registerP8Btn(domElement, btnIndex, playerIndex) { playerIndex = playerIndex || 0; window.pico8_buttons = window.pico8_buttons || []; pico8_buttons[playerIndex] = pico8_buttons[playerIndex] || 0; __btns[playerIndex] = __btns[playerIndex] || {}; domElement.addEventListener('touchstart', function() { __btns[playerIndex][btnIndex] = true; update_btns(playerIndex); }); domElement.addEventListener('touchend', function() { __btns[playerIndex][btnIndex] = false; update_btns(playerIndex); }); } window.registerP8Btn = registerP8Btn; })(); |

This is sort of out of left field, but I think it would be really neat to have built-in vibration support - specifically for use in mobile web browsers which support the web vibration API.
That might have limited application in general, but in any case I'd love to be able to hack this in for my own game. I'm checking out the possibility of using dset() in the game in combination with reading the indexedDB storage in the web browser to pass messages from Lua land to JavaScript land, which could trigger different types of vibrations depending on game state.
My main trouble right now is that I'm having trouble parsing the information stored in IndexedDB ... it's pretty esoteric. It might be some kind of binary format I don't understand.


Charlie is back from the research lab! Now he can lock the brain into keys and scales. He will still have to teach his neural network (music brain) how to make musical sounds.
When he starts the machine for the first time, it will make a random sound or maybe nothing at all. To hear the sound of this brain again he can press the green PLAY button in the upper left. To reward the machine for playing something sort of musical, he can press the red LEARN button. This will modify the brain and a new sound will play, usually similar to the first but not always. If the new sound is still "musical," he can press LEARN again to get more creative. To save this brain to the cartdata, he can press the gray SAVE button. To randomly reset the brain's concept of music, he can press the blue RESET button.



So this was a quick project made for mouse and keyboard functionality in future projects. Hopefully someone out there will find it useful for them as well! Below is a "Features" list which also serves as a guide that explains how it works and how to utilize it, as well as some notes about particulars. Enjoy!
Features:
Keyboard and Mouse state monitoring through the use of _keyboard() and _mouse() functions in the update step.*See below. |
Currently Pressed Keyboard Key is stored in _kbk. |
[box=111111]A keyboard string is stored in _kbs and sent to the "terminal," or _kbt, when return/enter is pressed. Afterwhich kbs is cleared.


Hey,
I'm trying to prepare a pico-8 web export that won't start up the game until the user has pressed a button. This is useful for determining whether to display a touch interface or a desktop interface based on the type of event we get.
My current solution is to dynamically add the game script tag to the document after the user clicks. This is working on my Android device but it seems to have issues on my friend's iPhone - there is no sound! I believe the problem is that the audio is taking too long to start after the button is pressed, so the iPhone browser believes the page is trying to serve audio that wasn't initiated by the user, and blocks it.
The ideal solution would be to add the script tag to the HTML document without any fancy async script loading, so the game parses and prepares immediately, but to just defer the part where the cart actually runs until I emit some kind of event to say "ok, you can play the cart now." I was having trouble finding a way to do this. Is there any documented (or undocumented) method I may have missed?
I noticed the Module object can use an array of "preRun" callbacks but there doesn't seem to be any obvious way to defer execution.


Super simple solar system. Left/right to adjust time, up/down to adjust zoom.
This is a port of an orrery I wrote in C++ back in 2003 or so. It was fun trying to cram it into the Pico-8, with its limited numeric precision.
Printing the date proved to be more of a challenge than just about anything else. I haven't tried to write the reverse function yet (year/month/day to Julian day number) so the cartridge just starts up somewhere near the beginning of the current year.
Not recommended to plan horoscopes or Mars missions with this thing, but compare it with https://ssd.jpl.nasa.gov/?ss_inner or https://ssd.jpl.nasa.gov/?ss_outer, which is where I got the orbital elements from.
Putting a Lambert solver in so you could plan Mars missions (despite what I just said) would be a fun next step.





MSX FAN 1991年2月号に掲載された、ADRESSさん作ICE-MANをPICO-8に移植してみました。
MSXは256x192ピクセル、PICO-8は128x128ということで、アレンジしました。
ステージは全9ステージ、全てクリアするとお楽しみもありますので、挑戦してみてください。
カーソルキーで移動、zで左にxで右にアイスブロックを出します。
アイスブロックは消すことが出来ません、詰んだらリトライをしてください(何もキーを押さないでいると、メニューが表示されます)。
--- Google translation ---
I tried transplanting ADRESS's ICE-MAN posted in the February 1991 issue of MSX FAN to PICO-8.
MSX was 256 × 192 pixels, PICO - 8 was 128 × 128, so I arranged it.
Since the stage has 9 stages all, if you clear it all, we also have fun, so please challenge.
Move with the cursor keys, z to the left and x to the right to issue an ice block.
Ice block can not be erased, please try retrying (if you do not press any key, the menu will be displayed).






1-2 player beat em up based on the Nes version of Bad Dudes with a bit of Mighty Final Fight mixed in. Made in 2 weeks for the metagamejam.
V.1.3
Added hit sprites.
Added 1 music track (More to come)
Fiddled with sfx a bit
Improved Ron-Bots dmg and shot animation.
V.1.2
Fixed another 2 player bug when 1st player dies.
Fixed tag-in bug after dying.
V.1.1
Fixed continue bug where level auto clears after continuing
Fixed stuck continue msg.
Fixed Negative health bar on enemies.
Fixed 2 player bug when 1st player dies.
Fixed 2 player Ron-Bot AI bug.
Added a short invunerablitly to enemies after falling.
Added stop/go staggering to stop people running through the level.(Beta)










I am printing on coordenates > 128, and the text is adjusted with camera().
However, if I
camera(0,128) print("text\nwith\nlines",0,135) |
But if I do the following, the text gets a scroll automatically, and you can only see the last line.
camera(0,128) cursor(0,135) print("text\nwith\nlines") |
Is this a bug, or is this expected? It's rather annoying and not quite what I would have expected.


So this is mostly for those of you who are thinking about ChessJam and wondering if the Pico8 is tough enough for the job.
The answer is clearly "Yes!" (1). Here is my implementation of a Sid Sackson classic board game Lines of Action. OF interest is that I'm using Negamax, bit boards and the 0x4300 user memory for the storing thereof.
There is unfortunately some kind of bug hiding in my (horrible, horrible) code that means the smart AI occasionally glitches the game state. I did mostly write this late at night during a period I wasn't sleeping well. I am very hapy with the code about the menus though.
(1) People have managed to fit (most of chess) into a ZX81 (that's a whole 1K of ram they were working with). http://users.ox.ac.uk/~uzdm0006/scans/1kchess/
This game was made in a game jam ran during a retrogaming event.
This year the theme was maze, a boss and the Odyssey.
My game is far from being finished, I didn't worked really long on it (4-5 hours maximum) and mostly only the rendering is done (and may still need some tweaks)
When playing the X button allow to display a debug view of the maze, which is for now, not generated randomly. I hope to update it at a later time to add all of what I wanted to include in it!
The final game should include some RPG elements, HP, EXP points, attack, treasure to find and grab, different levels and in the end the big boss that you have to kill to be able to escape the maze.
The polyfill function is from scgrn ( see https://www.lexaloffle.com/bbs/?tid=28312 ) modified to not directly write to memory to support the fill pattern.
If anyone have a better fillpoly function, one that can do even better dithering than using the fillp I will probably switch to it to have smoother gradients.



NEST, my first ever PICO-8 project is finished!
Now with better particle effects, two modes for more accessible controls and high-score saving!
At first, this was just a typical "make and throw away" first project, but while making it, it really evolved into a much better experience. I hope some of you will still enjoy it for a couple minutes even though it is far from perfect!
And if you like what you see, consider dropping a buck or two on the game's itch.io page:
https://doczi-dominik.itch.io/nest
Update v1.2
- 4-way control scheme
- Shielded enemies - Can only be defeated from one side
- Overheat - Cannot spam dash now
- Difficulty adjustments to timer and hitboxes








Nilbog is goblin spelled backwards, and this might be the worst video game ever made.
Can you defeat Mordred and unlock the treasure?
New in 0.75:
- Added Mordred as final Boss
- Switched Instructions to Expect a Keyboard Rather than Game Pag
New in 0.7:
- Combat has been rewritten to make it easier for enemies to behave differently.
- Slight changes have been made to text on multiple screens.
- Assassins now cloak themselves as they approach their attack.

I want to leave custom space between two lines of text.
I wanted to do something similar to
cursor(x,y) print("first line") cursor(current_x(), current_y()+2) print("second line") |
for this, I tried reading the cursor position with peak
function get_cursor() local x = peek(0x5f26) local y = peek(0x5f27) return x,y end |
But with this, you only get the least significant byte of each coordinate, and when the x is negative or > 255, I get problems.
Is there an easy way to solve this?
Thanks!



Controls: arrow keys to move, Z to jump to the other open space. Mouse also works.
This is a sliding block puzzle.
The object is to get the green 2x2 sheep block from the top left to the bottom right.
The design of the game is not mine. A friend had it in their house, and did not know its origins. Presumably the puzzle has a solution, but I could not find it, so I wished to make a version I could play with.
If you do solve it, let me know!
(I finally completed it the next day. Confirmed to be solvable.)
This puzzle was originally patented in 1928 by J.M. Schneider.
Information and patent links at Rob's Puzzle Page listed under C56 / C57.
http://robspuzzlepage.com/sliding.htm#rect-pcs


