We wanted to experiment and see whether we could build a simple cross platform game using the latest web tech. The idea was that it would run across the mobile platforms and be easy to develop using our existing skills and tools. So for some background we are using cocoonjs to hardware accelerate canvas drawing and melonjs which is an OSS game engine which is easy to run on cocoon.
Our initial attempt was running very smoothly at 60fps on our powerful desktop browsers, however I was getting half that on my Galaxy Nexus. Given how simple the game was we were concerned and looked to find out why. We are developing using Chrome Canary which has the latest developer tools within.
This was the first place we looked to see what was happening.
The trace is telling us we spend a majority of our time rendering rather than executing game logic. The sprites we are drawing are basic and we’ve made them as small as possible so this was the first surprise.
The flame chart puts into perspective how much idle time we have on a desktop machine and that each frame is speedily rendered in approximately 5ms. Initially that sounded good but given the lack of complexity in our graphics this performance is extremely disappointing and is a good indicator as to why the a mobile device might be struggling.
It wasn’t enough to know what to fix yet and for that we used the Canvas Debugger.
This is an experimental chrome feature which means you will need to manually enable it. I used the learningthreejs blog which has a good video explanation but if you prefer something more textual you can follow the guide at html5rocks.
With the ability to inspect each canvas call both at the API level and visually we could track down where we were losing the performance. Below is a gif animation of cycling through each draw call shown in the debugger:
And with that visual representation it has become quite obvious where the extra draw calls are coming from, the background gradient is a 1px wide repeating image! Ironically we chose to do it this way for performance thinking loading a smaller image would be lighter on resources.
We were able to easily fix this in the map editor and it resulted in a big reduction in draw calls.
The gif animation also highlights the draw call for each tile which is imported from the map editor and this could be a further avenue to investigate if we want to target even lower performance devices.
Each frame now takes between 2 and 3ms to complete and more importantly the draw portion of that has been greatly reduced. It only takes 1ms to render on the desktop and the game code is now visible in the profile.
These changes were not only enough to run the game at 60fps on our mobiles, but has allowed us to increase the animation and visual fidelity while keeping the frame rate smooth. If you are working with canvasses either for game development or visualisations like d3 I recommend you grab the latest chrome tools and give them a go.