As my role as lead developer for the iCARE project, I wanted to make sure this app works as well as possible on the mobile devices being sent out to Tonkolilli in the summer (iPad Air 2 – 16GB, WiFi only).
I’ve chosen to develop the app using open source code and frameworks to help speed up the development of the app as well as to help make it functional and cross compatible. The main tools and frameworks used for the app are:
- Adobe AIR – http://www.adobe.com/uk/products/air.html
- Starling Game Engine – http://gamua.com/starling/
- Citrus Game Engine – http://citrusengine.com/
- Feathers UI – http://feathersui.com/
The beauty of using these frameworks are: they work well together, they’re pretty robust, well supported and documented and they work well on mobile (60fps is achievable on modern devices). So good in fact, I believe using Adobe AIR with Starling and co will perform best on mobile without going native (which wasn’t an option due to time constraints!).
I’ve worked with the first 3 from the above list previously for projects with TELMeD and also for freelance projects and university projects before that.
There are a fair few challenges for this project. Some of which I plan on going into more detail in other blog posts. But one I will cover in this post is:
- How we’re loading in potentially hundreds of assets, including high resolution graphics, sounds and fonts
So, the plan with regards to loading many assets into the app was to simply load them all at the start. This worked perfectly in early app builds. However, once we hit around 500KB of GPU memory on a mobile device, this happened:
Two things to note from this screenshot from Adobe Scout, firstly the tooltip that says “Textures: 507,936 KB” and then right the right, “Error #3691“, not cool! So we reached the devices limit with GPU Memory and a plan B was in order.
This was a pretty big lesson learned for me, especially for future projects like this. The main issue was the sheer amount of textures, and large ones at that. With most reaching the device resolution of 2048×2048. This error was crashing the app after only 10 scenes were loaded… and the finished story will hold over 40! The graphics look awesome so I didn’t want to compromise with scaling them up from smaller textures or even setting them to 16bit which I tested and seemed to make a big difference, except the colours didn’t pop as well.
Plan B: To load just the scenes that are required during initial load, then to remove, load new when required. <– this sounds pretty obvious right!? Well the issue with this approach was one of flow and user experience. Naturally, any loading in and out of stuff would cause a frame rate drop and disrupt the flow during scene transitions. With this in mind, this is what I’ve done:
- Load 3 scenes during initial load (0, 1, 2)
- From then on, when user reaches an even scene number, the next 2 scenes assets are loaded and the previous two scenes are removed.
This works pretty good. But I had to time it right and add a few tricks behind the scenes to try and prevent a frame rate drop (which I hate!). During scene transitions, the camera pans from current to next scene and depending on the chosen speed, it can take up to 8 seconds before transition is complete. Its during this timeframe that new scenes absolutely should not be loaded in. So I coded in a listener for this time, then once complete, load the new scenes. This means the new scenes are loading and frame rate can drop all it wants when the user is viewing a fairly static scene. They wont notice it! Also for good measure, the next scene button is disabled during scene transition and then during loading of new scenes (which occur back to back) to prevent button bashing madness. It works pretty well! The only time I notice occasional frame drops is during first few scene transitions. Scout revealed this is because of the text fields on the first scene for capturing user input. So there is room for optimising there.
This is how to fix looks in Scout:
Notice the tooltip now says “Textures: 77,518 KB”. Well within the safety of the 500KB mark. Obviously with this method we could still have the same issue if for example we load too many assets into one particular scene. But for this project, this wont happen as each scene averages between 2-6 sprite sheets per scene. Also you can see a dip in the GPU Memory allocation before new scenes are loaded. This is due to the previous scenes textures and texture ATLAS’s being purged to make room for new. And the top most data row in the screenshot above: Frame Time shows some frame drops (noticeable when doing over the red line), but as mentioned, this shouldn’t be noticeable to the end user as this will only occur straight after scene transition has finished and before they are allowed to select the button to move to the next scene.
See below screen capture to view how and when this all works. From 10 seconds in.
With this new method in place, it means we can pretty much throw as many scenes as we like into the app without issues.