Some reader favorites:
EJB fundamentals and session beans
Create a scrollable virtual desktop in Swing
Wizard API updated!
Tim Boudreau has released a new version of the Swing Wizard library (version 0.997) that fixes the WizardException bug reported in JavaWorld's recent Open Source Java Project profile. The article's examples have been reworked to test out the new, improved WizardException. Thanks, Tim, for this helpful fix!
Open Source Java Projects: The Wizard API
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.
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);
}
}
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.
In this case, it really is necessary to spawn a new thread. The animation in this game is always moving, even when the user doesn't press a button, so I need to have a game loop that repeats constantly until the end of the game. I can't use the main thread for the game loop because the application management software may need to use the main thread while my game is running. While testing the game in the emulator, I found that if I use the main thread for my game's animation loop, the emulator is unable to respond to keystrokes. Of course, in general, it's good practice to spawn a new thread when you plan to go into a loop that's to be repeated throughout the duration of your program's active life cycle.
| Subject | Replies |
Last post
|
|
By MapperAdult |
0 |
05/16/08 06:28 AM
by Anonymous |
|
By MapperAdult |
0 |
04/09/08 04:02 PM
by Anonymous |
|
By Logitech |
0 |
10/24/07 09:59 PM
by Anonymous |
Free Download - 5 Minute Product Review. When slow equals Off: Manage the complexity of Web applications - Symphoniq
![]()
Free Download - 5 Minute Product Review. Realize the benefits of real user monitoring in less than an hour. - Symphoniq