Well, as it seems this topic gaining some traction, I guess it wouldn't hurt to give away some tips on the HTML5 version that we are creating. Hey, is a forum for HaxeFlixel users, after all!
First of all, while some maps did run actually fine, others did not, because optimization was missing. A quick compile from the normal version (the one that had all effects) to HTML5, produced 14 unplayable maps. Yay.
Now after lots of optimizations, 19 maps, from 20 works! 60/60 fps, with occasional tiny and acceptable drops on heavy moments. For those that wonder, the map that I still can't get to work is the one that needs the Tester thingy to draw lines between objects. Those lines are way too expensive, and the optimizations I made aren't enough.
Here's the tips I found successful while optimizing the HTML5 version:
HTML5 really really hates things such as alpha, rotations, scaling and coloring. If you are using some of them, and you are suffering from performance issues, consider using less and less of these. Do not understimate this tip!
There was a map that had 40 fps max. For the love of me, couldn't figure out what was causing that. Ended up being the colored sprites that I had. The solution was simple: use already colored buttons.
loadRotatedGraphic()whenever possible. I had particles and lots of effects that basically crippled the performance. Reducing the amount of these and by using baked rotations, made these effects possible.
Mind your assets. By default, you might ending up just loading all the assets in your folders (
<assets path="assets" />). That's is a no no, mainly because everything will be loaded. Not only because this will increase loading times, because increases memory usage as well.
Consider excluding things that you don't need and reduce the quality and size of your assets whenever you can. In my case, I use
excludeand I changed the paths on game.XML to use different sound folders (with lower quality) for the HTML5 version, while preserving high quality sounds for the Windows version. Here's a good article on how to handle this matter.
Not everything must be done 60 times per second! Is often a handy way to throw things that needs to always run, in your
update()function. It could be a
if(alive)check, or perhaps, an
isOnScreen()check, it doesn't matter. The question is, do you really need to? If the answer is no, then what it comes handy, first and foremost, are
FlxTimers. How so? You can create a (what I call) heart beat function, that you run aprox, once per second. In there you can check if your player is dead, or change the properties of all the members in a group, or you could update the text in your UI... anything really.
A case study: I've got lasers in my game. Those needed to always call
makeGraphic()and check for overlaps with elements in screen, such as props. I changed the frequency of those instructions, by removing them from
update()and placing them on a function that was called 10 times per second or so. The performance gain was inmediate with any side-effects.
super.update(elapsed) can be a life saver. The new option of update lets you specifically, change the update speed. I found it extremly useful, as I had some NPCs that had some heavy code. Reducing the update rate of these resulted in a performance gain I didn't thought it could be possible. And was by simply doing
super.update(elapsed/2). I combined it with a distance check, so the objects that were far from my main character, were updated less. This saved CPU cycles and the performance increased.
Be memory friendly. Use
destroy()for things that you won't ever ever need. In my case, I had permanent bodies. In some maps, the body count was way too high. You surely can use
exists = false, but if you have no plans to reuse them, use
destroy()This will free some memory, and that is always good :)
recycle() - revive()and try to create everything you are going to need, at the start of your state. Creating new objects at runtime is not always a good idea. You could
recyclebullets, instead of creating new ones. You could
reviveNPCs you previously killed, instead of creating a new one.
Common sense is your friend. Why to do a complex
overlapcheck, when you just can simple check the
.yof two objects? In my case, on the latest picture, I had some acid that did rise. Touching it of course, would kill the player. While overlap/collide was acceptable, I found out that just checking the Y position of the character and the Y of the acid, was 10x times better! This of course can't be applied on all your games, but if you are suferring from performance issues, you might find some answers by thinking outside the box!
You are human, you will miss out things, this is why you need profilers. Chrome bundles up a great profiler you can quickly use, by opening the console (F12) and going to the Profiles tab:
You can use the
Take Heap Snapshot option. This will show memory distribution in your game. You can sort the values, to see which functions are the most memory consuming ones. In my case, I've got 311 particle objects that I'm not even using. I will need to decrease a bit the
maxSize of my FlxEmitters :stuck_out_tongue_closed_eyes: - Also, I've memory allocated for things that I didn't add, but were created anyways (such as the character's cape).
Well, that's it for now. I hope someone else will find this tips useful! If something else pops up in my mind, I will be sure to edit this post. Laters! :heart_decoration:
EDIT: added the profiler tip.