Category Archives: Game Design

Transcript of Adventure Games Conference (Compuserve, 1990)

Poking around some old disks this week I found some files I’d downloaded from Compuserve in the early 1990’s, including this gem: a moderated online discussion between some of the biggest names in classic adventure games.

  • Steve Meretzky (Hitchhiker’s Guide, Leather Goddesses of Phobos)
  • Ron Gilbert (Indiana Jones, Maniac Mansion)
  • Bob Bates (author of SHERLOCK and ARTHUR)
  • Mike Berlyn (SUSPENDED and the upcoming ALTERED DESTINY)
  • Corey and Lori Cole (HERO’S QUEST, aka QUEST FOR GLORY)
  • Noah Falstein (INDIANA JONES AND THE LAST CRUSADE)
  • Dave Lebling (the ZORK trilogy)
  • Al Lowe (the LEISURE SUIT LARRY games)
  • Roberta Williams (the KING’S QUEST games)
  • Coincidentally, a heavily edited version of this was posted earlier this year on The Digital Antiquarian. It’s worth reading for Jimmy Maher’s excellent introduction and footnotes, not to mention some thoughtful comments from his readers (including Corey Cole, one of the conference participants.)

    The transcript below is the online discussion as it originally took place, unedited by me, though possibly by others before it was archived on Compuserve. It is messier but I like that it reads like a conversation. You can see participants responding to each others’ points and joking around. And at one point Al Lowe appears to be trying to send commands to his modem.

    Note: as the moderator explains early on, participants type “!” to ask for a turn, “…” to indicate they aren’t finished typing yet, and “GA” to yield the floor to someone else.
    Continue reading

    Handling Game Center With iOS Multitasking

    Apple’s Game Kit Programming Guide contains the following passage:

    A game that supports multitasking and Game Center must take additional steps when authenticating the local player. When your game is in the background, the status of the authenticated player may change. A player can use the Game Center app to sign out. Another player might sign in before your game returns to the foreground.

    Multitasking is available from iOS 4.0 onwards, though not all devices running 4.0 support multitasking. Game Center was added in iOS 4.1.

    So what exactly should my game do when the Game Center player changes behind it’s back? (Note: I’m concentrating on achievements here, as Pawns does not have leaderboards.)

    The simplest method that also allows for offline play is:

    • The iOS game tracks achievements that were earned on that device, and stores that information locally.
    • If Game Center is available, achievements are also pushed to the server.
    • All achievements are pushed to the server, not just as they are earned, but whenever a Game Center player is authenticated. This handles the case where the player may have earned some achievements offline.

    In short: make your game work offline, then push achievements to Game Center (one-way) whenever it is available without worrying about which player is now logged in.

    This method is straightforward but will lead to two glaring side effects:

    1. If a player logs into a second Game Center profile, the new profile will automatically get some or all of the achievements that were earned on the first profile.
    2. Since this is a one-way synchronization (i.e. from game to Game Center) a player with two devices may see some achievements on Game Center but not on one of the devices.

    We can try to fix these issues but it quickly gets complicated. (If you aren’t interested in a discussion of the complications, feel free to scroll down to the next section: The Experiment.)

    For example, fixing the first requires you to be strict about which achievements are earned by which player. You could read the achievements back from Game Center after every profile switch, but then you have to handle the case where the player earned some achievements offline- this requires merging the online and offline lists. If you do that you’ve also solved the second problem– a nice feature, but I personally think it’s pointless unless the player’s entire saved progress (saved games, list of finished levels, etc.) is also stored in the cloud using iCloud, Dropbox, or some other service.

    The situation is even more complicated if the game itself supports multiple local user profiles (as opposed to games that treat everyone on the device as the same player.) Note that when the user switches to a new local profile there’s no way to switch their Game Center profile for them automatically. We can only do the reverse: switch local profiles when the Game Center player has changed. This approach would work especially well for an online-only game.

    In short, there are a lot of decisions to make unless we opt for the simple, “stupid” approach. Being naturally lazy, my inclination was to do this and hope that players (and Apple) would put up with the side-effects. But try as I might I couldn’t find any blogs or forum posts describing how other developers handle this, and that made me very nervous.

    The Experiment

    I decided to see how other game developers handle this. I spent a happy evening playing six iOS games that I’d already earned achievements in, but as a different Game Center player. I also switched to a second device to see if any of them read the player’s Game Center achievements back from Apple server.

    It was a tough job, but someone had to do it.

    The results? Judging from the side effects, the following five games use the simple achievements model I described above:

    All of them had the side effect where the original profile’s achievements get copied to the new profile. This was even true for Plants vs Zombies, which lets you switch local profiles. The local profiles are completely ignorant of which Game Center profile you are logged into.

    The one game which didn’t take the easy way out was Space Miner. After switching to the second Game Center profile, Space Miner warned me whenever I tried to load a saved game that had been saved by a different Game Center player. (It was my choice whether to go ahead and load the saved game or cancel.) In addition, it seemed that some but not all of the old achievements were copied to the new Game Center profile! I’m guessing that the achievements specific to a single campaign of Space Miner were NOT copied to the new profile, but achievements that you’d earn over multiple games were copied. I don’t claim to understand the nuances of Space Miner’s design just from this test, but clearly the developers went above and beyond to try to intelligently reconcile local saved games and achievements with Game Center’s achievements.

    None of the 6 games ever seemed to read achievements back from Game Center. When I played on the second device, only my Game Center account showed the achievements that had not been earned on that device. (This looked especially odd in Pit Droids, where the achievement “Hutt Flats Unlocked” was shown in Game Center, even though the Hutt Flats puzzles were still locked on that device.)

    Note that none of the six games I tested store their saved games in the cloud for access on more than one device. Such a game would not take the simple approach I described here. I believe the easiest approach there would be to force the user to select local or cloud storage for each saved game to avoid having to merge them, but with effort it should be possible to synchronize the two more seamlessly.

    Conclusion

    It appears that most games simply take the straightforward approach: make and display achievements as if the game were offline, and push achievements to Game Center (one-way) whenever it is available. This wasn’t too surprising for games that have no local player profiles to switch between. I wasn’t so sure what to expect for games that do have them, but in retrospect it makes sense. Developers are simply counting on the fact that players just aren’t likely to switch to a different Game Center profile.

    Supporting iPhone and iPad Resolutions

    I recently added a profile of my forthcoming game, Pawns for iPhone, to the website IndieDB. As I was generating screenshots I found to my dismay that I could not generate high-resolution screenshots of games in progress. The iPhone version of Pawns is currently hard-wired for iPhones in landscape mode.

    I had planned all along to look into iPad and “retina display” support later on, possibly after the first release for iPhone. It never occurred to me that I would find those higher resolutions useful myself. Oops.

    Even more embarrassing, the original version of Pawns supported many screen resolutions. It’s something I lost as I tuned the game for iPhone.

    The original version used Unity’s GUI objects, which are always sized proportionally to the screen. To make the graphics crisper on the iPhone I had converted much of it over to UnityGUI. But pixel-correct textures come at the cost of needing to draw gui elements at every resolution that you will need them. The plan is to rebuild my gui elements at a much higher resolution and let them be scaled pretty much wherever they are used. Hopefully the result won’t be too blurry.

    Isometric vs Perspective Camera

    Recently I’ve been experimenting with using an isometric camera for Pawns for the iPhone.

    Isometric views have always felt a little cheesy to me, for historical reasons. In the old days it was often used to fake 3D. Since things don’t get smaller as they move further away from an isometric viewpoint, you could use 2D sprites instead of drawing true 3D objects. This was useful when the graphics hardware was only good at drawing sprites. (For example, old arcade games like Q*Bert or Zaxxon painted their 3D graphics this way.)

    The iPhone is of course perfectly capable of rendering true 3D. And with Unity I don’t gain any speed just by switching to a isometric view. Even so, the isometric view has a few advantages.

    Firstly, the squares near the rear of the board are the same size as those in front, making it easier for the player to place arrows. Pieces in the back are also more visible this way.

    I can also optimize the appearance of the 3D pieces. Under perspective it’s hard to make out the crosspiece on top of the king, for example, depending on the angle. In an isometric view the king’s rotation relative to the camera is always the same, whether it is on the left side of the board or the right. So each model only needs to look good from one angle.

    This isn’t just a matter of aesthetics, or covering up my mediocre artistic skills. Pawns will not be fun on the iPhone unless each type of piece is instantly recognizable despite the small screen.

    For that matter, with care I could improve the graphics by prerendering high-resolution chess models to make 2D sprites. This might improve their appearance- I’ve been having wrestling with lowering the polygon counts without having the pieces look too crappy. (A topic for a future blog entry, perhaps.)

    Of course, if I go to billboarded sprites I can’t simply reposition the camera or lights whenever I feel like. And after seeing Pawns in perspective for so many years, I’m having a hard time getting used to the isometric look. Still, I’ll leave it this way for a while longer and see if it grows on me.

    Reading Text Data Into A Unity Game

    Unity’s rapid edit-compile-test cycle encourages developers to build game levels interactively in the editor. Game parameters are often saved directly in the scene, or on prefabs. However, sometimes it makes sense to read that data from a file at run-time.

    For example: Pawns puzzles are defined by a simple arrangement of game elements on a grid. By putting this information in a text file, I was able to try changes to the puzzles without leaving the game. Even better, by giving public access to the file I have the option to allow other people to mod the game (i.e. make their own puzzles) even if they don’t have Unity or the Pawns source code!

    Below I post the code for the two techniques I used to read text files into Pawns. I also cover some of the differences to be aware of when loading data on different platforms.

    Method 1: Read a text file embedded in the game’s resources
    The simplest technique is to read a file that Unity has compiled into your game, just as it does for the other game assets like textures, sounds, and models. This is simple because Unity encrypts the file into your game bundle automatically. However the file is not visible to would-be-level editors, so you lose some of the advantages I talked about earlier. But if you want to avoid exposing the file’s contents to the public in a shipping game, this may be just the thing.

    Place the textfile (in this example, “puzzles.txt”) in the Resources folder of your Unity project. Unity will automatically package it into your game. To read it, your script just uses Unity’s built-in Resources class:

    FileInfo theSourceFile = null;
    StringReader reader = null; 
    
    TextAsset puzdata = (TextAsset)Resources.Load("puzzles", typeof(TextAsset));
    // puzdata.text is a string containing the whole file. To read it line-by-line:
    reader = new StringReader(puzdata.text);
    if ( reader == null )
    {
       Debug.Log("puzzles.txt not found or not readable");
    }
    else
    {
       // Read each line from the file
       while ( (string txt = reader.ReadLine()) != null )
          Debug.Log("-->" + txt);
    }
    

    Method 2: Read unencrypted text file bundled with the game
    This example reads text from a file that sits alongside other files of your compiled game. Anyone can see and edit the file, which makes it convenient for making changes without having to rebuild your game. The complication is that you have to remember to include the file with your game, either by manually adding it after every build, or by creating a Unity build post-processing script to do it for you.

    The following example reads a file called “puzzles.txt” from the game’s data folder as pointed to by Application.dataPath. This location varies depending on where your game is running:

    Where game is running Application.dataPath
    In the Unity editor project’s Assets folder
    Mac build ‘Contents’ folder in the package (right-click on the game, select “View Package Contents”)
    Windows build Data subfolder
    iPhone app In app’s writeable Documents directory; see comments below
    Webplayer build URL to webplayer’s data folder; use WWW class to access

    (Since Application.dataPath returns a URL for webplayers, the following code will probably not work for them. You would have to use the WWW class instead.)

    FileInfo theSourceFile = null;
    StreamReader reader = null;
    
    theSourceFile = new FileInfo (Application.dataPath + "/puzzles.txt");
    if ( theSourceFile != null && theSourceFile.Exists )
       reader = theSourceFile.OpenText();
    
    if ( reader == null )
    {
       Debug.Log("puzzles.txt not found or not readable");
    }
    else
    {
    // Read each line from the file
       while ( (string txt = reader.ReadLine()) != null )
          Debug.Log("-->" + txt);
    }
    

    Method 1+2: Read from plain text file, with fallback to embedded resource
    Pawns originally used method 2 exclusively, but since I plan to charge for the full set of puzzles I’d prefer not to have the final puzzle file exposed for all to see. On the other hand, I’d still like to have the ability to try out new puzzles occasionally, or allow others to design puzzles. A simple solution is to first look for the plain text file using method 2; if not found, load the default puzzles embedded in the game resources (method 1.)

    In fact, since StringReader (used to read lines from the embedded text resource) and StreamReader (used to read the plain text file) are both subclasses of TextReader, once either file is opened the rest of the code can parse it without caring whether it’s reading from a file or an in-memory string:

    FileInfo theSourceFile = null;
    TextReader reader = null;  // NOTE: TextReader, superclass of StreamReader and StringReader
    
    // Read from plain text file if it exists
    theSourceFile = new FileInfo (Application.dataPath + "/puzzles.txt");
    if ( theSourceFile != null && theSourceFile.Exists )
    {
       reader = theSourceFile.OpenText();  // returns StreamReader
    }
    else
    {
       // try to read from Resources instead
       TextAsset puzdata = (TextAsset)Resources.Load("puzzles", typeof(TextAsset));
       reader = new StringReader(puzdata.text);  // returns StringReader
    }
    if ( reader == null )
    {
       Debug.Log("puzzles.txt not found or not readable");
    }
    else
    {
       // Read each line from the file/resource
       while ( (string txt = reader.ReadLine()) != null )
       Debug.Log("-->" + txt);
    }
    

    Parsing XML in Unity
    People often use XML as a convenient text file format, and the Mono libraries contain powerful classes for parsing it. So this would seem to be a natural fit for Unity. But using those functions requires additional Mono libraries to be bundled with your game. You should particularly avoid this when building a webplayer or iPhone app. See the Unity documentation for details.

    Fortunately most tasks only require a small subset of the XML standard, so writing or borrowing a simple parser is an alternative. I found some alternatives being discussed in the Unity forums here.

    To use the Mono libraries to read and write XML, this article seems to cover the topic nicely.

    Accessing text files on the iPhone
    As mentioned above, iPhone apps each have a writeable Documents directory. The contents of this directory are preserved when the app is updated. However, that directory starts off empty and there is no way to install a file directly into that directory along with your app. The workaround is for your game to create whatever files it needs the first time it is run.

    The following code was posted in the Unity3d forums (and I’ve seen it elsewhere) for finding the location of the writeable Documents directory:

    string docsPath = Application.dataPath.Replace("/Data", "/Documents/");
    

    However, I imagine this may change in the future. Application.dataPath is a bit strange with Unity iPhone 1.5.1 in that it does not appear to point directly to a usable directory. To read from the Documents directory you need to use the above code. To read asset bundles you need to replace “Data” with “myappname.app/Data”. If the folks at Unity Technologies ever decide to fix Application.dataPath to point directly to the Data directory in a future release of Unity iPhone, the code for finding the Documents directory would need to be updated. (Or perhaps they will also add a method like Application.documentPath as well.) [3/6/2010: Unity 1.6 for iPhone was just released, and I see in the release notes that they have added the application name to the Data directory, just as I predicted. So the code sample above needs adjusting- the application name will also need to be removed from the path.]

    Unity Pro only: asset bundles
    Developers of webplayers and online games should also look into asset bundles, a Unity Pro feature that lets you collect game objects into a file ahead of time, and then load them at run time from a local file or from a web server.

    Comments and corrections welcome. Did you find an error? Did you have a particularly interesting use for runtime data in your game? I’d be interested to know.