MAIN MENU           BIODATA              ASSIGNMENTS                 TUTORIALS                EMAILS

DISTRIBUTED SYSTEMS (TCT 2034)

ASSIGNMENT 6

( INTERACTIVE GAME )

QUESTION:

Write a game and allow the students to play the game in a distributed environment. You can write any kind of interactive game .

 

Answer:

/*

* Main.java

* Created on February 17, 2001, 12:51 AM

*/

 import javax.swing.*;

/**

* This class is the starting proint of the program.

*

* @author Sammy Leong

* @version 1.0

*/

public class Main

{

    public static BomberMain bomberMain = null;

 

    /** relative path */

    public static final String RP = "./";

    /** flag: whether current machine's java runtime is version 2 or not */

    public static boolean J2 = false;

 

    static {

        /** get java runtime version */

        String version = System.getProperty("java.version");

        /** parse it */

        int major = Integer.parseInt(version.substring(0, 1));

        int minor = Integer.parseInt(version.substring(2, 3));

        /** if major is greater than or equal to 1 and */

        /** if minor is greater than or equal to 3 */

        /** then it's Java 2 */

        if (major >= 1 && minor >= 2)

           J2 = true;

    }

 

      /**

       * Starts Bomberman

       */

       public static void startBomberman() {

        bomberMain = new BomberMain();

       }

 

    /**

    * Starts the program by creating an instance of MainFrame.

    */

    public static void main(String[] args)

    {

        boolean bombermanMode = false;

        boolean badArg = false;

        /** default look and feel: metal */

        int lookAndFeel = 1;

        /** check supplied parameters (if any) */

        for (int i = 0; i < args.length; i++) {

            /** if "bomberman" parameter is supplied */

            if (args[i].equals("Bomberman") || args[i].equals("bomberman"))

               bombermanMode = true;

            /** if look and feel parameter is supplied */

            if (args[i].startsWith("-l")) {

               if (args[i].substring(2).equals("System")) lookAndFeel = 0;

               else if (args[i].substring(2).equals("Metal")) lookAndFeel = 1;

               else if (args[i].substring(2).equals("Windows")) lookAndFeel = 2;

               else if (args[i].substring(2).equals("Mac")) lookAndFeel = 3;

               else if (args[i].substring(2).equals("Motif")) lookAndFeel = 4;

            }

        }

        /** if look and feel isn't default: metal */

        if (lookAndFeel != 1) {

            try {

                /**

                 * available look and feels:

                 * =========================

                 * "javax.swing.plaf.metal.MetalLookAndFeel"

                 * "com.sun.java.swing.plaf.windows.WindowsLookAndFeel"

                 * "com.sun.java.swing.plaf.motif.MotifLookAndFeel"

                 * "javax.swing.plaf.mac.MacLookAndFeel"

                 */

                String laf = "javax.swing.plaf.metal.MetalLookAndFeel";

                if (lookAndFeel == 0)

                   laf = UIManager.getSystemLookAndFeelClassName();

                else if (lookAndFeel == 1)

                     laf = "javax.swing.plaf.metal.MetalLookAndFeel";

                else if (lookAndFeel == 2)

                     laf = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";

                else if (lookAndFeel == 3)

                     laf = "javax.swing.plaf.mac.MacLookAndFeel";

                else if (lookAndFeel == 4)

                     laf = "com.sun.java.swing.plaf.motif.MotifLookAndFeel";

                UIManager.setLookAndFeel(laf);

            }

            catch (Exception e) {

                new ErrorDialog(e);

            }

        }

 

        startBomberman();

    }

}

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

import java.lang.Integer;

import java.io.*;

 

/**

 * File:         BomberMain.java

 * Copyright:    Copyright (c) 2001

 * @author Sammy Leong

 * @version 1.0

 */

 

/**

 * This is the starting point of the game.

 */

public class BomberMain extends JFrame {

    /** relative path for files */

    public static String RP = "./";

    /** menu object */

    private BomberMenu menu = null;

    /** game object */

    private BomberGame game = null;

 

    /** sound effect player */

    public static BomberSndEffect sndEffectPlayer = null;

    /** this is used to calculate the dimension of the game */

    public static final int shiftCount = 4;

    /** this is the size of each square in the game */

    public static final int size = 1 << shiftCount;

 

    static {

        sndEffectPlayer = new BomberSndEffect();

    }

 

    /**

     * Constructs the main frame.

     */

    public BomberMain() {

        /** add window event handler */

        addWindowListener(new WindowAdapter() {

            /**

             * Handles window closing events.

             * @param evt window event

             */

            public void windowClosing(WindowEvent evt) {

                /** terminate the program */

                System.exit(0);

            }

        });

 

        /** add keyboard event handler */

        addKeyListener(new KeyAdapter() {

            /**

             * Handles key pressed events.

             * @param evt keyboard event

             */

            public void keyPressed(KeyEvent evt) {

                if (menu != null) menu.keyPressed(evt);

                if (game != null) game.keyPressed(evt);

            }

 

            /**

             * Handles key released events.

             * @param evt keyboard event

             */

            public void keyReleased(KeyEvent evt) {

                if (game != null) game.keyReleased(evt);

            }

        });

 

        /** set the window title */

        setTitle("Bomberman 1.0 by Sammy Leong");

 

        /** set the window icon */

        try {

            setIconImage(Toolkit.getDefaultToolkit().getImage(

                new File(RP + "Images/Bomberman.gif").getCanonicalPath()));

        }

        catch (Exception e) { new ErrorDialog(e); }

 

        /** create and add the menu to the frame */

        getContentPane().add(menu = new BomberMenu(this));

 

        /** set the window so that the user can't resize it */

        setResizable(false);

        /** minimize the size of the window */

        pack();

 

        /** get screen size */

        Dimension d = Toolkit.getDefaultToolkit().getScreenSize();

 

        int x = (d.width - getSize().width) / 2;

        int y = (d.height - getSize().height) / 2;

 

        /** center the window on the screen */

        setLocation(x, y);

        /** show the frame */

        show();

        /** make this window the top level window */

        toFront();

    }

 

    /**

     * Creates a new game.

     * @param players total number of players

     */

    public void newGame(int players)

    {

        JDialog dialog = new JDialog(this, "Loading Game...", false);

        dialog.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);

        dialog.setSize(new Dimension(200, 0));

        dialog.setResizable(false);

        int x = getLocation().x + (getSize().width - 200) / 2;

        int y = getLocation().y + getSize().height / 2;

        dialog.setLocation(x, y);

        /** show the dialog */

        dialog.show();

 

        /** remove existing panels in the content pane */

        getContentPane().removeAll();

        getLayeredPane().removeAll();

        /** get rid of the menu */

        menu = null;

        /** create the map */

        BomberMap map = new BomberMap(this);

 

        /** create the game */

        game = new BomberGame(this, map, players);

 

        /** get rid of loading dialog */

        dialog.dispose();

        /** show the frame */

        show();

        /** if Java 2 available */

        if (Main.J2) {

           BomberBGM.unmute();

           /** player music */

           BomberBGM.change("Battle");

        }

    }

 

    /**

     * Starting ponit of program.

     * @param args arguments

     */

    public static void main(String[] args) {

        BomberMain bomberMain1 = new BomberMain();

    }

}

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

import java.io.*;

 

/**

 * File:         BomberMenu.java

 * Copyright:    Copyright (c) 2001

 * @author Sammy Leong

 * @version 1.0

 */

 

/**

 * This class creates the main menu of the game.

 */

public class BomberMenu extends JPanel {

    /** main frame pointer */

    private BomberMain main = null;

    /** image button objects */

    private BomberImageButton[] imageButtons = null;

    /** current selection */

    private int selection = P2;

 

    /** background image object */

    private static Image backgroundImg = null;

    /** button images */

    private static Image[] buttonImagesDown = null;

    private static Image[] buttonImagesUp = null;

    /** rendering hints */

    private static Object hints = null;

    /** options enumeration */

    private static final int P2 = 0;

    private static final int P3 = 1;

    private static final int P4 = 2;

    private static final int CONTROL_SETUP = 3;

    private static final int EXIT = 4;

 

    static {

        /** if java runtime is Java 2 */

        if (Main.J2) {

            /** create the rendering hints for better graphics output */

            RenderingHints h = null;

            h = new RenderingHints(null);

            h.put(RenderingHints.KEY_TEXT_ANTIALIASING,

             RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

            h.put(RenderingHints.KEY_FRACTIONALMETRICS,

             RenderingHints.VALUE_FRACTIONALMETRICS_ON);

            h.put(RenderingHints.KEY_ALPHA_INTERPOLATION,

             RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);

            h.put(RenderingHints.KEY_ANTIALIASING,

             RenderingHints.VALUE_ANTIALIAS_ON);

            h.put(RenderingHints.KEY_COLOR_RENDERING,

             RenderingHints.VALUE_COLOR_RENDER_QUALITY);

            hints = (RenderingHints)h;

        }

 

        /** create the image objects */

        buttonImagesDown = new Image[5];

        buttonImagesUp = new Image[5];

 

        /** setup path names */

        Toolkit tk = Toolkit.getDefaultToolkit();

        String path = BomberMain.RP + "Images/BomberMenu/";

        String file = null;

        try {

            /** load background image */

            file = path + "Background.jpg";

            backgroundImg = tk.getImage(new File(file).getCanonicalPath());

 

            /** load each button image */

            for (int i = 0; i < 5; i++) {

                if (i <= P4) file = path + (i + 2) + " Player Game";

                else if (i == CONTROL_SETUP) file = path + "Control Setup";

                else if (i == EXIT) file = path + "Exit";

                buttonImagesDown[i] = tk.getImage(

                new File(file + " Down.gif").getCanonicalPath());

                buttonImagesUp[i] = tk.getImage(

                new File(file + " Up.gif").getCanonicalPath());

            }

        }

        catch (Exception e) { new ErrorDialog(e); }

    }

 

    /**

     * Constructs the menu.

     * @param main BomberMain object

     */

    public BomberMenu(BomberMain main) {

        this.main = main;

        /** set the menu dimensions */

        setPreferredSize(new Dimension(17 << main.shiftCount,

        17 << main.shiftCount));

        /** turn on double buffer */

        setDoubleBuffered(true);

 

        /** load the images */

        MediaTracker mt = new MediaTracker(this);

        try {

            int counter = 0;

            /** load the background image */

            mt.addImage(backgroundImg, counter++);

            /** load the button images */

            for (int i = 0; i < 5; i++) {

                mt.addImage(buttonImagesDown[i], counter++);

                mt.addImage(buttonImagesUp[i], counter++);

            }

            /** wait for images to finish loading */

            mt.waitForAll();

        }

        catch (Exception e) { new ErrorDialog(e); }

        /** create the button objects array */

        imageButtons = new BomberImageButton[5];

        for (int i = 0; i < 5; i++) {

            /** setup the images */

            Image[] images = { buttonImagesDown[i], buttonImagesUp[i] };

            /** create each object */

            imageButtons[i] = new BomberImageButton(this, images);

        }

        /** calculate distance between each button */

        int dy = buttonImagesDown[0].getHeight(this) / (32 / main.size * 2);

        /** setup the buttons' positions */

        for (int i = P2; i <= EXIT; i++)

            imageButtons[i].setInfo(0, (280 / (32 / main.size)) + (dy * i), i);

        /** set current selection to Player 2 */

        imageButtons[P2].setBevel(true);

    }

 

    /**

     * Handles key pressed events.

     * @param evt key event

     */

    public void keyPressed(KeyEvent evt) {

        /** store old selection */

        int newSelection = selection;

        switch (evt.getKeyCode()) {

            case KeyEvent.VK_UP:

            case KeyEvent.VK_LEFT: newSelection -= 1; break;

            case KeyEvent.VK_DOWN:

            case KeyEvent.VK_RIGHT: newSelection += 1; break;

            case KeyEvent.VK_ENTER: doCommand(selection);

        }

        /** if selection is new */

        if (selection != newSelection) {

            /** if new selection is less than 0 then set it to exit button */

            if (newSelection < 0) newSelection = EXIT;

            /** deselect old selection */

            imageButtons[selection].setBevel(false);

            /** set up selection */

            selection = newSelection;

            selection %= 5;

            /** select new selection */

            imageButtons[selection].setBevel(true);

        }

    }

 

    /**

     * Command handler.

     * @param command command

     */

    public void doCommand(int command) {

        switch (command) {

            case P2:

            case P3:

            case P4:

                 main.newGame(selection + 2);

                 break;

            case CONTROL_SETUP:

                 new BomberConfigDialog(main);

                 break;

            case EXIT:

                /** create the dialog content */

                JOptionPane pane =

                new JOptionPane("Are you sure you want to exit Bomberman?");

                /** setup the dialog content */

                pane.setOptionType(JOptionPane.YES_NO_OPTION);

                pane.setMessageType(JOptionPane.WARNING_MESSAGE);

                /** create the dialog */

                JDialog dialog = pane.createDialog(this, "Exit Bomberman?");

                dialog.setResizable(false);

                /** show the dialog */

                dialog.show();

                Object selection = pane.getValue();

 

                /** if user clicked on yes */

                if (selection != null && selection.toString().equals("0"))

                    /** terminate the program */

                    System.exit(0);

        }

    }

 

    /**

     * Painting method.

     * @param g graphics handler

     */

    public void paint(Graphics graphics) {

        Graphics g = graphics;

        /** if java runtime is Java 2 */

        if (Main.J2) { paint2D(graphics); }

        /** if java runtime isn't Java 2 */

        else {

            g.drawImage(backgroundImg, 0, 0, 17 <<

            main.shiftCount, 17 << main.shiftCount, this);

        }

        for (int i = 0; i < 5; i++) if (imageButtons[i] != null)

            imageButtons[i].paint(g);

    }

 

    /**

     * Drawing method for Java 2's Graphics2D

     * @param graphics graphics handle

     */

    public void paint2D(Graphics graphics) {

        Graphics2D g2 = (Graphics2D)graphics;

        /** set the rendering hints */

        g2.setRenderingHints((RenderingHints)hints);

        g2.drawImage(backgroundImg, 0, 0, 17 <<

        main.shiftCount, 17 << main.shiftCount, this);

    }

}

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

import java.io.*;

/**

 * File:         BomberGame.java

 * Copyright:    Copyright (c) 2001

 * @author Sammy Leong

 * @version 1.0

 */

 

/**

 * This class contains the player objects.

 */

public class BomberGame extends JPanel

implements ActionListener {

    /** main frame object */

    private BomberMain main = null;

    /** game over flag */

    private boolean gameOver = false;

    /** map object */

    private BomberMap map = null;

    /** winner */

    private int winner = -1;

    /** timer */

    private Timer timer = null;

    /** elapsed seconds */

    private int elapsedSec = 0;

 

    /** rendering hints */

    private static Object hints = null;

    /** end game images */

    private static Image[] images = null;

    /** total number of players */

    public static int totalPlayers = 4;

    /** players alive */

    public static int playersLeft = totalPlayers;

    /** player objects */

    public static BomberPlayer[] players = null;

 

    static

    {

        /** if java runtime is Java 2 */

        if (Main.J2) {

            /** create the rendering hints for better graphics output */

            RenderingHints h = null;

            h = new RenderingHints(null);

            h.put(RenderingHints.KEY_TEXT_ANTIALIASING,

             RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

            h.put(RenderingHints.KEY_FRACTIONALMETRICS,

             RenderingHints.VALUE_FRACTIONALMETRICS_ON);

            h.put(RenderingHints.KEY_ALPHA_INTERPOLATION,

             RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);

            h.put(RenderingHints.KEY_ANTIALIASING,

             RenderingHints.VALUE_ANTIALIAS_ON);

            h.put(RenderingHints.KEY_COLOR_RENDERING,

             RenderingHints.VALUE_COLOR_RENDER_QUALITY);

            hints = (RenderingHints)h;

        }

 

        String path = BomberMain.RP + "Images/BomberEndGame/";

        String str = null;

        /** create the images */

        images = new Image[6];

        /** open the image files */

        try

        {

            for (int i = 0; i < 4; i++) {

                str = path + "Player " + (i + 1) + " Wins.jpg";

                images[i] = Toolkit.getDefaultToolkit().getImage(

                new File(str).getCanonicalPath());

            }

            str = path + "Draw.jpg";

            images[4] = Toolkit.getDefaultToolkit().getImage(

            new File(str).getCanonicalPath());

            str = path + "Enter to Continue.jpg";

            images[5] = Toolkit.getDefaultToolkit().getImage(

            new File(str).getCanonicalPath());

        } catch (Exception e) { new ErrorDialog(e); }

    }

 

    /**

     * Constructs a game.

     * @param main main frame object

     * @param map map object

     * @param totalPlayers total number of players

     */

    public BomberGame(BomberMain main, BomberMap map, int totalPlayers) {

        this.main = main;

        this.map = map;

        this.totalPlayers = this.playersLeft = totalPlayers;

 

        /** load the images */

        try {

            MediaTracker tracker = new MediaTracker(this);

            for (int i = 0; i < 6; i++) tracker.addImage(images[i], i);

            tracker.waitForAll();

        }

        catch (Exception e) { new ErrorDialog(e); }

 

        /** create the players array */

        players = new BomberPlayer[totalPlayers];

        /** create the players */

        for (int i = 0; i < totalPlayers; i++)

            players[i] = new BomberPlayer(this, map, i + 1);

 

        /** double buffer on */

        setDoubleBuffered(true);

        setBounds(0, 0, 17 << main.shiftCount, 17 << main.shiftCount);

        /** set it to opaque */

        setOpaque(false);

        /** add it to the top layer */

        main.getLayeredPane().add(this, 0);

    }

 

    /**

     * Key pressed handler

     * @param evt key event

     */

    public void keyPressed(KeyEvent evt)

    {

        if (!gameOver) {

           for (int i = 0; i < totalPlayers; i++)

               players[i].keyPressed(evt);

        }

        else if (evt.getKeyCode() == KeyEvent.VK_ENTER)

        {

            timer.stop();

            timer = null;

            main.dispose();

            new BomberMain();

        }

    }

 

    /**

     * Key released handler

     * @param evt key event

     */

    public void keyReleased(KeyEvent evt)

    {

        if (!gameOver) {

           for (int i = 0; i < totalPlayers; i++)

               players[i].keyReleased(evt);

        }

    }

 

    /**

     * Drawing handler.

     * @param graphics graphics handle

     */

    public void paint(Graphics graphics) {

        Graphics g = graphics;

        /** if game is active */

        if (!gameOver) {

           for (int i = 0; i < totalPlayers; i++)

               players[i].paint(graphics);

        }

        /** if java runtime is Java 2 */

        if (Main.J2) { paint2D(graphics); }

        /** if java runtime isn't Java 2 */

        else {

            /** if game is over */

            if (gameOver) {

                /** draw end game image */

                g.drawImage(images[winner], 0,

                BomberMain.size == 16 ? -25 : -50,

                17 << BomberMain.shiftCount,

                17 << BomberMain.shiftCount, this);

                /** if elapsed seconds % 2 == 0 */

                /** then draw press enter to exit image */

                if (elapsedSec == 0)

                    g.drawImage(images[5], 0,

                    (17 << BomberMain.shiftCount) - images[5].getHeight(this) /

                    (BomberMain.size != 16 ? 1 : 2),

                    images[5].getWidth(this) / (BomberMain.size != 16 ? 1 : 2),

                    images[5].getHeight(this) /

                    (BomberMain.size != 16 ? 1 : 2), this);

                /** if elapsed seconds % 2 == 1 then clear the area */

                else

                    g.fillRect(0, (17 << BomberMain.shiftCount) -

                    images[5].getHeight(this) /

                    (BomberMain.size != 16 ? 1 : 2),

                    images[5].getWidth(this) /

                     (BomberMain.size != 16 ? 1 : 2),

                    images[5].getHeight(this) /

                    (BomberMain.size != 16 ? 1 : 2));

            }

            /** if 1 or less players left alive */

            if (playersLeft <= 1 && timer == null)

            {

                /** deactiavte all the players */

                for (int i = 0; i < totalPlayers; i++)

                    players[i].deactivate();

                timer = new Timer(1000, this);

                timer.start();

            }

        }

    }

 

    /**

     * Public accessor to paintImmediately(...).

     * @param x x-coordinate

     * @param y y-coordinate

     * @param w width

     * @param h height

     */

    public void pPaintImmediately(int x, int y, int w, int h) {

        paintImmediately(x, y, w, h);

    }

 

    /**

     * Drawing method for Java 2's Graphics2D

     * @param graphics graphics handle

     */

    public void paint2D(Graphics graphics) {

        Graphics2D g2 = (Graphics2D)graphics;

        /** set the rendering hints */

        g2.setRenderingHints((RenderingHints)hints);

        /** if game is over */

        if (gameOver) {

            /** draw end game image */

            g2.drawImage(images[winner], 0, BomberMain.size == 16 ? -25 : -50,

            17 << BomberMain.shiftCount, 17 << BomberMain.shiftCount, this);

            /** if elapsed seconds % 2 == 0 */

            /** then draw press enter to exit image */

            if (elapsedSec == 0)

                g2.drawImage(images[5], 0,

                (17 << BomberMain.shiftCount) - images[5].getHeight(this) /

                (BomberMain.size != 16 ? 1 : 2),

                images[5].getWidth(this) / (BomberMain.size != 16 ? 1 : 2),

                images[5].getHeight(this) /

                 (BomberMain.size != 16 ? 1 : 2), this);

            /** if elapsed seconds % 2 == 1 then clear the area */

            else

                g2.fillRect(0, (17 << BomberMain.shiftCount) -

                images[5].getHeight(this) / (BomberMain.size != 16 ? 1 : 2),

                images[5].getWidth(this) / (BomberMain.size != 16 ? 1 : 2),

                images[5].getHeight(this) / (BomberMain.size != 16 ? 1 : 2));

        }

        /** if 1 or less players left alive */

        if (playersLeft <= 1 && timer == null)

        {

            /** deactiavte all the players */

            for (int i = 0; i < totalPlayers; i++)

                players[i].deactivate();

            timer = new Timer(1000, this);

            timer.start();

        }

    }

 

    public void actionPerformed(ActionEvent evt) {

        /** increased elapsed time */

        elapsedSec += 1;

        /** if elapsed 4 seconds */

        if (elapsedSec >= 4)

        {

            /** if Java 2 available */

            if (Main.J2) {

               /** stop background music */

               BomberBGM.mute();

            }

            /** set default game result = draw */

            winner = 4;

            /** find winner */

            for (int i = 0; i < totalPlayers; i++) {

                if (!players[i].isDead()) { winner = i; break; }

            }

            gameOver = true;

            map.setGameOver();

            /** restart timer with new delay */

            timer.stop();

            timer = new Timer(500, this);

            timer.start();

        }

        /** if game is over */

        if (gameOver)

        {

            elapsedSec %= 2;

            paintImmediately(0,

            (17 << BomberMain.shiftCount) - images[5].getHeight(this) /

            (BomberMain.size != 16 ? 1 : 2),

            images[5].getWidth(this)  / (BomberMain.size != 16 ? 1 : 2),

            images[5].getHeight(this)  / (BomberMain.size != 16 ? 1 : 2));

        }

    }

}

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

import java.io.*;

import java.lang.Integer;

 

/**

 * File:         BomberPlayer.java

 * Copyright:    Copyright (c) 2001

 * @author Sammy Leong

 * @version 1.0

 */

 

/**

 * This class creates player objects.

 */

public class BomberPlayer extends Thread {

    /** game object handle */

    public BomberGame game = null;

    /** map object handle */

    private BomberMap map = null;

    /** player's own bomb grid (must have for synchronization) */

    public boolean[][] bombGrid = null;

    /** input key queue */

    private BomberKeyQueue keyQueue = null;

    /** bomb key is down or not */

    private boolean bombKeyDown = false;

    /** direction keys down */

    private byte dirKeysDown = 0x00;

    /** current direction key down */

    private byte currentDirKeyDown = 0x00;

    /** sprite width */

    private final int width = BomberMain.size;

    /** sprite height */

    private final int height = 44 / (32 / BomberMain.size);

    /** is exploding flag */

    private boolean isExploding = false;

    /** is dead flag */

    private boolean isDead = false;

    /** whether a key is pressed or not */

    private boolean keyPressed = false;

    /** the player's input keys */

    private int[] keys = null;

    /** total bombs the player has */

    public int totalBombs = 1;

    /** total bombs the player used */

    public int usedBombs = 0;

    /** the player's fire strength */

    public int fireLength = 2;

    /** if player is alive */

    public boolean isActive = true;

    /** player position */

    public int x = 0;

    public int y = 0;

    /** player's number */

    private int playerNo = 0;

    /** user's state : default to face down */

    private int state = DOWN;

    /** flag : whether the player is moving or not */

    private boolean moving = false;

    /** sprite frame number */

    private int frame = 0;

    /** clear mode flag */

    private boolean clear = false;

 

    /** byte enumerations */

    private static final byte BUP = 0x01;

    private static final byte BDOWN = 0x02;

    private static final byte BLEFT = 0x04;

    private static final byte BRIGHT = 0x08;

    private static final byte BBOMB = 0x10;

    /** number enumerations */

    private static final int UP = 0;

    private static final int DOWN = 1;

    private static final int LEFT = 2;

    private static final int RIGHT = 3;

    private static final int BOMB = 4;

    private static final int EXPLODING = 4;

    /** all player sprite images */

    private static Image[][][] sprites = null;

    /** rendering hints */

    private static Object hints = null;

 

    static {

        /** if java runtime is Java 2 */

        if (Main.J2) {

            /** create the rendering hints for better graphics output */

            RenderingHints h = null;

            h = new RenderingHints(null);

            h.put(RenderingHints.KEY_TEXT_ANTIALIASING,

             RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

            h.put(RenderingHints.KEY_FRACTIONALMETRICS,

             RenderingHints.VALUE_FRACTIONALMETRICS_ON);

            h.put(RenderingHints.KEY_ALPHA_INTERPOLATION,

             RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);

            h.put(RenderingHints.KEY_ANTIALIASING,

             RenderingHints.VALUE_ANTIALIAS_ON);

            h.put(RenderingHints.KEY_COLOR_RENDERING,

             RenderingHints.VALUE_COLOR_RENDER_QUALITY);

            hints = (RenderingHints)h;

        }

 

        /** create the images */

        sprites = new Image[4][5][5];

        int[] states = { UP, DOWN, LEFT, RIGHT, EXPLODING };

        Toolkit tk = Toolkit.getDefaultToolkit();

        String path = new String();

        /** open the files */

        try {

            for (int p = 0; p < 4; p++) {

                for (int d = 0; d < 5; d++) {

                    for (int f = 0; f < 5; f++) {

                        /** generate file name */

                        path = BomberMain.RP + "Images/";

                        path += "Bombermans/Player " + (p + 1) + "/";

                        path += states[d] + "" + (f + 1) + ".gif";

                        /** open the file */

                        sprites[p][d][f] = tk.getImage(

                        new File(path).getCanonicalPath());

                    }

                }

            }

        }

        catch (Exception e) { new ErrorDialog(e); }

    }

 

    /**

     * Constructs a player.

     * @param game game object

     * @param map map object

     * @param playerNo player's number

     */

    public BomberPlayer(BomberGame game, BomberMap map, int playerNo) {

        this.game = game;

        this.map = map;

        this.playerNo = playerNo;

 

        /** create the bomb grid */

        bombGrid = new boolean[17][17];

        for (int i = 0; i < 17; i++) for (int j = 0; j < 17; j++)

            bombGrid[i][j] = false;

 

        int r = 0, c = 0;

        /** find player's starting position */

        switch (this.playerNo)

        {

            case 1: r = c = 1; break;

            case 2: r = c = 15; break;

            case 3: r = 15; c = 1; break;

            case 4: r = 1; c = 15;

        }

        /** calculate position */

        x = r << BomberMain.shiftCount;

        y = c << BomberMain.shiftCount;

 

        MediaTracker tracker = new MediaTracker(game);

        try {

            int counter = 0;

            /** load the images */

            for (int p = 0; p < 4; p++) {

                for (int d = 0; d < 5; d++) {

                    for (int f = 0; f < 5; f++) {

                        tracker.addImage(sprites[p][d][f], counter++);

                    }

                }

            }

            /** wait for images to finish loading */

            tracker.waitForAll();

        }

        catch (Exception e) { new ErrorDialog(e); }

 

        /** create the key queue */

        keyQueue = new BomberKeyQueue();

        /** create the key configurations array */

        keys = new int[5];

        /** load the configurations */

        for (int k = BomberKeyConfig.UP; k <= BomberKeyConfig.BOMB; k++)

            keys[k] = BomberKeyConfig.keys[playerNo - 1][k];

        /** HOG THE CPU!!! */

        setPriority(Thread.MAX_PRIORITY);

        /** start looping */

        start();

    }

 

    /**

     * Key pressed event handler.

     * @param evt key event

     */

    public void keyPressed(KeyEvent evt)

    {

        /** assume no new key is pressed */

        byte newKey = 0x00;

        /** if player isn't exploding or dead and key pressed is in player's */

        /** key list */

        if (!isExploding && !isDead &&

        evt.getKeyCode() == keys[UP] ||

        evt.getKeyCode() == keys[DOWN] ||

        evt.getKeyCode() == keys[LEFT] ||

        evt.getKeyCode() == keys[RIGHT])

        {

            /** if down key pressed */

            if (evt.getKeyCode() == keys[DOWN]) {

                newKey = BDOWN;

                /** if only the up key is pressed */

                if ((currentDirKeyDown & BUP) > 0 ||

                ((currentDirKeyDown & BLEFT) == 0 &&

                (currentDirKeyDown & BRIGHT) == 0))

                currentDirKeyDown = BDOWN;

            }

            /** if up key is pressed */

            else if (evt.getKeyCode() == keys[UP]) {

                newKey = BUP;

                /** if only the down key is pressed */

                if ((currentDirKeyDown & BDOWN) > 0 ||

                ((currentDirKeyDown & BLEFT) == 0 &&

                (currentDirKeyDown & BRIGHT) == 0))

                currentDirKeyDown = BUP;

            }

            /** if left key is pressed */

            else if (evt.getKeyCode() == keys[LEFT]) {

                newKey = BLEFT;

                /** if only the right key is pressed */

                if ((currentDirKeyDown & BRIGHT) > 0 ||

                ((currentDirKeyDown & BUP) == 0 &&

                (currentDirKeyDown & BDOWN) == 0))

                currentDirKeyDown = BLEFT;

            }

            /** if right key is pressed */

            else if (evt.getKeyCode() == keys[RIGHT]) {

                newKey = BRIGHT;

                /** if only the left is pressed */

                if ((currentDirKeyDown & BLEFT) > 0 ||

                ((currentDirKeyDown & BUP) == 0 &&

                (currentDirKeyDown & BDOWN) == 0))

                currentDirKeyDown = BRIGHT;

            }

            /** if new key isn't in the key queue */

            if (!keyQueue.contains(newKey))

            {

                /** then push it on top */

                keyQueue.push(newKey);

                /** reset keys pressed buffer */

                dirKeysDown |= newKey;

                keyPressed = true;

                /** if thread is sleeping, then wake it up */

                interrupt();

            }

        }

        /** if no direction key is pressed */

        /** and bomb key is pressed */

        if (!isExploding && !isDead &&

        evt.getKeyCode() == keys[BOMB] && !bombKeyDown && isActive)

        {

            bombKeyDown = true;

            interrupt();

        }

    }

 

    /**

     * Key released handler.

     * @param evt key event

     */

    public void keyReleased(KeyEvent evt)

    {

        /** if a direction key is released */

        if (!isExploding && !isDead && (

        evt.getKeyCode() == keys[UP] ||

        evt.getKeyCode() == keys[DOWN] ||

        evt.getKeyCode() == keys[LEFT] ||

        evt.getKeyCode() == keys[RIGHT]))

        {

            /** if down key is released */

            if (evt.getKeyCode() == keys[DOWN]) {

                /** remove key from the all keys down buffer */

                dirKeysDown ^= BDOWN;

                /** reset current key down */

                currentDirKeyDown ^= BDOWN;

                /** remove it from the key queue */

                keyQueue.removeItems(BDOWN);

            }

            /** if up key is released */

            else if (evt.getKeyCode() == keys[UP]) {

                /** remove key from the all keys down buffer */

                dirKeysDown ^= BUP;

                /** reset current key down */

                currentDirKeyDown ^= BUP;

                /** remove it from the key queue */

                keyQueue.removeItems(BUP);

            }

            /** if left key is released */

            else if (evt.getKeyCode() == keys[LEFT]) {

                /** remove key from the all keys down buffer */

                dirKeysDown ^= BLEFT;

                /** reset current key down */

                currentDirKeyDown ^= BLEFT;

                /** remove it from the key queue */

                keyQueue.removeItems(BLEFT);

            }

            /** if right key is released */

            else if (evt.getKeyCode() == keys[RIGHT]) {

                /** remove key from the all keys down buffer */

                dirKeysDown ^= BRIGHT;

                /** reset current key down */

                currentDirKeyDown ^= BRIGHT;

                /** remove it from the key queue */

                keyQueue.removeItems(BRIGHT);

            }

            /** if no key is currently down */

            if (currentDirKeyDown == 0)

            {

                /** see if last key pressed is still pressed or not */

                boolean keyFound = false;

                /** search for last key pressed */

                while (!keyFound && keyQueue.size() > 0) {

                    /** if key is found then exit the loop */

                    if ((keyQueue.getLastItem() & dirKeysDown) > 0) {

                        currentDirKeyDown = keyQueue.getLastItem();

                        keyFound = true;

                    }

                    /** if key is not found then pop the current key */

                    /** and on to the next one */

                    else keyQueue.pop();

                }

                /** if no key found */

                if (!keyFound)

                {

                    /** remove all keys from queue if not already removed */

                    keyQueue.removeAll();

                    /** reset key buffers */

                    currentDirKeyDown = 0x00;

                    dirKeysDown = 0x00;

                    keyPressed = false;

                    interrupt();

                }

            }

        }

        /** if the bomb key is released */

        if (!isExploding && !isDead && evt.getKeyCode() == keys[BOMB])

        {

            bombKeyDown = false;

            interrupt();

        }

    }

 

    /**

     * Deactivates the player so it can't be controlled.

     */

    public void deactivate()

    {

        isActive = false;

    }

 

    /**

     * Kills the player

     */

    public void kill()

    {

        /** is player isn't dead or isn't dieing already */

        if (!isDead && !isExploding)

        {

            /** lower players left */

            BomberGame.playersLeft -= 1;

            /** reset frame counter */

            frame = 0;

            /** set exploding mode */

            state = EXPLODING;

            /** make it animate */

            moving = true;

            /** prepare to explode! */

            isExploding = true;

            /** release keys */

            keyPressed = false;

            BomberMain.sndEffectPlayer.playSound("Die");

            /** wake up and die */

            interrupt();

        }

    }

 

    /**

     * @return x co-ordinate

     */

    public int getX() { return x; }

 

    /**

     * @return y co-ordinate

     */

    public int getY() { return y; }

 

    /**

     * @return whether player is (dead or dieing) or not

     */

    public boolean isDead() { return (isDead | isExploding); }

 

    /**

     * Main loop

     */

    public void run()

    {

        /** can move flat */

        boolean canMove;

        /** keeps track of last key state */

        boolean lastState = false;

        /** shift count */

        int shiftCount = BomberMain.shiftCount;

        /** offset size */

        int offset = 1 << (BomberMain.shiftCount / 2);

        /** block size */

        int size = BomberMain.size;

        /** half the block size */

        int halfSize = BomberMain.size / 2;

        /** temporary variables */

        int bx = 0, by = 0;

        /** unconditional loop */

        while (true) {

            /** if bomb key is down */

            if (!isExploding && !isDead && bombKeyDown && isActive) {

                /** if bombs are available */

                if ((totalBombs - usedBombs) > 0 &&

                /** and a bomb isn't placed there already */

                map.grid[x >> shiftCount][y >> shiftCount]

                != BomberMap.BOMB && !bombGrid[(x + halfSize) >>

                BomberMain.shiftCount][(y + halfSize) >>

                BomberMain.shiftCount]) {

                    usedBombs += 1;

                    bombGrid[(x + halfSize) >> BomberMain.shiftCount]

                    [(y + halfSize) >> BomberMain.shiftCount] = true;

                    /** create bomb */

                    map.createBomb(x + halfSize, y + halfSize, playerNo);

                }

            }

            /** if other keys are down */

            if (!isExploding && !isDead && keyPressed) {

                /** store last state */

                lastState = keyPressed;

                /** increase frame */

                frame = (frame + 1) % 5;

                /** set moving to true */

                moving = true;

                /** assume can't move */

                canMove = false;

                /** make sure a key is down */

                if (dirKeysDown > 0) {

                    /** if left key is down */

                    if ((currentDirKeyDown & BLEFT) > 0) {

                        state = LEFT;

                        /** if west slot is empty then it can move */

                        canMove = (x % size != 0 || (y % size == 0 &&

                        (map.grid[(x >> shiftCount) - 1][y >> shiftCount]

                        <= BomberMap.NOTHING)));

 

                        /** if it can't move */

                        if (!canMove) {

                            int oy = 0;

                            /** if it's a little bit north */

                            for (oy = -offset; oy < 0; oy += (size / 4)) {

                                /** and west slot is empty */

                                if ((y + oy) % size == 0 &&

                                map.grid[(x >> shiftCount) - 1]

                                [(y + oy) >> shiftCount] <= BomberMap.NOTHING) {

                                    /** then move anyway */

                                    canMove = true; break;

                                }

                            }

                            /** if it still can't move */

                            if (!canMove) {

                                /** if it's a little bit south */

                                for (oy = (size / 4); oy <= offset;

                                oy += (size / 4)) {

                                    /** and west slot is empty */

                                    if ((y + oy) % size == 0 &&

                                    map.grid[(x >> shiftCount) - 1]

                                    [(y + oy) >> shiftCount]

                                    <= BomberMap.NOTHING) {

                                        /** move anyway */

                                        canMove = true; break;

                                    }

                                }

                            }

                            /** if it can move now */

                            if (canMove) {

                                /** clear original spot */

                                clear = true; game.paintImmediately(x,

                                y - halfSize, width, height);

                                /** move up or down */

                                y += oy;

                                /** redraw the sprite */

                                clear = false; game.paintImmediately(x,

                                y - halfSize, width, height);

                            }

                        }

                        /** if it can move */

                        if (canMove) {

                            /** clear original spot */

                            clear = true; game.paintImmediately(x,

                            y - halfSize, width, height);

                            /** move left */

                            x -= (size / 4);

                            /** redraw the sprite */

                            clear = false; game.paintImmediately(x,

                            y - halfSize, width, height);

                        }

                        /** if it can't move */

                        else {

                            /** refresh the sprite */

                            moving = false; game.paintImmediately(x,

                            y - halfSize, width, height);

                        }

                    }

                    /** if the right key is down */

                    else if ((currentDirKeyDown & BRIGHT) > 0) {

                        state = RIGHT;

                        canMove = false;

                        /** if east slot is empty */

                        canMove = (x % size != 0 || (y % size == 0 &&

                        (map.grid[(x >> shiftCount) + 1][y >> shiftCount]

                        <= BomberMap.NOTHING)));

 

                        /** if it can't move */

                        if (!canMove) {

                            int oy = 0;

                            /** see if it's a bit south */

                            for (oy = -offset; oy < 0; oy += (size / 4)) {

                                /** and the east slot is empty */

                                if ((y + oy) % size == 0 &&

                                map.grid[(x >> shiftCount) + 1]

                                [(y + oy) >> shiftCount] <= BomberMap.NOTHING) {

                                    /** move it */

                                    canMove = true; break;

                                }

                            }

                            /** if it still can't move */

                            if (!canMove) {

                                /** see if it's a bit north */

                                for (oy = (size / 4); oy <= offset;

                                oy += (size / 4)) {

                                    /** and the east slot if empty */

                                    if ((y + oy) % size == 0 &&

                                    map.grid[(x >> shiftCount) + 1]

                                    [(y + oy) >> shiftCount]

                                    <= BomberMap.NOTHING) {

                                        /** move it */

                                        canMove = true; break;

                                    }

                                }

                            }

                            /** if it can move now */

                            if (canMove) {

                                /** clear original spot */

                                clear = true; game.paintImmediately(x,

                                y - halfSize, width, height);

                                /** move up or down */

                                y += oy;

                                /** refresh the sprite */

                                clear = false; game.paintImmediately(x,

                                y - halfSize, width, height);

                            }

                        }

                        /** if it can move */

                        if (canMove) {

                            /** clear original spot */

                            clear = true; game.paintImmediately(x,

                            y - halfSize, width, height);

                            /** move right */

                            x += (size / 4);

                            /** refresh the sprite */

                            clear = false; game.paintImmediately(x,

                            y - halfSize, width, height);

                        }

                        /** if it can't move */

                        else {

                            moving = false;

                            /** refresh the sprite */

                            game.paintImmediately(x,

                            y - halfSize, width, height);

                        }

                    }

                    /** if up key is down */

                    else if ((currentDirKeyDown & BUP) > 0) {

                        state = UP;

                        canMove = false;

                        /** if north slot is empty */

                        canMove = (y % size != 0 || (x % size == 0 &&

                        (map.grid[x >> shiftCount][(y >> shiftCount) - 1]

                        <= BomberMap.NOTHING)));

 

                        /** if it can't move */

                        if (!canMove) {

                            int ox = 0;

                            /** see if it's a bit to the left */

                            for (ox = -offset; ox < 0; ox += (size / 4)) {

                                /** and the north slot is empty */

                                if ((x + ox) % size == 0 &&

                                map.grid[(x + ox) >> shiftCount]

                                [(y >> shiftCount) - 1] <= BomberMap.NOTHING) {

                                    canMove = true; break;

                                }

                            }

                            /** if it still can't move */

                            if (!canMove) {

                                /** see if it's a bit to the right */

                                for (ox = (size / 4); ox <= offset; ox += (size / 4)) {

                                    /** and the north block is empty */

                                    if ((x + ox) % size == 0 &&

                                    map.grid[(x + ox) >> shiftCount]

                                    [(y >> shiftCount) - 1]

                                    <= BomberMap.NOTHING) {

                                        canMove = true; break;

                                    }

                                }

                            }

                            /** if it can move */

                            if (canMove) {

                                /** clear original block */

                                clear = true; game.paintImmediately(x,

                                y - halfSize, width, height);

                                /** move right */

                                x += ox;

                                /** refresh the sprite */

                                clear = false; game.paintImmediately(x,

                                y - halfSize, width, height);

                            }

                        }

                        /** if it can move */

                        if (canMove) {

                            /** clear original block */

                            clear = true; game.paintImmediately(x,

                            y - halfSize, width, height);

                            /** move up */

                            y -= (size / 4);

                            /** refresh the sprite */

                            clear = false; game.paintImmediately(x,

                            y - halfSize, width, height);

                        }

                        /** if it can't move */

                        else {

                            /** refresh the block */

                            moving = false; game.paintImmediately(x,

                            y - halfSize, width, height);

                        }

                    }

                    /** if the down is is down */

                    else if ((currentDirKeyDown & BDOWN) > 0)

                    {

                        state = DOWN;

                        canMove = false;

                        /** if the south block is empty */

                        canMove = (y % size != 0 || (x % size == 0 &&

                        (map.grid[x >> shiftCount][(y >> shiftCount) + 1]

                        <= BomberMap.NOTHING)));

 

                        /** if it can't move */

                        if (!canMove) {

                            int ox = 0;

                            /** see if it's a bit to the west */

                            for (ox = -offset; ox < 0; ox += (size / 4)) {

                                /** and the south block is empty */

                                if ((x + ox) % size == 0 &&

                                map.grid[(x + ox) >> shiftCount]

                                [(y >> shiftCount) + 1] <= BomberMap.NOTHING) {

                                    canMove = true; break;

                                }

                            }

                            /** if it still can't move */

                            if (!canMove) {

                                /** see if it's a bit to the east */

                                for (ox = (size / 4); ox <= offset;

                                ox += (size / 4)) {

                                    /** and the south block is empty */

                                    if ((x + ox) % size == 0 &&

                                    map.grid[(x + ox) >> shiftCount]

                                    [(y >> shiftCount) + 1]

                                    <= BomberMap.NOTHING) {

                                        canMove = true; break;

                                    }

                                }

                            }

                            /** if it can move now */

                            if (canMove) {

                                /** clear orignal block */

                                clear = true; game.paintImmediately(x,

                                y - halfSize, width, height);

                                /** move left or right */

                                x += ox;

                                /** refresh the sprite */

                                clear = false; game.paintImmediately(x,

                                y - halfSize, width, height);

                            }

                        }

                        /** if it can move now */

                        if (canMove) {

                            /** clear original spot */

                            clear = true; game.paintImmediately(x,

                            y - halfSize, width, height);

                            /** move down */

                            y += (size / 4);

                            /** refresh the sprite */

                            clear = false; game.paintImmediately(x,

                            y - halfSize, width, height);

                        }

                        /** if it can't move */

                        else {

                            /** refresh the sprite */

                            moving = false; game.paintImmediately(x,

                            y - halfSize, width, height);

                        }

                    }

                }

            }

            /** if all keys are up */

            else if (!isExploding && !isDead && lastState != keyPressed)

            {

                /** reset frame to 0 */

                frame = 0;

                moving = false;

                /** refresh sprite */

                game.paintImmediately(x, y - halfSize, width, height);

                lastState = keyPressed;

            }

            /** if it's exploding */

            else if (!isDead && isExploding)

            {

                /** if frame reached 4 then it's dead */

                if (frame >= 4) isDead = true;

                /** refresh sprite */

                game.paintImmediately(x, y - halfSize, width, height);

                /** rotate frame count */

                frame = (frame + 1) % 5;

            }

            /** if it's dead */

            else if (isDead)

            {

                /** clear the block */

                clear = true;

                game.paintImmediately(x, y - halfSize, width, height);

                /** exit the loop */

                break;

            }

            /** see if the player stepped on any bonuses */

            /** try normal position */

            if (map.bonusGrid[x >> shiftCount][y >> shiftCount] != null)

               { bx = x; by = y; }

            /** try a bit to the north */

            else if (map.bonusGrid[x >> shiftCount][(y + halfSize)

                 >> shiftCount] != null) { bx = x; by = y + halfSize; }

            /** try a bit to the left */

            else if (map.bonusGrid[(x + halfSize) >> shiftCount][y

                 >> shiftCount] != null) { bx = x + halfSize; by = y; }

            /** if the player did step on a bonus */

            if (bx != 0 && by != 0) {

                map.bonusGrid[bx >> shiftCount][by >>

                shiftCount].giveToPlayer(playerNo);

                bx = by = 0;

            }

            /** if it's dead, then exit the loop */

            if (isDead) break;

            /** delay 65 milliseconds */

            try { sleep(65); } catch (Exception e) { }

        }

        interrupt();

    }

 

    /**

     * Drawing method.

     */

    public void paint(Graphics graphics)

    {

        Graphics g = graphics;

        /** if java runtime is Java 2 */

        if (Main.J2) { paint2D(graphics); }

        /** if java runtime isn't Java 2 */

        else {

            /** if player isn't dead and clear mode isn't on */

            if (!isDead && !clear)

            {

                /** if moving */

                if (moving)

                   /** draw the animating image */

                   g.drawImage(sprites[playerNo - 1][state][frame],

                   x, y - (BomberMain.size / 2), width, height, null);

                /** if not moving */

                else

                    /** draw the still image */

                    g.drawImage(sprites[playerNo - 1][state][0],

                    x, y - (BomberMain.size / 2), width, height, null);

            }

        }

    }

 

    /**

     * Drawing method for Java 2's Graphics2D

     * @param graphics graphics handle

     */

    public void paint2D(Graphics graphics) {

        Graphics2D g2 = (Graphics2D)graphics;

        /** set the rendering hints */

        g2.setRenderingHints((RenderingHints)hints);

        /** if player isn't dead and clear mode isn't on */

        if (!isDead && !clear)

        {

            /** if moving */

            if (moving)

               /** draw the animating image */

               g2.drawImage(sprites[playerNo - 1][state][frame],

               x, y - (BomberMain.size / 2), width, height, null);

            /** if not moving */

            else

                /** draw the still image */

                g2.drawImage(sprites[playerNo - 1][state][0],

                x, y - (BomberMain.size / 2), width, height, null);

        }

    }

}

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

import java.awt.event.KeyEvent;

import java.io.*;

 

/**

 * File:         BomberKeyConfig.java

 * Copyright:    Copyright (c) 2001

 * @author Sammy Leong

 * @version 1.0

 */

 

/**

 * This class keeps track of the keyboard configration for each player.

 * This class can't be instanciated.

 */

public abstract class BomberKeyConfig {

    /** the keys */

    public static int[][] keys = null;

    /** player numbers enumerations */

    public static final int P1 = 0;

    public static final int P2 = 1;

    public static final int P3 = 2;

    public static final int P4 = 3;

    /** key number enumerations */

    public static final int UP = 0;

    public static final int DOWN = 1;

    public static final int LEFT = 2;

    public static final int RIGHT = 3;

    public static final int BOMB = 4;

 

    /** open the key configuration file */

    static {

        /** try to open the file and if can't open file then */

        if (!openFile())

        {

            /** create the default configuration file */

            createDefaultFile();

            /** then try to open it again */

            openFile();

        }

    }

 

    /**

     * Opens the configuration file.

     */

    public static boolean openFile() {

        /** setup result to be returned */

        boolean result = true;

        /** try to open the file */

        try {

            /** create the file stream object */

            ObjectInputStream inputStream =

            new ObjectInputStream(new FileInputStream("BomberKeyConfig.dat"));

            /** read the file into memory */

            keys = (int[][])inputStream.readObject();

            /** close the file */

            inputStream.close();

        }

        /** if anything goes wrong, set result to to false */

        catch (Exception e) {

            result = false;

        }

        /** return the result */

        return result;

    }

 

    /**

     * Writes the file with current data in memory.

     */

    public static void writeFile() {

        /** try to create the file */

        try {

            /** create the file object, overwrite the file if needs to */

            ObjectOutputStream outputStream =

            new ObjectOutputStream(new FileOutputStream("BomberKeyConfig.dat"));

            /** write the file */

            outputStream.writeObject((int[][])keys);

            /** close the file */

            outputStream.close();

        }

        catch (Exception e) { new ErrorDialog(e); }

    }

 

    /**

     * Creates the configuration file with default configurations.

     */

    public static void createDefaultFile() {

        /** create the data, if it doens't exist already */

        if (keys == null) keys = new int[4][5];

 

        /** player 1 default key configurations */

        keys[P1][UP] = KeyEvent.VK_UP;

        keys[P1][DOWN] = KeyEvent.VK_DOWN;

        keys[P1][LEFT] = KeyEvent.VK_LEFT;

        keys[P1][RIGHT] = KeyEvent.VK_RIGHT;

        keys[P1][BOMB] = KeyEvent.VK_NUMPAD0;

 

        /** player 2 default key configurations */

        keys[P2][UP] = KeyEvent.VK_W;

        keys[P2][DOWN] = KeyEvent.VK_S;

        keys[P2][LEFT] = KeyEvent.VK_A;

        keys[P2][RIGHT] = KeyEvent.VK_D;

        keys[P2][BOMB] = KeyEvent.VK_SPACE;

 

        /** player 3 default key configurations */

        keys[P3][UP] = KeyEvent.VK_I;

        keys[P3][DOWN] = KeyEvent.VK_K;

        keys[P3][LEFT] = KeyEvent.VK_J;

        keys[P3][RIGHT] = KeyEvent.VK_L;

        keys[P3][BOMB] = KeyEvent.VK_BACK_SLASH;

 

        /** player 4 default key configurations */

        keys[P4][UP] = KeyEvent.VK_NUMPAD8;

        keys[P4][DOWN] = KeyEvent.VK_NUMPAD5;

        keys[P4][LEFT] = KeyEvent.VK_NUMPAD4;

        keys[P4][RIGHT] = KeyEvent.VK_NUMPAD6;

        keys[P4][BOMB] = KeyEvent.VK_NUMPAD9;

 

        /** write the file */

        writeFile();

    }

}

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

/**

 * File:         BomberKeyQueue.java

 * Copyright:    Copyright (c) 2001

 * @author Sammy Leong

 * @version 1.0

 */

 

/**

 * This class keeps track of the keyboard input in a queue for each player.

 */

public class BomberKeyQueue {

    /** head and tail nodes */

    private Node head = null, tail = null;

    /** total nodes */

    private int totalItems = 0;

 

    /**

     * Default constructor.

     */

    public BomberKeyQueue() {

        /** place holder */

    }

 

    /**

     * Pushes an item into the queue.

     * @param b byte to be pushed

     */

    public void push(byte b) {

        /** create the new node object */

        Node newNode = new Node(b);

        /** if list is empty then head and tail equals new object */

        if (head == null) head = tail = newNode;

        /** if list isn't empty */

        else {

            /** last object's next object equals new object */

            tail.next = newNode;

            /** new object's previous object equals last object */

            newNode.prev = tail;

            /** tail pointer now points to the new object */

            tail = newNode;

        }

        /** increase total items count */

        totalItems += 1;

    }

 

    /**

     * Removes an item from the list then return it.

     * @return last item in the list

     */

    public byte pop() {

        /** setup object to be returned */

        byte result = 0x00;

        /** if list isn't empty */

        if (tail != null) {

            /** copy last item's data */

            result = tail.data;

            /** last item now becomes last item's previous item */

            tail = tail.prev;

            /** if list isn't empty now then set last item to point to null */

            if (tail != null) tail.next = null;

            /** if list is empty then head = tail = null */

            else head = tail;

            /** decrease total items count */

            totalItems -= 1;

        }

        /** return the object */

        return result;

    }

 

    /**

     * Removes all instances of an item

     * @param b byte to be removed

     */

    public void removeItems(byte b) {

        /** create temporary node and set it to point to head */

        Node temp = head;

        /** loop while end of list not reached */

        while (temp != null) {

            /** if current pointed to object's data is equal to parameter */

            if (temp.data == b) {

                /** reset object's previous link */

                if (temp.prev != null) temp.prev.next = temp.next;

                /** reset object's next link */

                if (temp.next != null) temp.next.prev = temp.prev;

                /** if object is the head of list then reset head */

                if (temp == head) head = temp.next;

                /** if object is the tail of list then reset tail */

                if (temp == tail) tail = temp.prev;

                /** decrease total items count */

                totalItems -= 1;

            }

            /** get next item in the list */

            temp = temp.next;

        }

    }

 

    /**

     * Removes all elements

     */

     public void removeAll() {

        head = tail = null;

     }

 

    /**

     * @return size of the list

     */

    public int size() {

        return totalItems;

    }

 

    /**

     * @return the last item in the list.

     */

    public byte getLastItem() {

        /** setup data to be returned */

        byte result = 0x00;

        /** if list isn't empty then copy last item's data */

        if (tail != null) result = tail.data;

        /** return the data */

        return result;

    }

 

    /**

     * @return whether an item is in the list or not

     */

    public boolean contains(byte b) {

        /** setup data to be returned (default to false) */

        boolean result = false;

        /** create temporary Node object for navigation */

        Node temp = head;

        /** loop till end of list is reached */

        while (temp != null) {

            /** if data found then get otta here */

            if (temp.data == b) { result = true; break; }

            /** get next item in the list */

            temp = temp.next;

        }

        /** return the result */

        return result;

    }

 

    /**

     * This is the data object for the queue.

     */

    private class Node {

        /** the key data */

        public  byte data = 0x00;

        /** pointers / links */

        public Node prev = null, next = null;

 

        /**

         * Construct with data

         */

        public Node(byte b)

        {

            /** set data */

            data = b;

        }

 

        /**

         * Copy constructor.

         * @param n node to be copied

         */

        public Node(Node n)

        {

            /** copy data */

            data = n.data;

            /** copy the links */

            prev = n.prev;

            next = n.next;

        }

    }

}

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 import java.awt.*;

import javax.swing.*;

import java.io.*;

 

/**

 * File:         BomberImagePanel.java

 * Copyright:    Copyright (c) 2001

 * @author Sammy Leong

 * @version 1.0

 */

 

/**

 * This class creates a custom image button object.

 */

public class BomberImageButton {

    /** this object's container */

    private JPanel panel;

    /** x co-ordinate where the image is drawn */

    private int x;

    /** y co-ordinate where the image is drawn */

    private int y;

    /** ID of object (for command) */

    private int ID;

    /** image width */

    private int w;

    /** image height */

    private int h;

    /** area the object controls */

    private Rectangle rect;

    /** the images of the button: normal / outerglowed */

    private Image[] images;

    /** stae of button: normal / outglowed */

    private int state = 0;

 

    /** rendering hints */

    private static Object hints = null;

 

    static {

        /** if java runtime is Java 2 */

        if (Main.J2) {

            /** create the rendering hints for better graphics output */

            RenderingHints h = null;

            h = new RenderingHints(null);

            h.put(RenderingHints.KEY_TEXT_ANTIALIASING,

             RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

            h.put(RenderingHints.KEY_FRACTIONALMETRICS,

             RenderingHints.VALUE_FRACTIONALMETRICS_ON);

            h.put(RenderingHints.KEY_ALPHA_INTERPOLATION,

             RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);

            h.put(RenderingHints.KEY_ANTIALIASING,

             RenderingHints.VALUE_ANTIALIAS_ON);

            h.put(RenderingHints.KEY_COLOR_RENDERING,

             RenderingHints.VALUE_COLOR_RENDER_QUALITY);

            hints = (RenderingHints)h;

        }

    }

 

    /**

     * Construct with a MainMenu object and an array of images for use with

     * the button.

     * @param mainMenu object's container

     * @param images images for the button

     */

    public BomberImageButton(JPanel panel, Image[] images) {

        this.panel = panel;

        this.images = images;

        /** calculate image dimension */

        w = images[0].getWidth(panel);

        h = images[0].getHeight(panel);

    }

 

    /**

     * Set object's parameters.

     * @param x x co-ordinate on window

     * @param y y co-ordinate on window

     * @param ID object's ID or command return code

     */

    public void setInfo(int x, int y, int ID) {

        this.x = x;

        this.y = y;

        this.ID = ID;

        /** calculate area in which the object owns to handle mouse events */

        rect = new Rectangle(this.x, this.y - 5, w, h + 10);

    }

 

    /**

     * @return the ojbect's ID

     */

    public int getID() {

        return ID;

    }

 

    /**

     * Set bevel on or off

     * @param bevelOn true or false

     */

     public void setBevel(boolean bevelOn) {

        if (bevelOn) state = 1; else state = 0;

        panel.repaint();

        panel.paintImmediately(x, y, w / (32 / BomberMain.size * 2),

           h / (32 / BomberMain.size * 2));

     }

 

    /**

     * Draws the button onto the window.

     * @param graphics graphics handler

     */

    public void paint(Graphics graphics) {

        /** if java runtime is Java 2 */

        if (Main.J2) { paint2D(graphics); }

        /** if java runtime isn't Java 2 */

        else {

            Graphics g = graphics;

            /** draw the button */

            g.drawImage(images[state], x, y, w / (32 / BomberMain.size * 2),

            h / (32 / BomberMain.size * 2), null);

        }

    }

 

    /**

     * Drawing method for Java 2's Graphics2D

     * @param graphics graphics handle

     */

    public void paint2D(Graphics graphics) {

        Graphics2D g2 = (Graphics2D)graphics;

        /** set the rendering hints */

        g2.setRenderingHints((RenderingHints)hints);

        /** draw the button */

        g2.drawImage(images[state], x, y, w / (32 / BomberMain.size * 2),

        h / (32 / BomberMain.size * 2), null);

    }

}

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

import java.io.*;

import java.util.Vector;

 

/**

 * File:         BomberMap.java

 * Copyright:    Copyright (c) 2001

 * @author Sammy Leong

 * @version 1.0

 */

 

/**

 * This class draws the map and handles things like bonuses and bombs.

 */

public class BomberMap extends JPanel {

    /** frame object */

    private BomberMain main = null;

    /** game over flag */

    private boolean gameOver = false;

    /** background color */

    private Color backgroundColor = null;

    /** the map grid array */

    public int[][] grid = null;

    /** fire grid */

    public boolean[][] fireGrid = null;

    /** bomb grid */

    public BomberBomb[][] bombGrid = null;

    /** bonus grid */

    public BomberBonus[][] bonusGrid = null;

    /** bombs */

    private Vector bombs = null;

    /** bonuses */

    private Vector bonuses = null;

 

    /**

     * Bomb info class

     */

    private class Bomb {

        public Bomb(int x, int y) {

            r = (x >> BomberMain.shiftCount);

            c = (y >> BomberMain.shiftCount);

        }

        public int r = 0;

        public int c = 0;

    }

 

    /**

     * Bonus info class

     */

    private class Bonus {

        public Bonus(int x, int y) {

            r = (x >> BomberMain.shiftCount);

            c = (y >> BomberMain.shiftCount);

        }

        public int r = 0;

        public int c = 0;

    }

 

    /** image handles for the map images */

    private static Image[][] mapImages = null;

    /** bomb images */

    public static Image[] bombImages = null;

    /** fire images */

    public static Image[][] fireImages = null;

    /** fire brick images */

    public static Image[][] fireBrickImages = null;

    /** bonus images */

    public static Image[][] bonusImages = null;

    /** fire type enumerations */

    public static final int FIRE_CENTER = 0;

    public static final int FIRE_VERTICAL = 1;

    public static final int FIRE_HORIZONTAL = 2;

    public static final int FIRE_NORTH = 3;

    public static final int FIRE_SOUTH = 4;

    public static final int FIRE_EAST = 5;

    public static final int FIRE_WEST = 6;

    public static final int FIRE_BRICK = 7;

    /** grid slot type enumerations */

    public static final int BONUS_FIRE = -4;

    public static final int BONUS_BOMB = -3;

    public static final int NOTHING = -1;

    public static final int WALL = 0;

    public static final int BRICK = 1;

    public static final int BOMB = 3;

    /** random level generator */

    private static BomberRandInt levelRand = null;

    /** random bonus generator */

    private static BomberRandInt bonusRand = null;

    /** current level */

    public static int level = 0;

    /** rendering hints */

    private static Object hints = null;

 

    static {

        /** if java runtime is Java 2 */

        if (Main.J2) {

            /** create the rendering hints for better graphics output */

            RenderingHints h = null;

            h = new RenderingHints(null);

            h.put(RenderingHints.KEY_TEXT_ANTIALIASING,

             RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

            h.put(RenderingHints.KEY_FRACTIONALMETRICS,

             RenderingHints.VALUE_FRACTIONALMETRICS_ON);

            h.put(RenderingHints.KEY_ALPHA_INTERPOLATION,

             RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);

            h.put(RenderingHints.KEY_ANTIALIASING,

             RenderingHints.VALUE_ANTIALIAS_ON);

            h.put(RenderingHints.KEY_COLOR_RENDERING,

             RenderingHints.VALUE_COLOR_RENDER_QUALITY);

            hints = (RenderingHints)h;

        }

 

        /** create the level random generator */

        levelRand = new BomberRandInt(0, 100);

        /** create the bonus random generator */

        bonusRand = new BomberRandInt(0, 7);

        /** creat the image objects array */

        mapImages = new Image[3][3];

        /** create the bomb objects array */

        bombImages = new Image[2];

        /** create the fire objects array */

        fireImages = new Image[8][8];

        /** create the fire brick objects array */

        fireBrickImages = new Image[3][8];

        /** create the bonus image objects array */

        bonusImages = new Image[2][2];

 

        try {

            String[] strs = new String[3];

            /** load the map images */

            for (int i = 0; i < 2; i++) {

                strs[0] = BomberMain.RP + "Images/BomberWalls/" + (i + 1);

                strs[1] = BomberMain.RP + "Images/BomberBricks/" + (i + 1);

                strs[2] = BomberMain.RP + "Images/BomberFloors/" + (i + 1);

                for (int j = 0; j < 3; j++) {

                    if (i == 0) strs[j] += ".jpg";

                    else strs[j] += ".gif";

                }

                mapImages[i][0] = Toolkit.getDefaultToolkit().getImage(

                new File(strs[0]).getCanonicalPath());

                mapImages[i][1] = Toolkit.getDefaultToolkit().getImage(

                new File(strs[1]).getCanonicalPath());

                if (i == 0) mapImages[i][2] = null;

                else

                    mapImages[i][2] = Toolkit.getDefaultToolkit().getImage(

                    new File(strs[2]).getCanonicalPath());

            }

 

            String str = null;

            /** load the bomb images */

            for (int i = 0; i < 2; i++) {

                str = BomberMain.RP + "Images/BomberBombs/" + (i + 1) + ".gif";

                bombImages[i] = Toolkit.getDefaultToolkit().getImage(

                new File(str).getCanonicalPath());

            }

 

            /** load the fire images */

            for (int t = 0; t < 7; t++) for (int i = 0; i < 8; i++)

            {

                str = BomberMain.RP + "Images/BomberFires/";

                if (t == FIRE_CENTER) str += "C";

                else if (t == FIRE_VERTICAL) str += "V";

                else if (t == FIRE_NORTH) str += "N";

                else if (t == FIRE_HORIZONTAL) str += "H";

                else if (t == FIRE_EAST) str += "E";

                else if (t == FIRE_WEST) str += "W";

                else if (t == FIRE_SOUTH) str += "S";

                if (t == FIRE_BRICK) fireImages[t][i] = null;

                else {

                    str += (i + 1) + ".gif";

                    fireImages[t][i] = Toolkit.getDefaultToolkit().getImage(

                    new File(str).getCanonicalPath());

                }

            }

 

            int f = 0;

            /** load the fire brick images */

            for (int i = 0; i < 2; i++) for (f = 0; f < 8; f++)

            {

                str = BomberMain.RP + "Images/BomberFireBricks/" +

                (i + 1) + (f + 1) + ".gif";

                fireBrickImages[i][f] = Toolkit.getDefaultToolkit().getImage(

                new File(str).getCanonicalPath());

            }

 

            /** load the bonus image sprites */

            for (int i = 0; i < 2; i++) for (f = 0; f < 2; f++)

            {

                str = BomberMain.RP + "Images/BomberBonuses/" +

                (i == 0 ? "F" : "B") + (f + 1) + ".gif";

                bonusImages[i][f] = Toolkit.getDefaultToolkit().getImage(

                new File(str).getCanonicalPath());

            }

        }

        catch (Exception e) { new ErrorDialog(e); }

    }

 

    public BomberMap(BomberMain main) {

        this.main = main;

        /** generator random level */

        level = levelRand.draw() % 2;

        MediaTracker tracker = new MediaTracker(this);

        /** prepare the images */

        try

        {

            int counter = 0;

            /** load the map images */

            for (int i = 0; i < 2; i++) for (int j = 0; j < 3; j++) {

                if (mapImages[i][j] != null)

                { tracker.addImage(mapImages[i][j], counter++); }

            }

            /** load the bomb images */

            for (int i = 0; i < 2; i++)

                tracker.addImage(bombImages[i], counter++);

            /** load the fire brick images */

            for (int i = 0; i < 8; i++)

                fireImages[FIRE_BRICK][i] = fireBrickImages[level][i];

            /** load the fire images */

            for (int i = 0; i < 8; i++) for (int j = 0; j < 8; j++)

                tracker.addImage(fireImages[i][j], counter++);

 

            /** wait for images to finish loading */

            tracker.waitForAll();

        } catch (Exception e) { new ErrorDialog(e); }

 

        bombs = new Vector();

        bonuses = new Vector();

        /** create the fire grid */

        fireGrid = new boolean[17][17];

        /** create the bomb grid */

        bombGrid = new BomberBomb[17][17];

        /** create the bonus grid */

        bonusGrid = new BomberBonus[17][17];

        /** create the map grid */

        grid = new int[17][17];

        /** fill the map with walls by alternating r by c */

        for (int r = 0; r < 17; r++) for (int c = 0; c < 17; c++) {

            /** if it's the edge */

            if (r == 0 || c == 0 || r == 16 || c == 16) grid[r][c] = WALL;

            else if ( (r & 1) == 0 && (c & 1) == 0 ) grid[r][c] = WALL;

            else grid[r][c] = NOTHING;

            fireGrid[r][c] = false;

            bombGrid[r][c] = null;

            bonusGrid[r][c] = null;

        }

 

        int x, y;

        BomberRandInt ri = new BomberRandInt(1, 15);

        /** generate random bricks */

        for (int i = 0; i < 192 * 2; i++)

        {

            x = ri.draw();

            y = ri.draw();

            if (grid [x][y] == NOTHING)

               grid [x][y] = BRICK;

        }

 

        /** clear corners so players can stand there */

        grid [ 1][ 1] = grid [ 2][ 1] = grid [ 1][ 2] =

        grid [ 1][15] = grid [ 2][15] = grid [ 1][14] =

        grid [15][ 1] = grid [14][ 1] = grid [15][ 2] =

        grid [15][15] = grid [15][14] = grid [14][15] = NOTHING;

 

        /** create background color */

        backgroundColor = new Color(52, 108, 108);

        /** set panel size */

        setPreferredSize(new Dimension(17 << BomberMain.shiftCount,

        17 << BomberMain.shiftCount));

        /** double buffer on */

        setDoubleBuffered(true);

 

        setBounds(0, 0, 17 << main.shiftCount, 17 << main.shiftCount);

        setOpaque(false);

        /** add the map to the bottom layer */

        main.getLayeredPane().add(this, 1000);

    }

 

    /**

     * Sets game over flag on

     */

     public void setGameOver() {

        gameOver = true;

        paintImmediately(0, 0,

        17 << BomberMain.shiftCount, 17 << BomberMain.shiftCount);

     }

 

     /**

      * Creates a bonus.

      * @param x x-coordinate

      * @param y y-coordinate

      * @param owner owner

      */

    public synchronized void createBonus(int x, int y) {

        int _x = (x >> BomberMain.shiftCount) << BomberMain.shiftCount;

        int _y = (y >> BomberMain.shiftCount) << BomberMain.shiftCount;

        int type = bonusRand.draw();

        /** create bonus : 0 = fire; 1 = bomb */

        if (type == 0 || type == 1) {

           bonusGrid[_x >> BomberMain.shiftCount][_y >> BomberMain.shiftCount] =

           new BomberBonus(this, _x, _y, type);

           bonuses.addElement(new Bonus(_x, _y));

        }

    }

 

    /**

     * Removes a bonus.

     * @param x x-coordinate

     * @param y y-coordinate

     */

     public synchronized void removeBonus(int x, int y) {

        int i = 0, k = bonuses.size();

        int r = (x >> BomberMain.shiftCount);

        int c = (y >> BomberMain.shiftCount);

        Bonus b = null;

        while (i < k) {

            b = (Bonus)bonuses.elementAt(i);

            if (b.r == r && b.c == c) {

                bonuses.removeElementAt(i);

                bonusGrid[b.r][b.c].kill();

                bonusGrid[b.r][b.c] = null;

                paintImmediately(b.r << BomberMain.shiftCount,

                b.c << BomberMain.shiftCount, BomberMain.size,

                BomberMain.size);

                break;

            }

            i += 1;

            k = bonuses.size();

        }

     }

 

     /**

      * Creates a bomb.

      * @param x x-coordinate

      * @param y y-coordinate

      * @param owner owner

      */

    public synchronized void createBomb(int x, int y, int owner) {

        int _x = (x >> BomberMain.shiftCount) << BomberMain.shiftCount;

        int _y = (y >> BomberMain.shiftCount) << BomberMain.shiftCount;

        bombGrid[_x >> BomberMain.shiftCount][_y >> BomberMain.shiftCount] =

        new BomberBomb(this, _x, _y, owner);

        bombs.addElement(new Bomb(_x, _y));

    }

 

    /**

     * Removes a bomb.

     * @param x x-coordinate

     * @param y y-coordinate

     */

     public synchronized void removeBomb(int x, int y) {

        int i = 0, k = bombs.size();

        int r = (x >> BomberMain.shiftCount);

        int c = (y >> BomberMain.shiftCount);

        Bomb b = null;

        while (i < k) {

            b = (Bomb)bombs.elementAt(i);

            if (b.r == r & b.c == c) {

                bombs.removeElementAt(i);

                break;

            }

            i += 1;

            k = bombs.size();

        }

     }

 

    /**

     * Creates a fire.

     * @param x x-coordinate

     * @param y y-coordinate

     * @param owner owner

     * @param type fire type

     */

     public void createFire(int x, int y, int owner, int type)

     {

        int _x = (x >> BomberMain.shiftCount) << BomberMain.shiftCount;

        int _y = (y >> BomberMain.shiftCount) << BomberMain.shiftCount;

        boolean createFire = false;

        /** if there's a bomb here */

        if (grid[_x >> BomberMain.shiftCount][_y >> BomberMain.shiftCount] ==

        BOMB) {

            /** then short the bomb */

            if (bombGrid[_x >> BomberMain.shiftCount][_y

            >> BomberMain.shiftCount] != null)

            bombGrid[_x >> BomberMain.shiftCount][_y

            >> BomberMain.shiftCount].shortBomb();

        }

        /** if there's no fire there already */

        else if (!fireGrid[_x >>

        BomberMain.shiftCount][_y >> BomberMain.shiftCount]) {

            createFire = true;

            /** create a fire there */

            BomberFire f = new BomberFire(this, _x, _y, type);

        }

        /** if this is a center */

        if (createFire && type == FIRE_CENTER) {

            int shiftCount = BomberMain.shiftCount;

            int size = BomberMain.size;

            /** then create a chain of fire */

            int northStop = 0, southStop = 0, westStop = 0, eastStop = 0,

            northBlocks = 0, southBlocks = 0, westBlocks = 0, eastBlocks = 0;

            /** see how long the fire can be */

            for (int i = 1; i <= BomberGame.players[owner].fireLength; i++) {

                /** if it can still go south */

                if (southStop == 0) { if (((_y >> shiftCount) + i) < 17) {

                    /** if there isnt't a wall there */

                   if (grid[_x >> shiftCount][(_y >> shiftCount) + i] != WALL) {

                      /** if there's something there though */

                      if (grid[_x >> shiftCount][(_y >> shiftCount) + i]

                      != NOTHING)

                         /** then create a tail fire there */

                         { southStop = grid[_x >> shiftCount]

                            [(_y >> shiftCount) + i]; }

                        /** increase fire chain */

                      southBlocks += 1;

                    } else southStop = -1; }

                }

                /** if it can still go north */

                if (northStop == 0) { if (((_y >> shiftCount) - 1) >= 0) {

                    /** if there isn't a wall there */

                   if (grid[_x >> shiftCount][(_y >> shiftCount) - i] != WALL) {

                    /** if there's something there though */

                      if (grid[_x >> shiftCount][(_y >> shiftCount) - i]

                      != NOTHING)

                         /** then create a tail fire there */

                         { northStop = grid[_x >> shiftCount]

                            [(_y >> shiftCount) - i]; }

                        /** increaes fire chain */

                      northBlocks += 1;

                      } else northStop = -1; }

                }

                /** if it can still go east */

                if (eastStop == 0) { if (((_x >> shiftCount) + i) < 17) {

                    /** if there isn't a wall there */

                   if (grid[(_x >> shiftCount) + i][_y >> shiftCount] != WALL) {

                    /** if there's somethign there though */

                      if (grid[(_x >> shiftCount) + i][_y >> shiftCount]

                      != NOTHING)

                         /** then create a tail fire there */

                         { eastStop = grid[(_x >> shiftCount) + i]

                            [_y >> shiftCount]; }

                        /** increase fire chain */

                      eastBlocks += 1;

                    } else eastStop = -1; }

                }

                /** if it can still go west */

                if (westStop == 0) { if (((_x >> shiftCount) - i) >= 0) {

                    /** if there isn't a wall there */

                   if (grid[(_x >> shiftCount) - i][_y >> shiftCount] != WALL) {

                    /** if there's something there through */

                      if (grid[(_x >> shiftCount) - i]

                      [_y >> shiftCount] != NOTHING)

                          /** then create a tail fire there */

                         { westStop = grid[(_x >> shiftCount) - i]

                            [_y >> shiftCount]; }

                        /** increase fire chain */

                      westBlocks += 1;

                    } else westStop = -1; }

                }

            }

            /** create the north chain */

            for (int i = 1; i <= northBlocks; i++) {

                /** if this is a tail */

                if (i == northBlocks) {

                    /** if there's a brick */

                   if (northStop == BRICK)

                      /** then create a burning brick sprite */

                      createFire(_x, _y - (i * size), owner, FIRE_BRICK);

                    /** if it's not a brick then create a tail */

                   else createFire(_x, _y - (i * size), owner, FIRE_NORTH);

                }

                /** if it's not a tail then create a normal fire */

                else createFire(_x, _y - (i * size), owner, FIRE_VERTICAL);

            }

            for (int i = 1; i <= southBlocks; i++) {

                /** if this is a tail */

                if (i == southBlocks) {

                    /** if there's a brick */

                    if (southStop == BRICK)

                       /** then create a burning brick sprite */

                       createFire(_x, _y + (i * size), owner, FIRE_BRICK);

                    /** if it's not a brick then create a tail */

                    else createFire(_x, _y + (i * size), owner, FIRE_SOUTH);

                }

                /** if it's not a tail then create a normal fire */

                else createFire(_x, _y + (i * size), owner, FIRE_VERTICAL);

            }

            for (int i = 1; i <= eastBlocks; i++) {

                /** if this is a tail */

                if (i == eastBlocks) {

                    /** if there's a brick */

                    if (eastStop == BRICK)

                       /** then create a burning brick sprite */

                       createFire(_x + (i * size), _y, owner, FIRE_BRICK);

                    /** if it's not a brick then create a tail */

                    else createFire(_x + (i * size), _y, owner, FIRE_EAST);

                }

                /** if it's not a tail then create a normal fire */

                else createFire(_x + (i * size), _y, owner, FIRE_HORIZONTAL);

            }

            for (int i = 1; i <= westBlocks; i++) {

                /** if this is a tail */

                if (i == westBlocks) {

                    /** if there's a brick */

                    if (westStop == BRICK)

                       /** then create a burning brick sprite */

                       createFire(_x - (i * size), _y, owner, FIRE_BRICK);

                    /** if it's not a brick then create a tail */

                    else createFire(_x - (i * size), _y, owner, FIRE_WEST);

                }

                /** if it's not a tail then create a normal fire */

                else createFire(_x - (i * size), _y, owner, FIRE_HORIZONTAL);

            }

        }

     }

 

    /**

     * Drawing method.

     * @param graphics graphics handle

     */

     public synchronized void paint(Graphics graphics) {

        Graphics g = graphics;

        /** if java runtime is Java 2 */

        if (Main.J2) { paint2D(graphics); }

        /** if java runtime isn't Java 2 */

        else {

            /** if game is over */

            if (gameOver) {

                /** fill the screen with black color */

                g.setColor(Color.black);

                g.fillRect(0, 0, 17 << BomberMain.shiftCount,

                17 << BomberMain.shiftCount);

            }

            /** if game isn't over yet */

            else {

                /** fill window with background color */

                g.setColor(backgroundColor);

                g.fillRect(0, 0, 17 << BomberMain.shiftCount,

                17 << BomberMain.shiftCount);

                /** draw the map */

                for (int r = 0; r < 17; r++) for (int c = 0; c < 17; c++) {

                    /** if there's something in the block */

                    if (grid[r][c] > NOTHING &&

                    grid[r][c] != BOMB && grid[r][c] != FIRE_BRICK &&

                    mapImages[level][grid[r][c]] != null) {

                        g.drawImage(mapImages[level][grid[r][c]],

                        r << BomberMain.shiftCount, c << BomberMain.shiftCount,

                        BomberMain.size, BomberMain.size, null);

                    }

                    /** if the block is empty */

                    else {

                        if (mapImages[level][2] != null) {

                           /** draw the floor */

                           g.drawImage(mapImages[level][2],

                           r << BomberMain.shiftCount, c <<

                           BomberMain.shiftCount, BomberMain.size,

                           BomberMain.size, null);

                        }

                    }

                }

            }

        }

        if (!gameOver) {

            /** draw the bonuses */

            Bonus bb = null;

            int i = 0, k = bonuses.size();

            while (i < k) {

                bb = (Bonus)bonuses.elementAt(i);

                if (bonusGrid[bb.r][bb.c] != null)

                   bonusGrid[bb.r][bb.c].paint(g);

                i += 1;

                k = bonuses.size();

            }

            /** draw the bombs */

            Bomb b = null;

            i = 0; k = bombs.size();

            while (i < k)

            {

                b = (Bomb)bombs.elementAt(i);

                if (bombGrid[b.r][b.c] != null)

                   bombGrid[b.r][b.c].paint(g);

                i += 1;

                k = bombs.size();

            }

        }

     }

 

    /**

     * Drawing method for Java 2's Graphics2D

     * @param graphics graphics handle

     */

    public void paint2D(Graphics graphics) {

        Graphics2D g2 = (Graphics2D)graphics;

        /** set the rendering hints */

        g2.setRenderingHints((RenderingHints)hints);

        /** if game is over */

        if (gameOver) {

            /** fill the screen with black color */

            g2.setColor(Color.black);

            g2.fillRect(0, 0, 17 << BomberMain.shiftCount,

            17 << BomberMain.shiftCount);

        }

        /** if game isn't over yet */

        else {

            /** fill window with background color */

            g2.setColor(backgroundColor);

            g2.fillRect(0, 0, 17 << BomberMain.shiftCount,

            17 << BomberMain.shiftCount);

            /** draw the map */

            for (int r = 0; r < 17; r++) for (int c = 0; c < 17; c++) {

                /** if there's something in the block */

                if (grid[r][c] > NOTHING &&

                grid[r][c] != BOMB && grid[r][c] != FIRE_BRICK &&

                mapImages[level][grid[r][c]] != null) {

                    g2.drawImage(mapImages[level][grid[r][c]],

                    r << BomberMain.shiftCount, c << BomberMain.shiftCount,

                    BomberMain.size, BomberMain.size, null);

                }

                /** if the block is empty */

                else {

                    if (mapImages[level][2] != null) {

                       /** draw the floor */

                       g2.drawImage(mapImages[level][2],

                       r << BomberMain.shiftCount, c <<

                       BomberMain.shiftCount, BomberMain.size,

                       BomberMain.size, null);

                    }

                }

            }

        }

    }

}

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 import java.awt.*;

import javax.swing.*;

import java.io.*;

 

/**

 * File:         BomberBomb

 * Copyright:    Copyright (c) 2001

 * @author Sammy Leong

 * @version 1.0

 */

 

/**

 * This class creates the bombs in the game.

 */

public class BomberBomb extends Thread {

    /** map object */

    private BomberMap map = null;

    /** position */

    private int x = 0;

    private int y = 0;

    /** frame count */

    private int frame = 0;

    /** alive flag */

    private boolean alive = true;

    /** owner */

    private int owner = 0;

    /** count down : 3000 ms */

    private int countDown = 3900;

    /** bomb sprite image handles */

    private static Image[] images = null;

    /** rendering hints */

    private static Object hints = null;

 

    static {

        /** if java runtime is Java 2 */

        if (Main.J2) {

            /** create the rendering hints for better graphics output */

            RenderingHints h = null;

            h = new RenderingHints(null);

            h.put(RenderingHints.KEY_TEXT_ANTIALIASING,

             RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

            h.put(RenderingHints.KEY_FRACTIONALMETRICS,

             RenderingHints.VALUE_FRACTIONALMETRICS_ON);

            h.put(RenderingHints.KEY_ALPHA_INTERPOLATION,

             RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);

            h.put(RenderingHints.KEY_ANTIALIASING,

             RenderingHints.VALUE_ANTIALIAS_ON);

            h.put(RenderingHints.KEY_COLOR_RENDERING,

             RenderingHints.VALUE_COLOR_RENDER_QUALITY);

            hints = (RenderingHints)h;

        }

    }

 

    /**

     * Constructs a BOMB!

     * @param map game map

     * @param x x-coordinate

     * @param y y-coordinate

     * @param owner owner

     * @param images bomb images

     */

    public BomberBomb(BomberMap map, int x, int y, int owner) {

        this.map = map;

        this.x = x;

        this.y = y;

        this.owner = owner - 1;

        this.images = BomberMap.bombImages;

 

        map.grid[x >> BomberMain.shiftCount][y >> BomberMain.shiftCount] =

        BomberMap.BOMB;

        setPriority(Thread.MAX_PRIORITY);

        start();

    }

 

    /**

     * Main loop.

     */

    public synchronized void run() {

        while (alive) {

            /** draw the bomb */

            //paint();

            map.paintImmediately(x, y, BomberMain.size, BomberMain.size);

            /** rotate frame */

            frame = (frame + 1) % 2;

            /** sleep for 130 ms */

            try { sleep(130); } catch (Exception e) {}

            if (!alive) break;

            /** decrease count down */

            countDown -= 130;

            /** if count down reached 0 then exit */

            /** the loop and short the bomb */

            if (countDown <= 0) break;

        }

        /** remove it from the grid */

        map.grid[x >> BomberMain.shiftCount][y >> BomberMain.shiftCount] =

        BomberMap.NOTHING;

        /** give the bomb back to the player */

        BomberGame.players[owner].usedBombs -= 1;

        map.bombGrid[x >> BomberMain.shiftCount][y >> BomberMain.shiftCount] =

        null;

        BomberGame.players[owner].bombGrid

        [x >> BomberMain.shiftCount][y >> BomberMain.shiftCount] = false;

        map.removeBomb(x, y);

        BomberMain.sndEffectPlayer.playSound("Explosion");

        /** create the fire */

        map.createFire(x, y, owner, BomberMap.FIRE_CENTER);

    }

 

    /**

     * Explodes the bomb

     */

    public void shortBomb() {

        alive = false;

        interrupt();

    }

 

    /**

     * Drawing method.

     */

    public void paint(Graphics g) {

        /** if java runtime is Java 2 */

        if (Main.J2) { paint2D(g); }

        /** if java runtime isn't Java 2 */

        else {

             g.drawImage(images[frame], x, y,

             BomberMain.size, BomberMain.size, null);

        }

    }

 

    /**

     * Drawing method for Java 2's Graphics2D

     * @param graphics graphics handle

     */

    public void paint2D(Graphics graphics) {

        Graphics2D g2 = (Graphics2D)graphics;

        /** set the rendering hints */

        g2.setRenderingHints((RenderingHints)hints);

        g2.drawImage(images[frame], x, y,

        BomberMain.size, BomberMain.size, null);

    }

}

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 import java.awt.*;

import javax.swing.*;

 

/**

 * Title:        Bomberman

 * Description:

 * Copyright:    Copyright (c) 2001

 * @author Sammy Leong

 * @version 1.0

 */

 

public class BomberFire extends Thread {

    /** map object */

    private BomberMap map = null;

    /** map grid handle */

    private int[][] grid = null;

    /** position */

    private int x = 0;

    private int y = 0;

    /** fire type */

    private int type = 0;

    /** frame count */

    private int frame = 0;

    /** owner */

    private int owner = 0;

    /** bomb sprite image handles */

    private static Image[][] images = null;

    /** rendering hints */

    private static Object hints = null;

 

    static {

        /** if java runtime is Java 2 */

        if (Main.J2) {

            /** create the rendering hints for better graphics output */

            RenderingHints h = null;

            h = new RenderingHints(null);

            h.put(RenderingHints.KEY_TEXT_ANTIALIASING,

             RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

            h.put(RenderingHints.KEY_FRACTIONALMETRICS,

             RenderingHints.VALUE_FRACTIONALMETRICS_ON);

            h.put(RenderingHints.KEY_ALPHA_INTERPOLATION,

             RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);

            h.put(RenderingHints.KEY_ANTIALIASING,

             RenderingHints.VALUE_ANTIALIAS_ON);

            h.put(RenderingHints.KEY_COLOR_RENDERING,

             RenderingHints.VALUE_COLOR_RENDER_QUALITY);

            hints = (RenderingHints)h;

        }

    }

 

    public BomberFire(BomberMap map, int x, int y, int type) {

        this.map = map;

        grid = map.grid;

        this.x = x;

        this.y = y;

        this.type = type;

        this.owner = owner - 1;

        this.images = BomberMap.fireImages;

 

        if (type == BomberMap.FIRE_BRICK)

           grid[x >> BomberMain.shiftCount][y >> BomberMain.shiftCount] =

           BomberMap.FIRE_BRICK;

        map.fireGrid[x >> BomberMain.shiftCount][y >> BomberMain.shiftCount] =

        true;

 

        /** see if there is a bonus in the same spot */

        if (map.bonusGrid[x >> BomberMain.shiftCount]

        [y >> BomberMain.shiftCount] != null) {

           /** if yes then remove it */

           map.removeBonus(x, y);

        }

 

        setPriority(Thread.MAX_PRIORITY);

        start();

    }

 

    /**

     * Main loop.

     */

    public void run() {

        while (true) {

            /** draw the fire */

            paint();

            /** see if any players are in the way */

            for (int i = 0; i < BomberGame.totalPlayers; i++) {

                /** if there is */

                if ((BomberGame.players[i].x >> BomberMain.shiftCount) ==

                (x >> BomberMain.shiftCount) && (BomberGame.players[i].y >>

                BomberMain.shiftCount) == (y >> BomberMain.shiftCount)) {

                    /** then kill it */

                    BomberGame.players[i].kill();

                }

            }

            /** increase frame */

            frame = frame + 1;

            /** sleep for 65 ms */

            try { sleep(65); } catch (Exception e) {}

            /** if frame is greater than 7 then it's finish burning */

            if (frame > 7) break;

        }

        map.grid[x >> BomberMain.shiftCount][y >> BomberMain.shiftCount] =

        BomberMap.NOTHING;

        map.fireGrid[x >> BomberMain.shiftCount][y >> BomberMain.shiftCount] =

        false;

        /** if this is a tail or brick, then it's the last fire in the chain */

        /** then refresh the screen */

        map.paintImmediately(x, y, BomberMain.size, BomberMain.size);

        /** if this was a brick then create a bonus there */

        if (type == BomberMap.FIRE_BRICK) { map.createBonus(x, y); }

    }

 

    /**

     * Drawing method.

     */

    public void paint() {

        Graphics g = map.getGraphics();

        /** if java runtime is Java 2 */

        if (Main.J2) { paint2D(map.getGraphics()); }

        /** if java runtime isn't Java 2 */

        else {

             g.drawImage(images[type][frame], x, y,

             BomberMain.size, BomberMain.size, null);

        }

        g.dispose();

    }

 

    /**

     * Drawing method for Java 2's Graphics2D

     * @param graphics graphics handle

     */

    public void paint2D(Graphics graphics) {

        Graphics2D g2 = (Graphics2D)graphics;

        /** set the rendering hints */

        g2.setRenderingHints((RenderingHints)hints);

        g2.drawImage(images[type][frame], x, y,

        BomberMain.size, BomberMain.size, null);

    }

}

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 /**

 * File:         BomberRandInt.java

 * Copyright:    Copyright (c) 2001

 * @author Sammy Leong

 * @version 1.0

 */

 

/**

 * This class generates random integers within a given range by creating a

 * stack of 101 random doubles then generate random integers from the stack

 * randomly.  First, a stack of size 101 is created and filled with random

 * doubles.  Everytime an integer is drawn, an element is selected from the

 * stack randomly.  The value at the selected element is used to generate

 * a random integer then that element in the stack is filled with a

 * newly generated double.

 */

public class BomberRandInt {

    /** lowest integer in the range */

    private int low = 0;

    /** highest integer in the range */

    private int high = 0;

 

    /** stack size */

    private static final int BUFFER_SIZE = 101;

    /** stack to hold random doubles */

    private static double[] buffer = new double[BUFFER_SIZE];

 

    /**

     * Fill the stack with 101 random doubles using the built-in random double

     * generator.

     */

    static {

        for (int i = 0; i < BUFFER_SIZE; i++)

            buffer[i] = java.lang.Math.random();

    }

 

    /**

     * Constructs an object that generates random integers in a given range.

     * @param low the lowest integer in the range

     * @param high the highest integer in the range

     */

    public BomberRandInt(int low, int high) {

        this.low = low;

        this.high = high;

    }

 

    /**

     * Get the next random double from the stack then generate an integer from

     * it.

     * @return a random integer

     */

    public int draw() {

        int result = low + (int)((high - low + 1) * nextRandom());

        return result;

    }

 

    /**

     * Pick a random element in the stack and store the value of it into a

     * variable to be returned then fill that element with a new random double.

     * @return a random double

     */

    private static double nextRandom() {

        /** pick a random element in the stack */

        int position = (int)(java.lang.Math.random() * BUFFER_SIZE);

        if (position == BUFFER_SIZE)

            position = BUFFER_SIZE - 1;

        /** store the value of that element */

        double result = buffer[position];

        /** fill that element with a new random double */

        buffer[position] = java.lang.Math.random();

        /** return the value */

        return result;

    }

}

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

import java.io.*;

 

/**

 * File:         BomberBGM

 * Copyright:    Copyright (c) 2001

 * @author Sammy Leong

 * @version 1.0

 */

 

/**

 * This class plays the background music.

 */

public class BomberBGM {

 

    /** SoundPlayer object */

    private static Object player;

    /** last music played */

    private static int lastSelection = -1;

 

    static {

        /** if Java2 available */

        if (Main.J2) {

           /** create the SoundPlayer object and load the music files */

           try {

               player = new SoundPlayer(

           new File(BomberMain.RP + "Sounds/BomberBGM/").

           getCanonicalPath());

           }

           catch (Exception e) { new ErrorDialog(e); }

           ((SoundPlayer)player).open();

        }

    }

 

    /**

     * Change BGM music.

     * @param arg BGM music to chagne to

     */

    public static void change(String arg) {

        /** if Java 2 available */

        if (Main.J2) {

            /**

             * change music only if the the current music is not equal to

             * the specified music

             */

            int i = 0;

            while (i < ((SoundPlayer)player).sounds.size() &&

            ((SoundPlayer)player).sounds.elementAt(i).

            toString().indexOf(arg) < 0) i += 1;

            if (i != lastSelection && i <

               ((SoundPlayer)player).sounds.size()) {

                lastSelection = i;

                ((SoundPlayer)player).change(lastSelection, true);

            }

        }

    }

 

    /**

     * Stop playing the BGM.

     */

    public static void stop()

    {

        /** if Java 2 available */

        if (Main.J2) {

           ((SoundPlayer)player).controlStop();

        }

    }

 

    /**

     * Mute the BGM.

     */

    public static void mute()

    {

        /** if Java 2 available */

        if (Main.J2) {

           ((SoundPlayer)player).mute();

        }

    }

 

    /**

     * Unmute the BGM.

     */

    public static void unmute()

    {

        /** if Java 2 available */

        if (Main.J2) {

            ((SoundPlayer)player).unmute();

        }

    }

}

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

import java.awt.*;

import javax.swing.*;

import java.io.*;

 

/**

 * File:         BomberBonus

 * Copyright:    Copyright (c) 2001

 * @author Sammy Leong

 * @version 1.0

 */

 

/**

 * This class creates the bonuses in the game.

 */

public class BomberBonus extends Thread {

    /** map object */

    private BomberMap map = null;

    /** position */

    private int x = 0;

    private int y = 0;

    /** frame count */

    private int frame = 0;

    /** alive flag */

    private boolean alive = true;

    /** bonus type */

    private int type = 0;

    /** bomb sprite image handles */

    private Image[] images = null;

    /** rendering hints */

    private static Object hints = null;

 

    private static int FIRE = 0;

    private static int BOMB = 1;

 

    static {

        /** if java runtime is Java 2 */

        if (Main.J2) {

            /** create the rendering hints for better graphics output */

            RenderingHints h = null;

            h = new RenderingHints(null);

            h.put(RenderingHints.KEY_TEXT_ANTIALIASING,

             RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

            h.put(RenderingHints.KEY_FRACTIONALMETRICS,

             RenderingHints.VALUE_FRACTIONALMETRICS_ON);

            h.put(RenderingHints.KEY_ALPHA_INTERPOLATION,

             RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);

            h.put(RenderingHints.KEY_ANTIALIASING,

             RenderingHints.VALUE_ANTIALIAS_ON);

            h.put(RenderingHints.KEY_COLOR_RENDERING,

             RenderingHints.VALUE_COLOR_RENDER_QUALITY);

            hints = (RenderingHints)h;

        }

    }

 

    /**

     * Constructs a bonus.

     * @param map map object

     * @param x x-coordinate

     * @param y y-coordinage

     * @param type bonus type;

     */

    public BomberBonus(BomberMap map, int x, int y, int type) {

        this.map = map;

        this.x = x;

        this.y = y;

        this.type = type;

        this.images = BomberMap.bonusImages[type];

 

        setPriority(Thread.MAX_PRIORITY);

        start();

    }

 

    /**

     * Main loop.

     */

    public synchronized void run() {

        while (alive) {

            /** draw the bonus */

            map.paintImmediately(x, y, BomberMain.size, BomberMain.size);

            /** rotate frame */

            frame = (frame + 1) % 2;

            /** sleep for 130 ms */

            try { sleep(130); } catch (Exception e) {}

            if (frame == 10) break;

        }

        /** remove it from the grid */

        map.removeBonus(x, y);

    }

 

    /**

     * Gives this bonus to a user then removes it.

     */

    public void giveToPlayer(int player) {

        BomberMain.sndEffectPlayer.playSound("Bonus");

        /** if it's a fire bonus */

        if (type == FIRE) /** then increase the fire length by 1 */

           BomberGame.players[player - 1].fireLength += 1;

        /** if it's a bomb bonus */

        else if (type == BOMB) /** then increase the bomb count by 1 */

             BomberGame.players[player - 1].totalBombs += 1;

        kill();

    }

 

    /**

     * Kills the object along with the thread

     */

    public void kill() {

        alive = false;

        interrupt();

    }

 

    /**

     * Drawing method.

     */

    public void paint(Graphics g) {

        /** if java runtime is Java 2 */

        if (Main.J2) { paint2D(g); }

        /** if java runtime isn't Java 2 */

        else {

             g.drawImage(images[frame], x, y,

             BomberMain.size, BomberMain.size, null);

        }

    }

 

    /**

     * Drawing method for Java 2's Graphics2D

     * @param graphics graphics handle

     */

    public void paint2D(Graphics graphics) {

        Graphics2D g2 = (Graphics2D)graphics;

        /** set the rendering hints */

        g2.setRenderingHints((RenderingHints)hints);

        g2.drawImage(images[frame], x, y,

        BomberMain.size, BomberMain.size, null);

    }

}

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

 

/**

 * File:         BomberConfigDialog

 * Copyright:    Copyright (c) 2001

 * @author Sammy Leong

 * @version 1.0

 */

 

/**

 * This class shows a dialog which allows the user to

 * configure the game.

 */

public class BomberConfigDialog extends JDialog

implements ActionListener {

    /** temporary key datas used for manipulation */

    private int[][] keys = null;

    /** keys being set offset values */

    private int[] keysBeingSet = { -1, -1 };

    /** waiting for key flag */

    private boolean waitingForKey = false;

    /** the buttons that allow the user to set the keys */

    private JButton[][] buttons = null;

    /** the text fields that display the keys */

    private JTextField[][] keyFields = null;

 

    /**

     * Constructs the dialog.

     * @param owner the dialog's owner

     */

    public BomberConfigDialog(JFrame owner) {

        /** call base class constructor */

        super(owner, "Bomberman Keys Configuration", true);

 

        /** create the temporary key objects */

        keys = new int[4][5];

        /** set the object's data from the currently configurations */

        for (int i = 0; i < 4; i++) for (int j = 0; j < 5; j++)

            keys[i][j] = BomberKeyConfig.keys[i][j];

 

        /** create the panel that holds the config. stuff */

        JPanel centerPanel = new JPanel(new GridLayout(2, 2));

        /** panel for each player's config. stuff */

        JPanel[] panels = new JPanel[4];

        /** create the text fields array of array */

        keyFields = new JTextField[4][];

        /** create the buttons array */

        buttons = new JButton[4][5];

        for (int i = 0; i < 4; i++) {

            /** create the key fields array */

            keyFields[i] = new JTextField[5];

            /** create the 4 panels */

            setupPanel(i, centerPanel, panels[i], keyFields[i]);

        }

 

        /** create the panel to display the help message */

        JPanel helpPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));

        /** setup the border */

        helpPanel.setBorder(BorderFactory.createEtchedBorder());

        /** add a label to it */

        helpPanel.add(new JLabel("Click on the buttons to edit the keys.",

        JLabel.CENTER));

        /** add the help panel to the north side of the dialog */

        getContentPane().add(helpPanel, "North");

        /** add the key setup panels to the center */

        getContentPane().add(centerPanel, "Center");

        /** create the panel to hold the buttons */

        JPanel buttonsP = new JPanel(new FlowLayout(FlowLayout.CENTER));

        buttonsP.setBorder(BorderFactory.createEtchedBorder());

        /** create the save configuration button */

        JButton saveButton = new JButton("Save Configurations");

        saveButton.addActionListener(this);

        buttonsP.add(saveButton);

        /** create the close button */

        JButton closeButton = new JButton("Close");

        closeButton.addActionListener(this);

        buttonsP.add(closeButton);

        /** add the buttons panel to the south side of the dialog */

        getContentPane().add(buttonsP, "South");

 

        /** set the dialog so user can't resize it */

        setResizable(false);

        /** minimize the size of the dialog */

        pack();

 

        int x = owner.getLocation().x + (owner.getSize().width -

                getSize().width) / 2;

        int y = owner.getLocation().y + (owner.getSize().height -

                getSize().height) / 2;

 

        /** center the dialog relative to the owner */

        setLocation(x, y);

        /** finally, show the dialog */

        show();

    }

 

    /**

     * Creates a panel for each player.

     * @param pn player number

     * @param m master panel

     * @param p player's panel

     * @param fields key fields

     */

    private void setupPanel(int pn, JPanel m, JPanel p, JTextField[] fields)

    {

        /** create the left and right panels, 5 rows each */

        JPanel left = new JPanel(new GridLayout(5, 1));

        JPanel right = new JPanel(new GridLayout(5, 1));

 

        /** create the buttons and text fields */

        for (int i = 0; i < 5; i++) {

            /** create the button */

            buttons[pn][i] = new JButton();

            /** create the text field */

            fields[i] = new JTextField(10);

            /** setup the button */

            switch (i) {

                case 0: buttons[pn][i].setText("Up"); break;

                case 1: buttons[pn][i].setText("Down"); break;

                case 2: buttons[pn][i].setText("Left"); break;

                case 3: buttons[pn][i].setText("Right"); break;

                case 4: buttons[pn][i].setText("Bomb"); break;

            }

            /** add action handler to the button */

            buttons[pn][i].addActionListener(this);

            /** setup the text field from data */

            fields[i].setText(KeyEvent.getKeyText(keys[pn][i]));

            /** user can't edit the text field */

            fields[i].setEditable(false);

            /** add the button to the left side */

            left.add(buttons[pn][i]);

            /** add the text field to the right side */

            right.add(fields[i]);

        }

 

        /** create the player's panel */

        p = new JPanel(new GridLayout(1, 2));

        /** set the border */

        p.setBorder(BorderFactory.createTitledBorder(BorderFactory.

        createEtchedBorder(), "Player " + (pn + 1) + " Keys Configuration"));

        /** add the buttons and the keys to the panel */

        p.add(left);

        p.add(right);

        /** add the panel to the master panel */

        m.add(p);

    }

 

    /**

     * Action event handler.

     * @param evt action event info.

     */

    public void actionPerformed(ActionEvent evt) {

        /** if save configuration button is clicked */

        if (evt.getActionCommand().equals("Save Configurations")) {

            /** copy new keys back to glocal variables */

            for (int i = 0; i < 4; i++) for (int j = 0; j < 5; j++)

                BomberKeyConfig.keys[i][j] = keys[i][j];

            /** write the file */

            BomberKeyConfig.writeFile();

            /** destroy this dialog */

            dispose();

        }

        /** if close button is clicked then destroy the dialog */

        else if (evt.getActionCommand().equals("Close")) dispose();

        /** if other buttons are clicked */

        else {

            /** find which key setup button is clicked */

            int i = 0, j = 0;

            boolean found = false;

            for (i = 0; i < 4; ++i) {

                for (j = 0; j < 5; ++j) {

                    /** if key found then exit the loop */

                    if (evt.getSource().equals(buttons[i][j])) found = true;

                    if (found) break;

                }

                if (found) break;

            }

            /** set keys being set indexes */

            keysBeingSet[0] = i;

            keysBeingSet[1] = j;

            /** setup get key loop */

            waitingForKey = true;

            /** create the get key dialog */

            new GetKeyDialog(this, "Press a key to be assigned...", true);

        }

    }

 

    /**

     * This class gets a new key from the user then set it.

     */

    private class GetKeyDialog extends JDialog {

        /** points to itself */

        private JDialog me = null;

        /**

         * Constructs a new dialog.

         * @param owner dialog's owner

         * @param title dialog title

         * @param modal modal or not

         */

        public GetKeyDialog(JDialog owner, String title, boolean modal) {

            /** call base class constructor */

            setTitle(title);

            setModal(modal);

            /** setup pointer to point to itself */

            me = this;

 

            /** add keyboard event handler */

            addKeyListener(new KeyAdapter() {

                /**

                 * Handles key pressed events.

                 * @param evt keyboard event

                 */

                public void keyPressed(KeyEvent evt) {

                    /** if it's waiting for a key */

                    if (waitingForKey) {

                        /** get index of key to set */

                        int i = keysBeingSet[0];

                        int j = keysBeingSet[1];

                        /** get the key pressed */

                        int newKey = evt.getKeyCode();

                        /** key used flag */

                        boolean keyUsed = false;

                        /** see if the key is used already or not */

                        for (int p = 0; p < 4; ++p) {

                            for (int k = 0; k < 5; ++k) {

                                /** if key is used already */

                                if (keys[p][k] == newKey) {

                                    /** if it isn't the key being set */

                                    if (!(p == i && j == k))

                                       /** set key used flag to true */

                                       keyUsed = true;

                                }

                                /** if key used flag is true, then exit loop */

                                if (keyUsed) break;

                            }

                            /** if key used flag is true, then exit loop */

                            if (keyUsed) break;

                        }

                        /** if key isn't used */

                        if (!keyUsed) {

                            /** copy new key */

                            keys[i][j] = newKey;

                            /** reset the key field */

                            keyFields[i][j].setText(

                            KeyEvent.getKeyText(keys[i][j]));

                            /** set waiting for key to false */

                            waitingForKey = false;

                            /** destroy the dialog */

                            dispose();

                        }

                        /** if key is used already */

                        else {

                            /** then show an error dialog */

                            /** create the dialog content */

                            JOptionPane pane = new JOptionPane(

                            "Key: [" + KeyEvent.getKeyText(newKey) +

                            "] is used already.  Pick a different key.");

                            /** setup the dialog controls */

                            pane.setOptionType(-JOptionPane.NO_OPTION);

                            pane.setMessageType(JOptionPane.ERROR_MESSAGE);

                            /** create the dialog */

                            JDialog dialog = pane.createDialog(me, "Error");

                            /** set it so user can't resize the dialog */

                            dialog.setResizable(false);

                            /** show the dialog */

                            dialog.show();

                        }

                    }

                }

            });

 

            /** set the dialog so the user can't resize it */

            setResizable(false);

            /** set dialog size */

            setSize(300, 0);

 

            int x = owner.getLocation().x + (owner.getSize().width -

            getSize().width) / 2;

            int y = owner.getLocation().y + (owner.getSize().width -

            getSize().height) / 2;

            /** center the dialog relative to the owner */

            setLocation(x, y);

 

            /** finally show the dialog */

            show();

        }

    }

}

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 /*

 * ErrorDialog.java

 * Created on March 9, 2001, 3:06 PM

 */

import java.awt.*;

import javax.swing.*;

import java.io.*;

 

/**

 * This class displays an error dialog then exits the program when specified.

 *

 * @author Sammy Leong

 * @version 1.0

 */

public class ErrorDialog

{

    /**

     * Construct from an Exception object.

     * @param e exception object thrown

     */

    public ErrorDialog(Exception e)

    {

        /** store the stack trace (error message) into a string variable */

        CharArrayWriter writer = new CharArrayWriter();

        e.printStackTrace(new PrintWriter(writer, true));

        String result = new String(" " + writer.toString() + "\n" +

        " CLICK OK TO TERMINATE THE PROGRAM.");

       

        /** create a text field and put the error message into it */

        JTextArea ta = new JTextArea(result);

        /** make it read only */

        ta.setEditable(false);

       

        /** create a scrollpane to contain the text field */

        JScrollPane scroller = new JScrollPane(ta);

        /** create a container to contain the scrollpane */

        JOptionPane pane = new JOptionPane(scroller);

        /** setup the scrollpane */

        pane.setOptionType(-JOptionPane.NO_OPTION);

        pane.setMessageType(JOptionPane.ERROR_MESSAGE);

       

        /** create and show the dialog */

        JDialog dialog = pane.createDialog(null, "Exception Caught");

        dialog.setResizable(false);

        dialog.show();

        Object selection = pane.getValue();

       

        /** exit the program */

        System.exit(-1);

    }

   

    /**

     * Construct from an Exception object and a boolean flag of whether to

     * terminate the program or not.

     * @param e exception object thrown

     */   

    public ErrorDialog(Exception e, boolean terminate)

    {

        /** store the stack trace (error message) into a string variable */

        CharArrayWriter writer = new CharArrayWriter();

        e.printStackTrace(new PrintWriter(writer, true));

        String result = new String(" " + writer.toString());

       

        /** create a text field and put the error message into it */

        JTextArea ta = new JTextArea(result);

        ta.setEditable(false);

       

        /** create a scrollpane to contain the text field */

        JScrollPane scroller = new JScrollPane(ta);

        /** create a container to contain the scrollpane */

        JOptionPane pane = new JOptionPane(scroller);

        /** setup the scrollpane */

        pane.setOptionType(-JOptionPane.NO_OPTION);

        pane.setMessageType(JOptionPane.ERROR_MESSAGE);

       

        /** create and show the dialog */

        JDialog dialog = pane.createDialog(null, "Exception Caught");

        dialog.setResizable(false);

        dialog.show();

        Object selection = pane.getValue();

       

        /** exit the program if terminate is tree */

        if (terminate)

            System.exit(-1);

    }       

}

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 import java.io.*;

 

/**

 * File:         BomberBGM

 * Copyright:    Copyright (c) 2001

 * @author Sammy Leong

 * @version 1.0

 */

 

/**

 * This class plays the background music.

 */

public class BomberSndEffect extends Thread {

    public BomberSndEffect() {

        start();

    }

 

    public void playSound(String str) {

        /** if Java 2 is available */

        if (Main.J2) {

            SoundPlayer sound = null;

            try {

                /** create sound player */

                sound = new SoundPlayer(

                new File(BomberMain.RP +

                "Sounds/BomberSndEffects/" +  str + ".mid").

                getCanonicalPath());

            }

            catch (Exception e) { }

            /** open file */

            ((SoundPlayer)sound).open();

            /** then play sound */

            sound.change(0, false);

        }

    }

}

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

/*

 * SoundPlayer.java

 * Created on March 10, 2001, 4:23 PM

 */

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

import javax.sound.midi.*;

import javax.sound.sampled.*;

import java.io.File;

import java.io.FileInputStream;

import java.io.BufferedInputStream;

import java.util.Vector;

import java.net.URL;

 

/**

 * This class is used to play sound files.

 *

 * @author Sammy Leong

 * @version 1.0

 */

public class SoundPlayer extends JPanel

implements Runnable, LineListener, MetaEventListener, ActionListener

{

    /** sound object list */

    public Vector sounds = new Vector();

    /** thread used to play the sound */

    private Thread thread;

    /** sound sequencer */

    private Sequencer sequencer;

    /** flag: playing midi or audio file */

    private boolean midiEOM, audioEOM;

    /** sound synthesizer */

    private Synthesizer synthesizer;

    /** channel objects for playing midi */

    private MidiChannel channels[];

    /** current playing sound */

    private Object currentSound;

    /** current sound name */

    private String currentName;

    /** sound list offset */

    private int num = -1;

    /** flag: change of sound */

    private boolean bump;

    /** flag: paused or not */

    private boolean paused = false;

    /** flag: loop or not */

    public boolean loop = true;

    /** volumn */

    private int volumn = 100;

    /** control buttons */

    JButton startB, pauseB, prevB, nextB;

 

    /**

     * Construct a sound player with directory name of music files.

     * @param dirName directory with sound files

     */

    public SoundPlayer(String dirName)

    {

        if (dirName != null)

        {

            /** load the sound files */

            loadFile(dirName);

        }

 

        /** create control buttons the panel */

        JPanel jp = new JPanel(new GridLayout(4, 1));

        /** create the buttons */

        startB = addButton("Start", jp, sounds.size() != 0);

        pauseB = addButton("Pause", jp, false);

        prevB = addButton("<<", jp, false);

        nextB = addButton(">>", jp, false);

    }

 

    /**

     * Create a button.

     * @param name name of button

     * @param panel container of button

     * @param state enabled or disabled

     */

    private JButton addButton(String name, JPanel panel, boolean state)

    {

        /** create the button */

        JButton b = new JButton(name);

        /** add action handler */

        b.addActionListener(this);

        /** set state */

        b.setEnabled(state);

        if (panel != null)

            /** add it to the container */

            panel.add(b);

        /** return the button */

        return b;

    }

 

    /**

     * Create and open the sequencer.

     */

    public void open()

    {

        try

        {

            /** get the system sequencer */

            sequencer = MidiSystem.getSequencer();

            if (sequencer instanceof Synthesizer)

            {

                synthesizer = (Synthesizer)sequencer;

                /** get the system channels */

                channels = synthesizer.getChannels();

            }

        }

        catch (Exception e)

        {

            return;

        }

        /** add the meta event listener */

        sequencer.addMetaEventListener(this);

    }

 

    /**

     * Close the sequencer.

     */

    public void close()

    {

        /** if a sound is playing */

        if (thread != null && startB != null)

        {

            /** stop playing */

            startB.doClick(0);

        }

        /** if the sequencer is opened */

        if (sequencer != null)

        {

            /** close it */

            sequencer.close();

        }

    }

 

    /**

     * Loads all sound files ina directory.

     * @param name directory name

     */

    public void loadFile(String name)

    {

        try

        {

            /** create the file object */

            File file = new File(name);

            /** if the object is a directory */

            if (file != null && file.isDirectory())

            {

                /** get the list of files in the directory */

                String files[] = file.list();

                /** iterate through the list */

                for (int i = 0; i < files.length; i++)

                {

                    /** get the path */

                    File leafFile = new File(file.getAbsolutePath(), files[i]);

                    /** if it's a directory */

                    if (leafFile.isDirectory())

                    {

                        /** recurse into the directory */

                        loadFile(leafFile.getAbsolutePath());

                    }

                    /** if it's a file */

                    else

                    {

                        /** load the file */

                        addSound(leafFile);

                    }

                }

            }

            /** if the object is a file and it exists */

            else if (file != null && file.exists())

            {

                /** load the file */

                addSound(file);

            }

        }

        catch (Exception e)

        {

        }

    }

 

    /**

     * Attemps to add a sound file.

     * @param file file object to add

     */

    private void addSound(File file)

    {

        String s = file.getName();

        /** if the file has right extension */

        if (s.endsWith(".au") || s.endsWith(".rmf") ||

        s.endsWith(".mid") || s.endsWith(".wav") ||

        s.endsWith(".aif") || s.endsWith(".aiff"))

        {

            /** add the file */

            sounds.add(file);

        }

    }

 

    /**

     * Loads a sound object.

     * @param object sound object to load

     */

    public boolean loadSound(Object object)

    {

        /** if the object is a URL object */

        if (object instanceof URL)

        {

            /** get the file name */

            currentName = ((URL) object).getFile();

            try

            {

                /** try to create an audio sound object */

                currentSound = AudioSystem.getAudioInputStream((URL) object);

            }

            /** if it's not an audio sound object */

            catch(Exception e)

            {

                try

                {

                    /** try to create a midi sound object */

                    currentSound = MidiSystem.getSequence((URL) object);

                }

                /** if it's not a midi sound object neither */

                catch (InvalidMidiDataException e1)

                {

                }

                catch (Exception e2)

                {

                }

            }

        }

        /** if the object is a File object */

        else if (object instanceof File)

        {

            /** get the file name */

            currentName = ((File) object).getName();

            try

            {

                /** try to create an audio sound object */

                currentSound = AudioSystem.getAudioInputStream((File) object);

            }

            /** if it's not an audio sound object */

            catch(Exception e)

            {

                /** load midi & rmf as inputstreams for now */

                //try {

                //currentSound = MidiSystem.getSequence((File) object);

                //} catch (Exception e2) {

                try

                {

                    /** open the file */

                    FileInputStream is = new FileInputStream((File) object);

                    /** try to create a midi sound object */

                    currentSound = new BufferedInputStream(is, 1024);

                }

                catch (Exception e1)

                {

                }

                //}

            }

        }

 

        /** if no sequencer available */

        if (sequencer == null)

        {

            /** set sound object to null */

            currentSound = null;

            /** and otta here */

            return false;

        }

 

        /** if the sound object is an AudioInputStream object */

        if (currentSound instanceof AudioInputStream)

        {

            try

            {

                /** create the stream */

                AudioInputStream stream = (AudioInputStream) currentSound;

                /** create the file format object */

                AudioFormat format = stream.getFormat();

 

                /**

                 * we can't yet open the device for ALAW/ULAW playback,

                 * convert ALAW/ULAW to PCM

                 */

                if ((format.getEncoding() == AudioFormat.Encoding.ULAW) ||

                (format.getEncoding() == AudioFormat.Encoding.ALAW))

                {

                    /** setup the format */

                    AudioFormat tmp = new AudioFormat(

                    AudioFormat.Encoding.PCM_SIGNED,

                    format.getSampleRate(), format.getSampleSizeInBits() * 2,

                    format.getChannels(), format.getFrameSize() * 2,

                    format.getFrameRate(), true);

                    /** open the stream with specified format */

                    stream = AudioSystem.getAudioInputStream(tmp, stream);

                    /** store the formst for later use */

                    format = tmp;

                }

                /** create the line to play the sound */

                DataLine.Info info = new DataLine.Info( Clip.class,

                stream.getFormat(), ((int) stream.getFrameLength() *

                format.getFrameSize()));

 

                /** convert the sound into a clip */

                Clip clip = (Clip) AudioSystem.getLine(info);

                clip.addLineListener(this);

                clip.open(stream);

                /** store the clip */

                currentSound = clip;

            }

            catch (Exception e)

            {

            }

        }

        /** if the sound object is a sequence */

        else if (currentSound instanceof Sequence ||

        currentSound instanceof BufferedInputStream)

        {

            try

            {

                /** open the sequencer */

                sequencer.open();

                /** if the object is a sequence */

                if (currentSound instanceof Sequence)

                {

                    /** set the sequence to the sequencer */

                    sequencer.setSequence((Sequence) currentSound);

                }

                /** if the object is a buffered input stream */

                else

                {

                    /** set the stream to the sequencer */

                    sequencer.setSequence((BufferedInputStream) currentSound);

                }

            }

            catch (InvalidMidiDataException imde)

            {

                return false;

            }

            catch (Exception ex)

            {

                return false;

            }

        }

        /** otta here */

        return true;

    }

 

    /**

     * Plays the current sound object.

     */

    public void playSound() {

        /** set volumn */

        setGain(volumn);

        /** set pan */

        setPan();

        /** reset flags to false */

        midiEOM = audioEOM = bump = false;

        /** if object is a sequencer */

        if (currentSound instanceof Sequence

        || currentSound instanceof BufferedInputStream && thread != null)

        {

            /** play the sound */

            sequencer.start();

            /** iterate */

            while (!midiEOM && thread != null && !bump)

            {

                try

                {

                    thread.sleep(99);

                }

                catch (Exception e)

                {

                    break;

                }

            }

            /** stop playing */

            sequencer.stop();

            /** close the sequencer */

            sequencer.close();

        }

        /** if the current sound object is a clip */

        else if (currentSound instanceof Clip && thread != null)

        {

            /** get the clip */

            Clip clip = (Clip) currentSound;

            /** play the clip */

            clip.start();

            try

            {

                thread.sleep(99);

            }

            catch (Exception e)

            { }

            /** iterate */

            while ((paused || clip.isActive()) && thread != null && !bump)

            {

                try

                {

                    thread.sleep(99);

                }

                catch (Exception e)

                {

                    break;

                }

            }

            /** stop playing */

            clip.stop();

            /** close the clip */

            clip.close();

        }

        currentSound = null;

    }

 

    /**

     * Must have method.

     * @param event line event

     */

    public void update(LineEvent event)

    {

        if (event.getType() == LineEvent.Type.STOP && !paused)

        {

            audioEOM = true;

        }

    }

 

    /**

     * Must have method.

     * @param message meta message

     */

    public void meta(MetaMessage message)

    {

        /** 47 is end of track */

        if (message.getType() == 47)

        {

            midiEOM = true;

        }

    }

 

    /**

     * @return current thread

     */

    public Thread getThread()

    {

        return thread;

    }

 

 

    /**

     * Creates the thread and start it.

     */

    public void start()

    {

        /** create the thread */

        thread = new Thread(this);

        /** name the thread */

        thread.setName("SoundPlayer");

        /** start the thread */

        thread.start();

    }

 

    /**

     * Stops then destroys the thread.

     */

    public void stop()

    {

        /** if thread is alive */

        if (thread != null)

        {

            /** destroy it */

            thread.interrupt();

        }

        /** set it to null */

        thread = null;

    }

 

    /**

     * Thread method.

     */

    public void run() {

        /** iterate */

        do

        {

            /** if the sound object exists */

            if( loadSound(sounds.elementAt(num)) == true )

            {

                /** play the sound */

                playSound();

            }

        }

        /** while loop is on and the thread isn't killed */

        while (loop && thread != null);

 

        /** if the thread isn't dead */

        if (thread != null)

        {

            /** kill it */

            startB.doClick();

        }

        /** reste everything */

        thread = null;

        currentName = null;

        currentSound = null;

    }

 

    /**

     * Set pan.

     */

    public void setPan() {

        /** default value of 0: pan left / right evenly */

        int value = 0;

        /** if the sound object is a clip */

        if (currentSound instanceof Clip)

        {

            try

            {

                /** get the clip */

                Clip clip = (Clip) currentSound;

                /** get the current pane value */

                FloatControl panControl =

                (FloatControl) clip.getControl(FloatControl.Type.PAN);

                /** set the pan value */

                panControl.setValue(value/100.0f);

            }

            catch (Exception ex)

            {

            }

        }

        /** if the sound object is a sequence */

        else if (currentSound instanceof Sequence ||

        currentSound instanceof BufferedInputStream)

        {

            /** iterate through all the channels */

            for (int i = 0; i < channels.length; i++)

            {

                /** and set the pan values */

                channels[i].controlChange(10,

                (int)(((double)value + 100.0) / 200.0 *  127.0));

            }

        }

    }

 

    /**

     * Set gain (volumn).

     * @param value volumn value

     */

    public void setGain(double value)

    {

        /** if current sound object is a clip */

        if (currentSound instanceof Clip)

        {

            try

            {

                /** get the clip */

                Clip clip = (Clip) currentSound;

                /** get the current gain */

                FloatControl gainControl =

                (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);

                /** create and calculate the gain value */

                float dB = (float)

                (Math.log(value==0.0?0.0001:value)/Math.log(10.0)*20.0);

                /** set the gain value */

                gainControl.setValue(dB);

            }

            catch (Exception ex)

            {

            }

        }

        /** if current sound object is a sequence */

        else if (currentSound instanceof Sequence ||

        currentSound instanceof BufferedInputStream)

        {

            /** iterate through all the channels */

            for (int i = 0; i < channels.length; i++)

            {

                /** set gain */

                channels[i].controlChange(7, (int)(value * 127.0));

            }

        }

    }

 

    /**

     * Set gain to 0.

     */

    public void mute()

    {

        volumn = 0;

        setGain(volumn);

        /** pause the sound for a mili second */

        bump = true;

    }

 

    /**

     * Set gainto 100.

     */

    public void unmute()

    {

        volumn = 100;

        setGain(volumn);

        /** pause the sound for a mili second */

        bump = true;

    }

 

    /**

     * Change to different sound.

     * @param n new sound offset

     * @param l loop or not

     */

    public void change(int n, boolean l)

    {

        paused = false;

        /** change text of pause button */

        pauseB.setText("Pause");

        /** get loop and offset */

        loop = l;

        num = n;

        /** pause the sound for a mili second */

        bump = true;

        /** if no sound is playing */

        if (startB.getText().equals("Start"))

            /** play the sound */

            startB.doClick();

    }

 

    /**

     * Play the current sound.

     */

    public void controlPlay()

    {

        startB.doClick();

    }

 

    /**

     * Stop the current sound.

     */

    public void controlStop()

    {

        startB.doClick();

    }

 

    /**

     * Play the previous sound.

     */

    public void controlBack()

    {

        prevB.doClick();

    }

 

    /**

     * Play the next sound.

     */

    public void controlNext()

    {

        nextB.doClick();

    }

 

    /**

     * Set buttons states.

     * @param state enabl or disable

     */

    public void setComponentsEnabled(boolean state)

    {

        pauseB.setEnabled(state);

        prevB.setEnabled(state);

        nextB.setEnabled(state);

    }

 

    /**

     * @return whether something is playing or not

     */

     public boolean isPlaying() {

        return (startB.getText().equals("Start") ? false : true);

     }

 

    /**

     * Action listener.

     * @param e action event

     */

    public void actionPerformed(ActionEvent e)

    {

        /** get source of event */

        JButton button = (JButton) e.getSource();

        /** if the start button is clicked */

        if (button.getText().equals("Start"))

        {

            /** not paused */

            paused = false;

            /** if offset is out of range than set it to 0 */

            num = num == -1 ? 0 : num;

            /** start playing */

            start();

            /** change button text to "Stop" */

            button.setText("Stop");

            /** change buttons states */

            setComponentsEnabled(true);

        }

        /** if the stop button is clicked */

        else if (button.getText().equals("Stop"))

        {

            /** not paused */

            paused = false;

            /** stop playing */

            stop();

            /** change texts of buttons */

            button.setText("Start");

            pauseB.setText("Pause");

            /** change buttons states */

            setComponentsEnabled(false);

        }

        /** if the pause button is clicked */

        else if (button.getText().equals("Pause"))

        {

            /** paused */

            paused = true;

            /** if the sound object is a clip */

            if (currentSound instanceof Clip)

            {

                /** stop the clip */

                ((Clip) currentSound).stop();

            }

            /** if the sound object is a sequence */

            else if (currentSound instanceof Sequence ||

            currentSound instanceof BufferedInputStream)

            {

                /** stop the sequence */

                sequencer.stop();

            }

            /** change the button text */

            pauseB.setText("Resume");

        }

        else if (button.getText().equals("Resume"))

        {

            /** not paused anymore */

            paused = false;

            /** if sound is a clip */

            if (currentSound instanceof Clip)

            {

                /** start the clip */

                ((Clip) currentSound).start();

            }

            /** if sound is a sequence */

            else if (currentSound instanceof Sequence ||

            currentSound instanceof BufferedInputStream)

            {

                /** start the sequence */

                sequencer.start();

            }

            /** change the button text */

            pauseB.setText("Pause");

        }

        /** if the back button is clicked */

        else if (button.getText().equals("<<"))

        {

            paused = false;

            /** change button text */

            pauseB.setText("Pause");

            /** go to previous sound */

            num = num-1 < 0 ? sounds.size()-1 : num-2;

            /** change sound */

            bump = true;

        }

        /** if the next button is clicked */

        else if (button.getText().equals(">>"))

        {

            paused = false;

            /** change button text */

            pauseB.setText("Pause");

            /** go to next sound */

            num = num+1 == sounds.size() ? -1 : num;

            /** change sound */

            bump = true;

        }

    }

}

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

OUTPUT