Best Projects

Bug Trackingsystem,Books online shopping,college management system,HR management system,Internet banking,Online chat room ,Online exam,Telephone billing system,Banking application,ATM database,airways reservation system,virtual network computing ,calculator,SMTP(simple mail transfer protocol)

Bomber Man














//BomberBGM.java
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();
}
}
}


//BomberBomb.java
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);
}
}


//Bomber Bonus.java
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);
}
}




//BomberConFigdialog.java
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();
}
}
}



//BomberFire.java
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);
}
}




//BomberGame.java
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));
}
}
}



//Bomberimagebutton.java
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);
}
}




//BomberkeyConfig.java
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();
}
}






//BomberkeyQueue.java
/**
* 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;
}
}
}




//Bombermain.java
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();
}
}





//Bombermap.java
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);
}
}
}
}
}
}






//Bombermenu.java
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);
}
}





//BomberPlayer.java
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);
}
}
}




//BomberRandINt.java
/**
* 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;
}
}



//BomberSndEffect.java
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);
}
}
}



//Error Dialog
/*
* 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);
}
}


//main
/*
* 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();
}
}




/*
* 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 */ //sound player
pauseB.setText("Pause");
/** go to next sound */
num = num+1 == sounds.size() ? -1 : num;
/** change sound */
bump = true;
}
}
}

1 comment:

Anonymous said...

I am currently working on a Bomberman game for my programming and i am having trouble getting my Bomb() class to allow the user to place multiple bombs currently set to 5 max and each bomb have its own timer the starts as soon as the bomb is placed and ends when it explodeds