Example: Using 3D graphics in application development

The example developed in this tutorial is a maze traversing game.

In the game, the player sees the world from a traditional, first-person point of view and walks around the maze. The objective is to solve the maze in a minimum amount of time. The game doesn't use any complicated geometry; everything is built using planes. The objects in the game are basically the floor and the maze walls. Two labels were also added to indicate the start and end of the maze. The end marker is animated, moving up and down the y axis. The scene has a background sky simulating a star field. The player is located where the main camera is, as s/he moves around the maze. The maze's floor is located in the xz plane. The figure below shows what the game looks like.

Figure 58: Normal view

As an aid to the player, there is a second camera, which is located high in the y axis and looks down on the maze. This camera can be used to view the maze from the top. It is complemented by a small square that indicates the player's location.

Figure 59: Top view

Another aid for the player is the ability to make walls semitransparent. By pressing the Fire button, the wall in front of the player is made semitransparent. The next time the player moves, the wall returns to the normal view.

Figure 60: Semitransparent wall

The game is designed for MIDP 2.0, and uses the GameCanvas class. It contains a thread that is running continuously:

while(playing)
{
 checkInput();
 draw3D();
 draw2D();
 flushGraphics();
}

The method checkInput will verify the state of the keys and update the player's position if necessary. The player can move forward and backward, and rotate to the right or left. The player position will be used to update the main camera's location. If the Fire button is pressed, the nearest wall in front of the player will be selected and made semitransparent.

In method draw3D, the scene graph is rendered by binding the target, advancing the animation, and calling render(world), as follows:

    try
    {
      g3d.bindTarget(g); 
      binded = true;
      world.animate((int)(System.currentTimeMillis() - gameStart));
      g3d.render(world);
    }
    finally
    {
      // release the target
      if (binded)
      {
        g3d.releaseTarget();
      }
    }

The method draw2D in turn will write text to the upper and lower parts of the screen. It is important to do the 2-D drawing after the 3-D rendering is ready, since upon clearing the 3-D buffers the 2-D part will be removed. It is also important not to mix 2-D and 3-D Graphics while the target is bound. Although M3G does not forbid it, performing 2-D drawing commands onto a Graphics object while bound has unpredictable results.