The
MIDP 2.0 Game API supplies a rich game development framework. A lot of
the functionality was incorporated into the MIDP 2.0 specification as a
result of real-world experiences writing early Java ME games.
1. The Full-Screen Canvas
The game canvas supplied as
part of MIDP 2.0 allows the game to take over the full screen real
estate – or at least as much as the implementation allows (UIQ devices
do not allow complete
use but they tend to have larger screens in any case). Prior to this,
developers were stuck with even smaller areas than are around today,
unless they leveraged custom libraries provided by the phone
manufacturers. One example of this was the Nokia UI which provided a
full-screen canvas.
2. Game Key Mappings
These are an abstraction of the
basic actions taken by players during a game. In most cases, these
actions are moving left or right, up or down and triggering some action
such as firing a weapon or jumping. This allows Java ME game code to
work over a variety of hardware input methods as each manufacturer can
map, for example, the UP action to an input method best suited to the
device.
Game actions are defined as fields of the Canvas class. The code snippet below demonstrates how to extract the game action in an event handler:
public void keyPressed(int keyCode){
int gameAction = getGameAction(keyCode);
switch(gameAction){
case Canvas.FIRE: ...
case Canvas.UP: ...
3. Painting and Double Buffering
The GameCavas
provides double buffering by default. The painting model is such that
all drawing occurs to an offscreen buffer which is then sent to the
display using the flushGraphics() method. As a developer, your task is to provide an implementation of the paint()
method. It is called by the framework: you should never call this
method yourself. Application-initiated painting is done via the repaint() and serviceRepaints() methods. Calling repaint() only issues a request to update the screen – it completes immediately and the framework calls your paint() method asynchronously. In this manner, a number of calls to repaint() may actually result in only a single update. The serviceRepaints()
method is synchronous and forces any pending repaints to be completed
immediately.
4. Key-Stroke Detection
Games often need to detect fast key strokes in the game loop. In order to make sure that no key strokes go undetected, the Game-Canvas.getKeyStates()
method is used. This returns an integer representing the states of the
keys on the phone, where each bit represents a specific key. The bit is 1
if the key is currently down or has been pressed at least once since
the last time the method was called. It is 0 if the key is currently up
and has not been pressed at all since the method was last called. The
following code snippet demonstrates the use of this:
private void processUserInput(){
if(!gameOver){
int keys = getKeyStates();
if((keys & GameCanvas.FIRE_PRESSED) != 0){
gameEngine.startFiring();
...
}
if((keys & GameCanvas.UP_PRESSED) != 0){
gameEngine.upAction();
...
In addition, the constructor of the GameCanvas class takes a Boolean value indicating whether to suppress key events. When true, the framework does not call keyPressed, keyRepeated and keyReleased
event handlers, which can reduce unnecessary overhead. Two points to
remember here is that it only applies to game actions and is appropriate
only if you want to use the getKeyStates() method for input detection.
5. Sprites, Layers and Collision Detection
The game API has excellent support for sprites. A Sprite
can be moved, positioned, flipped, and mirrored around both the
horizontal and vertical axes or about an arbitrary point by using the defineReferencePixel()
method. A sprite can also be constructed from a single image consisting
of a set of equally sized frames which can then be animated using the nextFrame() and prevFrame() methods.
You can also use the collidesWith() and defineCollision-Rectangle()
methods for collision detection between sprites and other layers in the
game world at either a bounding box or pixel level. Pixel-level
collision tests only check for collisions between opaque pixels, which
gives the best visual results but requires more processing.
Finally while not part of the
game API, the MIDP 2.0 specification made support for tone generation
mandatory as part of the Media API which is a subset of MMAPI. This
meant that there was always some way of creating basic sounds in games.
When you put all of this together the MIDP 2.0 Game API is without peer
in the mobile space.
For a more detailed example of
how to build simple MIDP-based games using many of the other techniques
outlined above, please refer to [Mason 2008].