So I'm working on a game with the windows sdk using lua where there are multiple sprites moving on screen at once and am running into some performance issues. Across the board I'm having fps drops, but in one mode in particular I'm losing frames when it seems like it shouldn't. I've been trying to optimize for a while but can't seem to get a consistent 30 fps.
The main mode in question has these target sprites moving in a straight line up or down the screen and they are destroyed if hit with a projectile from the player. There's about 3-9 moving sprites on screen at once and they all just move by 2 pixels up or down per frame. This doesn't seem like it would be maxing out the hardware but I can only seem to get 20-25 fps on this. Each target has a collision rect so not sure if this is what is causing the problems or not.
I've attached the scripts for my game along with the most recent build. It's a bit messy since I've been commenting a bunch of extra stuff out to only keep the core systems and testing things to find the root of the frame rate problem. If anyone who is knowledgable on good lua/playdate practice and optimization wants to take a look (targetRushSpawner.lua and target.lua are the files for the problem I mentioned) to see what's wrong in this instance, or if I'm coding in general in a very non-performant way that would be greatly appreciated. I don't have a playdate yet so I had someone test it for me so I can't consistently make tiny changes and test them so I'm a bit lost with what I'm doing wrong here.
(Here's a link if you're trying to see what the game looks like Reflector by Justin Searcy)
Scripts.zip (36.2 KB)
Reflector.pdx.zip (20.2 MB)
I noticed the sampler indicates almost all of the load is from C code, so I tried the C sampler which says it’s mostly from MC2S and FDC32. From a google search, these appear to be related to MP3 decoding, so I’m guessing there’s something about your music file that the Playdate can barely handle. Sure enough, turning off music results in a constant 30fps with low CPU load. I’m not sure what the proper optimization steps for music are, other than using ADPCM instead of MP3.
That said, I glanced at your code and noticed a few other things that could probably be optimized, although they don’t seem to be causing any problems with music off (with a lot of balls on the screen, CPU load is around 30% and I don’t notice any stuttering), so it probably isn’t necessary to worry about them for now:
Some of your objects create a new image in
:init for every instance – I noticed this on at least Projectile, Powerup, and Particle. You could save memory and processing by just creating the image(s) at load time and sharing that between every instance. It looks you’re already doing this for the player and targets by creating a file-local image and having all instances reference that. For Particle, if it’s just a solid rectangle, I’m not sure but it might be slightly faster to implement
Particle:draw to just use
gfx.fillRect directly rather than using an image at all.
It looks like you’re initializing new sprites frequently during gameplay, most notably Target, Projectile, and Particle. These seem like good candidates for object pooling where you create as many as you might need on load, and then
:remove() them from the draw list as needed (and reset any properties back to their initial values) instead of constantly creating new ones (note: that link isn’t Playdate or Lua-specific, but the principles still apply). At the very least, any performance hit from not pooling objects is worsened by also creating a new image for every instance (see #1).
Wow thank you so much, that's a huge help I'll work on implementing those suggestions. Thank you again for taking the time to look at it
I can confirm the fps is a solid 30 with music disabled. MP3 decoding is so slow on device it's not really useful for anything more than an MP3 player app. Converting your MP3s to IMA ADPCM should fix the performance issues, although it might slightly increase the size of your music files. You can do it with Audacity, or there is a program called WavePad that can export IMA ADPCM with seamless looping. You could also encode to mono if you want to reduce the file size.
Here is the settings to use for WavePad mono export:
Yeah just changing the file ended up working so thank you guys very much for the help
Using a lower bitrate, using a lower sample rate, and/or mixing down to mono will reduce the CPU demands of mp3 decoding. But it'll only get you so far.. If you can't get it to work ADPCM is your next best option.