Faster button polling? Rapid presses bringing slower variable changes

Hi, I'm the maker of Mash Gadget. I recently, finally got a real Playdate, and the game doesn't run as well as in the simulator! Shocking, right?

The main gameplay mode is where you press A or B as rapidly as you can to increment a score (int), but playing this on device is jankier than expected. I would like the number to update at least as fast as the Shooting Watch it's mimicking (here's a video of ideal performance), but ironically, it appears that the faster the button's pressed, the less often the number updates -- to the naked eye, every other press or so.

The game modes run in update() states, and originally I had an if-then inside this mode that checked buttonJustPressed then just adds 1 to the score. (I realize that's per update, but again, it was fast enough in the simulator...!) On device, if you press A & B alternately, the score increases as rapidly as I'd like it to be with one button (though that's for novices anyway!) Similarly, if we try the if-then with buttonIsPressed and I hold the button, the score's naturally increasing every tick, so I imagine this can be done on a single-rapid-press basis.

An attempted solution was moving the score-changing outside update() to an AButtonDown() function, which might be more efficient but didn't change anything. I then tried a test script with the bare essentials -- AButtonDown changing a number and a three-line update() -- but no change. Using buttonIsPressed and checking button states that way also wasn't working.

There were some other dead-end tries that maybe I did or didn't do correctly, but I'm out of theories. Is this a hardware issue? Do we need to integrate C? I'm very much a neophyte as you can tell by the simple game, but any insight here would be helpful. This is Lua on Windows, btw. Thanks.

(Attached is my test script. ) (480 Bytes)

Hi Ray!

In your sample code buttons are polled once per frame. That is, if I set refresh rate to 1Hz, I can press the A button multiple times between updates and the score only goes up by one. Maybe there are other ways to do the button polling? Like an InputHandler? Or put the test in your main loop and use playdate.buttonIsPressed(button) or similar?

Next the default frame/refresh rate is 30Hz (fps)
...which means the minimum time between button presses would be 1000/30 = 33ms

It can be changed with playdate.display.setRefreshRate(rate)
...if you increase to 50Hz, minimum response time decreases to 20ms.

It does improve things, I guess my fastest presses got to about 8 out of 10 on the readout in your sample code. Maybe not fast enough for Mash Gadget.

If you need to deeper, what you could do is set it to 0 (zero, unrestricted/unlocked frame rate), then you will decrease the minimum time to however long it takes for one cycle of your main loop to complete. It might be tied to the rate at which your time is changing, as that is influencing screen redraws.

If your screen drawing becomes the bottleneck of performance you may want to optimise that by drawing to sprites and letting the sprite system take care of drawing only what is changing on screen (your numbers).

To set expectations: your numbers are 112px tall, so even if only one of those numbers changes all of those 112 rows will need to be redrawn. It's not a linear scale, rather exponential, something like (measurements taken a long time ago)

  • 240 lines = 50Hz
  • 175 lines = 60Hz
  • 75 lines = 200Hz

Final thought, there may be some in-built hardware "debounce" on buttons to prevent accidental presses that might be getting in the way here. But let's assume not.

1 Like

Thanks Matt, some good things to think on for now! I didn't want to flood the post with every detail and attempted fix, but since you bring some up...

I did consider an input handler but it didn't seem like the right fit, though it looks like the one "textbook approach" I haven't tried yet, so worth a shot.
I did also play with refresh rate, (50) and (0) and still no noticeable change (at 0, the FPS readout reached 82). That just reinforced my confusion around the fact that the other button methods (the A&B mashing; the holding buttonIsPressed) were as fast as desired, but hyper-tapping one button wasn't, so I'm still a bit hung up on that.

Nevertheless, given what you've said about line drawing and sprites/text, there could be something there. The digits are indeed drawn as fonts ('big' and 'small') and may be too large, so maybe I'll look into using them as sprites. Till next post!

Perhaps it's debounce after all...?

Looking likely given the above :upside_down_face:

1 Like

To be continued in Feature Requests