Mobile game development using J2ME is not all it's chalked up to be. In theory, J2ME offers a compile once, run everywhere environment. In practice, however, the platform is very fragmented. From game developer's point of view, this platform consists of hardware, software, and back-end technology that is very often unique or proprietary to the mobile phone hardware or service provider.
Finland-based Sumea is an award-winning publisher and developer for downloadable mobile games. Our current portfolio contains 17 games, but we have developed over 40 J2ME titles in total. Our games are played in more than 40 countries through over 55 distribution partners in Europe, the United States and Asia. As the Chief Technology Officer at Sumea, I have developed coding techniques that deal with these disparities-by carefully structuring our code and separating the segments that need to change depending on the device and service provider.
This fragmentation not only makes it difficult for individual developers to create games that work on multiple mobile phones and with multiple service providers, it also hurts the mobile game market as a whole. At Sumea, we've felt the strain from this fragmentation. I remember the excitement I felt in 2000 when the first version of the J2ME Wireless Toolkit from Sun was released, and the high hopes I had for the first handset based on it. Sumea started developing J2ME games in the summer of 2001, when that handset, the Siemens SL45i, was released. I recall the thrill of getting our first MIDlet running on it.
we started mobile game development, we couldn't find references
to proven techniques nor ideas -- therefore we had to come up with
the ideas described here on our own. This doesn't mean all these
ideas have originated from us: The mobile game development community
is strong, and we talk with each other a lot--sharing new ideas,
daily pains, and so on. Thanks to all of you.
In this article I'll provide insight into the J2ME platform from the perspective of a developer who's kept an eye on this moving target. Let's see where the market stands today, examine how we got here, and try to get a sense of what direction J2ME is going.
Until things shake out and we see some de facto standards emerge, we're in for a wild ride, but I hope the techniques I present below will help you to get a grasp on the situation, better plan upcoming mobile game projects, and enjoy the ride.
J2ME Fragmentation Today
It's amazing to look back a few years and see how much mobile devices have changed. Today there are over 30 different J2ME-enabled handsets, many with color screens, support for polyphonic sounds, and interesting keyboard configurations.
But of course, the growth hasn't been painless. With this rapid evolution has come an assortment of capabilities, yet no real standards for many of the features. For instance, screen resolutions range from 101×80 pixels up to 640×320-with a dozen sizes in between. The range of processing power in these devices is also vast, with the high-end handsets having up to 90 times the processing power of the feeblest ones. The amount of heap memory ranges from 200K to over 1MB. In addition, application file size limitations are different: In the early days the limitation ranged from 30K to 50K, whereas today it ranges from 60K to about 200K.
Underlying software layers have proliferated, too. The basis of Java mobile game development lies with the Connected Limited Device Configuration (CLDC) 1.0 and Mobile Information Device Profile (MIDP) 1.0 APIs. On top of these there are usually manufacturer-specific APIs, which give game developers access to sounds, vibration, backlight, and in some cases other functionality (such as game-specific APIs). These APIs are proprietary and must be provided because there is currently no standard way to access this functionality. Some handsets provide other standardized APIs as well, such as the Mobile Media API (with which one can play MIDI sounds) and Wireless Messaging API (to send SMS messages).
Furthermore, the base API implementations are different. For example, MIDP 1.0 does not strictly define program flow and phone event handling. In practice this means that the behavior can be different in the case of an incoming call, calendar event, and incoming SMS. This means that a game developed for one MIDP version might not work the same way in another-or it might not work at all.
of the hot topics at the moment are so-called communal and network
features, which enable features such as centralized high scores
and event-based billing. This lets a player send his best score
to a server, or buy additional features for the game. Yet because
the means to implement these features are provided by, for
example, the mobile game provisioners, we again face the problem of disparate APIs. To support these features, one has to either implement the network communication interface or embed a third-party API into the game. At the moment, Sumea supports six different high score APIs.
J2ME Fragmentation Tomorrow
While today the base platform consists of MIDP 1.0 and manufacturer-specific extensions, the next step will be MIDP 2.0. There are already some MIDP 2.0 devices available on the market, and there will be more of them next year. The most important aspect of MIDP 2.0 is that it assumes the functionality of most manufacturers' proprietary APIs. MIDP 2.0 provides standard access to vibration, sounds, and game-specific APIs. Additionally, MIDP 2.0 contains other useful features, including an optional API for socket-based communication. This means that devices don't have to poll for updates from a server using HTTP-the server can push data to the device instead. There are other interesting features that help make the application work more seamlessly in the device: it is possible to launch a browser from within a MIDlet using a URL, or to launch a MIDlet by sending an SMS targeted at the application, for example. Yet while MIDP 2.0 is great in all of these respects, it does introduce one rather significant problem: for the time being, game developers have to support MIDP 1.0 and MIDP 2.0.
The future of handsets looks bright: The processing power will improve, the screens are getting larger, they have better refresh rates, and the amount of memory is increasing. One interesting topic is the various combinations of screen sizes, processing power, amount of heap memory, and file sizes. Large resolution screens look good, but on the other hand, large graphics require lots of run-time memory and processing power and they increase the application file size. Exactly how tomorrow's mobile phones will deal with these issues remains to be seen, but we developers will be the ones who will have to live with the eventual outcome.
Whatever happens, one thing is certain: The capabilities of the high-end hardware will improve faster than the low end can follow. From game developer's point of view, this means more devices to support with more disparity between their capabilities. Yet there are two important reasons to support as many platforms as possible: to reach the widest possible audience, and because content providers (like mobile game publishers) spend more money marketing games which support many devices.
Coping With Device Fragmentation
In the summer of 2001 we at Sumea realized that the number of platforms our games would have to support in the future would be vast. As such, we started to develop technology and tools to ease our daily work. We targeted five key areas for our efforts: reusable components, scalability, localization, profile management, and testing.
Reusable components. Development cycles for mobile games are short compared to traditional game development--currently development cycles range from three to six months. On the other hand, when comparing one mobile game to another, one can see that there are many components in common: The games have a certain menu structure, program flow, features such as sounds, vibration and high scores, instruction page, and so on. In figure 1, only the screen framed in yellow is unique to this specific game-all the other screens can be reused in other games. By reusing components we shorten the development time of the game significantly.
Figure 1. Game structure flowchart.
Reusing code is an obvious advantage. To take full advantage of these components, we defined an abstract interface between the game and the generic components. We call these generic components our "game toolkit" The game has access to the toolkit as well as to standard APIs such as MIDP and CLDC, and the toolkit takes care of interfacing with proprietary APIs. This interface makes it possible to develop the game once, and exchange the underlying implementation to support any handset or any third-party API (see figure 2). For any new device or high score interface that didn't exist at the time the game was originally created, we update only the toolkit part, and keep the game code intact.
Figure 2. Game toolkit structure.
Scalability. Making games scale to the capabilities of the various mobile devices is not always easy. Games cannot be developed for the lowest common denominator platform; we have to take advantage of the capabilities each platform provides. This means that the game should look top-notch on each platform. For example, in a racing game we may have raindrops and lightning effects for high-end devices, and leave them out for the low-end devices. Scalability means just this: to make a customized version of the game for a certain platform as cost-efficiently as possible.
Scalability covers static content, such as graphics and audio, game specific features, such as level of detail, and devicespecific features. A good example of device-specific features are game controls. The devices out in the shops have various different keypad configurations: Most of the devices have an ordinary 3×4 keypad, some have game controllers, some support multiple key presses, and some devices have exotic keypad layouts, such as the Nokia 3650.
In the case of static content, the problem is solved by using different sets of content. For graphics this means that we use different sets of game graphics, and full-screen images are be customized for each screen resolution (see figure 3). For audio, the situation is even simpler: Either the device does not support sounds, it supports MIDI, or uses some proprietary audio technology.
Figure 3. Screenshots from a game designed for three different resolutions.
On the coding side, the problem can be solved in a similar way: by introducing different sets of features. A feature can be, for example, a lightning effect, support for sounds, or extra levels. We solved this problem in two ways: developing features at the component level and at the function level.
Component-level features are easy: we define an interface for a component, and select the version of the component to be used at compile time. In figure 4 you can see a practical example of this: We have a static component Sounds, which is used to play sounds in a game. The interface will remain the same, but the component can be exchanged to contain any sound implementation. This way we will get rid of an extra file for an actual interface, and Java obfuscators can optimize a class containing only static functions.
Figure 4: Code example of sound component for Nokia proprietary mono-sounds and Mobile Media API MIDI-sounds
Function-level features are more complicated: applications for wireless devices have to be optimized for speed and memory as well as for size. This means, for example, that we cannot have numerous different files. That, in turn, means that we must forget about pure object-oriented programming for a moment, even when using compile-time interfaces. Component-level features are not sufficient, as we cannot divide the code into as many components as we would need to. To tackle this problem we developed code preprocessing tools: If a certain tag is defined, the code remains intact-otherwise it is removed. An extreme example of this method can be seen in figure 5. The example is taken from a game in which the player can collect coins. When a coin is collected, a sound effect is played. When all the coins have been collected, a bonus game is opened. We defined two features: whether sounds are used (USE_SOUNDS) and whether the bonus game is included (BONUS_GAME). Either one of these features can be enabled or disabled. In figure 6 you can see the preprocessed code, where sounds have been disabled and the bonus game is enabled.
Figure 5: Code example of original source code
Figure 6: Code example of preprocessed source code
With these types of features, porting a game to new handsets becomes easier. It is a matter of selecting the features to use, and compiling the game. The process is a bit like playing with building blocks.
Localization. The most important reason to localize games is that localized games sell better. Usually all the text in a game is translated--in some special cases even the title screen is translated. From Sumea's point of view, the most exotic language our games have been localized to is Chinese. By default we support five languages (English, French, German, Italian, and Spanish), and the number is increasing.
Usually the localization process goes like this: we deliver text assets for a certain game to the party taking care of the localization, get the translated assets back, build the game, and then deliver it to our customer. In some cases the game bounces back from the distributor's QA team due to errors in the localized assets. In some cases the context is wrong: it might be that a device uses certain terminology for navigation, and using different terminology confuses the user. This is straightforward work, and usually solving the problem once is enough.
Another problem arises from the different platforms supported. For example, controls have to be customized for certain handsets due to different keypad layouts. The easiest way of solving this is to have parameterized text assets. This means that we define the text once, define device specific parts as parameters, and fill those in either at compile time or at run time. In figure 7 you can see some of the English text assets used in Yoyo Fighter.
Parameters for Nokia 7210:
Parameters for Nokia 3650:
Figure 7: Some text assets used in Yoyo Fighter.
From an implementation point of view, the simplest way to localize content is to use standard components provided by MIDP. These components take care of all the different aspects you can encounter: length of text in various languages, different font sizes, reading direction, handset user interface, and so on. The drawback to using system components is that you lose control over the graphical appearance. For example, it might be disturbing to show a system text box in the middle of a hectic gaming session.
The solution is to implement text components of your own. There are two simple rules to follow: never embed text in an image, and be conscious of the restrictions when drawing text. The reason for the first rule is simple: text is easier to replace than images (and it takes up far less memory). The second rule is more complicated, and is not easily fulfilled with a generic implementation because of strict limitations. We have compromised on this rule: When we know the limitations exactly, we use components of our own. In other cases we rely on the system components.
Profile management. Because of strict filesize limitations we will have to build a game file of its own for each device or device platform. To make things more straightforward, we include text assets for one language into a single build. One game build consists of JAD and JAR files. In practice, this means that for a game which supports eleven different platforms and eight languages, we have 88 different game builds-176 separate files. In most cases both of these files contain device-specific information. Managing all these files can be a tedious task, but luckily the process can be automated.
At Sumea we call the parameters that define a devicespecific version of a game a "profile". The profile defines source code and resource files to be used in a certain build of the game, as well as all device-specific parameters. These parameters define general properties such as whether sounds are used, whether the build is a debug or release version, whether the game is a demo version, and which system components are used, as well as game-specific properties such as which game controls and text assets will be used. We have developed tools with which we can define the profiles to be compiled with certain text assets, using just a single command.
Testing. Almost every device manufacturer provides device emulators to ease application development. The problem is that these emulators provide (at best) only an approximation of the actual device. Therefore we cannot rely on the emulators; we have to test the game in the actual handset. As most of the devices don't support on-device debugging, we have had to implement a logging mechanism to make the testing process easier. This logging mechanism gives the developer a means to store text-based information in the persistent memory, then to view it later. A good practice is to test games in new device software releases: software is rarely bug-free, and it might be that there are new bugs in the device software, or functionality of a certain API has changed enough to reveal or cause a bug in your game.
Fortunately, though, the emulators are getting better. In the early days we often received a device and a piece of documentation stating which APIs the device supports. The rest we had to figure out ourselves. Now emulators are starting to be more accurate and the documentation is, in the best cases at least, more than sufficient. The base software in devices is getting more stable as well-this means that when a new handset with a proven base software is released, we don't have to necessarily test the game in this new device, but can generally rely on it working flawlessly.
Insights For The Future
Despite the challenges mobile game developers face today with the fractured Java landscape, the future still looks exciting to me. One bright spot is the Java Community Process, which was originally founded by Sun Microsystems. JCP is an open organization working on Java standards. It uses a formalized process to develop new Java technology specifications and revises existing ones. Any member of JCP can submit a new Java specification request (JSR), so it's an important tool for all of us Java developers to help evolve the standard. For more information on JCP and a full list of JSRs, visit www.jcp.org. I have selected five JSRs that are interesting from mobile game developer's point of view.
1. Java APIs for Bluetooth (JSR-82) is, as the name states, a Java API which gives the developer access to Bluetooth functionality. Bluetooth is a close proximity, low latency communication channel between two or more devices. This makes it possible to develop real-time multiplayer games. Today Bluetooth functionality can be found in most high-end devices.
2. Sony's Playstation brought gaming and 3D graphics to every household. But with today's devices and J2ME implementations, it hasn't been possible to implement real-time 3D applications. The Mobile 3D Graphics API for J2ME (JSR-184, which is coupled with OpenGL ES) will bring 3D graphics to mobile devices.
3. Today the whole J2ME application is contained in a single package. This means that the application is downloaded once, and it stays in the device memory for as long as the user wants to, or for as long as the subscription lasts. Each application has a certain amount of persistent memory it can use, but the amount of memory is low. PDA Optional Packages for the J2ME Platform (JSR-75) contains the file API, which gives the application an access to removable storage devices such as memory cards. This enables game developers to develop nearly infinite game worlds, as the user can download new graphics and levels for their games.
4. MIDP 2.0 makes it possible to launch the browser from within an application. This can be used, for example, when an episode of a game is finished and a page containing information on the sequel is shown, or when the user is taken to a community site for the game. The Content Handler API (JSR-211) makes it possible to do vice versa: launch a J2ME application from within a browser based on URI. As an example, the user can open the game site and download new levels just by selecting a link from the page.
5. Today the business model for mobile games is based either on single download fee or subscription model. Some operators give the developer access to their billing mechanism, but in any case the developer has to have different implementation for each operator. The Payment API (JSR-229) provides a standardized API for micro payments. With this the content provider can bill for extra levels, sequels, sending high scores, and so on.
To summarize, mobile applications are today merely add-ons to the device. The above- mentioned new APIs make it possible to create more seamless applications-providing new and exciting possibilities. The challenge, however, is that mobile game development is not only about producing games. All these APIs provide potentially an even more fragmented technology base -- and at the same time the developers have to support the current installed base of handsets, which is based on yesterday's technology. All the parties involved realize the problems brought by fragmentation and try to fight against it.
One of the most interesting JSRs is JSR-185, "Java Technology for the Wireless Industry." The purpose of this JSR is not to produce new APIs but to provide an overall architectural description and to coordinate selected JCP efforts for the wireless industry. One of the most practical outcomes of this JSR is that, for example, instead of saying that a certain device supports MIDP 1.0 and Wireless Messaging API, it is JTWI 1.0 compliant.
JTWI does give recommendations for minimum device capabilities, but it doesn't define actual categories, such as certain display resolutions or amount of memory. However, most manufacturers have adopted so called series thinking. This means that a manufacturer has a number of categories, which again have a number of devices in them. Examples of such categories are Nokia's Series 40 and Series 60. In the best cases the series thinking is working so well that application developers don't have to test an application on every device.
Quality assurance has been taken into account as well. In June 2003 Motorola, Nokia, Siemens, Sony Ericsson, and Sun Microsystems announced their plans for unified testing and certification programs. For more information on this one go to www.javaverified.com. We at Sumea eagerly await the results of this initiative.
The biggest problem at the moment I see in K Virtual Machine implementations: The APIs and specifications are not strict enough, leaving space for various different implementations. This should be solved soon, as the number of devices and APIs is growing. My wish-list is long, but it's clearly shorter than a year ago. I think that is a good sign.
For Further Reading
Or see http://www.jcp.org/en/jsr/all for a list of all current JSPs
Optional Packages for the J2ME Platform (JSR-75)
APIs for Bluetooth (JSR-82)
Technology for the Wireless Industry (JSR-185)
3D Graphics API for J2ME (JSR-184)
Technology for the Wireless Industry (JTWI 1.0/JSR-185)
Handler API (JSR-211)
Testing Initiative for Java Platform, Micro Edition