adnzzzzZ wrote:If I were to fix this the solutions for improving performance they would be: reusing particle systems and creating them less frequently; using SpriteBatches instead of normal calls for drawing most things. Any other obvious improvements?
Yep, those are good places to start. I didn't look too closely at your code, so I can't really comment much about it. But here are a few general rules that I remember from game development. Of course, it is always important to measure and profile your performance! Also, some changes require making the code harder to read, understand and modify. So you should weigh developer productivity gains against the performance gains. And don't get obsessed with performance: the game that does nothing interesting but does it really fast, probably isn't a good game.
* Creating and destroying resources while the game is running is potentially slow, so avoid it if possible. Some ways to do this:
1) If you know how many resources of a certain type you need for this level, allocate them when the level starts. Use a free list to allow quick adding/removing of resources (not sure if this will be any faster in Lua, though).
2) If you don't know how many resources you need, pick a number and try it out. Have the code fail if you run out. Can you change the game design so it is OK if the number of these resources is limited?
3) If you don't know how many you need and you don't want to limit it arbitrarily, then reuse if possible, and allocate if not. That's the technique I used for the particle systems in your game.
* If you can, don't allocate/deallocate memory while the game is running either. This is just a corollary of the above rule. It may be a bit harder to achieve this in Lua, but should be possible. Of course, if you take it too far, then you lose a lot of the niceness of working with a scripting language.
* The fastest code is the code that never runs. Don't do any work that isn't necessary. Some ideas:
1) Partition your data. A common example: if you have N objects in your game, don't do O(N^2) collision checks if you don't care about enemy projectiles hitting player projectiles. Only check for collisions you care about (not sure if you do this, just saying in general). Another example: can you avoid updating/drawing objects when they are offscreen? There is a trade-off here, because keeping track of what is onscreen/offscreen could be more expensive than updating it always. Measure it!
2) Push changes instead of pulling -- that is, instead of checking "is this true", can you detect when it becomes true and perform the action then?
* When working in a scripting language, try to make your host environment do most of the work. Your host environment is almost always faster than your scripting language. Can you munge your data so that you can use a built-in function to do the work? Here's a silly example: use table.sort rather than writing your own sort algorithm in Lua. Here's a more realistic example: using SpriteBatch rather than looping over all things you want to draw in Lua.
* Abstractions are useful, but they have a cost. When you add an abstraction, you're typically also adding another layer of code that has to execute. It makes it easier to extend your code, but often can sacrifice performance. This is especially important to be aware of with Lua, where the cost of execution is higher. I've seen a few games fall into the trap of "death by 1000 cuts" -- there's no one thing that is slow, everything is!
Always important to remember: performance is a balance between technical constraints and design constraints. You probably don't have to think too much about performance if you're making tic-tac-toe or tetris. You may need to think about it more if you're making an open-world game or a bullet hell game. But even then you can "design around" the technical constraints of your code: if you write a game where you draw really awesome-looking enemies, but you can only draw one per frame, can you change the design so that fighting just that one enemy is fun?
I'm way off-topic now, though, so I'm going to stop.