ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Your First Micro Java Game

by David Fox
12/23/2002

Mobile phone manufacturers have embraced Java in a way that not even PC manufacturers have. Java is clearly one of the platforms of choice for mobile devices, and an ideal language for throwing together mobile games.

The Mobile Information Device Profile (MIDP) of J2ME is a subset of the standard Java you know and love, with a few minor modifications. Writing a basic MIDlet game is simple as apple pie. This article will show you how to start cookin'.

The Dope: What We Can and Can't Do

Let's be honest here: programming good games for handheld devices is not easy. The screen is miniscule, the dynamic and storage memory is limited, there's limited network connectivity, and the processor itself is often hundreds of times slower than your average desktop. Some of the limitations are discussed in the article "Developing Cutting-Edge Mobile Games."

Of course, several brands of Java phones offer neat extension APIs that let you access special, native features. Motorola, Siemens, and Nokia, for example, have game APIs that allow for audio, animations, sprites, tiled backgrounds, transparency, and better graphics. Parts of this API will be folded into MIDP 2.0, which is due out soon.

Related Reading

J2ME in a Nutshell
By Kim Topley

In the meantime, it's important to remember that Java is perhaps the easiest modern language to develop in. With garbage collection of old objects and lack of memory allocation and pointers, it's a great way to create quick prototypes and develop them out into full apps. The object-oriented nature of Java makes it easy to maintain, making sweeping code changes with a little modification to a superclass.

Perhaps the most compelling argument for using Java is -- you guessed it -- write once and run everywhere. Theoretically, an application written for a Motorola cell phone can also run on Nokia, an Ericsson, a Siemens, or a Palm. The same code could even be compiled and run as an applet in a Web browser, as an application on a million-dollar server machine, in your car's dashboard, or -- eventually -- in a Java-powered neural link to your own brain! In reality, things might not be so easy -- but it's still much, much simpler than developing a custom native version for each handset.

Creating a MIDlet

If you have any experience creating Java applications or applets, then programming in J2ME won't seem like a stretch at all. The steps are basically the same:

  1. Write your program and save it as a .java text file.
  2. Compile it.
  3. Preverify it.
  4. Package it as a .jad file.
  5. Test it.
  6. Debug it.
  7. Release it and reap the rewards!

The only thing that should set off your mental alarms is step number three: preverification. This may sound weird and complicated, but is actually quite easy. The purpose of preverification, theoretically, is to go through your bytecode and set hints up so that the actual verification of bytecode will happen much more quickly, saving you valuable startup time.

Most development environments do all the compiling, preverification, and packaging for you. They also let you emulate various devices on your development desktop. For example, check out Metrowerk's Code Warrior Wireless Studio or Borland's JBuilder Mobile Set. Sun's own J2ME Wireless Toolkit is free, complete, really easy, and available for Windows, Linux, and Solaris. It also comes with a bunch of source code, including sample games such as Snake, Sokoban, a tile sliding game, Pong, and Star Cruiser.

Note that in order to run the Wireless Toolkit, you'll need Java itself (JDK1.3 or better), which has all of the engines and libraries necessary to compile code. Be sure to install the JDK and the Wireless Toolkit per directions, with all the proper settings for classpaths and paths.

Write Your Program

Enough talk. Let's look at some code.

Just like an applet is based on the java.applet.Applet class, a MIDLet always extends javax.microedition.midlet. A MIDlet handles basic event handling and can be thought of as the one and only "window" that your application runs within. The heart of every MIDlet is the startApp() method. It kicks the MIDlet into action and should set up all the components or other objects you are interested in. Every MIDlet must also contain pauseApp() and destroyApp() methods, which are called if and when a user chooses to either pause or quit your program.

Graphically speaking, the actual screen on your mobile phone is a Display object. Every MIDlet has one and only one Display object, which you can access using getDisplay(this).

The Display: Using a Canvas

A Display can consist of either a Screen object or a Canvas. The Screen class makes it easy to use standard GUI components such as Lists, Alerts, Forms, or TextBoxes. A mobile phone's Display can only show one Screen or Canvas at a time. A typical application starts with a List as a main menu of choices, branching into other types of Screens, depending on the user's selection. But while Screens are good for navigation, the cool graphical action is going to be happening in a Canvas.

A Canvas defines the paint() method, which gets called as often as the device is able to refresh the screen. The Graphics object allows for simple renderings using familiar Java methods such as drawArc(), drawImage(), drawLine(), drawRect(), drawString(), and fillRect().

Note that images need to be in the PNG format, and color images are supported on phones that have color screens. For example, if we had a simple 10x14 image of a spaceship like this:

You could create the image as follows:

Image spaceship = Image.createImage("/ship.png"); 

If you're using the Sun Wireless Toolkit, you simply drop your images into the img folder beneath your main project.

You should always create your own Canvas subclass. For example:

class SpaceCanvas extends Canvas 
{
     public void paint(Graphics g) 
     {
        g.drawRect(1,1,getWidth()-2,getHeight()-2);
        g.setFont(Font.getFont(Font.FACE_MONOSPACE, 
           Font.STYLE_PLAIN,Font.SIZE_SMALL));
        g.setColor(0);
        g.drawString("Space Game", getWidth() / 2, 0, 
           Graphics.HCENTER | Graphics.TOP);
        g.drawImage(spaceship, 10,30, g.TOP|g.LEFT); 
     }
}

This Canvas contains a rectangle bordering the entire screen with the string "Space Game" at the top, horizontal center. A spaceship image is also drawn at the (10,30) coordinate. You could drop this Canvas into the Display by creating it in your main MIDlet class:

private SpaceCanvas aCanvas = new SpaceCanvas();

And then, in the MIDlet's startApp() method or anywhere else that made sense, you could set the current Display to show the special canvas:

theDisplay.setCurrent(aCanvas);

Using Sprites

A typical 2D game involves characters moving around and about, interacting with each other. The graphical versions of these characters are known as sprites. Sprites have an x coordinate to indicate how far across the screen they should be positioned and a y coordinate to indicate how far down. Sprites can also be hidden or made visible.

A basic Sprite class can look like this:

import javax.microedition.lcdui.*;
 
public class Sprite
{
  protected Image image;
  protected int x; 
  protected int y;
  protected boolean visible;
 
  public Sprite(Image image)
  {
    this.image = image;
  }
 
  public void paint(Graphics g)
  {
    g.drawImage(image, x, y, Graphics.TOP | Graphics.LEFT);
  }
 
  public Image getImage()
  {
    return this.image;
  }
 
  public int getX()
  {
    return this.x;
  }
 
  public void setX(int x)
  {
    this.x = x;
  }
 
  public int getY()
  {
    return this.y;
  }
 
  public void setY(int y)
  {
    this.y = y;
  }
 
  public boolean isVisible()
  {
    return this.visible;
  }
 
  public void setVisible(boolean visible)
  {
    this.visible = visible;
  }
}

Better yet, you could add variables for x and y velocities to set how fast your sprite is moving horizontally. For example, an x velocity of -2 would move the sprite to the left at the rate of 2 pixels per frame.

A more complicated Sprite class can handle animated images with multiple frames, collision with other sprites, etc. Also, you may want to create your own floating point class, so that sprites can move smoothly (based on simple decimal math), rather than forcing the position and velocity to be full integers.

Pages: 1, 2

Next Pagearrow