Today we released our first complete iPhone game, Reiner Knizia's Money. It's a "Eurogame", which means that it's part of a stream of very intelligent game design that's been coming out of Germany (primarily) for the last 30 years. It's full of games that are often quick to play, but have carefully designed mechanics, and allow for a lot of strategy. Depending on how you classify it, Money is either a card game or an auction game. You're trying to use money you're dealt to earn more money, eventually collecting sets of the same currency to earn points.
If you've enjoyed this blog, and want to see what one of our actual designs looks like, I encourage you to buy a copy. We're offering it for $1.99 until Sunday, after which we increase to our normal price of $2.99.
With that crass commercialism out of the way, I'm now going to talk a bit about some of the decisions we made when putting together the game, as a guide to what you might want to consider in your own designs. This is going to be a code-free blog entry. My goal is to talk about higher-level design considerations, specifically on the topics of output and input, which together represent the foundation of the program. If you think the code for any section would be particularly interesting, leave me a note in the comments, and I'll consider it for a future entry.
Choosing the Graphic System
The first step in writing the game was figuring out how to represent the playing field and the cards. Clearly, they'd need to be drawn on the iPhone in some way, but there were several possibilities, including using Core Graphics to write directly to a view, designing with UIImageViews (or something similar), and going with a more complex language like OpenGL. I believe that building with Apple's core expertise is likely to benefit you in the long run, as it's probably more likely to be upgraded and improved through future releases. Thus I threw out OpenGL pretty early.
However, I also didn't want to use a higher-level class like UIImageView, because I was afraid it would create additional overhead, and that could really add up, as I'd have almost 70 cards on the screen in Money. That left me with two potential middle grounds: creating each card as a UIView and creating each card as a CALayer of a UIView. To be honest, I'm still not certain how much of an efficiency difference either would have made, but since I know that every UIView is backed by a CALayer, clearly going with a UIView would have meant something more in resource allocation. So I went with the simplest answer possible, the CALayer, which could be created as a sublayer of my main GameTableView.
Choosing an individual object--the CALayer--over something more kludgy--like scribbling card images directly onto the main rectangle of my GameTableView--also offered a few more advantages. First, I could directly access Core Animation--and that's in fact how almost all the animations in the game are managed. Second, it abstracted things well, in the way that you'd expect from an object-oriented program.
That meant that I could actually expand on Apple's basic CALayer a bit, attaching more information to each object. And, I did. When I was done I'd created a subclass called CArdLayer which actually included a number of different CALayers (for the front and back of the card, plus some additional layers to brighten or darken the card) and several properties (most importantly, a tag, which let me uniquely identify the layer).
Just having all of those cards shuffling around as sublayers of a UIView did most of what I wanted. It allowed me to represent a card game. However late in the process I ran into one other problem: I wanted to create some popups and other information that would always appear above my cards.
I discovered that I couldn't guarantee the position of layers relative to each other, but it was a pretty simple matter to instead break out two subviews from my GameTableView and keep the cards on the lower view and the info on the higher one.
Figure 1-1 shows how these various objects ended up laying out in relation to one another.
Before I close out, I should offer one final caveat about my graphic design. There turned out to be some performance problems with the display of my 70 cards, which makes them slower than I wanted when animations like dealing ran on my actual iPhone. My colleague noted that he'd read about some people moving over to OpenGL as a result of similar problems. Fortunately, the performance problems turned out to be related only to 1st generation iPhones, which is what I was testing on. The GPUs on everything newer offered very sprightly animation speeds. So though I'm still not thrilled that 1st-gen iPhones go slower than I'd like, I can now see that it's an issue that affects just a fraction of the user base, and one getting smaller day by day. So for the moment I feel confident in my decision about how to display things graphically, as I go forward.
Designing the Touch Interface
Now that I knew how I was going to display the output of the game, I needed to figure out how to manage the input. That meant building touch interfaces as described on pages 240-252 of iPhone in Action.I don't find the code itself that interesting. It builds out of touchesBegan:withEvent:, touchesEnded:withEvent:, and touchesMoved:withEvent: as you'd expect. Beyond that it's a rat's nest of conditionals to support three different types of touches for active cards (card selection, card movement, and deck movement--only two of which are used in this particular game) and touches for "nonactive" cards (e.g., actions for decks other than the one you're currently holding), both over multiple game phases.
However, I do think the design of the big-picture input is more interesting, and so that's what I'm going to talk about here.
When designing the input of Money, I set two major goals:
- Every object must do something when touched, to create a playing space that feels alive and three-dimensional.
- The UI must be consistent.
These goals haven't been entirely fulfilled in the first release of Money, but the framework is there, which will allow for self-consistent expansion if the game does well enough to warrant more work.
To accomplish the second goal, of consistency, I broadly defined four types of input. As you'll see, when I had this rich set of gestures in hand, I could then assign actions to most objects on the screen.
- tap-and-release could be used to simultaneously select multiple objects. In Money you bid with your cards by selecting several of them, one at a time, then clicking a "bid" button to mark that you're done.
- tap-drag-and-release could be used to move one object to another, initiating an action. In Money this is used to drag your completed bid to an available set of money, exchanging them.
- tap-and-hold could be used to view information on an object. In Money, this is what allows for actions to occur on most "non-active" cards on the screen. For example, touching an opponent's deck tell you their win-loss stats, touching an opponent's bid makes it easier to see, and touching the draw deck tells you (approximately) how many cards are left.
- double-tap could be used to initiate a default action for an object. This is not coded into the game yet, but in a future revision you'll be able to continue to tap-drag-and-release to exchange your bid with an available set of money, or you can alternatively double-click on an available set of money to do so automagically.
The trick of overloading this many input functions is making sure that they don't bash into each other. For the purposes of Money, all of the single-tap functions are singular: no object supports more than one of them, and the interface strives to make it obvious which you'd want to use on each place. tap-and-release and tap-drag-and-release are only used for manipulating your active deck of cards while tap-and-hold are only used for revealing information on other objects.
Implementing the double-taps is a bit trickier, because it means you need to slightly delay your single-tap results, so that they don't show up when a double-tap is intended. That's the main reason that they haven't gone into the game yet.
However, as soon as they do, I think we'll make an intuitive interface even stronger, and that we'll be creating a model of interactivity that we can continue using across similar games. (There are also still a few objects that don't have touch-and-hold info--namely the two lots, our game logo, and our score info--mainly because we're still thinking about the best info to include for each.)
Conclusion
So those are my thoughts on how we designed input and output for our first iPhone game. I'm considering a future article talking about how we designed the game infrastructure. In the meantime you can read a companion article on what was specifically required to adapt an existing game over at BoardGameNews.com.
And finally I'll again encourage you to buy a copy of Reiner Knizia's Money if you're interested. I hope that knowing a bit about how it was designed will help you enjoy the game that much more!
