When Apple brought the world of touch to smartphones, developers leaped into the new opportunity. A similar opportunity is hitting the industry again now in the form of touch screen PCs. The Ultrabook™ device movement may have ignited touch's potential, but the trend is now spreading to other notebook types, desktop displays, and all-in-one (AIO) designs. The field is wide open, and Intel is spurring developers' creativity around the world with contests, some of which contain categories ripe for touch technology innovation. Recently, the Intel® App Innovation Contest in partnership with the Intel® Developer Zone sent developers a challenge to find the next big target in touch, and Adam Hill may have blasted it with his award-winning Hot Shots* spaceship game (Figure 1).
Figure 1: Adam Hill surveys the main interface of Hot Shots* on the Lenovo Horizon* AIO.
Origins, Form, and Function
Like many developers, Hill has pursued programming professionally while carrying on a fondness for many classic video games, including Asteroids* (1979), Micro Machines* (1991), and Geometry Wars* (2003). He progressed through writing spreadsheet macros as an administrator to receiving on-the-job training as a software programmer, but always with an eye on entertainment and one day pursuing game creation. By the time Intel ran its first App Innovation Contest in 2012, Hill felt qualified to take a stab at it. That project, a tunnel game called Celerity*, gave Hill several valuable insights. Hill knew he had to pare down his ideas and keep them focused. Most of all, he knew that whatever he did needed to appeal to himself; after all, he would be the first user, and if the game wasn't fun for him, others were unlikely to enjoy it either.
When the 2013 Intel App Innovation Contest opened in July, Hill went to work. Intel announced that competitors would receive a Lenovo Horizon AIO, based on a 27-inch touch screen, and coordinators specifically requested a compelling use case for the platform. Hill resolved to give them that and more. Logging in hundreds of hours over six months, the resulting game looked very much like a mashup of the Asteroids and Geometry Wars games from earlier years. Brimming with stunning graphics, gravity physics, and a highly competitive player-versus-player co-op design (Figure 2), Hill admits that the aim of the game focused on one thing: chaos.
Figure 2: Hot Shots* clearly favors touch-based input, but it is also compatible with gamepad, keyboard, and even Lenovo joystick input.
Hill wanted to create a game that would revive the old school face-to-face element of game sharing rather than competing remotely over the Internet. Players' spacecraft materialize on the screen a la Asteroids, streaming exhaust behind and firing glowing projectiles ahead. A star in the center of the screen exerts gravity on all objects. (Players can also spawn a second sun on the screen.) A sort of wire-mesh grid rests under the entire play area, warping with the gravity of objects above it and giving the game a 3D feel lacking in older arcade favorites. Up to nine players can use the on-screen Touch controls located around the screen's edge, including Lenovo's touch screen-compatible joysticks and strikers, and additional players can join through a keyboard and Microsoft Xbox*-compatible controllers. Gameplay was designed for sessions of any duration. Players can simply jump into the madness and destruction, enjoy the havoc, and then leave without disrupting other players.
As with most modern touch screen panels, Lenovo's display is 10-point touch-capable. Hill situated his player control zones around the screen's edge, but he gave one of these edge regions over to game controls, hence having a maximum of nine touch players instead of 10 (Figure 3). The game can be played with one finger, but the experience tends to be better with two, which caps the touch player count at five.
Figure 3: Hill could fit up to 10 touch control regions around the edge of the display. One of these ended up being used for in-game menu controls.
I used on-screen icon buttons because I need complete strangers and non-English speakers to understand how to control the app at a glance, said Hill. Many of the controls are binary?on or off?and a throwback to retro games like Asteroids. Also, I'm dealing with a large number of independent touches. When a touch comes down, for simplicity's sake, I want to understand which user out of several created it, and that's easier when they're touching within a zone. From a technical perspective, it's largely a case of knowing your API, designing out gestural conflicts, and considering the idea of visual feedback.
To round out the game, Hill sought the services of freelance musician Patrick Ytting, who delivered a stellar soundtrack. The stunning visuals can be attributed to gameplay designer and graphic artist Thomas Tamblyn. Both men were willing to work for a slice of the intellectual property ownership and revenue, which was the only way Hill, as a lone programmer, could feasibly complete the project.
Development Challenges AddressedParticle System and Graphics Load
Not surprisingly, the graphics load behind Hot Shots could become significant. With two players, the GPU load wasn't bad, but with as few as three players, the particles and warp grid disturbances, plus the sun's crepuscular rays and other effects, could seize a formidable amount of processing resources. This load compounded if the underlying engine wasn't coded properly. As a result, Hill offloaded as much of the graphics processing as possible to the GPU. In the quest for fluid performance that would scale across both integrated and discrete graphics processors, Hill rewrote his particle engine from scratch three times.
As soon as I knew something was an obstacle, I'd go to town on it, said Hill. I'd rework it until it was one of the fastest things in the system rather than the slowest. The usual method for this was offloading to the GPU, although for particles the trick was to use a simple pool of particles in a boring array rather than a fancy linked list or queue. The optimization decisions you make are always specific to the program at hand.
Hill's initial particle system was based on a class holding a LinkedList of particle objects. He thought that he would create new particles, add them to the LinkedList, and be able to remove dead particles from anywhere in the list without needing to re-index. Unfortunately, Hill had overlooked the performance impact of rapidly creating and destroying a large number of new instances in C#, where at a certain rate of instantiations and destructions, the garbage collector would struggle under the burden and cause noticeable slowdowns.
To diagnose this performance trough, Hill began swapping software components. As soon as he eliminated particles, he found the culprit. However, he wanted the aesthetic look that large numbers of particles gave Hot Shots, so he began browsing through the source code of different particle engines for inspiration. He discovered that others generally preferred an object pool approach rather than a linked list. Also, a FIFO queue of dead/free particles is maintained. That is, one has a fixed length array, and particle objects are created only once. Particles are logically activated and deactivated as needed by moving a reference to them into and out of the queue?recycling rather than recreating. As a result, the garbage collector never has to kick in because nothing is being created or destroyed after the initial semi-instantaneous setup.
The big take-away lesson is that during intensive mid-game processing, you don't want to be using the ?new' keyword anywhere, said Hill. Load everything you can once at the beginning of the level, then recycle like crazy.
Hill's second particle engine was orders of magnitude faster and therefore more stable than its predecessor. In effect, more players could create more particles before any noticeable change. However, this newer engine still suffered inefficiency in managing the queue for the list of free particles. While they weren't being recreated each time, this still felt inefficient. Particles such as a bullet trail or thrust trail have very short lives, and they fade and lose importance with age. Hill realized that he didn't have to recycle particles only known to be free. Rather than iterate through the list until finding a free particle, he could simply use the next particle in the iteration. This allowed him to keep a single index value rather than manage an entire queue, resulting in much less work. By the time the index wrapped around to an already-used particle, that particle was likely either to be dead or at least mostly transparent. The user would probably never notice a sudden particle death, especially in the midst of other visual distraction. Essentially, Hill realized that he could get away with murder in this context.
The optimization for the v3 was not just technical, he added, but relied on an epiphany relating to the obscure relationship between the recycling algorithm and the ability of a user to perceive mostly transparent particles. In your game, you'll have to weigh this. Maybe there's another cheeky trick you can pull instead?
The following code illustrates Hill's particle engine before and after reworking:
01 | // Version 2 Init |
02 | public override void Initialize() |
03 | { |
04 | this.particles = new FastParticle[MaxParticles]; |
05 | this.freeParticles = new Queue<FastParticle>(MaxParticles); |
06 | |
07 | for (int i = 0; i < particles.Length; i++) |
08 | { |
09 | particles[i] = new FastParticle(); |
10 | freeParticles.Enqueue(particles[i]); |
11 | } |
12 | |
13 | base.Initialize(); |
14 | } |
15 | |
16 | // Version 3 Init – can't get much more simple than this |
17 | public override void Initialize() |
18 | { |
19 | this.particles = new FastParticle[totalParticles]; |
20 | |
21 | for (int i = 0; i < particles.Length; i++) |
22 | { |
23 | particles[i] = new FastParticle(); |
24 | } |
25 | |
26 | base.Initialize(); |
27 | } |
28 | |
29 | // Version 3 Update, with Version 2's redundant code commented out |
30 | public override void Update(GameTime gameTime) |
31 | { |
32 | foreach (var p in particles) |
33 | { |
34 | if (p.Active) |
35 | { |
36 | ??this.UpdateParticle(gameTime, p); |
37 | // No need to Queue up free particles any more |
38 | / Just wrap round and re-use regardless |
39 | // Recycle First. Recycle Hard. NO MERCY (or indeed, queuing). |
40 | //if (!p.Active) |
41 | ?//{ |
42 | //??? this.freeParticles.Enqueue(p); |
43 | // this.freeParticles.Enqueue(p); |
44 | //} |
45 | } |
46 | } |
47 | |
48 | base.Update(gameTime); |
49 | } |
Speech Recognition
Hill found the time to experiment with non-essential game elements (Figure 4). Probably the most noticeable is the game's profanity police, which uses speech recognition to scold players who swear by having hostile objects swarm toward them. (Remember that play was meant to focus on group settings, potentially with younger players mixed in.) However, the implementation proved quite tricky. The underlying engine assumes that all speech is meaningful, but the purpose here was to ignore most speech and focus on only known profanity. Hill was trying to shoehorn an API into doing the opposite of its original purpose. Predictably, he got a fair number of false positives.
Figure 4: Hot Shots* gameplay can get rather heated. Hill implemented a profanity police feature to encourage players to keep the experience appropriate for all ages.
In response, I went contrary to the practice of providing the recognition database with a very limited set of words and gave it a colossal 20,000-word dictionary of words to ignore, Hill explained. This way, if it thought it had heard one of my 30 or so key swear words to the exclusion of 20,000 other random words, then there was a much higher probability that swearing had occurred. At the time I thought of it, I'd not heard of anyone else doing this, but I've since seen this type of profanity management employed by at least one EA Sports game.
Touch Development
Hill enjoys working with XNA 4, but coding for touch screens on Windows* 8 can be a challenge as the built-in TouchPanel class tends to be under-supported given the industry move toward MonoGame*. Luckily, Hill already had a solution for this issue from his prior game, Celerity*. The solution is to include Windows7.Multitouch.dll, noted Hill. Don't be put off by the name; it's still very useful for Windows 8 solutions. This provides access to lower-level touch handling, which is great for speed and reliability. While it supports a wrapped version of the WM_GESTURE API, I much prefer working directly with the WM_TOUCH API.
Access to the TouchUp, TouchDown, and TouchMove events can be accomplished with the following necessary TouchHandler:
var touchHandler = Factory.CreateHandler<TouchHandler>(game.Window.Handle);
Hill also encountered an obstacle with sticky touches. In some cases, the lifting of a finger doesn't result in a TouchUp event. Obviously, this can pose a serious problem when, for instance, stopping a ship from firing or adding additional users. The solution proved to be touch culling.
With culling, a countdown gets reset every time new information is received from a touch point. Effectively, a touch times out. At first glance this might seem like it would yield occasions when a depressed button would simply stop working, but in practice the sensor resolution of the touch screen is sufficient to register tiny finger movements, even when the user believes he or she is holding still. These small motions register as TouchMove events and restart the countdown.
Lessons Learned, Advice Given
Hot Shots won the All-In-One (AIO) Category of the Intel App Innovation Contest 2013 for several good reasons. Clearly, the game makes excellent use of the large touch screen interface, but it does so in a way that fosters group involvement and bonding. Hot Shots carries forward some classic game nostalgia while adding several layers of graphical wizardry that both make the app modern while simultaneously leveraging so much of the horsepower that current-gen processors can offer. The visuals and soundtrack are drop-dead gorgeous, and, perhaps most of all, Hot Shots makes it intuitively clear how tomorrow's AIO systems can serve a whole new set of uses flat on their back as well as standing upright.
Sometimes, there's more to coding than instructions. To nail an app perfectly, sometimes the programmer needs to step back and think about paradigms, especially when new hardware capabilities are involved. We have to accept that the old interaction metaphors of buttons and scroll bars are very often suboptimal interactions, said Hill. The swipe gesture is so simple, but so powerful. Think about how much easier it is to arbitrarily drag your fingertip approximately over a surface rather than aim and tap. Successful gestures are often very rough and approximate. The less accurate the user needs to be, the faster they can go. Do your own analysis. For further reinforcement, Hill recommends that interaction designers begin with Josh Clark's Buttons are a Hack talk.
Sometimes, experience will lead a programmer into bucking conventional wisdom under certain circumstances. For example, Hill notes that for competitions such as the Intel App Innovation Contest 2013, he doesn't use unit tests. Many programmers consider unit tests essential in order to assure quality. However, while he acknowledges the need for unit testing in professional code, ?for me personally, in a competition like this, I find it a net win to ?just code.'
Adam Hill sees a bright future ahead for touch screens and haptic technologies. He is now working to start a company to publish Hot Shots in the Windows 8 store and help promote table computing. Lenovo's Horizon proves that the form factor can now be sold at affordable levels, which means that this is the time to dive in and explore just how far one's imagination can take the platform.
For more such windows resources and tools from Intel, please visit the Intel® Developer Zone