Dungeon game : Game « J2ME « Java

Java
1. 2D Graphics GUI
2. 3D
3. Advanced Graphics
4. Ant
5. Apache Common
6. Chart
7. Collections Data Structure
8. Database SQL JDBC
9. Design Pattern
10. Development Class
11. Email
12. Event
13. File Input Output
14. Game
15. Hibernate
16. J2EE
17. J2ME
18. JDK 6
19. JSP
20. JSTL
21. Language Basics
22. Network Protocol
23. PDF RTF
24. Regular Expressions
25. Security
26. Servlets
27. Spring
28. Swing Components
29. Swing JFC
30. SWT JFace Eclipse
31. Threads
32. Tiny Application
33. Velocity
34. Web Services SOA
35. XML
Microsoft Office Word 2007 Tutorial
Java Tutorial
Java Source Code / Java Documentation
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
C# / C Sharp
C# / CSharp Tutorial
ASP.Net
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
PHP
Python
SQL Server / T-SQL
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Java » J2ME » GameScreenshots 
Dungeon game

/*
 Title:  J2ME Games With MIDP2
 Authors:  Carol Hamer
 Publisher:  Apress
 ISBN:   1590593820
 */

import java.io.*;

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

/**
 * This is the main class of the dungeon game.
 
 @author Carol Hamer
 */
public class Dungeon extends MIDlet implements CommandListener {

  //-----------------------------------------------------
  //    game object fields

  /**
   * The canvas that the dungeon is drawn on.
   */
  private DungeonCanvas myCanvas;

  /**
   * the thread that advances the game clock.
   */
  private GameThread myGameThread;

  //-----------------------------------------------------
  //    command fields

  /**
   * The button to exit the game.
   */
  private Command myExitCommand = new Command("Exit", Command.EXIT, 99);

  /**
   * The command to save the game in progress.
   */
  private Command mySaveCommand = new Command("Save Game", Command.SCREEN, 2);

  /**
   * The command to restore a previously saved game.
   */
  private Command myRestoreCommand = new Command("Restore Game",
      Command.SCREEN, 2);

  /**
   * 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("Next Board", Command.SCREEN, 1);

  //-----------------------------------------------------
  //    initialization and game state changes

  /**
   * Initialize the canvas and the commands.
   */
  public Dungeon() {
    try {
      // create the canvas and set up the commands:
      myCanvas = new DungeonCanvas(this);
      myCanvas.addCommand(myExitCommand);
      myCanvas.addCommand(mySaveCommand);
      myCanvas.addCommand(myRestoreCommand);
      myCanvas.addCommand(myPauseCommand);
      myCanvas.setCommandListener(this);
    catch (Exception e) {
      // if there's an error during creation, display it as an alert.
      errorMsg(e);
    }
  }

  /**
   * Switch the command to the play again command. (removing other commands
   * that are no longer relevant)
   */
  void setNewCommand() {
    myCanvas.removeCommand(myPauseCommand);
    myCanvas.removeCommand(myGoCommand);
    myCanvas.addCommand(myNewCommand);
  }

  /**
   * Switch the command to the go command. (removing other commands that are
   * no longer relevant)
   */
  void setGoCommand() {
    myCanvas.removeCommand(myPauseCommand);
    myCanvas.removeCommand(myNewCommand);
    myCanvas.addCommand(myGoCommand);
  }

  /**
   * Switch the command to the pause command. (removing other commands that
   * are no longer relevant)
   */
  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 we always check fields for null
  // before calling methods on them.

  /**
   * Start the application.
   */
  public void startApp() throws MIDletStateChangeException {
    if (myCanvas != null) {
      if (myGameThread == null) {
        // create the thread and start the game:
        myGameThread = new GameThread(myCanvas);
        myCanvas.start();
        myGameThread.start();
      else {
        // in case this gets called again after
        // the application has been started once:
        myCanvas.removeCommand(myGoCommand);
        myCanvas.addCommand(myPauseCommand);
        myCanvas.flushKeys();
        myGameThread.resumeGame();
      }
    }
  }

  /**
   * Stop the threads and throw out the garbage.
   */
  public void destroyApp(boolean unconditional)
      throws MIDletStateChangeException {
    myCanvas = null;
    if (myGameThread != null) {
      myGameThread.requestStop();
    }
    myGameThread = null;
    System.gc();
  }

  /**
   * Pause the game.
   */
  public void pauseApp() {
    if (myCanvas != null) {
      setGoCommand();
    }
    if (myGameThread != null) {
      myGameThread.pause();
    }
  }

  //----------------------------------------------------------------
  //  implementation of CommandListener

  /*
   * Respond to a command issued on the Canvas. (reset, exit, or change size
   * prefs).
   */
  public void commandAction(Command c, Displayable s) {
    try {
      if (c == myGoCommand) {
        myCanvas.setNeedsRepaint();
        myCanvas.removeCommand(myGoCommand);
        myCanvas.addCommand(myPauseCommand);
        myCanvas.flushKeys();
        myGameThread.resumeGame();
      else if (c == myPauseCommand) {
        myCanvas.setNeedsRepaint();
        myCanvas.removeCommand(myPauseCommand);
        myCanvas.addCommand(myGoCommand);
        myGameThread.pause();
      else if (c == myNewCommand) {
        myCanvas.setNeedsRepaint();
        // go to the next board and restart the game
        myCanvas.removeCommand(myNewCommand);
        myCanvas.addCommand(myPauseCommand);
        myCanvas.reset();
        myGameThread.resumeGame();
      /*} else if (c == Alert.DISMISS_COMMAND) {
        // if there was a serious enough error to
        // cause an alert, then we end the game
        // when the user is done reading the alert:
        // (Alert.DISMISS_COMMAND is the default
        // command that is placed on an Alert
        // whose timeout is FOREVER)
        destroyApp(false);
        notifyDestroyed();*/
      else if (c == mySaveCommand) {
        myCanvas.setNeedsRepaint();
        myCanvas.saveGame();
      else if (c == myRestoreCommand) {
        myCanvas.setNeedsRepaint();
        myCanvas.removeCommand(myNewCommand);
        myCanvas.removeCommand(myGoCommand);
        myCanvas.addCommand(myPauseCommand);
        myCanvas.revertToSaved();
      else if (c == myExitCommand) {
        destroyApp(false);
        notifyDestroyed();
      }
    catch (Exception e) {
      errorMsg(e);
    }
  }

  //-------------------------------------------------------
  //  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 class represents doors and keys.
 
 @author Carol Hamer
 */

class DoorKey extends Sprite {

  //---------------------------------------------------------
  //    fields

  /**
   * The image file shared by all doors and keys.
   */
  public static Image myImage;

  /**
   * A code int that indicates the door or key's color.
   */
  private int myColor;

  //---------------------------------------------------------
  //    get/set data

  /**
   @return the door or key's color.
   */
  public int getColor() {
    return (myColor);
  }

  //---------------------------------------------------------
  //    constructor and initializer

  static {
    try {
      myImage = Image.createImage("/images/keys.png");
    catch (Exception e) {
      throw (new RuntimeException(
          "DoorKey.<init>-->failed to load image, caught "
              + e.getClass() ": " + e.getMessage()));
    }
  }

  /**
   * Standard constructor sets the image to the correct frame (according to
   * whether this is a door or a key and what color it should be) and then
   * puts it in the correct location.
   */
  public DoorKey(int color, boolean isKey, int[] gridCoordinates) {
    super(myImage, DungeonManager.SQUARE_WIDTH, DungeonManager.SQUARE_WIDTH);
    myColor = color;
    int imageIndex = color * 2;
    if (isKey) {
      imageIndex++;
    }
    setFrame(imageIndex);
    setPosition(gridCoordinates[0* DungeonManager.SQUARE_WIDTH,
        gridCoordinates[1* DungeonManager.SQUARE_WIDTH);
  }

}

/**
 * This class is a set of simple utility functions that can be used to convert
 * standard data types to bytes and back again. It is used especially for data
 * storage, but also for sending and receiving data.
 
 @author Carol Hamer
 */

class DataConverter {

  //--------------------------------------------------------
  //  utilities to encode small, compactly-stored small ints.

  /**
   * Encodes a coordinate pair into a byte.
   
   @param coordPair
   *            a pair of integers to be compacted into a single byte for
   *            storage. WARNING: each of the two values MUST BE between 0 and
   *            15 (inclusive). This method does not verify the length of the
   *            array (which must be 2!) nor does it verify that the ints are
   *            of the right size.
   */
  public static byte encodeCoords(int[] coordPair) {
    // get the byte value of the first coordinate:
    byte retVal = (new Integer(coordPair[0])).byteValue();
    // move the first coordinate's value up to the top
    // half of the storage byte:
    retVal = (new Integer(retVal << 4)).byteValue();
    // store the second coordinate in the lower half
    // of the byte:
    retVal += (new Integer(coordPair[1])).byteValue();
    return (retVal);
  }

  /**
   * Encodes eight ints into a byte. This could be easily modified to encode
   * eight booleans.
   
   @param eight
   *            an array of at least eight ints. WARNING: all values must be 0
   *            or 1! This method does not verify that the values are in the
   *            correct range nor does it verify that the array is long
   *            enough.
   @param offset
   *            the index in the array eight to start reading data from.
   *            (should usually be 0)
   */
  public static byte encode8(int[] eight, int offset) {
    // get the byte value of the first int:
    byte retVal = (new Integer(eight[offset])).byteValue();
    // progressively move the data up one bit in the
    // storage byte and then record the next int in
    // the lowest spot in the storage byte:
    for (int i = offset + 1; i < + offset; i++) {
      retVal = (new Integer(retVal << 1)).byteValue();
      retVal += (new Integer(eight[i])).byteValue();
    }
    return (retVal);
  }

  //--------------------------------------------------------
  //  utilities to decode small, compactly-stored small ints.

  /**
   * Turns a byte into a pair of coordinates.
   */
  public static int[] decodeCoords(byte coordByte) {
    int[] retArray = new int[2];
    // we perform a bitwise and with the value 15
    // in order to just get the bits of the lower
    // half of the byte:
    retArray[1= coordByte & 15;
    // To get the bits of the upper half of the
    // byte, we perform a shift to move them down:
    retArray[0= coordByte >> 4;
    // bytes in Java are generally assumed to be
    // signed, but in this coding algorithm we
    // would like to treat them as unsigned:
    if (retArray[00) {
      retArray[0+= 16;
    }
    return (retArray);
  }

  /**
   * Turns a byte into eight ints.
   */
  public static int[] decode8(byte data) {
    int[] retArray = new int[8];
    // The flag allows us to look at each bit individually
    // to determine if it is 1 or 0. The number 128
    // corresponds to the highest bit of a byte, so we
    // start with that one.
    int flag = 128;
    // We use a loop that checks
    // the data bit by bit by performing a bitwise
    // and (&) between the data byte and a flag:
    for (int i = 0; i < 8; i++) {
      if ((flag & data!= 0) {
        retArray[i1;
      else {
        retArray[i0;
      }
      // move the flag down one bit so that we can
      // check the next bit of data on the next pass
      // through the loop:
      flag = flag >> 1;
    }
    return (retArray);
  }

  //--------------------------------------------------------
  //  standard integer interpretation

  /**
   * Uses an input stream to convert an array of bytes to an int.
   */
  public static int parseInt(byte[] datathrows IOException {
    DataInputStream stream = new DataInputStream(new ByteArrayInputStream(
        data));
    int retVal = stream.readInt();
    stream.close();
    return (retVal);
  }

  /**
   * Uses an output stream to convert an int to four bytes.
   */
  public static byte[] intToFourBytes(int ithrows IOException {
    ByteArrayOutputStream baos = new ByteArrayOutputStream(4);
    DataOutputStream dos = new DataOutputStream(baos);
    dos.writeInt(i);
    baos.close();
    dos.close();
    byte[] retArray = baos.toByteArray();
    return (retArray);
  }

  //--------------------------------------------------------
  //  integer interpretation illustrated

  /**
   * Java appears to treat a byte as being signed when returning it as an
   * int--this function converts from the signed value to the corresponding
   * unsigned value. This method is used by nostreamParseInt.
   */
  public static int unsign(int signed) {
    int retVal = signed;
    if (retVal < 0) {
      retVal += 256;
    }
    return (retVal);
  }

  /**
   * Takes an array of bytes and returns an int. This version will return the
   * same value as the method parseInt above. This version is included in
   * order to illustrate how Java encodes int values in terms of bytes.
   
   @param data
   *            an array of 1, 2, or 4 bytes.
   */
  public static int nostreamParseInt(byte[] data) {
    // byte 0 is the high byte which is assumed
    // to be signed. As we add the lower bytes
    // one by one, we unsign them because because
    // a single byte alone is interpreted as signed,
    // but in an int only the top byte should be signed.
    // (note that the high byte is the first one in the array)
    int retVal = data[0];
    for (int i = 1; i < data.length; i++) {
      retVal = retVal << 8;
      retVal += unsign(data[i]);
    }
    return (retVal);
  }

  /**
   * Takes an arbitrary int and returns an array of four bytes. This version
   * will return the same byte array as the method intToFourBytes above. This
   * version is included in order to illustrate how Java encodes int values in
   * terms of bytes.
   */
  public static byte[] nostreamIntToFourBytes(int i) {
    byte[] fourBytes = new byte[4];
    // when you take the byte value of an int, it
    // only gives you the lowest byte. So we
    // get all four bytes by taking the lowest
    // byte four times and moving the whole int
    // down by one byte between each one.
    // (note that the high byte is the first one in the array)
    fourBytes[3(new Integer(i)).byteValue();
    i = i >> 8;
    fourBytes[2(new Integer(i)).byteValue();
    i = i >> 8;
    fourBytes[1(new Integer(i)).byteValue();
    i = i >> 8;
    fourBytes[0(new Integer(i)).byteValue();
    return (fourBytes);
  }

  /**
   * Takes an int between -32768 and 32767 and returns an array of two bytes.
   * This does not verify that the argument is of the right size. If the
   * absolute value of i is too high, it will not be encoded correctly.
   */
  public static byte[] nostreamIntToTwoBytes(int i) {
    byte[] twoBytes = new byte[2];
    // when you take the byte value of an int, it
    // only gives you the lowest byte. So we
    // get the lower two bytes by taking the lowest
    // byte twice and moving the whole int
    // down by one byte between each one.
    twoBytes[1(new Integer(i)).byteValue();
    i = i >> 8;
    twoBytes[0(new Integer(i)).byteValue();
    return (twoBytes);
  }

}
/**
 * This class contains the data for the map of the dungeon..
 
 @author Carol Hamer
 */

class BoardDecoder {

  //--------------------------------------------------------
  //  fields

  /**
   * The coordinates of where the player starts on the map in terms of the
   * array indices.
   */
  private int[] myPlayerSquare;

  /**
   * The coordinates of the goal (crown).
   */
  private int[] myGoalSquare;

  /**
   * The coordinates of the doors. the there should be two in a row of each
   * color, following the same sequence as the keys.
   */
  private int[][] myDoors;

  /**
   * The coordinates of the Keys. the there should be of each color, following
   * the same sequence as the doors.
   */
  private int[][] myKeys;

  /**
   * The coordinates of the stone walls of the maze, encoded bit by bit.
   */
  private TiledLayer myLayer;

  /**
   * The data in bytes that gives the various boards. This was created using
   * EncodingUtils... This is a two-dimensional array: Each of the four main
   * sections corresponds to one of the four possible boards.
   */
  private static byte[][] myData = {
      00, -108, -100, -2465215853, -54, -116, -58, -56, -84,
          115, -118, -1, -1, -1281, -103, -15, -12825, -97, -127,
          -12879, -141, -126121, -1221, -113, -49, -1161,
          -100, -3, -1245, -25, -27, -1281, -1, -},
      0112290, -6234, -4372, -59, -2956, -5598126, -79,
          61, -1, -1, -1251, -12817, -2629, -3157, -721,
          -128, -51, -10065, -12457, -21, -12613, -1131,
          -9725, -127, -99, -81, -1, -},
      02108, -2418, -2610230, -5846, -28, -8834, -9897,
          -41, -1, -1, -961, -12657, -997, -12769, -11973,
          -1271, -10959, -1261, -26103, -12765, -103115,
          -12765, -2573, -1281, -1, -},
      03, -11418, -3427, -39, -60, -76, -501189082, -88,
          34, -74, -1, -1, -661, -128121, -26125, -128, -123,
          -10329, -1121, -10949, -1121, -116, -31, -1285,
          -1225, -3213, -127, -51, -1251, -1, -}};

  //--------------------------------------------------------
  //  initialization

  /**
   * Constructor fills data fields by interpreting the data bytes.
   */
  public BoardDecoder(int boardNumthrows Exception {
    // we start by selecting the two dimensional
    // array corresponding to the desired board:
    byte[] data = myData[boardNum];
    // The first two bytes give the version number and
    // the board number, but we ignore them because
    // they are assumed to be correct.
    // The third byte of the first array is the first one
    // we read: it gives the player's starting coordinates:
    myPlayerSquare = DataConverter.decodeCoords(data[2]);
    // the next byte gives the coordinates of the crown:
    myGoalSquare = DataConverter.decodeCoords(data[3]);
 &