Top 5 Things A Game Can Teach Your Business App

Guest Blog Post

One of the reasons why I love programming is that it’s an incremental learning process. Every app that I develop at Fig Leaf Software teaches me important lessons that I can often apply to future projects. And my favorite projects are the ones that we develop purely for business-development purposes, where we get to show off all of our programming and design-fu…and usually find a few platform bugs and weaknesses along the way.

Sencha’s Raiders, depicted below, is a space-combat game developed in Sencha Touch over a period of six weeks. No other frameworks or libraries were used in its creation.

We undertook this challenge:

  • To demonstrate Fig Leaf Software’s competence and creativity with building mobile applications on the Sencha platform.
  • To illustrate that the Sencha Touch drawing and sprite components were mature enough to handle the demanding world of arcade game development.
  • To highlight some of the areas where HTML5 on mobile devices still falls a bit short in meeting critical gaming requirements.
  • To enter the app in various programming competitions (including the Blackberry App Challenge in which we were declared a winner)

While Sencha’s Raiders — or any game for that matter — would rarely be seen as a mission critical application, there are aspects of building a game app that can be applied to even the most data-centric, corporate application. In this article, I’ll share 5 key things we learned that you can apply in your business application development.

Monitoring Stylesheets Based on Deployment Mode

Conventional wisdom dictates that your mobile app’s images should be base-64 encoded into your CSS file. This process reduces the number of HTTP requests that need to be made to retrieve the files resulting in enhanced overall performance at the expense of file size (base-64 encoded images are generally 1.3X the size of their binary counterparts). In SASS & Compass, you can base-64 encode an image quite easily by invoking the inline-image mixin as illustrated below:

	.starbackground {
	   background-image: inline-image('starrybackground.png');

In this example, the file ‘starrybackground.png’ is read from my project’s /resources/images/ folder, encoded as text, and stored in the stylesheet resulting in the following output:

	.starbackground {
	   background-image: url('data:image/png;base64,iVBORw...[truncated]...C');

You can change the base path for the inline-image() mixin by configuring the images_dir variable in your config.rb file:

	dir = File.dirname(__FILE__)
	load File.join(dir, '..', '..', 'touch', 'resources', 'themes')
	sass_path = dir
	css_path = File.join(dir, "..", "css")
	// used by compass
	images_dir = File.join(dir, "..", "images")
	// used by sass
	images_path= File.join(dir, "..", "images")
	output_style = :compressed
	environment = :production

Since most Sencha Touch apps make relatively minimal use of artwork, base-64 encoding assets makes a lot of sense. However, Sencha’s Raiders used a series of high-quality PNG’s that generated a stylesheet in excess of 6 MB. Rather surprisingly, the app still loaded and ran with this overhead, it just did so…poorly (particularly on Android). Going back to using a standard CSS URL reference and reducing our stylesheet to less than 1MB in size resolved many of our performance issues, and since the app was primarily going to be downloaded and installed from an app store instead of run from the web, dealing with http latency was much less important than improving overall stability and performance.

Lesson learned: Best practices for mobile web are not necessarily the best practices for a packaged app.

Features Can Be Misinterpreted — Give Users Control

One of the features that I like to build into our apps is the appearance of breaking the “third wall.” That is to say, I like it when the action inside an app tries to “manifest” itself into the “real world.” During the game, when your ship’s hull takes a critical amount of damage, we simulate the “breaking” of your phone’s screen, which everyone considered to be a very cool effect.

However, one of the other features we added was that whenever your ship took a hit, the entire screen would shake. This was misconstrued by most users (and even some developers), as a glitch in the game. Unfortunately, we ultimately disabled that feature, requiring the user to activate it from their game preferences screen. Notwithstanding the above, if you’d like to add a screen-shake special effect to your app, just invoke the following code from a controller:

	onExplosion: function() {
	   // shake viewport
	   Ext.Function.defer(function() {
	   }, 20, this);
	   Ext.Function.defer(function() {
	   }, 40, this);

Lesson learned: You need to either make app features clearly understandable or give the user the ability to control their implementation.

No one reads instructions, ever.

It should go without saying that users don’t read instructions. And yet, everything that I’ve ever learned in life, I’ve had to learn again.

Sencha’s Raiders seemed vaguely familiar to the 40 and older crowd (it’s based on the 1979 Atari 400/800 classic, Star Raiders). However, these new young whippersnappers who were born the year I graduated from high school and will never know the utter enjoyment of typing in thousands of lines of AtariBasic code with a membrane keyboard had no earthly idea of how to play the game. Forcing users through the instructions screen when they first launch the game helped somewhat in this regard, but we ultimately wound up having to re-engineer the gameplay to use on-screen controls that would be familiar to the touchscreen generation, e.g. a virtual joystick:

During playtesting, most users expected to use either the device accelerometer or swipe motion to change the ship direction. None used the navigation gestures that we detailed in the instructions. Since I’m not a big fan of trying to tweak the accelerometer for precision control, we went with the virtual joystick (based loosely on the Sencha Touch Slider) as it seemed to be the lowest common denominator.

And, when all else fails, you can try to force the user to read the instructions by making it a prerequisite for using the app:

Lesson learned: if your app requires reading detailed instructions for a user to get started, then you should probably re-think your UX.

Animating Sprites is easy!

There aren’t a lot of great Sencha sprite examples available. This is truly unfortunate since the Sencha Touch draw package, which is the underpinning of the Charts system, is quite powerful. Even if you’re building a corporate app, you should at least pitch the idea of adding either gratuitous animation or gamification to your apps. Studies have shown that gamification improves user engagement, return on investment, data quality, timeliness, and learning.

To animate a sprite, simply call the fx.setDuration() method as illustrated below. Any transforms that you subsequently apply to the sprite will occur gradually over the specified time period (in milliseconds).

	var component = new Ext.draw.Component();
	var sprite = component.getSurface().add(
	   type: 'rect',
	   x: 50,
	   y: 50,
	   width: 50,
	   height: 50,
	   fillStyle: 'blue'
	   x: 200,
	   y: 200,
	   rotationRads: 3

You can apply this technique to adding interactive effects to Sencha Charts. After all, who doesn’t want to see a Klingon battlecruiser fire a photon torpedo at a pie chart, obliterating one of the data series?

Protip: You could easily modify this code to theme it for zombies.

Lesson learned: Canvas-based animation outperforms CSS animation, but GPU performance in mobile browsers varies significantly.Tread lightly, develop multiple proof-of-concepts, and test frequently on a broad range of physical devices.

HTML5 Audio — You won’t need to purchase a “crazed screaming developer” sound effect

Cross-device compatible precision HTML5 audio still isn’t available for all devices. While you can try to “make do” with the JavaScript methods of the basic HTML5 <audio> element, this level of support is typified by poor performance, bugs, and memory usage issues. Developers have come up with a lot of kludges (“Audio Sprite”) to try to mitigate these issues, but make no mistake about it — working with HTML5 audio is just a big bucket of disappointment.

In the near future, we hope to see broader implementation of the more robust HTML5 Audio API, whose support is currently limited to the following browses/devices:

  • Google Chrome for Android 28 (enabled by default since 29)
  • Mobile Safari 6
  • Mozilla Firefox 23 (needs configuration at about:config)
  • Tizen
Lesson learned: Low latency, cross-device audio support isn’t quite ready for prime time yet.

It’s a Wrap!

So, there you have it. We suffered so hopefully you won’t have to!