I'm trying to make a rhthm-based game, and although the timing looks OK both on pico-8 and in my computer after exported in HTML, when running it through my cellphone everything has ~300ms delay, which ruins the experience.
I've done a very simple cartridge to test the timing - Try to press X to follow the rhythm. Again, on my desktop computer it's fine, but when running it on a cellphone the timing is definetly off.
I've debugged a bit, trying to see if it's some lag added by the browser on cellphones to detect gestures, but the same function that sets the button as on is triggered as soon as it's pressed down. It looks like the delay happens in between the buttons
JS variable and pico-8 runtime.
Is there an alternative way of getting input with close to no lag or it's just the browser export? Any way to fix it?
I've made a spike for cartriges to send http requests and receive their response.
The way it works is the cartrige communicates with the browser through gpio. In here I'm using 2 assumptions (I guess dangerous ones) that make it quite simple to send messages:
- We get synchronous interrupts from p8 -> JS when p8 writes to a GPIO.
- We read an analog value 0-255 in perfect accuracy.
So... yep, this code atm only works in a browser. And it might be posible that it breaks later on (specially for assumption 1, as it depends on the runtime implementation)
It's separated in two layers: The first one just abstracts over sending and receiving any message
html_messaging.lua html_messaging={ send_message=function(self, message) -- sends a `message` string to the host HTML end, add_listener=function(self, listener) -- adds the `listener` function to be called with receiving messages end, remove_listener=function(self, listener) -- stops sending message updates to the listener end, update=function(self) -- this function must be called on every update, so that html_messaging can check for new messages end } |
gpio_messaging.js // This file also sets window.pico8_gpio - Make sure not to override it, or it won't get the interrupts! window.pico8_gpioMessaging={ sendMessage(message) { // sends the string `message` to p8 // returns a promise that resolves when the message was completely sent // (we don't have synchronous interrupts from js -> p8) } } // pico8_gpioMessaging is an EventEmitter of 'message' events // which have a 'message' prop with the received message |
The other layer needs to have that one imported first - This is the one to send and receive HTTP requests
http_request.lua http_request={ get=function(self,url,cb) -- sends a GET request to url, sending the message as a string to callback once it's received end } |
http_request.js // Exports nothing: This file listens for p8 http requests and proxies them to the real BE |
I can't embed an example cartrige here because it also needs some setup on the HTML/JS side, but a simple script that requests the datetime from worldclockapi:
#include html_messaging.lua #include http_request.lua function _update() if btnp(🅾️) then http_request:get("http://worldclockapi.com/api/json/utc/now", function (response) printh(response) end ) end html_messaging:update() end |
The only thing the host HTML needs is importing both gpio_messaging.js and http_request.js.
Now I only need to write a JSON parser :'D (/s - I know this would be a bad idea).
I think this might be useful for simple ad-hoc services, like global highscores. Also maybe to run around the size limit in cartridge for things like level data, or maybe even to some extend turn-based multiplayer games? :exploding_head:
I present my very first game in pico-8 - Inspired by a predecessor of the very well known Mine Sweeper, a game for the ZX Spectrum called "Mined Out!"
In this game you must reach an objective (the bottom right corner) without stepping on a mine. As you move, you'll get information of how many mines are around you.
The level selector (0 -> 9) only the number of mines added, the size of the board and a score multiplier. The position of the mines is completely random.
It also uses a seed system so you can share the same RNG with another player so you can compete in the same conditions.