Game Programming Crash Course (for J2ME): MIDlet

Koder & Ko logo
 
 
Home | Tools Setup | MIDlet | Background | Sprites | Collision Detection | User Input | Artificial Intelligence | Optimization
 
 
Koder & Ko

J2ME Tutorial
 

MIDlet is one of the words you'll most frequently encounter when developing J2ME applications. According to WikiPedia: "A MIDlet is a Java program for embedded devices, more specifically the Java ME virtual machine. Generally, these are games and applications that run on a cell phone".

So our game is a MIDlet. On this page you'll learn how to create a very simple MIDlet, as well as lay the foundation for our game. This will probably seem a bit confusing at first, but please perservere; it will all make sense later on.

 
  Tip!

When you read about J2ME development, you'll encounter a lot of acronyms; MIDP, CLDC, MIDlet, WTK, CDC, JSR, etc., etc., etc.

Most often they confuse more than they add to your understanding. My suggestion is to skip them when you are starting out, and only look them up if really necessary.
 
 

Our First Bit of Code

In Eclipse, go to "File", "New", "Project". In the Window that shows up, expand the "J2ME" folder, choose "J2ME MIDlet Suite" and press next. As Project Name I suggest you choose "Pong" and use the default location. In the "MIDlet Suite Properties" remember to select "DefaultColorPhone" in the "Device" dropdown.

After the project has been created, your Eclipse IDE is updated. Go to the Package Explorer to the left and expand the "Pong" folder. Right click on the "src" folder and select "New", "Class". In the window that shows up, specify the Package as "dk.koderko.games.pong" (or whatever you feel like), and set the "Name" to "Pong". You will end up with a new file that looks like this:

package dk.koderko.games.pong; public class Pong { }

It does not do much, it would not even run in an emulator, so we must add a bit code:

package dk.koderko.games.pong; import javax.microedition.midlet.MIDlet; public class Pong extends MIDlet { public void startApp() { } public void pauseApp() { } public void destroyApp(boolean unconditional) { } }

This is a MIDlet as simple as they come. A MIDlet must be a subclass of javax.microedition.midlet.MIDlet, and it must implement the three methods startApp(), pauseApp() and destroyApp(unconditional). To run the MIDlet in an emulator, go to the "Run" menu, and select "Run". A window with a mobile phone will show up with your game - and you will see absolutely nothing happens, which is of course a result of our MIDlet being entirely empty.

startApp() is executed when the MIDlet is launched on the phone or when it is resumed on the phone. pauseApp() is called when the MIDlet is interupted, ie. when the phone rings while playing. Finally, destroyApp is called when the MIDlet is destroyed by the phone.

 
  More Information

A bit more information about the three methods startApp(), pauseApp() and destroyApp() is available here - it is a worthwhile read.
 
 

The Game Canvas

Now we have a MIDlet, but it does not do anything. It is time to add a GameCanvas class. The GameCanvas class is great for games, since it helps you with double-buffering the screen (which results in smooth animation), and it assists you in handling user input common to games.

To create your own GameCanvas right click "dk.koderko.games.pong" package in the "Package Explorer" and select "New", "Class". Specify the name as "PongCanvas", and make sure the Package is set to the same as you set for the Pong class. This will create a new file for the PongCanvas class, which will look like:

package dk.koderko.games.pong; public class PongCanvas { }

This code must be updated to:

package dk.koderko.games.pong; import javax.microedition.lcdui.game.GameCanvas; public class PongCanvas extends GameCanvas implements Runnable { public PongCanvas() { super(false); } public void run() { } }

This is the most simple GameCanvas class possible. The constructor must include the method super(), which specify if ordinary key events should be suppressed. These "ordinary key events" is events from the Canvas class, that the GameCanvas class is based on.

We implement the interface "Runnable" to be able to use threads. This class require us to implement the run() method.

 
  More Information

J2ME has a "gaming API", which is the javax.microedition.lcdui.game package. This includes the GameCanvas and Sprite classes, which we will use in this course. It also includes Layer, TiledLayer and LayerManager, which is normally used for tile-based games and not during this course. For more information about GameCanvas, have a look at Game Canvas Basics.

You can read more about Runnable here.
 
 

How A Game Works

Games work in a sligthly different manner than most applications. They in general compromise of a setup-step followed by an (almost) infinite loop when the game is running. MIDlet games is sligthly bit different, since they have the MIDlet setup-step, as well as the GameCanvas setup-step.

Game Flow

Setting up the MIDlet

To have our GameCanvas shown on the screen, we must add a bit of code to the MIDlet in Pong.java. It now looks like this:

package dk.koderko.games.pong; import javax.microedition.lcdui.Display; // Added import javax.microedition.midlet.MIDlet; public class Pong extends MIDlet { public Pong() { // Added pongCanvas = new PongCanvas(); // Added } // Added public void startApp() { Display display = Display.getDisplay(this); // Added pongCanvas.start(); // Added display.setCurrent(pongCanvas); // Added } public void pauseApp() { } public void destroyApp(boolean unconditional) { } private static PongCanvas pongCanvas; // Added }

Lets walk through each of the new lines.

import javax.microedition.lcdui.Display;

This line imports the Display class. This class have a very convenient method, getDisplay(), which get the Display object that is unique to this MIDlet.

public Pong() { pongCanvas = new PongCanvas(); }

The constructor method of the MIDlet simply initializes the PongCanvas.

public void startApp() { Display display = Display.getDisplay(this); pongCanvas.start(); display.setCurrent(pongCanvas); }

Remember that the startApp() is executed when the MIDlet is launched? What we do here is that we get the current display (through the getDisplay() method). We then call the start() method of our PongCanvas class (not yet implemented), and finally we set the current display to our pongCanvas object.

private static PongCanvas pongCanvas;

This linie just declares the pongCanvas to be of the type PongCanvas.

Setting up the GameCanvas

We can now complete the foundation of our PongCanvas class. The code is updated to:

package dk.koderko.games.pong; import javax.microedition.lcdui.game.GameCanvas; public class PongCanvas extends GameCanvas implements Runnable { public PongCanvas() { super(false); } public void run() { while(true) { // Added // Here is where the game will run try { // Added Thread.sleep(sleepTime); // Added } catch (Exception e) { // Added } // Added } // Added } public void start() { // Added Thread runner = new Thread(this); runner.start(); } // Added private int sleepTime = 30; // Added }

Let us once again go through each change.

while(true) { // Here is where the game will run try { Thread.sleep(sleepTime); } catch (Exception e) { } }

This is the infinite loop mentioned earlier. This loop will be built out with tasks like moving objects on the screen, handle the user input and more. The Thread.sleep() method is a way to control the speed of the game. If we did not ask the game to "rest" for a while, it would move far too fast. I use a variable called sleepTime to specify how long the game should sleep.

public void start() { Thread runner = new Thread(this); runner.start(); }

This is the method I call from the Pong.java MIDlet. This method will later on be used to load images and setup sprites. For now, it is only used to initialize a new Thread and starting it with the run() method.

private int sleepTime = 30;

Well, this is just the variable to control the speed of the game. It specifies how many milliseconds the game must sleep/rest/wait, so the lower the number, the faster the game.

It is not expected for you to understand everything on this page. It will all come together later on.

Next Page: We finally get to paint something on the screen

 
 
 

Call +45 2078 7221 or write ave at koderko.dk

Koder & Ko | Nordre Fasanvej 166 | 2000 Frederiksberg | Denmark