We outlined some of the constraints that devices and operating systems
in the feature phone market impose on Java ME. Most of the limitations
you encounter on other platforms do not apply when building MIDP games
on Symbian OS. Within the bounds of available resources, Symbian OS does
not place any limits on JAR size, the number of sockets you can open,
or the number of threads you can have; the local storage space and the
size of the heap can grow and shrink dynamically as required.
This means that you can do some
things in a Symbian OS MIDlet that you would not even consider on other
platforms. For example, you can load a large number of high-resolution
images at once, play advanced sound formats instead of MIDI sequences,
and distribute detailed models or level data as JAR file resources. That
is not to say that you should be lax with your memory management but it
need not be your first concern .
More importantly, as we see in
this section, you can adopt a more abstract framework for your code base
which translates directly into a high degree of re-usability. There is
no need to use the extreme Java ME optimization techniques that are
needed on low-end platforms (such as, avoiding abstract classes and
interfaces to keep JAR sizes down).
We work through the main features of a sample game called Finding Higgs
in honor of recent work done (well, planned anyway, before it shut down
for repairs in its first week) at the Large Hadron Collider in CERN.
The aim is to review a first-person-shooter game that demonstrates the
use of various JSRs commonly used in game development and that are
provided with Symbian OS. Figure 1 shows a screen shot of the game in action.
1. Planning
Having clear answers to
the following questions before development begins directly reduces risk
and development time for the project. It also helps simplify your game
design from the outset:
What are the aims of the player?
The
player has one minute to destroy as many attackers as possible while
using the least amount of ammunition. Bonus points are awarded if the
player's hit rate exceeds 60%. In single-player mode, the aim is to beat
the previous high score. In two-player, head-to-head mode the aim is to
beat your opponent.
What are the 'game over' conditions?
The game completes after one minute has elapsed.
What controls are available for player input?
The
player can use the five-way navigation joystick or the keys marked 2,
4, 5, 6 and 8 on the keypad for navigation. In this game, the FIRE
action fires the gun and the up, down, left and right keys move the
player in a polar orbit around the world origin in 3D space.
How are scores and game status displayed?
As you can see in Figure 8.3,
the top left corner shows the current frame rate at all times. The top
right shows the opponent's score during multi-player mode. This is
updated via Bluetooth in real time. The bottom left shows the remaining
game time; the bottom centre shows the number of shots fired; and the
bottom right shows the player's current score.
How is the pause–resume cycle handled?
The MIDlet class monitors its own state, keeping itself in sync with notifications from the AMS at all times. The Controller class manages the application lifecycle and the GameController
manages the game lifecycle. A separate pause menu is used to allow the
player to quit the current game or change the settings at any time.
How is the game world represented?
The
game world is 3D space where a series of attacks are launched along the
z-axis towards the player. The Mobile 3D Graphics API (JSR-184) is used
to represent this world.
How are frame and simulation rates managed?
The
frame rate is capped at 25 FPS by granting up to 40 ms for each frame.
This works by tracking the amount of time it takes to complete the
rendering phase of the game loop. If this is found to be less than 40
ms, the thread sleeps for a short period in order to re-synchronize
itself. This approach enables other active threads to use processor
cycles for other useful tasks and allows CPU power management which can
help increase battery life.
Be
careful with this – on Symbian OS, the native timer has a resolution of
1/64 seconds so what you request may not be what you actually get.
Using a periodic timer in this manner is susceptible to drift because
you actually only receive an event once about every 30 ms – so your
actual frame rate is slightly less than expected.
The
simulation rate runs at a different rate than the frame rate by
tracking the time since the last simulation step and only performing a
new one if a sufficient time period has elapsed.
Does the game respond to a change in display size?
In this case, the game is not designed to respond to changes in screen size.
What multimedia effects are employed?
A
WAV file is used for the sound effect of the weapon and a set of MIDI
sequences are used to provide background music. At the start of each
music sequence, a vibration event is triggered.
How is navigation between screens in the application managed?
In
this case, the entire application navigation is abstracted over three
packages with the main management being the responsibility of the Navigator
class. The point is to provide both a custom-drawn menu system using
only the low-level graphics routines in MIDP 2.0 and a more advanced
menu system using the Scalable 2D Vector Graphics API (JSR-226) where
supported.
2. Design
The game design consists of the logical subsystems shown in Figure 2.
The AMS and the MIDlet
together represent the interface between the application and the outside
world, i.e. the operating system. The application itself is designed on
a Model-View-Controller (MVC) pattern, where the Controller
class manages application view changes and navigation using the active
menu system. Its primary role is to respond to lifecycle events from the
operating system and to drive the application framework. To a large
extent, the controller is not aware that is a 'game' so to speak. It
owns a GameController instance that it notifies when events occur. Other than that, the controller remains independent of the particular application.
Figure 3
shows the application's main classes and their relationships. As you
can see from the names, most of the classes are designed for re-use and
have little to do with the particular game being built.
3. Menus and Navigation
This game uses a relatively
heavy UI layer in the form of three packages. This is not necessarily
recommended practice – it has been done this way to demonstrate how you
can support two different menu system implementations and select the one
to use at run time based on the target device.
public interface IMenuSupplier {
public void showMainMenu();
public void showPauseMenu();
public void showSettings();
public void showMultiPlay();
public IMessageScreen showMessageScreen(String message);
}
Application navigation is performed by the Navigator
class which delegates menu requests to the appropriate implementation.
In this way the rest of the application is completely isolated from the
menu system in use. Figure 4 shows the main game menu with the SVG version on the left and the low-resolution graphics version on the right.
Incidentally, you should be
able to see that the menus overlay different background images. Every
time a new game is started, the game randomly selects a new background
from a set of 10 high-resolution images included in the application JAR
file. That becomes the active background for the entire MIDlet until a
new game is played.
There is no particular
point to this other than that it varies the feel of the game increasing
its interest level and the pictures look great (they're all from NASA).
This also shows just one of the things you can do on Symbian OS when
you do not have to operate under the stringent limitations imposed by
other operating systems. You can use your imagination to come up with an
almost endless variety of great effects and features.