Newsletter sign-up
View all newsletters

Sign up for our technology specific newsletters.

Enterprise Java
Email Address:

Using the MIDP 2.0 Game API

Get started building games for J2ME with MIDP 2.0

  • Digg
  • Reddit
  • SlashDot
  • Stumble
  • del.icio.us
  • Technorati
  • dzone

Let's look at the most important package you'll be dealing with when writing games with Mobile Internet Device Profile (MIDP) 2.0: the package javax.microedition.lcdui.game. In this chapter, I show you the main parts of a MIDP 2.0 game by explaining the code of an example game called Tumbleweed. The game involves a cowboy walking through a prairie jumping over tumbleweeds. It's kind of a silly game, but it illustrates most of the basics you'll need when writing more reasonable games.

Starting with the MIDlet class

As usual, the application starts with the MIDlet class. In this case, my MIDlet subclass is called Jump. This class is essentially the same as the MIDlet subclass. The only differences here are the use of a separate GameThread class and the fact that when the user presses a command button, I have the MIDlet change the command that's available on the screen. The command change is because the user can pause the game only when it's unpaused, can unpause the game only when it's paused, and can start over only when the game has ended.

Listing 1 shows the game's MIDlet subclass called Jump.java.

Listing 1. Jump.java

package net.frog_parrot.jump;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
/**
 * This is the main class of the Tumbleweed game.
 *
 * @author Carol Hamer
 */
   public class Jump extends MIDlet implements CommandListener {
   //---------------------------------------------------------
   // Commands
    /**
    * The command to end the game.
    */
   private Command myExitCommand = new Command("Exit", Command.EXIT, 99);
   /**
    * The command to start moving when the game is paused.
    */
   private Command myGoCommand = new Command("Go", Command.SCREEN, 1);
   
   /**
    * The command to pause the game.
    */
   private Command myPauseCommand = new Command("Pause", Command.SCREEN, 1);
   /**
    * The command to start a new game.
    */
   private Command myNewCommand = new Command("Play Again", Command.SCREEN, 1);
   //---------------------------------------------------------
   // Game object fields
   /**
    * The canvas that all of the game will be drawn on.
    */
   private JumpCanvas myCanvas;
   /**
    * The thread that advances the cowboy.
    */
   private GameThread myGameThread;
   
//-----------------------------------------------------
   // Initialization and game state changes
   /**
    * Initialize the canvas and the commands.
    */
   public Jump() {
      try {
         myCanvas = new JumpCanvas(this);
         myCanvas.addCommand(myExitCommand);
         myCanvas.addCommand(myPauseCommand);
         myCanvas.setCommandListener(this);
      } catch(Exception e) {
         errorMsg(e);
      }
   }
   
   /**
    * Switch the command to the play again command.
    */
   void setNewCommand () {
      myCanvas.removeCommand(myPauseCommand);
      myCanvas.removeCommand(myGoCommand);
      myCanvas.addCommand(myNewCommand);
   }
   
   /**
    * Switch the command to the go command.
    */
   private void setGoCommand() {
      myCanvas.removeCommand(myPauseCommand);
      myCanvas.removeCommand(myNewCommand);
      myCanvas.addCommand(myGoCommand);
   }
   
   /**
    * Switch the command to the pause command.
    */
   private void setPauseCommand () {
      myCanvas.removeCommand(myNewCommand);
      myCanvas.removeCommand(myGoCommand);
      myCanvas.addCommand(myPauseCommand);
   }
   
   //----------------------------------------------------------------
   // Implementation of MIDlet.
   // These methods may be called by the application management
   // software at any time, so you always check fields for null
   // before calling methods on them.
   
   /**
    * Start the application.
    */
   public void startApp() throws MIDletStateChangeException {
      if(myCanvas != null) {
         if(myGameThread == null) {
            myGameThread = new GameThread(myCanvas);
            myCanvas.start();
            myGameThread.start();
         } else {
            myCanvas.removeCommand(myGoCommand);
            myCanvas.addCommand(myPauseCommand);
            myCanvas.flushKeys();
            myGameThread.resumeGame();
         }
      }
   }
   
   /**
   * Stop and throw out the garbage.
   */
   public void destroyApp(boolean unconditional)
         throws MIDletStateChangeException {
      if(myGameThread != null) {
         myGameThread.requestStop();
      }
      myGameThread = null;
      myCanvas = null;
      System.gc();
   }
   
   /**
    * Request the thread to pause.
    */
   public void pauseApp() {
      if(myCanvas != null) {
         setGoCommand();
      }
      If(myGameThread != null) {
         myGameThread.pauseGame();
      }
   }
   
   //----------------------------------------------------------------
   // Implementation of CommandListener
   /*
    * Respond to a command issued on the Canvas.
    * (either reset or exit).
    */
   public void commandAction(Command c, Displayable s) {
      if(c == myGoCommand) {
         myCanvas.removeCommand(myGoCommand);
         myCanvas.addCommand(myPauseCommand);
         myCanvas.flushKeys();
         myGameThread.resumeGame();
      } else if(c == myPauseCommand) {
         myCanvas.removeCommand(myPauseCommand);
         myCanvas.addCommand(myGoCommand);
         myGameThread.pauseGame();
      } else if(c == myNewCommand) {
         myCanvas.removeCommand(myNewCommand);
         myCanvas.addCommand(myPauseCommand);
         myCanvas.reset();
         myGameThread.resumeGame();
      } else if((c == myExitCommand) || (c == Alert.DISMISS_COMMAND)) {
         try {
            destroyApp(false);
            notifyDestroyed();
         } catch (MIDletStateChangeException ex) {
         }
      }
   }
   
   //-------------------------------------------------------
   // Error methods
   
   /**
    * Converts an exception to a message and displays
    * the message.
    */
   void errorMsg(Exception e) {
      if(e.getMessage() == null) {
         errorMsg(e.getClass().getName());
      } else {
         errorMsg(e.getClass().getName() + ":" + e.getMessage());
      }
   }
   
   /**
    * Displays an error message alert if something goes wrong.
    */
   void errorMsg(String msg) {
      Alert errorAlert = new Alert("error", msg, null, AlertType.ERROR);
      errorAlert.setCommandListener(this);
      errorAlert.setTimeout(Alert.FOREVER);
      Display.getDisplay(this).setCurrent(errorAlert);
   }
}


Using the Thread class

This game requires only the simplest use of the Thread class. But even in this simple case, I'd like to mention a few points.

  • Digg
  • Reddit
  • SlashDot
  • Stumble
  • del.icio.us
  • Technorati
  • dzone
Comment
Login
Forgot your account info?
Add comment
Anonymous comments subject to approval. Register here for member benefits.
Have a JavaWorld account? Log in here. Register now for a free account.
Resources