Jumping from Web to Mobile, Part 2
This is a continuation of my previous post Jumping from Web to Mobile, Part 1 about planning a multi-platform game.
Here I will present a blueprint for an actual port of a specific game project. This is a typical 2D game that feature scrolling backgrounds, animated characters and touch (or mouse) controls. This should give an overview to the practical aspets of planning and building a game on Flash as the primary platform and iOS as the secondary, with possible porting to Android later on.
Choosing Flash as the primary platform enables experienced Flash developers to take advantage of the quick designer-to-developer tooling available, namely Adobe Flash Builder and Flash CS, to easily setup gameplay code over a framework, and create a quick prototype of the game before spending more resources on porting to mobile. Although this is a subjective choice I made, it makes more sense to start developing on a desktop environment, as iOS developers often do, to achieve shorter development cycles.
There are few different options for going mobile from Flash, the first is Adobe AIR mobile. Adapting a game to AIR requires very little code changes and it deploys to a wide range of mobile platforms. AIR has its advantages, and while it may be the right choice for some projects, it is not in the scope of this article- the focus here is on using native code for mobile.
Frameworks and Platform Differences
In recent years, a new breed of modern game frameworks has emerged and is gaining popularity among game developers. Most of them free and open source, they borrowed practices from web, desktop and mobile platforms and include an impressive array or out of the box features.
Such frameworks are Cocos2d and Sparrow for iOS, and Starling and ND2D for Flash. Starling is actually a port of Sparrow, using almost identical class names, while ND2D is closer to Cocos2d in style. Regarding content, all of them use the same asset types for images and animation, which make the game content portable when switching between one framework to another. This includes sprite sheets, animation data files and particle effect data (in json and xml).
As a side note, both Starling and ND2D use the hardware accelerated GPU rendering (Stage3D) available in Flash 11. In some cases, developers opt for the software renderer to target wider range of users - and use their own custom framework that supports blitting, or alternative game frameworks like Flixel, FlashPunk and PushButton.
Whatever choice is made, being comfortable with the language and framework you use translates directly to efficiency and shorter timelines. The same goes for art tooling.
Armed with a game framework for the platform and a set of tools we are ready to move on to technical design.
Architecture and Code Structure
As it turns out, clean and structured code is much easier to port than messy, over complicated one. Rule #1 is keep it clean.
The key for easy porting between platforms is building the right architecture. All the proper OOD methodologies apply, and most of all encapsulation and minimizing dependencies. First we need to create a separation between framework (engine) and game logic.These form the two tier architecture where dependencies goes from higher level to lower level modules.
Within each tier, we make a subdivision between platform independent code and platform specific code. This may not be clear cut. The goal is to isolate the platform specific code and keep it to minimum. In some cases we need to create an abstraction layer over that module, but usually this abstraction is already in place in the framework.
The Content Tools
As already mentioned, the said frameworks all use the same type of assets, so the same tools can be used across platforms and frameworks. All graphical assets are bitmap based and the most common use is for textures, sprite sheets and animation data. Here are a few good tools for packing sprite sheets and designing particle effects:
The Game Entity
Another important aspect is the way we design a ‘game entity’ class. Composition is preferred to inheritance here, specially when display object classes are concerned. To be more specific: avoid basing your game entity class on a display class (like Sprite or MovieClip in AS3 and CCSprite in Cocos2d), as its commonly being done in tutorials and sample demos. In real life games, the game entity need to remain neutral and hold a reference to its display object. So instead of the game entity ‘is -a’ display class, it would be a ‘has-a’ relationship.
When done properly, the framework code should manage two separate lists: one for game objects and one for their corresponding display objects, which would be the display list, or scene graph. Note that processing the scene graph (i.e. draw code) is done internally by the framework and never by the game objects. The game loop would look like that:
- process user input and game state
- update all game objects
- draw/render the display list
Making the move
Once the game is up and running on the primary platform, it is ready to be ported from web (Flash / AS3) to the first mobile platform: iOS with Cocos2d.
The process of porting can be summarized in the following steps:
- Switching the Framework
- Porting the Game code
- Porting the contents (game assets)
- Converting to touch controls
- Adjusting to screen size, language constrains and specific platform optimization
Practically we need to create a new project on the target platform and start with the Framework. In this case it would be an XCode project with Cocos2d. The game code comes next.
Since the game contents and logic are now completely neutral, and porting it into the new project should be straight forward - off course language and syntax conversion should be made. While this can be a tedious job going class by class, it is very much doable.
AS3 to Objective-C
Converting classes and code to Cocos2d requires some knowledge in Objective-C. For simplicity, I’ll skip the detailed description of language porting, and just state that while there are a few differences, both languages are close in the way they handle classes and OOD. For those interested in this topic I recommend this excellent tutorial by Rogers Engelbert.
The hard part is getting it to compile, and adjusting the display code. Another issue is user controls: depending on the type of controls used, they should be converted to touch controls. These can be simple touch and drag, or more complex, like a virtual joy-pad and on screen buttons.
As each framework uses its own terminology of display objects, it may require some amount of work in replacing references, but since the display code is well contained in the framework and mostly referenced by the game entity, that should not be too difficult. Following is a simple conversion of the main display classes in pure AS3 and ND2D and their equivalents in Cocos2d.
Coordinate systems are different between Flash and Cocos2D. Flash uses the top left corner as origin with Y-down, while cocos2d uses the OpenGL coordinate system, where the origin is at the center and Y-up. If you used Nd2D, there is no need for conversion of coordinates.
More Mobile: Android
The same process applies for Android, using libGDX as the game framework. It may be easier to use the ActionScript project as the source and use the iOS project as a reference, since Java is closer in nature to ActionScript that to Objective-C.
There are plenty of Android specific issues to address, but I will not discuss them here. The main idea is that most of the game code and content (assets) will work almost without change and the project can leverage the work that was already done in the iOS port without having to rewrite any of the components.
Planning a game to be deployed on multiple platform is now within reach for small, indie studios. With borrowed practices from the desktop and console space, modern frameworks such as Cocos2D allow a team of developers to leverage knowledge and expertise gained in one platform to be applied on other platforms.