Releasing a game on iOS

From Adventure Game Studio | Wiki
Jump to: navigation, search

Please note that the discussion about this topic is constantly updated on the AGS forums : How Wadjet Eye updated AGS to release commercial games on iOS (forums discussion)


Introduction

Historically, AGS was created to work on Windows. Both the Editor and the Engine. But for several years now, the Engine has been ported to more platforms (PSP, iOS, Linux, Steam...). However, making a game for iOS is always a bit trickier: Not only you need to make it "work" on that system, but Apple also has a validation system for the Apple Store. Additionally, you'll expect players to use iPads and all sorts of Apple systems, which means many versions of iOS to deal with. This will be rendering the right-click unusable in your game, for example. Janet helps you avoiding all the traps and headaches.


The article below was originally written by Janet from the "Wadjet Eye company", which created Gemini Rue and other games.

Overview

When I first released an AGS game on iOS, I based it on JJS's (Jochen Schleu's) brilliant port of 3.2.1. Over a couple of years the AGS project moved on but I was unable to take advantage of the updates due to my old code. I finally decided to take on the task of updating my port to the latest version (3.3.3), as well as adding new fixes to problems that have arisen as the iOS operating system has grown and changed. The biggest problems were that Apple now requires a 64-bit build in anything submitted to the App Store, and recent changes to iOS have made the engine unstable, crashing more frequently than I am happy with.

I decided to keep an account of the process, because people keep asking me what I did to get a version of AGS that can be published on the App Store. Jochen's version was aimed at people with jailbroken iPhones who wanted to put their existing PC AGS game collection on iOS. This wasn't ideal for Wadjet Eye as it didn't have the signings necessary for submission to the App Store, and also the controls were designed to be universal, so that any AGS game could be played, which ended up feeling kind of clunky for the Wadjet Eye style of interface (which is classic Lucasarts inspired.)

My version of this can be found at:

https://github.com/JanetGilbert/ags
Branch name: iOS

Feel free to fork it to your own account for your own use; AGS is open source after all!

Code Signing

You need to go to the Apple Developer website to set up the code signing and profiles: https://developer.apple.com/

  1. Enroll in the Apple Developer program ($99 a year). You can't really avoid opening your wallet at this point; you can fuss about with jailbroken devices and old versions of XCode if you really like headaches and never want anyone else to play your game. :-)
  2. Go to the "Member Center", and the "Certificates, Identifiers & Profiles" section.
  3. Go to "Certificates", and make yourself "Development/iOS and App store" and "Production/App Store and Ad Hoc" certificates.
  4. Go to "Identifiers" and add an App ID for your game (eg com.wadjeteyegames.YourGame)
  5. Go to "Devices" and add the UDIDs for all devices you will be testing on personally. You used to have to add all beta tester UDIDs here, but Apple has now added a service called "Testflight" that makes this unnecessary. The UDID is the string under "Identifier" for your device if you open Windows/Devices from the XCode menu.
  6. Go to "Provisioning Profiles" and make "iOS App Development", "App Store" and "Ad Hoc" profiles.
  7. Go back to XCode. Open the XCode/Preferences menu item. Go to "Accounts" and click the "+" sign in the bottom left to add your Apple ID. Any time you make a change in Apple Developer, you need to come back to this page, click the "View Details" button, and then the refresh arrow in the bottom left of the details page. The profiles should then refresh. If some seem to be missing, leave it a while and try again. I am honestly not sure why sometimes this doesn't work. Sometimes exiting XCode and re-trying seems to help. It's magic. If anything ever goes wrong with compiling your game that doesn't make sense, refresh, clean and rebuild. Solves 90% of all possible problems.

Create a Project

  1. Duplicate the ags project and open it in XCode (open ags.xcodeproj )
  2. Rename the project to your project name. Slow double click on the name of the project in the top-left (just above something that says something like 1 target, iOS SDK 8.2). Type in your project name (eg YourGame). If you can't see the game name, click on the icon in the top left that looks like a folder. Don't ever rename the game in any other way; XCode needs to rename a bunch of internal things that get really borked if you try to edit the .xcodeproj in a text editor. I found out the hard way!
  3. Click on the name of the project in the top left. You should now have a pane which has a project and a target, hopefully both called YourGame.

There are two sections in the middle horizontal column of the screen, one labelled "PROJECT" and one labelled "TARGETS", which should both be named "YourGame." This section is called "General Target Settings"


Xcode-4-Build-Settings-Window.png


The "PROJECT" is the game project overall, and the "TARGET" is a subset of that. I use multiple Targets to make different versions of a game with different files included, all in one big project. I use this feature often when making Mac games for Steam/non-Steam, but I've never made more than one Target for an iOS game. Some things need to be set in *both* "Project" and "Target", so if something doesn't seem to be taking effect, check that it is the same in both "Project" and "Target."

General Target Settings

* This Represents the tabs at the top of the window in the right-hand pane (e.g. Summary, Info, Build pahes, etc. in the image above)
  This represents the expandable areas in the lists (e.g. "Architectures" or "Build Locations" in the image above)

PROJECT

  • Info

(no specific information)

  • Build Settings
Architectures
  1. Architectures: Set this to $(ARCHS_STANDARD_INCLUDING_64_BIT)
  2. Valid architectures: Set this to arm64 armv7
Code Signing
  1. Set the Debug Code Signing Identities to your Developer ID, and the Release code signing identities to your Distribution ID.
  2. Set the Debug Provisioning Profiles to your Ad Hoc profile, and the Release Provisioning Profiles to your game's Provisioning Profile.
  3. Remove "-gta" from Other Code Signing Flags/Debug. This allows the app to be deployed on Jailbroken devices, but prevents it compiling to be released on the App Store.
Deployment
  1. Set iOS Deployment Target to 5.1.1. You have to enter this in the box manually. This version is significant because it allows you to retain compatibility with the iPhone 3G, and also use 64-bit builds. If you don't care about compatibility with older devices, set it higher.


TARGETS

  • General
Identity
  1. Bundle identifier: Don't set here, set in "Info"
  2. Version (CFBundleShortVersionString): The version of the game displayed to users. Try 1.0. Increase every time you publish a new version to the public.
  3. Build (CFBundleVersion): The internal build number. Increase by every time you publish externally (even to Testflight)
App Icons and Launch Images
  1. Set up your icons here! You need to use an "Asset Catalogue"

Here are Apple's constantly-changing icon size/launch screen size requirements: https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/MobileHIG/IconMatrix.html

Ugh. They literally add more required images every iOS version update. This used to be nice and simple. 
When you add the icon asset catalogue, you need to drag the appropriate sized icons to the box (from Finder.) This is like a cute little puzzle game. Watch out for the 2x and 3x sizes - this means that you need an icon 2 or 3 times the listed size (eg 57x57 x2 = 114x114)
The launch image asset catalogue is much the same, except it doesn't tell you the pixel sizes. Click on the icon in the top right that looks like a box with a vertical line on the right side. This gives you some stats including the expected size of the image.
  • Info

Ensure the Bundle Identifier is set to the same thing as in Member Center/Identifiers, and the Status Bar is initially hidden.

  • Build Settings
Architectures
  1. Set "Architectures" and "Valid Architectures" to same as "Project"
Code Signing
  1. Set "Code Signing Identity" and "Provisioning Profile" to same as "Project"
  2. Remove "-gta" from Other Code Signing Flags/Debug. This was to allow the app to be deployed on Jailbroken devices, but prevents it compiling to be released on the App Store.
  • Build Phases
Run script
  1. Remove the script relating to code signing (it begins "export CODESIGN_ALLOCATE" and ends "fi") - this is code allowing the engine to run on jailbroken devices and will interfere with compilation of a version that can be submitted the the App Store.

Schemes

Schemes are necessary for compiling the game. At the very top of the screen, just to the right of the "Play" arrow button, there should be a label that still reads "ags".

  1. Click on "ags", then select "Manage Schemes" from the drop-down.
  2. Delete the "ags" scheme.
  3. Use the "+" to create a scheme named "YourGame"

The Project Navigator

This is the section of the screen to the left, where you renamed the project in the section "Create A Project." It has several views - ensure you are using the top-left view, by clicking on the top-left icon that looks like a single folder.

  • Resources

This section is what you will be looking at most often. You need to add the files ac2game.dat, audio.vox, speech.vox, ios_ipad.cfg, ios_iphone.cfg and any other data files your game requires. Add them by dragging from Finder.

ac2game.dat is just your windows .exe renamed. You can snip out the unnecessary executable parts by opening it in a hex editor and searching for the string "PADDING". There is a block of text that repeats "PADDINGXX" for a bit, then "CLIB". Chop out everything before CLIB (but leave CLIB). This saves a little space.

If you wish to make more than one variant of a game, you can create multiple targets, and include different resource files for each target. I find this very useful for OSX to make different builds for Steam and non-Steam.

  • .cfg files

Here's what I use (with the variants for iPad)

[misc]
config_enabled = 1
rotation = 2
translation = default
[controls]
mouse_method = 0
mouse_longclick = 1
[compatibility]
clear_cache_on_room_change = 0
[sound]
samplerate = 44100
enabled = 1
threaded = 0
cache_size = 10
[midi]
enabled = 1
preload_patches = 0
[video]
framedrop = 0
[graphics]
renderer = 0
smoothing = 1 (0 on iPad)
scaling = 1
super_sampling = 1 (0 on iPad)
smooth_sprites = 1 (0 on iPad)
[debug]
show_fps = 0
logging = 0

The variants for iPad produce a "blockier" more pixelated look that I like (but some people do not), as opposed to a blurred "anti-aliased" look that I prefer on the iPhone. Experimentation is key here to find out what works for your game.

Since there is only one (universal) build, I include settings files for both iPad and iPhone and select the right one at runtime.

Libraries

The standard version of AGS has only 32-bit libraries. Apple no longer accepts builds without 64-bit libraries.Obtain these from me or just look in my fork of AGS (ios branch) and take them. There are also XCode projects for these libraries available in my fork of AGS if you need to recompile them.

Code Changes

Here is an overview of the changes I made to the code to get Wadjet Eye Games running smoothly. My plan was to make them play as if they had been designed for touch-screen platforms, with no awkward work-arounds that betray their PC origins.

To see exactly what I did, take a look in my fork of AGS, "iOS" branch.

  • Path to game files

The game files are added in Resources, and copied over to the root of the iOS App. (YourGame.app.) This is not where AGS expects to find them.

The engine is still working under the assumption that you are running on a jailbroken device and you will manually copy over into the documents folder and select your game files. I remove the ability to select files, and just load the default file name (ac2game.dat) in the root folder.

  • Dragging and Dropping
Drag'n'Drop 

This commit ("Drag'n'Drop") removes the ability to run standard PC AGS games in a jailbroken iPhone, (by removing the ability to right-click) but allows much finer control over touchscreen controls in script.

JJS designed the iOS controls to be one-finger-tap for left-click, and two-finger-tap for right click. This was to allow existing PC versions of games to be played on iOS device.

I re-wrote the game script to use a verb-coin interface on iOS, making a right-click unnecessary. The game script is able to tell when and where the user's finger is pressed to the screen, and when it is removed. This allows taps and tap-and-drags to be simulated in-code.

  • Tap past dialogue
Tap past dialogue on mouse up, not down. ,
More responsive dialogs

The engine, by default, skips past dialog when you press your finger to the screen. I changed this to when you press and release, because the other way was accidentally activating the next dialog option.

  • Wadjet Eye Utils
Added AGSWadjetUtils plugin

This is a plugin that exposes some useful functions to the script.

FakeKeyPress() allows the script to pretend a key was pressed. This is used in Gemini Rue's combat system (which was key controlled on PC, button controlled on iOS) and for making a software keyboard (the built in keyboard does not look nice in a game, has some characters that AGS cannot display, and the close button is too small.)

It also has some functions for achievements, but I couldn't get them working. Anyone who wants to fix them up, tell me how you did it!

  • Cutscene skipping
Cutscene skipping

In PC AGS games, you skip cutscenes by pressing "Esc". Lacking a keyboard, I needed some other way. It needed to be something implemented at engine level because the script is blocked in cutscenes.

I first experimented by skipping cutscenes with a long press (hold the finger to the screen for a long time) but it was too easy to activate. So I hit upon swiping the finger from left to right at the top of the screen.

I'm not sure how many players use this feature, since most adventure games get played only once, due to being roughly the same each time. It was more a feature for debug (It gets OLD watching the same cutscenes every game) which I left in for people to use or not, depending on whether they remembered it existed.

  • Set Mouse Position
Fixed mouse position

Simple fix to the scaling of the mouse position. Without it, you can't correctly set the mouse position from script. I use this to place the cursor neatly in the middle of the screen when you change scenes.

  • Config Files
Load different config files for iPhone and iPad

ios_ipad.cfg is loaded on iPad, and ios_iphone.cfg on iPhone. The difference is in the scaling and smoothing settings, to give an "anti-aliased" effect on iPhone and a sharp, pixelated effect on iPad.


  • Misc bugs & bug-ettes

Small, but important.

("Memory leak in ReadString") 
("Sound crash bug fix")
("Dismiss Display() boxes on mouse up, not mouse down")
("Fake keypress support")
("Hide status bar")
("Move iOS-specific classes")
("Bug: Keypress not detected")
("Restore audio after phone call")
("Crude hack to restore audio after answering phone call")


  • 64-bit

This was a beast of a bug. Apple introduced a requirement that all games must include a 64-bit build, but that meant that I needed to recompile all the dependencies with a 64-bit slice. The last time the libraries were compiled was in Ye Olde Times by JJS.

The system that JJS used to compile the libraries was called cmake. He wrote scripts for this that simultaneously patched the library code (with his bug fixes) and built them. Unfortunately the latter half of the process (building) was very outdated and no longer worked.

The system I came up with was to comment out the building portion of the scripts and just run the patching portion (see my commit "Allegro patch only"). Don't forget to use chmod u+x to get permission to run the scripts (which are in the ags\ios\buildlibs\armv7 folder)

I then made the resulting source files into an XCode project, and built the library as a Cocoa Touch Static Library. I built it for the required architectures armv7 and arm64. Set "Always search user paths" in "Build Settings" to "Yes" and set "User Header Search Paths" to "${SOURCE_ROOT}/[LIBNAME]/include ${SOURCE_ROOT}/../../nativelibs/fat/include" (or whatever needed) or else you will get errors like "Lexical or preprocessor issue 'internal/it.h' file not found" (double-click on the paths and ensure they are recursive). Remove the autogenerated files called something like allegro.h and allegro.m from the project or else you get a lot of errors like "Semantic Issue: Unknown type name 'NSString'". "Product->Destination" must be a real iOS device you have plugged into the computer, or else the Product will not be created even though the build apparently succeeds.

Then I encountered a different problem. I added the resulting library to my project and I got errors complaining "Undefined symbols for architecture x86_64" which turned out to mean that XCode expects a library containing both iOS device architectures (armv7, arm64) AND iOS simulator (i386, x86_64) architectures.

Unfortunately XCode can't build all these simultaneously in one library. You need to build for both device and simulator separately, then combine them using a command-line tool called "lipo"

First: build for device (Product->Build For->Running) THEN build for simulator (Product->Build For->Testing). Note that by default the "Run" scheme is Debug, which you don't really want. So "Edit Schemes" and on the "Info" tab for "Run", set the "Build Configuration" to "Release". To build for simulator, you must set a simulator as "Destination"

Then use lipo to combine the two in the following way.

lipo -create Release-iphoneos/liballegro.a Release-iphonesimulator/liballegro.a -output liballeg.a

Use lipo to test success:

lipo -info liballeg.a

Desired result: Architectures in the fat file: liballeg.a are: armv7 i386 x86_64 arm64

Next

That should give you a working version of the AGS engine, but you still need to alter the script of your game to work with the engine. The most important thing to do is to remove all instances of needing to right-click in the game, because if you followed my instructions, you can now only left-click by tapping on the screen. I'll write a post in the future describing the process I go through to update the script of our AGS games to work well with iOS.

Feel free to email me with any questions at janet AT wadjeteyegames DOT com. AGS is open source, and so is my fork, so you can fork it yourself if you want, or use any of my alterations freely.


Reminder:

https://github.com/JanetGilbert/ags
Branch name: iOS


Please note that the discussion about this topic is constantly updated on the AGS forums : How Wadjet Eye updated AGS to release commercial games on iOS (forums discussion)