Running out of performance optimization ideas...worth porting to C?

I've been constantly running into performance snags with my space shoot em up type game in Lua. I checked the sampler and nothing stood out. Seems like the highest cost is in collision detection which would make sense.

Basically, once I go above like 15 enemy sprites on screen the frame rate drops to about 25 on my device. I've also noticed that it makes the audio start clipping, i'm guessing due to low CPU.

At this point I'm considering giving up for now, and eventually porting the whole game over to C. However that'll be a massive undertaking because I don't know C at all (though I have always wanted to learn :wink: )

I guess overall my theory is that maybe the style of game I'm making isn't exactly suited for Lua, as there are tons of constantly moving animated sprites all over the screen (on top of lots of collision detection/etc)

Things i've tried:

Here's a pic of the sampler output:

...and here's a gif of the game running in the simulator:

Any ideas?

project source code: GitHub - jordanbleu/hyena: PlayDate Game

1 Like

Probably not related but make sure you don't use mp3 for music, it can be quite taxing


Yeah, I did convert to the wav format recommended by the docs. Thanks for the suggestion though :slight_smile:

I had a look at your repository but I wasn't sure where to look.
How do you instance your sprites? If you instance them one by one, would be possible to have a Sprite Manager instead?

Finally, I don't know if your ship moves up but you could otherwise only start detecting once your sprites reach a certain Y for instance.
I believe the latest shmup released on Catalog is in lua so there is surely a way. Look at his devlog, you may find some idea as well (and also double check the lua thing I am not 100% sure)

I would not recommend porting the game to C. It will require a lot of efforts and even if you will improve the performance, that would be nothing compared to try to understand how to architecture your game to optimise it.

In general you "just" have to find places where you can avoid running code, like loop through the least number of entries, exit a function as soon as possible, use as little structural code as possible etc.

For example in your gif all the enemy move at the same time with the same animation. Looking at the code the behaviour is run for each enemy. So the game loops through all the sprites, and for each enemy they run the behaviour code and for each enemy the result will be the same.
Instead if you run an enemy manager (for each type), the enemy manager will define once of many pixel the enemy will move, loop through the enemies and just move them.

In general your code is super well organised and structured, but that also mean that the codepath is much less clear. When you write an enemy manager that handle one type of enemy, it is easier to see each step and how to find optimisation.

One last point regarding the collision detection: The sprite collision detection in the SDK is very handy but it is also designed to be generic and performant in all cases. The issue however is that it is harder for you to find optimisation.
For example you could run you own collision detection between the bullet and enemies, you could just test between a point (a bullet) and a box (an enemy) which is simpler. But you could also test rows of enemies and if the bullet is vertically not high enough compared to a row of enemies, you can skip all the detection for all the enemies in the row.

That's just some ideas from the top of my head.


Sprites are instantiated in my scene classes. If you check the “scenes” folder of the repo you see I instantiate most of the in game stuff there. I went with the whole “everything is a sprite” approach, which I’ve since learned was probably one of the worst things I could do :sob:

1 Like

The enemy manager suggestion isn’t a bad idea, I’ll have to experiment with that, and maybe taking a less OO style approach. I’ll have to go back and do some re-architecting

Can confirm that the manager solution does help. I went from ~8fps moving around 100 sprites and (with other optimizations) got it closer to 20-25 when there's a lot going on.
I used one of Squid's livestreams to figure out how to do it, idk if there's a better guide LOL
(starts at ~23:50)