Gidlet
 
 


Forth example

Purpose: Since MPanel is derived from javax.microedition.lcdui.game.GameCanvas it's easy to use sprites for animated graphics. The sprite image is stored as frame that is part of an image that contains several frames of the same size. Some useful transformations are available such as flipping and rotation. A sprite collision detection mechanism is available that simplifies the construction of animated games. In the following example a series of sprite images are repeatedly shown.

// SpriteFrameGidlet.java

import ch.aplu.gidlet.*;
import javax.microedition.lcdui.game.*;

public class SpriteFrameGidlet extends Gidlet
{
  public void main()
  {
    String res = "/res/teacher.png";
    int frameWidth = 54;
    int frameHeight = 74;

    MPanel p = new MPanel();
    Sprite teacher = 
      p.
getSprite(res, 
                  frameWidth, frameHeight
);
    p.bgColor(MAGENTA);
    if (teacher == null)
    {
      p._label("Can't load sprite image", 10);       return;
    }

    int ulx = 
      
(p._displayWidth() - frameWidth) / 2;
    int uly = 
      
(p._displayHeight() - frameHeight) / 2;
    p.enableFlush(false);
    while (!isExiting())
    {
      p._drawSprite(teacher, ulx, uly);
      p.flush();
      delay(200);
      p.clear();
      teacher.nextFrame();
    }
  }
}

Execute SpriteFrameGidlet (if you have the Sun's Wireless Toolkit (WTK) installed and the JAD extension registered. Learn how to register the JAD extension)

Discussion: The image file teacher.png resides in the subdirectory res of the class root and should be packed into the MIDlet distribution jar file. It contains 12 sprite images of the same size.

   Download teacher.png

In order to create a smooth animation, the following steps are necessary:

  • call enableFlush(false) to disable the automatic flushing of the offscreen buffer to the screen window when drawing into the MPanel. In the body of the while-loop do:
  • Draw the sprite at a given position (upper left corner) into the offscreen buffer using drawSprite()(window coordinates) or _drawSprite() (pixel coordinates) respectively
  • Flush the buffer to the screen and wait a moment
  • Clear the offscreen buffer (but not the screen window)
  • Advance to the next frame
  • Test with isExiting(), if the Exit soft button is hit in order to terminate the endless loop

Fifth example

Purpose: Because MForm is derived from Form, any of the usual GUI elements may be added to it. In the following example a ChoiceGroup is shown where the user may select one of the predefined system audio clips.

// ChoiceGidlet.java

import javax.microedition.lcdui.*;
import ch.aplu.gidlet.*;

public class ChoiceGidlet extends Gidlet 
   implements
 ItemStateListener
{
  private ChoiceGroup cg =
    new ChoiceGroup("Choose a sound"
                     Choice
.EXCLUSIVE);
  public void main()
  {
    cg.append("Confirmation"null);
    cg.append("Info"null);
    cg.append("Warning"null);
    cg.append("Alarm"null);
    cg.append("Error"null);

    MForm f = new MForm();
    f.setItemStateListener(this);
    f.append(cg);
    f.show();
  }

  public void itemStateChanged(Item item)
 
 {
    switch (cg.getSelectedIndex())
    {
      case 0:
        AlertType.INFO.playSound(display);
        break;
      case 1:
        AlertType.CONFIRMATION.playSound(display);
        break;
      case 2:
        AlertType.WARNING.playSound(display);
        break;
      case 3:
        AlertType.ALARM.playSound(display);
        break;
      case 4:
        AlertType.ERROR.playSound(display);
        break;
    }
  }
}

Execute ChoiceGidlet (if you have the Sun's Wireless Toolkit (WTK) installed and the JAD extension registered. Learn how to register the JAD extension)

Discussion: If an ItemStateListener is registered, the callback method itemStateChanged() is triggered whenever the selection in the ChoiceGroup is changed. When running the phone emulator, use the cursor up/down key to change the group item and confirm the selection with the enter key.

 

Sixth example

Purpose: The full set of Logo-like commands are implemented in the Turtle class. Since the famous work of Seymour Papert the Logo turtle is used from introductory courses in elementary schools to programming and math courses at university level. Turtle graphics combined with recursions let you create very easily the famous fractal pictures (Mandelbrot set, Julia set, Peano curve, etc.). Programming with the turtle is a great mental training for everyone and much fun due to the dynamic and esthetic outcome.

In the following example the famous space-filling Hilbert curve is drawn.

// HilbertGidlet.java

import ch.aplu.gidlet.*;

public class HilbertGidlet extends Gidlet      
{
  private Turtle t = 
               
new Turtle("Hilbert Curve");

  public void main()
  {
    fig(5590);
  }

  private void fig(int n, int s, int w)
  {
    if (== 0)
      return;
    t.lt(w);
    fig(- 1, s, -w);
    t.fd(s);
    t.rt(w);
    fig(- 1, s, w);
    t.fd(s);
    fig(- 1, s, w);
    t.rt(w);
    t.fd(s);
    fig(- 1, s, -w);
    t.lt(w);
  }
}

Execute HilbertGidlet (if you have the Sun's Wireless Toolkit (WTK) installed and the JAD extension registered. Learn how to register the JAD extension)

Discussion: For an explanation of the highly recursive algorithm consult Internet resources. The Turtle may be instantiated (globally) as class instance variable. Transparent to the user, the initialization is deferred until main() starts.

 

Seventh example

Purpose: Mobile devices are more than just mobile phones. They are often used as portable music player. The Gidlet frameworks includes the class AudioPlayer that is a simple wrapper for the class Player in the Multimedia API (MMAPI) of JavaME.

The following example simulates the usual command buttons of a real player: start to start playing from beginning or to resume playing after the pause command, pause to suspend playing for a while, stop to stop playing.

// PlayAudioGidlet.java

import ch.aplu.gidlet.*;

public class PlayAudioGidlet extends Gidlet
{
  private MList list;
  private AudioPlayer ap = null;
  private final String uri = 
    "http://www.aplu.ch/g/b.wav";

  public void main()
  {
    setDebug(true);
    list = new MList("AudioPlayer");
    list.setTitle("Loading. Please wait...");
    list.show();
    ap = new AudioPlayer(uri);
    if (ap.getPlayer() == null)
    {
      showMessage(
        "Access to the internet denied", false);
      return;
    }

    list.append("Start"null);
    list.append("Pause"null);
    list.append("Stop"null);
    list.setTitle("Ready");

    while (true)
    {
      waitOk();
      int index = list.getSelectedIndex();
      switch (index)
      {
        case 0:
          ap.start();
          list.setTitle("Playing...");
          break;
        case 1:
          ap.pause();
          list.setTitle("Pausing...");
          break;
        case 2:
          ap.stop();
          list.setTitle("Stopped");
          break;
      }
    }
  }

  public void doExit()
  {
    if (ap == null)
      return;
    ap.close();
    super.doExit();
  }

  public void notifyPlayerUpdate(String event, Object eventData)
  {
    if (event.equals("readyToStart"))
      list.setTitle("Ready to start");
    if (event.equals("endOfMedia"))
      list.setTitle("Finished");
  }
}

Execute PlayAudioGidlet (if you have the Sun's Wireless Toolkit (WTK) installed and the JAD extension registered. Learn how to register the JAD extension)

Discussion: An instance of AudioPlayer creates the MMAPI Player and opens the connection to the audio resources and the output sound device. To avoid blocking, all work is done in a separate thread. doExit() must release all resources by calling close(). The callback method notifyPlayerUpdate() is called each time when the player's state changes. It may be used to inform the user when the playing is over.

Be aware that it takes some time to load a big wav file from the internet. When running on a real device, it may cost you a lot of money!