EA Air Hockey: Designing a One-Button Mobile Game

Note: This article was originally published in two parts on Gamasutra (now Game Developer) in 2007 and may be found here. Though I have made various edits for clarity and grammar, I've maintained the original two-part demarcation (albeit condensed into one post). EA Air Hockey (yes, that EA, Electronic Arts) shipped in 2006, and as noted this article was originally published in 2007; as such, it uses the mobile development vernacular of the period (pre-iPhone remember) such as BREW, J2ME, and so on. Yes, there were mobile games before the iPhone! For about 6 years before the iPhone App Store opened in July 2008 my company, Uztek Games was doing game development for mobile devices, fragmented and awful how they (some of them) may. There were basically no (usable) touch screen phones during this period, hence the focus on a one-button game design. Eurogamer reviewed the game at 8/10, IGN reviewed the game at a clearly finely grained 7.6/10.

EA Air Hockey: Designing A One-Button Mobile Game: Part One [05.10.07]

This article covers the design and development process of a shipping one-button mobile game - EA Air Hockey, which was released in the first half of 2006. This is not so much a post mortem as it is a dissection of the game. I was the designer and lead coder on this game, and I've taken the opportunity here to go into some detail about how the design evolved and how various technical and playability problems were addressed. Hopefully, this will prove interesting or perhaps even useful for others who are tackling the same sort of design challenges.


Before embarking on a detailed discussion of EA Air Hockey, I want to acknowledge the valuable input and guidance I received from key people at EA Mobile (then Jamdat). First, credit goes to Zack Norman for signing the game in the first place, for his valuable input and suggestions throughout development, and mostly for coming up with the idea of doing an Air Hockey game. Next, credit goes to Travis Boatman, again for his valuable input through development and for his help with project administration (and for giving permission for me to publish this!). And last, but by no means least, credit goes to Adam Schwenk - my long-suffering producer who put up with all the stuff that producers have to put up with.

What is "Air Hockey"?

Some people know the game as shuffle puck, table hockey, shuffleboard, and no doubt other name variations. Air Hockey is a game where two players each use a disc-shaped "mallet" (or "hammer") to hit a "puck" around a table. The table has a perforated surface through which air is blown by a fan - the air provides a cushion for the puck, which literally floats around the table due to the reduced friction. Each player defends a "goal", which is simply a slot that is several puck-widths wide, and basically the first player to score 7 goals wins.

EA Air Hockey (aka JAMDAT Air Hockey)

Why one-button?

The primary reason to develop a one-button game for a mobile phone is one of simple practicality: the keypads on most mobile phones are not really very good for playing games on. The trend with phones is always smaller, slimmer, flatter - and of course, much of the "size" of a phone device comes from the keypad itself. Keypads are designed to look cool (e.g. RAZR), and so that you can dial a number and (maybe) text a message. Expecting anything much more than that is a luxury for many of the phones out there. Requiring only one button really nullifies this concern - no scrambling to find the right key.

The other compelling reason to create a one-button game is to appeal to the so-called "casual" gamers and the non-gamers (the "to be converted") as it's these folks who make up the vast majority of "mobile phone users". A game that is playable with one button should contain little to scare away or embarrass such a player. I wanted to make a game that the salesperson in the cellphone store could just hand to any customer and say, "just press the OK button to play".

One-button design

So, I wanted to make a game that would work on any phone on which the following statements are true:
  1. Program code can detect that a single key is ‘pressed'.
  2. Program code can detect that a single key is ‘held'.
  3. Program code can detect that a single key is ‘released'.
Thus, the game design I had in mind had to allow the player to control the entire game using just a single key, and where 100% of player input would resolve to pressing, holding, and releasing a single button.

Now at this point, some readers will have no doubt noted that there are already games like this for mobile, and there have been for some time. In fact, some of the most successful mobile games ever already use such a system - Jamdat Bowling for example. So where's the innovation with what I had in mind? Well, the big difference is this: what I wanted to do was a "real-time" game - one that is not quantized into "strength, aim, spin, watch" slices. Rather, I wanted to apply a single-button control dynamic to a game that runs in real-time, and which at no time pauses to allow the player to set a strength-gauge, or an aim-meter, or anything like that. The goal was to create a fluid, controllable "action" game where the only control available to the player was a single button.

So, here's what I came up with. I am going to cover the design in terms of the primary challenges encountered, by detailing the solution to each challenge.

Timing of player shots

When the player presses the OK button, the mallet moves to intercept the puck.

When the player presses the OK button, the mallet moves to intercept the puck.
Timing of shots was one of the more approachable design challenges. All that happens is that when a player presses OK, his mallet starts to move toward the puck. Shot aiming was a different matter, but the only real wrinkle with the shot timing is that pressing the button commences the shot, but the actual collision with the puck will happen at some time in the future when the mallet (hopefully) collides with the puck. It is a subtle point, but this does cause some complications in the actual aiming logic, which I will cover below. The player must hold the button in order to continue the shot.

When the player releases the button, when a collision with the puck occurs, or when the mallet reaches the centerline, the shot is canceled and the mallet returns to a more defensive position on the table (covered in mallet positioning below).

Strength of player shot

In order to provide some nuance and subtlety to the control, I modeled shot strength based on the length of time the button is held. So, if your mallet is near your goal, and you anticipate a cracking shot near the centerline, you'd get pretty close to full strength. More defensive shots nearer your goal line would have less strength. Essentially, the longer you hold the button, the further your mallet moves, the stronger the shot. Note that the speed of your shot is always constant - there is no shot acceleration.

Positioning of the player mallet

The player's mallet performs an oscillating arc around the current position of the puck.

Positioning the mallet has some challenges. Taking a shot can be controlled with one button in a fairly obvious way, but how to position the mallet when not taking a shot? Using just one button, there's really no alternative but for the mallet to position itself. I considered some other approaches, such as adding an "override" so that more advanced players could alter the mallet position using the d-pad arrow keys, but in the end, I eliminated this logic and instead worked on ways to make the mallet move in useful ways with no player input. After analyzing how the real game is played, I realized that there are two main modes of play: offensive positioning (where the puck is in front of your mallet - i.e., closer to the opponent goal), and defensive positioning (where the puck is behind your mallet - closer to your goal). There's also a transition mode, where the best mallet position is likely to be obtained by moving the mallet so that the puck is between it and the player's own goal.

Here's what I did:

When the puck is in front of the mallet, the mallet performs an oscillating arc around the position of the puck. Essentially, a line is imagined between the center of the puck and the mallet, a position along the line is chosen (it is a fixed proportion of the line length) and then this distance is used as the radius of an arc. Then, the angle around this arc simply oscillates and the mallet moved toward the resultant location. Since the mallet "falls back" into this oscillation mode after the player takes a shot, I was concerned that the resume position on the arc would need to know the context (i.e., where is the mallet coming from), but in practice, the angle simply keeps oscillating at all times, and the mallet just "tends toward" the location currently dictated by the oscillation.

When the puck is between the mallet and the player's goal, the positioning logic smoothly transitions into an alternate arc pattern.

When the puck is within a certain distance of the player's own goal and moving toward that goal line, the mallet enters a different mode. This time the mallet moves itself to a location further away from the player's own goal line than the puck, and again performs an orbiting oscillation around the puck.

In the transition between the two main modes (which appear seamless to the player - that is, the positioning of the mallet does not have any obvious discontinuity), there are some subtleties - the mallet has to make sure not to travel through the path of the puck, for example, and cause an inadvertent collision with the puck. This was more of a problem when the mallet was moving from defensive mode back to offensive mode, as the likelihood is that a collision with the puck will result in an own goal.

In both cases, the oscillation is performed in order to present alternate shot possibilities to the player. Fundamentally, this is really an application of the oscillating "aim" bar in games such as Jamdat Bowling to a game that is happening in real-time.

Aiming player shots

Player shots have to take into account the path of the puck, including rebounds from the sides of the table.

Aiming was one of the most interesting challenges. Given that the player has only one button to control the game, and that we want the button to cause the player mallet to do something sensible at all times (the player may need to defend or attack, and the puck could be located anywhere on the table relative to the mallet), there are quite a few factors to take into account. After much experimentation, I was finally able to resolve the reaction of the mallet to the player's input consistently at all times. The solution to how to move the mallet resolved into an intercept problem. Essentially, the mallet moves in a direction that will result in the shortest (time-wise) intercept of the puck, given the puck's current velocity and location. I am not going to get into the detail of how to solve that problem mathematically, but suffice it to say that the solution takes into account the fact that the puck is decelerating, that it may bounce off any of the edges of the table multiple times before the mallet can hit it, and that the puck might actually go into one or the other players' goals before the mallet has a chance to hit it! In practice, the intercept code proved to "feel" right to the player - it seems to intuitively move toward where a player would move the puck, including anticipating bounces and so on.

The latter point is a key factor in the controllability of the game because it changes the notion of "aiming" into an act of "timing" - pressing the button earlier or later will result in different collision points with the puck, giving the player the opportunity to try different shots against the opponent (bank shots, etc). This works nicely with the one-button control mechanism, and again this takes your Jamdat Bowling "choose when to press the button" sort of activity and maps it onto a real-time game.

EA Air Hockey: Designing A One-Button Mobile Game: Part Two [05.17.07]

One-button AI

Early in development, the AI was quite a simplistic affair. It would pleasantly take shots back at you, without any real strategy or tactical analysis on its part. In fact, this played just fine, but it was decided that we needed to up the AI intelligence level so that those non-casual gamers could be presented with more of a challenge. It would have been easy enough to cheat and give the AI abilities that the human player does not have (in terms of positioning for shots, etc). However, I decided to "take the high road" and make the AI follow the same rules as the player (more or less). What I did was to make the positioning of the AI player's mallet 100% identical to the player. So, the AI mallet would do the oscillating arc movement, etc. This left just one problem to solve, "when should the AI take a shot?". What I did was to periodically calculate the result of an AI shot. The frequency of this evaluation was proportional to the smartness of the AI and is one of the main factors between the three difficulty levels offered by the game. During the AI shot evaluation, various statistics are collected, obvious ones such as whether the shot is a scoring shot (or a home goal!), but also additional stats such as how many bounces the puck will take, whether the puck hits the other player's "goal line" and so on. These are then fed into the AI logic, and filtered using the current "mindset" of the AI, which changes according to a table of "moods" defined for each difficulty level. As an example, some AI moods dictate that only direct scoring shots will be considered, others that only indirect scoring shots will be considered, and yet others that appraise a shot positively if it merely hits the player's goal line. By stepping through AI moods, and using different tables of moods for different difficulty settings I was able to implement a scalable and challenging AI.

Referring to the AI moods - these are named "banker", "acer" etc in the source code as there was some initial thought to surfacing the AI opponents with characterizations, as has been done with other table sports games (pool, etc). In the end, we did not go down that road, but it would make a nice addition if there's ever an Air Hockey 2.

One-button Gamesmanship

Gamesmanship is the act of "gaming the game". In other words, it is the use of tactics that exploit a weakness in a particular game's design to the advantage of the player. In this case, there was one such issue that pervaded the testing process - "button-mashing". It was discovered during the testing process that by "mashing" the button (ie, repeatedly pressing the button as fast as possible) it was possible to effectively block the AI. This did not give the player an unfair scoring advantage directly, but since the AI would not retaliate in this fashion (one possible solution was to make the AI button-mash in response, but that did not seem very satisfying), the AI was prevented from scoring and the random goals scored by the player while doing this resulted in player wins. It's an interesting problem, and it's something that would not happen in real life - if you were to employ this tactic against a human opponent, your opponent would simply slap you upside the head. This is generally borne out in EA Air Hockey's 2-player mode - not (that I've witnessed) the head-slapping, but the fact that humans tend not to try to game each other in the same way as they would with a computer opponent. With regard to the button-mashing, part of me felt that if a player wanted to game the game in this way (futile as it would be to do so) then so be it. But then another part of me felt challenged to address this. In any case, after a while, the folks in QA were complaining so loudly about this "flaw" that something just had to be done. I ended up trying many different solutions, but QA proved very adept at poking holes in any anti-mashing defenses, so I just had to keep trying different things. In the end, the solution turned out to be in keeping with the design of the game. What I needed to do was step back, and think a little about the "real" Air Hockey, and some of the physical realities of playing the game. What I realized is that when, in the real game, a player goes to make a shot from the centerline, they will physically have their playing arm at full stretch. Accordingly, shots played from the centerline (that is, shots that originate when the player's mallet is at or near the centerline) will of necessity be lower-powered. This was simple to model, and fed nicely into the "shot strength" dynamic described above. The result is that button-mashing will still cause the player's mallet to hover around the middle of the table, and this will still potentially "block" the AI, but the resulting blocked shot will be very weak, leaving the AI plenty of time to counter, and get a shot past the player.

One Button Per Player, Two Players Per Game?

Two-player mode switches to a top-down perspective where players control one button.

When I started work designing EA Air Hockey, I'd been given a mandate by Zack Norman that the game must feature a two-player mode. Initially, thoughts were along the lines of doing a split-screen, with each player having his own "perspective" view of the action. Ultimately, I implemented a top-down view, which was more satisfying for a number of reasons. With the top-down view, I was able to orient the table sideways, so that two players could hold the phone between them. Then, to play the game, player 1 (at the right-hand side of the screen) would use the ‘6′ button, and player 2 (at the left) would use the ‘4′ button. Each player has the exact same controls and in effect, the phone is treated as a miniature arcade table.

One-button Final Thoughts

Here are some final thoughts on the completed game, some things that worked, others that worked out differently to my expectations, and details of a couple of features that did not make it into the game.

Intuitive controls

Although much time and energy were devoted to creating an intuitive control system, in practice there's one issue that people seem to trip over. The idea of pressing and then holding the OK button to take your shot seems to trip some people up. When the controls are explained to people, they understand it quickly enough, but people, especially non-gamers, seem to intuitively press OK and then immediately release the button. In retrospect, this is understandable because that's what you do in regular use of the phone, dialing numbers, sending a text message, etc. As a direct result of this, I ended up implementing a fairly extensive tutorial system that aims to train the player to hold the button down for longer shots. It was interesting just how much the use of a single button could be misinterpreted - but since there is only one button, it's really an all-or-nothing proposition in some ways!

Dropped gameplay modes

The 4-player mode was dropped early on, but it might have looked like this.

As with most projects, some features were cut due to lack of time or space, or both. A couple of the more interesting (although possibly marginal in terms of additional value) modes were the 2 x players vs 2 x AI mode, and the 2 x players vs 2 x players modes. In principle, there's no reason why both of these modes can't be implemented using exactly the same techniques used elsewhere in the game, but there was just no time to include them in the game.

Leading development on BREW

I developed the game initially on the BREW platform, and therefore it was developed in native code (C++ and ARM assembler for some special effects). The game runs marvelously on BREW, and because you have raw access to such things as the primary graphics buffer and so on, you can squeeze every ounce of performance out of the BREW devices. When it came time to get the game finalized on the J2ME platform, it became clear that performance was going to be an issue. Ultimately, things resolved themselves in a fairly satisfactory way - we achieved the frame rates that are expected on the J2ME devices. That said, when the "expected" frame rate is 5 fps or less, you can imagine that the gameplay experience is going to be significantly different from that on BREW platforms which ran at 15 fps on all but one of the reference platforms (the VX6000 is well known to be a slug, and even that ran at a respectable 12 fps - though not without some hoop-jumping it must be said!).

Creating art assets with a 3D package

See here for some examples.

One design decision I made early on was to create all of the in-game art assets directly using a 3D art package. The game uses sprites to display its perspective view of the table, and generating these with a 3D package provided a neat way to generate all the different sizes of images needed to give the illusion of perspective movement. There were some issues with this approach, such as the edge aliasing problem that always arises when attempting to create 2D "sprites" using a 3D package, but those problems were overcome and we did in fact create 100% of the in-game art using 3DS Max on all but some of the very tiniest screens. On some of the really small screens (the KX414 BREW phone for example), we applied some simple filtering to the output of Max, so it really was not an issue. The other advantage of using a 3D package is that generating assets for varying screen sizes is as easy as changing the render target size, and then adjusting a couple of constants in the code. In this way, the game artist, Shaun Tsai, was able to generate the art for all BREW (from the 104×68 pixel KX414 up to the 320×240 pixel VX9800) and J2ME versions from the exact same art assets by simply rendering to the specifications I gave him for the various screen sizes needed. It's an approach that will not work well for all games, but for Air Hockey with its non-organic, solid game objects, this was ideal. This approach does also require that the game moves objects in a virtual space (not pixel space), and in fact, internally, Air Hockey tracks all objects in a virtual 3D coordinate space. I've even created a test version of the game that replaces the 2D sprite rendering with real 3D, though that's just a personal project at this point.

AI surprises

The AI evaluates all shots equally, it does not distinguish between offensive and defensive play - if there's a scoring opportunity while in defense mode, go ahead and take it! An interesting side-effect of this is that the AI is quite capable of bouncing a scoring shot against the player off its own back table edge (the goal line). It does not occur too frequently in regular play, but it does happen, and when it does it is quite intentional.

Rejected art

Vector-style art sketch (I kinda like this one).

Flying saucer style art sketch.

This stone-age style looks cool - the physics would be interesting though!

The final art for the game I think does a good job of representing the look of a classic Air Hockey table, garish primary colors are all the rage for the real game. We did create a number of other prototype art styles for the game (there was at one point some thought of unlocking these), which were rejected for one reason or another. I've included a couple of samples of these prototypes here.

Genesis of EA Air Hockey

Projectyle on the Atari ST circa 1991.

Projectyle prototype running on a mobile device circa 2003.

Projectyle prototype running in 3D on a mobile device circa 2004.

Although I give Zack Norman credit for the idea of doing an Air Hockey game, in fact, the mobile game came about directly because of another game I designed and developed some 16 years or so ago. The game was Projectyle, which was published (ironically, as it turns out) by Electronic Arts for Atari ST and Amiga in about 1991. Projectyle was not a one-button game, and it wasn't that Zack had been a huge fan, or anything like that (I doubt he knew it existed), but I had obtained the rights to the game from EA and as I've mentioned previously, there does exist a playable mobile version of the game. In fact, it was this version of Projectyle, running on a Microsoft Smart Phone as I recall, that I showed to Zack, this would be E3 2004, and it was Projectyle that piqued Zack's interest in developing an Air Hockey game with me. Projectyle (the original) was a three-player game (using keyboard and multiple joysticks) which I've described previously as a cross between Air Hockey and Subbuteo. The mobile version of the game supported Bluetooth, three-player multiplayer. The mobile versions remain unfinished and unpublished.

January 10, 2022, addendum

Here's a YouTube video showing EA Air Hockey (also known as JAMDAT Air Hockey, since JAMDAT was acquired by Electronic Arts just as the game was being finalized).

And here's another YouTube video, this one from KillerShrew with a nice (recent - 2021!) review of my Projectyle game for the Commodore Amiga. Clearly a nod to Air Hockey in there. :)

If you enjoy my blog, you can help support it by buying me a coffee!


Popular posts from this blog

Nodes of Yesod : ZX Spectrum Next : Update #4

Odin Computer Graphics Part One : 1985

Software Projects : 1984