No Commands: Delicious Graphical Menus

Aesthetics plays an important part in the games that you make. Making the main menu look like it fits the game is equally as important. If done right, it can set the mood for the player even before actually playing the game.

Let's face it. Using Command Listeners and objects for your menus just doesn't feel right. Command objects just don't look like they're part of the game. On some phones, the game is hidden when the menu is activated. Phones don't even display the label for the keys you have to press to activate the menu when the game is in fullscreen mode. Graphical menus solves these problems and makes the game look cool too.

Clipping is used extensively in this tutorial. If you need a quick study, turn to this tutorial : Clipping Images or Displaying Only Parts of an Image.


Loading the Images
In this tutorial we will make a simple vertical menu in the middle of the canvas. The MIDlet will be designed for mobile phones with 176x208 screen resolution.


Sample Vertical Menu


I have prepared a clean project for you to start with. It includes the basic game template and the input handling code from the tutorial Input Handling : Keypress with Repeat Rate. It also includes the images we're going to use for the menu. Download the one for the version of NetBeans you will use:


When you open the project in NetBeans, you should see these 2 files inside the images folder:

logo.png - 176x208 pixels

logo.png


menuitems.png - 82x80 pixels

menuitems.png



First we'll have to load the images. So open the clsCanvas code and add these variable declarations above the constructor:

private midMain fParent;

private Image imgBG;
private Image imgMenu;

public clsCanvas(midMain m) {


Add the actual image loading code in the load() method. Make sure they are inside the try..catch or exception handling code:

public void load(){
try{
// load the images here
imgBG = Image.createImage("/images/logo.png");
imgMenu = Image.createImage("/images/menuitems.png");

}catch(Exception ex){

Add these lines inside the unload() method to make sure the resources reserved for those objects will get freed:


public void unload(){
// make sure the object get's destroyed
imgMenu = null;
imgBG = null;

}



The logo can now replace the call to fillRect() that we used to clear the screen since the logo takes up the whole screen. Remove or comment the lines from the main loop as indicated below:


//restore the clipping rectangle to full screen
g.setClip(0, 0, getWidth(), getHeight());

/* start - delete lines
//set drawing color to black
g.setColor(0x000000);
//fill the whole screen
g.fillRect(0, 0, getWidth(), getHeight());
*/ end - delete lines

// set drawing color to white
g.setColor(0xffffff);


Now we can draw the logo. Insert this code under the call to setClip() inside the main loop :


//restore the clipping rectangle to full screen
g.setClip(0, 0, getWidth(), getHeight());

g.drawImage(imgBG, 0, 0, Graphics.TOP | Graphics.LEFT);





Drawing the Menu
We'll need a variable to store the currently focused menu item. Let's call it menuIndex and declare it under the other variables we declared earlier:


private Image imgMenu;

private int menuIndex = 0;

public clsCanvas(midMain m) {



The drawing code for the menu will be placed on a new method name drawMenu(). Add this code above the run() method:


public void drawMenu(Graphics g){
int cy = 0;
for (int i = 0; i < 5; i++){
//compute the Y position of the menu item
cy = 64 + (i * 22);
//set the clipping rectangle to where the item will be drawn
g.setClip(47, cy, 82, 20);
if (menuIndex == i){
//draw the light button if the item is focused
g.drawImage(imgMenu, 47, cy - 20, Graphics.TOP | Graphics.LEFT);
} else {
//draw the dark button if the item is not focused
g.drawImage(imgMenu, 47, cy, Graphics.TOP | Graphics.LEFT);
}
//offset of the label is 6 pixels from the top of the button
cy += 6;
//set the clipping rectangle to where the label will be drawn
g.setClip(47, cy, 82, 8);
//draw the label so that it is inside the clipping rectangle
g.drawImage(imgMenu, 47, cy - (40 + (i * 8)), Graphics.TOP | Graphics.LEFT);
}
}

public void run() {



The menu will be drawn 64 pixels from the top of the screen and the menu items are drawn at 22 pixel intervals and since each of the menu items is only 20 pixels in height, a 2 pixel space will be left between the menu items acting as a margin. Depending on the value of menuIndex, either a light-blue or a dark-blue button will be drawn. Finally, the label of each menu item is drawn 6 pixels lower than the menu items position.

To show the menu on the screen, simply insert the following lines of code at the point after which the logo has been drawn:


//restore the clipping rectangle to full screen
g.setClip(0, 0, getWidth(), getHeight());
//draw the logo
g.drawImage(imgBG, 0, 0, Graphics.TOP | Graphics.LEFT);

//draw the menu
drawMenu(g);
//restore the clipping rectangle to full screen again
g.setClip(0, 0, getWidth(), getHeight());

// set drawing color to white



Notice that we now have 2 calls to setClip() where the clipping rectangle is reset to fullscreen. The second call is necessary because when the drawMenu() is finished, the method would have resized and positioned the clipping rectangle to that of the last label in the menu. Reseting the clipping rectangle after drawMenu() is called allows us to draw more stuff in other parts of the screen.

The only thing left to do now is to make the menu respond to keypresses. Modify the conditional statement under the call to the checkKeys() method inside the main loop like so:


checkKeys(iKey, lCurrTick);

if (isDown[upKey]){
//move focus up
if (menuIndex > 0){
menuIndex--;
} else {
menuIndex = 4;
}
} else if (isDown[downKey]){
//move focus down
if (menuIndex < 4){
menuIndex++;
} else {
menuIndex = 0;
}
} else if (isDown[fireKey]){
//do action depending on the menu item selected
if (menuIndex == 4){
isRunning = false;
}
}



The last code allows us to move the highlight or focus from one menu item to the other. Pressing the UP key should now move the focus one menu item higher in the list. Pressing the DOWN key should move the focus one menu item lower in the list. Pressing the FIRE key should select the focused menu item and initiate an "action". So far, there is only one "action" defined in this menu and that is for exiting the MIDlet from the EXIT menu item.

Here's the completed clsCanvas code so you can check if you missed something:


package MyGame;

import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.game.GameCanvas;

public class clsCanvas extends GameCanvas implements Runnable {
// key repeat rate in milliseconds
public static final int keyDelay = 250;

//key constants
public static final int upKey = 0;
public static final int leftKey = 1;
public static final int downKey = 2;
public static final int rightKey = 3;
public static final int fireKey = 4;

//key states for up, left, down, right, and fire key
private boolean[] isDown = {
false, false, false, false, false
};
//last time the key changed state
private long[] keyTick = {
0, 0, 0, 0, 0
};
//lookup table for key constants :P
private int[] keyValue = {
GameCanvas.UP_PRESSED, GameCanvas.LEFT_PRESSED,
GameCanvas.DOWN_PRESSED, GameCanvas.RIGHT_PRESSED,
GameCanvas.FIRE_PRESSED
};

private boolean isRunning = true;
private Graphics g;
private midMain fParent;

private Image imgBG;
private Image imgMenu;
//stores the focused menu item
private int menuIndex = 0;

public clsCanvas(midMain m) {
super(true);
fParent = m;
setFullScreenMode(true);
}

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

public void load(){
try{
// load the images here
imgBG = Image.createImage("/images/logo.png");
imgMenu = Image.createImage("/images/menuitems.png");

}catch(Exception ex){
// exit the app if it fails to load the image
isRunning = false;
return;
}
}

public void unload(){
// make sure the object get's destroyed
imgMenu = null;
imgBG = null;
}

public void checkKeys(int iKey, long currTick){
long elapsedTick = 0;
//loop through the keys
for (int i = 0; i < 5; i++){
// by default, key not pressed by user
isDown[i] = false;
// is user pressing the key
if ((iKey & keyValue[i]) != 0){
elapsedTick = currTick - keyTick[i];
//is it time to toggle key state?
if (elapsedTick >= keyDelay){
// save the current time
keyTick[i] = currTick;
// toggle the state to down or pressed
isDown[i] = true;
}
}
}
}

public void drawMenu(Graphics g){
int cy = 0;
for (int i = 0; i < 5; i++){
//compute the Y position of the menu item
cy = 64 + (i * 22);
//set the clipping rectangle to where the item will be drawn
g.setClip(47, cy, 82, 20);
if (menuIndex == i){
//draw the light button if the item is selected
g.drawImage(imgMenu, 47, cy - 20, Graphics.TOP | Graphics.LEFT);
} else {
//draw the dark button if the item is not selected
g.drawImage(imgMenu, 47, cy, Graphics.TOP | Graphics.LEFT);
}
//offset of the label is 6 pixels from the top of the button
cy += 6;
//set the clipping rectangle to where the label will be drawn
g.setClip(47, cy, 82, 8);
//draw the label so that it is inside the clipping rectangle
g.drawImage(imgMenu, 47, cy - (40 + (i * 8)), Graphics.TOP | Graphics.LEFT);
}
}

public void run() {
int iKey = 0;
long lCurrTick = 0; // current system time in milliseconds;

load();
g = getGraphics();
while(isRunning){

lCurrTick = System.currentTimeMillis();
iKey = getKeyStates();

checkKeys(iKey, lCurrTick);

if (isDown[upKey]){
//move focus up
if (menuIndex > 0){
menuIndex--;
} else {
menuIndex = 4;
}
} else if (isDown[downKey]){
//move focus down
if (menuIndex < 4){
menuIndex++;
} else {
menuIndex = 0;
}
} else if (isDown[fireKey]){
//do action depending on the menu item selected
if (menuIndex == 4){
isRunning = false;
}
}

//restore the clipping rectangle to full screen
g.setClip(0, 0, getWidth(), getHeight());

//draw the logo
g.drawImage(imgBG, 0, 0, Graphics.TOP | Graphics.LEFT);

//draw the menu
drawMenu(g);
//restore the clipping rectangle to full screen again
g.setClip(0, 0, getWidth(), getHeight());

// set drawing color to white
g.setColor(0xffffff);
//display the key code last pressed
g.drawString(Integer.toString(iKey), 2, 2, Graphics.TOP | Graphics.LEFT);

flushGraphics();

try{
Thread.sleep(30);
} catch (Exception ex){

}
}
g = null;
unload();
fParent.destroyApp(false);
fParent = null;
}
}



Press the F6 key in NetBeans to see if it actually works.




Here's a link to a low-res flash video of the MIDlet running on an N70:
Click to View Video

The technique used here to draw the vertical menu is pretty old school. I've been using it in DOS based games written in Turbo Pascal, DirectX games written in VisualBasic 6.0, and in C# using XNA Game Studio Express. One thing to remember is that you're not just limited to using vertical menus in your game. I just used a vertical menu as an example because they are very user friendly and easy to make. You can change the shape of the menu items to anything you want, knowing that you can use transparent images or change the colors to match your game. Here's a screenshot of a character selection screen for a demo quiz game:


Character sprites came from the MMORPG Trickster.


Using the graphics methods to make the menus for your game let's you use your creativity and the design is only limited by your imagination. Just remember that however unlimited your imagination may seem to be, the phone on the other hand, has limited capabilities.

~John Constantime:
"There's always a catch...damn cellphones!"

Something is unclear? I missed something? Got a question? Post a comment.

Adding an Icon to Your MIDlet or Game

I was looking at my blog's search statistics at Google Webmaster Tools when I found a few users using key words like "j2me icon MIDlet", "MIDP icon bit depth", "MIDlet icon transparency". So I decided to write this tutorial just for those people...how ever late it might seem to be.

If you we're following the series of tutorials presented here, you would recall (or not) that in first part of the tutorial Creating a Basic MIDP 2.0 Game Template you were prompted for an icon to associate with your MIDlet.


Name and Location Screen



We chose to ignore the field because it seemed trivial at the time. But I bear great news to you! Because in NetBeans you can still add an icon to your MIDlet through the Project Properties window!!! Oh, so you knew that already. Well, for those of you who don't, you can access the Project Properties from the File Menu and choosing the menu item labeled with "Your-Project-Name" Properties, with the double quotes.


Project Properties via File Menu



You can also reach the Project Properties by right-clicking on the project name from the Projects Panel treeview and selecting Properties at the bottom of the context menu.


Project Properties via Projects Panel Context Menu



Before you go adding those uber cool icons one thing you have to remember is that size does matter when it comes to MIDlet icons. Meaning the width and height of the icon. If you also read the tutorial Loading Images Into Your Game, it was mentioned that the number of colors used should be kept at a minimum, preferably at the 8-bit depth of 256 colors max. You should also avoid anti-aliased icons because some phones don't support them and will display the anti-aliased icon with "dirty" edges or with random pixels around the edges that are supposed to be semi-transparent. The PNG format is also the preferred and widely used file format for a MIDlet icon.

Here are some icon sizes you may consider:
Phone/
Model
Resolution
128x128128x160176x208208x176208x208240x320320x240352x416416x352
BlackBerry45x45
Motorola15x15
16x16
32x32
Nokia S4016x1618x18
24x24
29x29
n/an/a46x4646x48
42x29
n/an/an/a
Nokia S60
1st/2nd Edition
n/an/a42x29
29x29
n/an/an/an/a76x76n/a
Nokia S60
3rd Edition
n/an/a31x31
42x29
37x3737x3753x53
55x55
64x64
52x52
54x54
64x6476x76
84x58
Sagem18x18
Samsung16x16
29x29
32x32
Sanyo24x24
Sharp27x27
Siemens18x18
Sony Ericsson16x16
32x32
Note that most of the icon sizes for the Nokia mobile phones came from the Using Icons in Midlets technical note at Forum Nokia. Some of the additional sizes came from personally testing them on various phone models. The icon sizes for the other brands of mobile phones came from other developers experiences.

Mobile phones behave differently from one another on the way they try to display an incorrectly sized icon. Some phones will scale your icons to the right size. Other phones will display the icon as a small glyph at the upper-left corner of the area where the full sized icon should appear. The glyph displayed is so small you can barely see it. If that's the case, then you can try the next larger icon size. Some phones will also clip the icon to fit the area reserved for it like in the case of using 42x29 pixel icons on older Series 60 phones with a resolution of 176x208.

There are several ways to find out what icon size you can use. One sure way to find the size that fits your target phone is by extracting the contents of the jar file of a game or application designed for that phone. Somehow that didn't quite come out right...

If your phone supports themes or allows you to customize the skin, you can usually download a theme editor or supplemental documents for creating themes/skin for your phone and from there you can gather the information you need.


Here are some tools you can use to make the PNG images:

I won't go into details as to how to use those applications as such is beyond the scope of this tutorial. I'll just give you a screenshot of the settings I use in Fireworks. It should provide some insight on the settings you can use in other applications.

These are the settings I use on icons with a transparent background. Notice that there's only one transparent color in the pallet:

Settings for Icon with Alpha Transparency


These are the settings I use on icons with no transparency:

Settings for Icon with No Transparency



I have prepared a transparent icon for you to use in this tutorial. You can use your own work of art if you want to.

game icon
42x29 pixels


Firefox users can right-click on the image and choose Save Image As from the context menu while IE users can choose Save Picture As from the context menu. Save the PNG file inside the images folder inside the projects src. If you can't find the images folder then make one.

You can always just place the file inside the src folder and it will be listed under the Default package. But then again I find it easier to work on the game when all the images are kept inside a folder of their own.

Open the Project Properties in NetBeans and navigate your way to the MIDlets section which is listed under Application Descriptor. You will find your MIDlets listed here. Double-click on the MIDlet or select the MIDlet and click on the Edit button to the right of the list.

By now, NetBeans would have detected the new image you have saved earlier and you can simply choose it from the images listed in the combo box of the Edit MIDlet dialog box.


Edit MIDlet Dialog with Icons List



Click the "Ok" button on the Edit MIDlet dialog to confirm your selection then click the "Ok" button again in the Project Properties window to commit your changes. Press F6 to test your MIDlet in the emulator.


View of MIDlet with the Icon on the Emulator


When you run the emulator you will see the MIDlet brandishing your new icon. Hold on a second?!! Why does our 42x29 icon look squashed and squarish? That's only how the emulator displays your icon. You will only find out what it actually looks like once you have tested your MIDlet on a real phone.

I hope this tutorial have at least given you a clue of how to find your way through the murky world of MIDlet icons.

Some humble words from Forrest Grumpy:
My momma always said, "MIDlet Icons was like a box of chocolates. You never know what you're gonna get."

Was the read too long? You've got a question? Better yet, do you know a tight-fitting or well-tested MIDlet icon size that's not listed here? Don't hesitate to leave a comment.

Have fun!!!


Input Handling : Keypress with Repeat Rate

There are a lot of ways to deal with user input in your game. This tutorial will show one of the solutions that you can use on certain parts of the game. Like when your prompting the user to exit the game or not, while in the main menu, or when you want the user to choose from some options on the screen. As a warning, we're going to limit the code to using the getKeyStates() method only.


The Problem : It's Like The Keys Get Stuck..
Continues key presses are good while playing the game because the game can respond at the heat of the moment and match the users super reflexes. But not during selection screens. Why so? Let's say your game has a frame rate of 15 frames per second. That's also the speed at which it can act every time the user presses a key on the phone.

Imagine that in your game the second item from the top of the list is the View Instructions item and the current selected or highlighted item is the New Game item which is the first item on the menu. The user, trying to get to the Instructions item, presses the down button and the selection moves down from one item to the other at an alarming rate of 15 times in one second. The confused user will not be able to accurately pick items from the menu.





Better yet, imagine typing a document in a text editor and every time you hit the keyboard you get 15 of each character you type in. It would be like driving a car without breaks (No, I'm not drawing that for you!!!).


Making the Keys Toggle
In this tutorial we're going to add some interactivity to the spinning globe we made in the last tutorial : Clipping Images or Displaying Only Parts of an Image. We'll change the code so that the user can adjust the speed at which the globe spins. So load the project in NetBeans and open the clsCanvas code.

Let's declare some constants and variables. Insert this code under the clsCanvas class declaration:


public class clsCanvas extends GameCanvas implements Runnable {

// key repeat rate in milliseconds
public static final int keyDelay = 250;

//key constants
public static final int upKey = 0;
public static final int leftKey = 1;
public static final int downKey = 2;
public static final int rightKey = 3;
public static final int fireKey = 4;

//key states for up, left, down, right, and fire key
private boolean[] isDown = {
false, false, false, false, false
};

//last time the key changed state
private long[] keyTick = {
0, 0, 0, 0, 0
};

//lookup table for key constants :P
private int[] keyValue = {
GameCanvas.UP_PRESSED, GameCanvas.LEFT_PRESSED,
GameCanvas.DOWN_PRESSED, GameCanvas.RIGHT_PRESSED,
GameCanvas.FIRE_PRESSED
};




The value assigned to the constant keyDelay will determine how fast a key state changes from being pressed to not pressed while holding down a key. In other words, this will be the repeat rate. The higher the number, the slower the repeat rate gets and vice versa.

The next five constants we declared are for the 5 standard game keys Up, Left, Down, Right, and the Fire key. We just defined them so our code won't become confusing, so instead of using numbers we can use "meaningful words". Also, someone told me about 12-14 years ago that it was good practice to define constants for numbers or other fixed values your going to use repeatedly all over your code.

The boolean array isDown[] is going to hold the state for each of the standard keys we've defined while the long array keyTick[] will hold the time when a key last changed from being down to up.

The last array keyValue[], an integer array to hold the actual key codes for each key. We defined this so we can loop through each key in our key detection code which you will see in the next code section.

We'll add a new method to our clsCanvas class called checkKeys(). Add the code above the run() method:


public void checkKeys(int iKey, long currTick){
long elapsedTick = 0;

//loop through the keys
for (int i = 0; i < 5; i++){

// by default, key not pressed by user
isDown[i] = false;

// is user pressing the key
if ((iKey & keyValue[i]) != 0){
elapsedTick = currTick - keyTick[i];

//is it time to toggle key state?
if (elapsedTick >= keyDelay){

// save the current time
keyTick[i] = currTick;

// toggle the state to down or pressed
isDown[i] = true;
}
}
}
}


public void run() {



The checkKeys() method takes the value returned by the getKeyStates() method in the iKey parameter and the current time in milliseconds in the currTick parameter. It then loops through all the keys in the keyValue[] array too see if a certain key is being pressed. It then toggles the value of the appropriate element in the isDown[] array depending on how long it's been since the key was in the pressed state. It also makes sure that the isDown[] array is updated as to which keys are not being pressed.

Let's change our run() method so that when the user presses the left key the spinning animation speeds up and when the user presses the right key the animation slows down. First let's get rid of the old way we detect the fire key so that it makes use of the new code we just added. So delete or comment the following lines from the run() method, from inside the while loop:


/*
if ((iKey & GameCanvas.FIRE_PRESSED) != 0){
isRunning = false;
}
*/



Next, insert the following code under the line where we store the current time in lCurrTick so we can pass that value to the checkKeys() method:


lCurrTick = System.currentTimeMillis();

checkKeys(iKey, lCurrTick);

if (isDown[leftKey]){
if (lDelay > 0){
lDelay-=10;
}
} else if (isDown[rightKey]){
if (lDelay < 1000){
lDelay+=10;
}
} else if (isDown[fireKey]){
isRunning = false;
}




Add this next code just before the second call to setClip() so we can display some feedback when the keys are pressed:


g.drawString("lDelay : " + Long.toString(lDelay), 2, 108, Graphics.TOP | Graphics.LEFT);
if (isDown[upKey]) {
g.drawString("up key pressed", 2, 128, Graphics.TOP | Graphics.LEFT);
} else if (isDown[leftKey]) {
g.drawString("left key pressed", 2, 128, Graphics.TOP | Graphics.LEFT);
} else if (isDown[downKey]) {
g.drawString("down key pressed", 2, 128, Graphics.TOP | Graphics.LEFT);
} else if (isDown[rightKey]) {
g.drawString("right key pressed", 2, 128, Graphics.TOP | Graphics.LEFT);

}

//clip the drawing area to a single frame
g.setClip(50, 50, 16, 16);



The last code we added displays the value of lDelay so we know if it's actually getting changed. It also displays notification whenever one of the directional keys are pressed. It doesn't display feedback for the Fire key because when that is pressed the MIDlet is terminated.

Here's the completed clsCanvas source code:


package MyGame;

import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.game.GameCanvas;

public class clsCanvas extends GameCanvas implements Runnable {

// key repeat rate in milliseconds
public static final int keyDelay = 250;

//key constants
public static final int upKey = 0;
public static final int leftKey = 1;
public static final int downKey = 2;
public static final int rightKey = 3;
public static final int fireKey = 4;

//key states for up, left, down, right, and fire key
private boolean[] isDown = {
false, false, false, false, false
};

//last time the key changed state
private long[] keyTick = {
0, 0, 0, 0, 0
};

//lookup table for key constants :P
private int[] keyValue = {
GameCanvas.UP_PRESSED, GameCanvas.LEFT_PRESSED,
GameCanvas.DOWN_PRESSED, GameCanvas.RIGHT_PRESSED,
GameCanvas.FIRE_PRESSED
};

private boolean isRunning = true;
private Graphics g;
private midMain fParent;
private Image imgEarth;

public clsCanvas(midMain m) {
super(true);
fParent = m;
setFullScreenMode(true);
}

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

public void load(){
try{
// try to load the image file
imgEarth = Image.createImage("/images/earthstrip.png");
}catch(Exception ex){
// exit the app if it fails to load the image
isRunning = false;
return;
}
}

public void unload(){
// make sure the object get's destroyed
imgEarth = null;
}

public void checkKeys(int iKey, long currTick){
long elapsedTick = 0;

//loop through the keys
for (int i = 0; i < 5; i++){

// by default, key not pressed by user
isDown[i] = false;

// is user pressing the key
if ((iKey & keyValue[i]) != 0){
elapsedTick = currTick - keyTick[i];

//is it time to toggle key state?
if (elapsedTick >= keyDelay){

// save the current time
keyTick[i] = currTick;

// toggle the state to down or pressed
isDown[i] = true;
}
}
}
}

public void run() {
int iKey = 0;

int imgX = 50; // x coordinate of the image
int frameIndex = 0; // current frame to be drawn
long lDelay = 250; //time to pause between frames in milliseconds
long lStart = 0; //time we last changed frames in milliseconds
long lCurrTick = 0; // current system time in milliseconds;

load();
g = getGraphics();
while(isRunning){

iKey = getKeyStates();
/*
if ((iKey & GameCanvas.FIRE_PRESSED) != 0){
isRunning = false;
}
*/

lCurrTick = System.currentTimeMillis();

checkKeys(iKey, lCurrTick);

if (isDown[leftKey]){
if (lDelay > 0){
lDelay-=10;
}
} else if (isDown[rightKey]){
if (lDelay < 1000){
lDelay+=10;
}
} else if (isDown[fireKey]){
isRunning = false;
}

if ((lCurrTick-lStart) >= lDelay){
lStart = lCurrTick; // save the current time
if (frameIndex < 8) {
frameIndex++; // skip to the next frame
} else {
frameIndex = 0; // go back to first frame
}
imgX = 50 - (frameIndex * 16); // compute x relative to clip rect
}

//restore the clipping rectangle to full screen
g.setClip(0, 0, getWidth(), getHeight());

//set drawing color to black
g.setColor(0x000000);
//fill the whole screen
g.fillRect(0, 0, getWidth(), getHeight());
// set drawing color to white
g.setColor(0xffffff);
//display the key code last pressed
g.drawString(Integer.toString(iKey), 2, 2, Graphics.TOP | Graphics.LEFT);

g.drawString("Frame : " + Integer.toString(frameIndex), 2, 68, Graphics.TOP | Graphics.LEFT);
g.drawString("X : " + Integer.toString(imgX), 2, 88, Graphics.TOP | Graphics.LEFT);

g.drawString("lDelay : " + Long.toString(lDelay), 2, 108, Graphics.TOP | Graphics.LEFT);
if (isDown[upKey]) {
g.drawString("up key pressed", 2, 128, Graphics.TOP | Graphics.LEFT);
} else if (isDown[leftKey]) {
g.drawString("left key pressed", 2, 128, Graphics.TOP | Graphics.LEFT);
} else if (isDown[downKey]) {
g.drawString("down key pressed", 2, 128, Graphics.TOP | Graphics.LEFT);
} else if (isDown[rightKey]) {
g.drawString("right key pressed", 2, 128, Graphics.TOP | Graphics.LEFT);

}

//clip the drawing area to a single frame
g.setClip(50, 50, 16, 16);
//draw the image
g.drawImage(imgEarth, imgX, 50, Graphics.TOP | Graphics.LEFT);

flushGraphics();

try{
Thread.sleep(30);
} catch (Exception ex){

}
}
g = null;
unload();
fParent.destroyApp(false);
fParent = null;
}
}



Great! Now you can hit F6 and view the result of your work.

Output on Sun Java WTK 2.5.1




Ponts to Ponder
There are a few more things you can do to the sample code presented in this tutorial. For instance, you can add support for the other game keys or move the checkKeys() method in it's own class along with the supporting variables and even make it a static method. You can also change the value of keyDelay to that which suits you. Finally, with a few modification you can use the same technique when handling key codes from keyPressed() and keyReleased() call back methods.

Although the sample code used here is quite usable, it doesn't mean you can't do it in your own way. What matters most is that you have a general understanding of the problem and how to solve it in a simple but effective manner.

Something is not working? I got it totally wrong? You got a question? Feel free to post a comment. XD

Search the Web for Source Code with Google Code Search
If you haven't heard about it already, Google has a service called Google Code Search. Description straight from the Google Code Search FAQ:


Google Code Search helps you find function definitions and sample code by giving you one place to search publicly accessible source code hosted on the Internet. With Google Code Search, you can:

  • Use regular expressions to search more precisely

  • Restrict your search by language, license or filename

  • View the source file with links back to the entire package and the webpage where it came from



So if you're looking for that elusive A.I. algorithm or just want to see "how other people did it", just head on to Google Code Search and zero in on that code.

Additional Resources:
The Official Google Code Search Forum
The Official Google Data API Developer Forum

Tutorial Updated : Making a FullScreen Canvas
I updated the tutorial FullScreen Canvas. It seems there are some issues with using setFullScreenMode() inside the GameCanvas constructor as pointed out by an anonymous comment.

You can reach it via the tutorial links or you can simply click here : Link to Post

If you find some issues with the code presented in these tutorials, don't hesitate to post a comment about it. It will be a great help to the other readers and not to mention myself :).

Evaluate My Blog
According to the statistics I get from ClustrMaps and Google Analytics, this blog is getting a modest amount of attention from readers.

I'm quite new to blogging and started this blog because I was impressed, you might even say inspired, by the blogs that I've come across while surfing the web.

I also wanted to share what little knowledge I have on the topic this blog is based on and at the same time enhance my own understanding of the topics I write about.

But as people from all over are starting to reach this little corner of the web, I've become conscious of what impression my blog would give those visitors. Skepticism? Frustration? Eureka? Still no? I can keep on guessing forever and never find the right answer. I just want to know what I can do to improve this blog.

So tell me. What do you think about this blog?

Clipping Images or Displaying Only Parts of an Image
Sometimes you just need to display certain parts of an image. Like for instance, when you want to show some animation, It would be better to place all the animation frames inside a single image file rather than to store them in several files. This will help save some precious phone memory since you only have to load one image file into one Image object so there's no extra overhead from using multiple Image object instances.

Once again we will just be using the project we last modified in the previous tutorial : Loading Images Into Your Game.

I'm also writing this in preparation for the next tutorial which is about graphical menus where clipping plays a major part.


Reintroducing Earth: Animated
In this tutorial we're going to show earth spinning on the phone screen like the image displayed below:

Spinning Earth
Spinning Earth 16 x 16 pixels


Here is the image strip for that animation. Firefox users can right-click and choose "Save Image As" from the context menu while IE users can choose "Save Picture As" instead. Save the image inside the "images" folder of the "src" folder of the project.

Spinning Earth Image Strip
Spinning Earth animation with all frames in a single image.
Dimensions: 144 x 16 pixels
Frame Size: 16 x 16 pixels



Just in case you're wondering, both images were made from using a satellite image of earth which you can see here:


Earth from a Satellite


...which is a bit of an overkill.


Juggling Frames
What we're actually going to do is to draw one frame at a time from the image strip you just downloaded. All the while keeping the frame we want to draw inside the clipping rectangle. An illustration would be best to demonstrate what I'm trying to say:

Clipping Rectangle Illustration


The red rectangle represents the clipping rectangle and everything outside that rectangle will not be visible on the screen. The dimmed portion of the image strip represents the portion that will not be visible on the screen. The frame number being displayed is the current frame that is inside the clipping rectangle and is visible on the screen. We decrement the X of the image strip by 16 pixels to skip to the beginning of each frame going from right to left. Again the most important thing to remember about clipping rectangles is that everything outside it is invisible and everything inside it is visible.

It's now time to start NetBeans and open the project. Upon opening the project you should see the "earthstrip.png" file inside the images folder. Navigate your way to clsCanvas.java so we can start editing some code. In the load() method, change "earth.png" to "earthstrip.png".


// try to load the image file
imgEarth = Image.createImage("/images/earthstrip.png");



Let's add some variables in the run() method under the iKey declaration:


public void run() {
int iKey = 0;

int imgX = 50; // x coordinate of the image
int frameIndex = 0; // current frame to be drawn
long lDelay = 250; //time to pause between frames in milliseconds
long lStart = 0; //time we last changed frames in milliseconds
long lCurrTick = 0; // current system time in milliseconds;



Add this code inside the main loop after we check for key presses and before we call the drawing methods:


if ((iKey & GameCanvas.FIRE_PRESSED) != 0){
isRunning = false;
}


lCurrTick = System.currentTimeMillis();
if ((lCurrTick-lStart) >= lDelay){
lStart = lCurrTick; // save the current time
if (frameIndex < 8) {
frameIndex++; // skip to the next frame
} else {
frameIndex = 0; // go back to first frame
}
imgX = 50 - (frameIndex * 16); // compute x relative to clip rect
}

//restore the clipping rectangle to full screen
g.setClip(0, 0, getWidth(), getHeight());

//set drawing color to black
g.setColor(0x000000);



There's a lot happening there. First, we store the current system time in milliseconds to the lCurrTick variable. We use that to check if the time that has passed since the last time we changed the frame, lStart, is greater than the delay we set, lDelay. If so, then it's time to change frames. And since we are changing frames, we will set lStart to the current time for our delay to work on the next loop.

We have a total of 9 frames in that animation which we index starting at 0. That means the last frame would have an index of 8. So we check if the current frame index which is stored in frameIndex is the last index. If not, then we increment it by 1 frame. If it is the last frame, we then return to the first frame.

After we have figured out if it's time to change frames and what frame to display next, we can now compute the X coordinate of the image strip so the frame we want to show will be drawn inside the clipping rectangle. Here's the formula in pseudo code:


image_X = X_of_clipping_rectangle - (frame_index * frame_width);



setClip(), Not Scissors!!
You might have also noticed that we called a new method: setClip(). The setClip() method of the Graphics class is what let's us define the position and size of the clipping rectangle. The first two parameters defines the position, x and y, and the last two parameters defines the width and height of the clipping rectangle.

Let's draw some more.

Add this code in the main loop just before the call to drawImage():


g.drawString("Frame : " + Integer.toString(frameIndex), 2, 68, Graphics.TOP | Graphics.LEFT);
g.drawString("X : " + Integer.toString(imgX), 2, 88, Graphics.TOP | Graphics.LEFT);

//clip the drawing area to a single frame
g.setClip(50, 50, 16, 16);




...and modify the drawImage() function call like so:


g.drawImage(imgEarth, imgX, 50, Graphics.TOP | Graphics.LEFT);



Notice that we placed two calls to the setClip() method of the Graphics object g. The first call sets the clipping rectangles dimensions to match that of the whole screen area of the phone. The second call sets the clipping rectangle to where the animated globe will be drawn. This is because the dimensions you pass to the setClip() method the last time you call it will be in effect until you call setClip() again with a different set of parameters. This means if you don't reset the clipping rectangle, you won't be able to draw anywhere else on the screen. Anything you draw outside the clipping rectangle will not show up on the phone screen. So it's good practice to call the setClip() method with full screen dimensions at the top of your drawing code.

Your clsCanvas source code should now look like this:



package MyGame;

import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.game.GameCanvas;

public class clsCanvas extends GameCanvas implements Runnable {
private boolean isRunning = true;
private Graphics g;
private midMain fParent;
private Image imgEarth;

public clsCanvas(midMain m) {
super(true);
fParent = m;
setFullScreenMode(true);
}

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

public void load(){
try{
// try to load the image file
imgEarth = Image.createImage("/images/earthstrip.png");
}catch(Exception ex){
// exit the app if it fails to load the image
isRunning = false;
return;
}
}

public void unload(){
// make sure the object get's destroyed
imgEarth = null;
}

public void run() {
int iKey = 0;

int imgX = 50; // x coordinate of the image
int frameIndex = 0; // current frame to be drawn
long lDelay = 250; //time to pause between frames in milliseconds
long lStart = 0; //time we last changed frames in milliseconds
long lCurrTick = 0; // current system time in milliseconds;

load();
g = getGraphics();
while(isRunning){

iKey = getKeyStates();

if ((iKey & GameCanvas.FIRE_PRESSED) != 0){
isRunning = false;
}

lCurrTick = System.currentTimeMillis();
if ((lCurrTick-lStart) >= lDelay){
lStart = lCurrTick; // save the current time
if (frameIndex < 8) {
frameIndex++; // skip to the next frame
} else {
frameIndex = 0; // go back to first frame
}
imgX = 50 - (frameIndex * 16); // compute x relative to clip rect
}

//restore the clipping rectangle to full screen
g.setClip(0, 0, getWidth(), getHeight());

//set drawing color to black
g.setColor(0x000000);
//fill the whole screen
g.fillRect(0, 0, getWidth(), getHeight());
// set drawing color to white
g.setColor(0xffffff);
//display the key code last pressed
g.drawString(Integer.toString(iKey), 2, 2, Graphics.TOP | Graphics.LEFT);

g.drawString("Frame : " + Integer.toString(frameIndex), 2, 68, Graphics.TOP | Graphics.LEFT);
g.drawString("X : " + Integer.toString(imgX), 2, 88, Graphics.TOP | Graphics.LEFT);

//clip the drawing area to a single frame
g.setClip(50, 50, 16, 16);

//draw the image
g.drawImage(imgEarth, imgX, 50, Graphics.TOP | Graphics.LEFT);

flushGraphics();

try{
Thread.sleep(30);
} catch (Exception ex){

}
}
g = null;
unload();
fParent.destroyApp(false);
fParent = null;
}
}



You can start up the MIDlet now. You should see a spinning globe with the current frame and x coordinate displayed below it. You can also change the speed in which the globe rotates by increasing or decreasing the value of iDelay in the run() method. Increasing iDelay will make the animation run slower while setting it to a lower value will make the animation run faster.


SUN JAVA WTK 2.5.1


That's it for clipping. If you have a question or would like to point out a mistake, feel free to post a comment. Have fun!!!

Making a FullScreen Canvas
Updated : 10/24/2007

In this rather short tutorial, we're going to make our canvas take up the whole screen area of the phone. Open the project you created in the tutorial Basic MIDP 2.0 Game Template. Open the file clsCanvas.java then insert setFullScreenMode(true); at the end of the contructor:

public clsCanvas(midMain m) {
super(true);
fParent = m;
setFullScreenMode(true);
}



That's all there is to it.

Update
As commented by our anonymous tipper, some of you might encounter a bug while calling the setFullScreenMode() function from the constructor of the GameCanvas class.

I decided to dig deeper on this and I was able to find a post at Sun's Java Forums. One poster mentioned a problem with the SonyEricsson P900 and P910 phones. You can read the whole thread here: Link to Thread.

I will try to find more information about bugs or other weird behaviors when using the setFullScreenMode() function.


Loading Images Into Your Game

Updated : 10/22/2007

The title says it all. We're gonna load some graphics into your game. We're going to build upon the project we made in the tutorial Basic MIDP 2.0 Game Template. So better do that part first if you haven't already. I will be referring to that project as "project".


Image Format
The preferred image format is the PNG format. This is a good thing since PNG supports alpha transparency which means that the images can be anti-aliased and smoother looking. The bad news is not all phones can display images with alpha transparent pixels correctly. It depends on your target phone. But it's still better to avoid alpha transparent pixels as much as possible.


Color Depth
Take note that different phones have different color depths. The color depth of the phones today ranges from 8-bit(256colors) to 24-bit color (16,777,216 colors). What does this all mean? While your hi-res imagery looks great on phones with higher depth, they would get dithered on phones with lower color depth making the images look pixelated. Further loss of color might even make your images unrecognizable given the small screen size the game will be viewed from.

There's also only a small amount of memory available on mobile phones for you to work with and pictures that use more colors eats up more memory. So as a rule of thumb use less colors for your graphics.


Introducing earth.png
For this tutorial I've prepared a quick-and-dirty 16x16 pixel version of your home planet. W000t!! I drew a whole planet in less than 5 minutes!! It's a bit large though coz' it used up 34 colors (502 bytes).

Actual Size of Earth (16x16)

earth.png




Enlarged View of Earth (64x64)

earth.png



Open an explorer window and navigate to the folder where you saved the project and make a backup of the whole project folder just in case something goes wrong (or for historical purposes). Better yet use a VCS like CVS or VSS. NetBeans supports either (VSS via plug-in). I

After making a backup, go inside the the project folder and inside the src folder.

So if the path to your project folder is:
c:\YourDocs\netbeans\BasicGameTemplate

...the path to the src folder should be:
c:\YourDocs\netbeans\BasicGameTemplate\src

Create a new folder inside the src folder named "images". The path to which should look like this:
c:\YourDocs\netbeans\BasicGameTemplate\src\images

Firefox users can right-click on the earth.png image and choose Save Image As from the context menu. IE users can right-click on the earth.png image and choose Save Picture As from the context menu. Save the PNG file in the images folder you just created. You can save any of the images above as they are the same file.

An even easier way to create the "images" folder is to:
  1. Open the project in NetBeans.
  2. Right-click on the project name in the Projects panel.
  3. From the pop-up menu, choose New and then Folder.
  4. Type "images" as the Folder Name in the resulting dialog box.
  5. Make sure src is selected as the Parent Folder.
  6. Click on the "Finish" button.


Loading the Image
Open NetBeans and press CTRL+Shift+O. This will bring about the Open Project dialog box where you can choose the project folder. You can also click on the purple/violet colored folder icon in the main toolbar. Don't forget to set it as the main project by selecting the Open as Main Project at the right side of the dialog box. If that was the same project you had open when you closed NetBeans, the project would be automatically loaded the next time you open NetBeans.

Open Project Dialog Box


Expand the nodes of the treeview in the Projects panel. You should now see the images folder listed there and earth.png listed under that folder.

Open Project Dialog Box


You can now open the class file clsCanvas.java so we can start coding.

First we need to make a global variable to hold our image. Let's name it "imgEarth". Declare imgEarth right under the fParent declaration like so:


private midMain fParent;
private Image imgEarth;



Now would be a good time to press Shift+ALT+F to update the imports section.

Let's make a new method named load() where we will place all the code to initialize our game. This is where we actually load the image file. Place it right after the start() method like so:


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

public void load(){
try{
// try to load the image file
imgEarth = Image.createImage("/images/earth.png");
}catch(Exception ex){
// exit the app if it fails to load the image
isRunning = false;
return;
}
}




The createImage() method of the Image class is used to load the image and assign the resulting Image object to our imgEarth variable. We used the method inside an exception handling block so you can catch the exception error it generates when it fails to load the image. Just so you know, NetBeans won't let you use it without exception handling.

Let's make an unload() method where we can place all the shutdown or cleanup code our game needs. Place it after the newly created load() method:


public void load(){
try{
// try to load the image file
imgEarth = Image.createImage("/images/earth.png");
}catch(Exception ex){
// exit the app if it fails to load the image
isRunning = false;
return;
}
}

public void unload(){
// make sure the object get's destroyed
imgEarth = null;
}





Now it's time to call the new functions inside the run() method. Place the load() method under the iKey variable declaration like so:


public void run() {
int iKey = 0;
load();
g = getGraphics();




...then call the unload() method after we assign null to the g variable:


}
g = null;
unload();
fParent.destroyApp(false);



When you're done, your clsCanvas code should look like this:


package MyGame;

import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.game.GameCanvas;

public class clsCanvas extends GameCanvas implements Runnable {
private boolean isRunning = true;
private Graphics g;
private midMain fParent;
private Image imgEarth;

public clsCanvas(midMain m) {
super(true);
fParent = m;
setFullScreenMode(true);
}

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

public void load(){
try{
// try to load the image file
imgEarth = Image.createImage("/images/earth.png");
}catch(Exception ex){
// exit the app if it fails to load the image
isRunning = false;
return;
}
}

public void unload(){
// make sure the object get's destroyed
imgEarth = null;
}

public void run() {
int iKey = 0;
load();
g = getGraphics();
while(isRunning){

iKey = getKeyStates();

if ((iKey & GameCanvas.FIRE_PRESSED) != 0){
isRunning = false;
}

//set drawing color to black
g.setColor(0x000000);
//fill the whole screen
g.fillRect(0, 0, getWidth(), getHeight());
// set drawing color to white
g.setColor(0xffffff);
//display the key code last pressed
g.drawString(Integer.toString(iKey), 2, 2, Graphics.TOP | Graphics.LEFT);
flushGraphics();

try{
Thread.sleep(30);
} catch (Exception ex){

}
}
g = null;
unload();
fParent.destroyApp(false);
fParent = null;
}
}




Drawing the Image
To draw the image on the screen insert this line of code inside the run() method just before the flushGraphics() function call:



//draw the image
g.drawImage(imgEarth, 50, 50, Graphics.TOP | Graphics.LEFT);

flushGraphics();





The drawImage() method of the Graphics object g is used to draw the image unto our canvas at the coordinates 50(X), 50(Y). The last parameter, Graphics.Top | Graphics.Left, defines the anchor point or part of the image that will reside at the given coordinates. In this example the top-left part of the image will be positioned at coordinates 50,50 , X and Y respectively.

The completed clsCanvas source code:


package MyGame;

import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.game.GameCanvas;

public class clsCanvas extends GameCanvas implements Runnable {
private boolean isRunning = true;
private Graphics g;
private midMain fParent;
private Image imgEarth;

public clsCanvas(midMain m) {
super(true);
fParent = m;
setFullScreenMode(true);
}

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

public void load(){
try{
// try to load the image file
imgEarth = Image.createImage("/images/earth.png");
}catch(Exception ex){
// exit the app if it fails to load the image
isRunning = false;
return;
}
}

public void unload(){
// make sure the object get's destroyed
imgEarth = null;
}

public void run() {
int iKey = 0;
load();
g = getGraphics();
while(isRunning){

iKey = getKeyStates();

if ((iKey & GameCanvas.FIRE_PRESSED) != 0){
isRunning = false;
}

//set drawing color to black
g.setColor(0x000000);
//fill the whole screen
g.fillRect(0, 0, getWidth(), getHeight());
// set drawing color to white
g.setColor(0xffffff);
//display the key code last pressed
g.drawString(Integer.toString(iKey), 2, 2, Graphics.TOP | Graphics.LEFT);

//draw the image
g.drawImage(imgEarth, 50, 50, Graphics.TOP | Graphics.LEFT);

flushGraphics();

try{
Thread.sleep(30);
} catch (Exception ex){

}
}
g = null;
unload();
fParent.destroyApp(false);
fParent = null;
}
}




Whenever your ready you can hit F6 on your keyboard and start the MIDlet when the emulator pops up. You should see the something like the screeny below.


Screen Shot of Output


Got an error? Something could've been done better? --> Post a comment.

Update
The code in this tutorial now runs in fullscreen mode. Details can be found here : Making a FullScreen Canvas

Overflow Madness
I've updated the blog design and it should now work in IE....hopefully.
I think I can continue updating the rest of the blog.

Blog Design Glitch
The custom blog template I came up with seems to behave differently in IE for some reason I can't figure out. I'm using a normal template for the time being while I fix the template for this blog.

Basic MIDP 2.0 Game Template Part 3

Jump to part: 1 | 2 | 3

Displaying the GameCanvas

In this last part of the tutorial entitled Basic Game Template, we will modify the code of our MIDlet and Canvas classes to make the both ends meet and the application to run. It is recommended that you start with Part 1 of this tutorial if you haven't done so.

First, we'll need to add a new global variable to reference the MIDlet from the canvas class. Let's call it fParent. So add this code to clsCanvas like so:

private Graphics g;
private midMain fParent;



Modify the contructor to accept the MIDlet class as a parameter and assign the value to our global variable:

public clsCanvas(midMain m) {
super(true);
fParent = m;
}


The canvas needs a way to notify the MIDlet that the main loop has ended and the program needs to terminate. Add this code at the end of our run() method:

}
g = null;
fParent.destroyApp(false);
fParent = null;

}



We need a new method that the MIDlet can call to start the game thread. Let's call it the start() method and add the code under the clsCanvas constructor:


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



You should press Shift+ALT+F after editing the code...just in case.

Here's the completed clsCanvas source code:

package MyGame;

import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.game.GameCanvas;

public class clsCanvas extends GameCanvas implements Runnable {
private boolean isRunning = true;
private Graphics g;
private midMain fParent;

public clsCanvas(midMain m) {
super(true);
fParent = m;
}

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


public void run() {
int iKey = 0;
g = getGraphics();
while(isRunning){

iKey = getKeyStates();

if ((iKey & GameCanvas.FIRE_PRESSED) != 0){
isRunning = false;
}

//set drawing color to black
g.setColor(0x000000);
//fill the whole screen
g.fillRect(0, 0, getWidth(), getHeight());
// set drawing color to white
g.setColor(0xffffff);
//display the key code last pressed
g.drawString(Integer.toString(iKey), 2, 2, Graphics.TOP | Graphics.LEFT);
flushGraphics();

try{
Thread.sleep(30);
} catch (Exception ex){

}
}
g = null;
fParent.destroyApp(false);
fParent = null;

}
}



Now open the source code of our MIDlet. We will define a new global variable called myCanvas that will allow the MIDlet to create and reference the clsCanvas class. Place the code just under the midMain class declaration:

public class midMain extends MIDlet {
clsCanvas myCanvas;



Next, we will modify the startApp() method of our midlet so that it creates a new instance of the clsCanvas class, starts it in a new thread, and finally making the the canvas the current displayed item. Add this code to the startApp() method:

public void startApp() {
Display d = Display.getDisplay(this);
myCanvas = new clsCanvas(this);
myCanvas.start();
d.setCurrent(myCanvas);

}



The last code we will add is for making sure we release all the resources our MIDlet has used and terminate gracefully when your game has ended. Place this code in the destroyApp() method:

public void destroyApp(boolean unconditional) {
myCanvas = null;
notifyDestroyed();

}



Here's the completed midMain source code:

package MyGame;

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

public class midMain extends MIDlet {
clsCanvas myCanvas;

public void startApp() {
Display d = Display.getDisplay(this);
myCanvas = new clsCanvas(this);
myCanvas.start();
d.setCurrent(myCanvas);

}

public void pauseApp() {
}

public void destroyApp(boolean unconditional) {
myCanvas = null;
notifyDestroyed();

}
}



Yay! We're done! You can now test your by pressing the F6 key on your keyboard or clicking on the Run Main Project icon on the toolbar. That ends our tutorial on creating a basic template for your game. I will also be using this template for the rest of the tutorials that will be posted here. If you have some comments, suggestions or having problem with the source code, feel free to leave a comment or use the ShoutBox. Have fun.