Committing historical code from 2001 with minor tweaks to make function

in maven.
This commit is contained in:
Rob 2016-09-11 11:25:08 -05:00
parent 92bdd9b4d8
commit 3bc978ed3a
99 changed files with 4305 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
/target/
/.classpath
/.project
/.settings/

BIN
doc/current/GamePlay.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

BIN
doc/original/Bomb.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 941 B

BIN
doc/original/Exit.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 895 B

BIN
doc/original/GameScreen.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
doc/original/HelpScreen.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

BIN
doc/original/Mine.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 889 B

BIN
doc/original/Mouse.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 914 B

BIN
doc/original/MouseMaze.dsk Normal file

Binary file not shown.

BIN
doc/original/Robot.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 924 B

BIN
doc/original/Skull.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 941 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

46
pom.xml Normal file
View File

@ -0,0 +1,46 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>a2geek.games</groupId>
<artifactId>mouse-maze-2001</artifactId>
<version>1.9.0-FINAL</version>
<name>Mouse Maze 2001</name>
<description>A recreation of a game developed in 1983.</description>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.shade.version>2.4.3</maven.shade.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>${maven.shade.version}</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>a2geek.games.mousemaze2001.MouseMaze2001</Main-Class>
<Implementation-Title>Mouse Maze 2001</Implementation-Title>
<Implementation-Version>${project.version}</Implementation-Version>
</manifestEntries>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,308 @@
package a2geek.games.mousemaze2001;
import java.util.*;
import javax.swing.border.*;
import a2geek.games.mousemaze2001.domain.*;
import a2geek.games.mousemaze2001.images.ImageManager;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
/**
* Provides the panel used for game settings.
*
* Creation date: (10/27/01 7:32:59 PM)
* @author: <a href='mailto:greener@charter.net'>Rob Greene</a>
* @version: RJG 10/29/2001 22:40:54
*/
public class GameSettingsPanel extends JPanel implements ActionListener {
private static final String HARD = "hard";
private static final String EASY = "easy";
private static final String DEFAULT = "default";
private JSlider bombsPerLevel;
private JSlider robotRange;
private JSlider robotShotFrequency;
private JSlider robotMineFrequency;
private JCheckBox mouseShoots;
private JCheckBox robotShotDistanceFixed;
private JCheckBox animatedImages;
private JCheckBox unlimitedLevels;
private JCheckBox unlimitedLives;
private JCheckBox shieldedRobots;
private GameSettings easySettings;
private GameSettings hardSettings;
private GameSettings defaultSettings;
private GameSettings currentSettings;
/**
* GameSettingsPanel constructor comment.
*/
public GameSettingsPanel() {
super();
initializeSettings();
initializeComponents();
copyFromCurrentSettings();
}
/**
* Handle action events from buttons.
*
* Creation date: (10/27/01 7:45:27 PM)
*/
public void actionPerformed(ActionEvent actionEvent) {
String command = actionEvent.getActionCommand();
if (command != null) {
if (DEFAULT.equals(command)) {
currentSettings = new GameSettings(defaultSettings);
} else if (EASY.equals(command)) {
currentSettings = new GameSettings(easySettings);
} else if (HARD.equals(command)) {
currentSettings = new GameSettings(hardSettings);
}
copyFromCurrentSettings();
}
}
/**
* Copy the current settings values to the screen components.
*
* Creation date: (10/27/01 11:38:39 PM)
*/
public void copyFromCurrentSettings() {
bombsPerLevel.setMaximum(currentSettings.getMaxBombsPerLevel());
bombsPerLevel.setValue(currentSettings.getBombsPerLevel());
robotRange.setMaximum(currentSettings.getMaxRobotShotRange());
robotRange.setValue(currentSettings.getRobotShotRange());
robotShotDistanceFixed.setSelected(currentSettings.isFixedRobotShotRange());
robotShotFrequency.setValue(currentSettings.getRobotShootFrequency());
robotMineFrequency.setValue(currentSettings.getRobotMineFrequency());
mouseShoots.setSelected(currentSettings.isShootingMouse());
animatedImages.setSelected(currentSettings.isAnimatedImages());
unlimitedLevels.setSelected(currentSettings.isUnlimitedGameLevels());
unlimitedLives.setSelected(currentSettings.isUnlimitedLives());
shieldedRobots.setSelected(currentSettings.isShieldedRobots());
repaint();
}
/**
* Copy the current settings values from the screen components.
*
* Creation date: (10/27/01 11:38:39 PM)
*/
public void copyToCurrentSettings() {
currentSettings.setBombsPerLevel(bombsPerLevel.getValue());
currentSettings.setRobotShotRange(robotRange.getValue());
currentSettings.setFixedRobotShotRange(robotShotDistanceFixed.isSelected());
currentSettings.setRobotShootFrequency(robotShotFrequency.getValue());
currentSettings.setRobotMineFrequency(robotMineFrequency.getValue());
currentSettings.setShootingMouse(mouseShoots.isSelected());
currentSettings.setAnimatedImages(animatedImages.isSelected());
currentSettings.setUnlimitedGameLevels(unlimitedLevels.isSelected());
currentSettings.setUnlimitedLives(unlimitedLives.isSelected());
currentSettings.setShieldedRobots(shieldedRobots.isSelected());
}
/**
* Create a bordered panel.
*
* Creation date: (10/27/01 8:35:30 PM)
*/
protected JPanel createBorderedPanel(String title) {
return createBorderedPanel(title, BoxLayout.Y_AXIS);
}
/**
* Create a bordered panel.
*
* Creation date: (10/27/01 8:35:30 PM)
*/
protected JPanel createBorderedPanel(String title, int axis) {
JPanel thePanel = new JPanel();
thePanel.setLayout(new BoxLayout(thePanel, axis));
TitledBorder titledBorder = new TitledBorder(title);
titledBorder.setTitleColor(Color.black);
thePanel.setBorder(titledBorder);
return thePanel;
}
/**
* Create a standard image button.
*
* Creation date: (10/27/01 3:05:07 PM)
*/
protected JButton createImageButton(String resourceName, String commandString) {
return createImageButton(resourceName, commandString, this);
}
/**
* Create a standard image button.
*
* Creation date: (10/27/01 3:05:07 PM)
*/
protected JButton createImageButton(String resourceName, String commandString, ActionListener actionListener) {
JButton button = new JButton(new ImageIcon(ImageManager.getInstance().getImage(resourceName)));
button.setActionCommand(commandString);
button.addActionListener(actionListener);
return button;
}
/**
* Create a slider panel.
*
* Creation date: (10/27/01 8:38:48 PM)
*/
protected JSlider createSlider(int minimumValue, int maximumValue, int currentValue) {
JSlider theSlider = new JSlider(minimumValue, maximumValue, currentValue);
if (maximumValue >= 100) {
theSlider.setMinorTickSpacing(1);
theSlider.setMajorTickSpacing(10);
} else {
theSlider.setMajorTickSpacing(1);
}
theSlider.setPaintTicks(true);
theSlider.setPaintLabels(true);
theSlider.setSnapToTicks(true);
theSlider.setForeground(Color.black);
// change the foreground color of all labels (numbers)
Dictionary table = theSlider.getLabelTable();
Enumeration e = table.elements();
while (e.hasMoreElements()) {
JLabel label = (JLabel) e.nextElement();
label.setForeground(Color.black);
}
return theSlider;
}
/**
* Retrieve the current game settings.
*
* Creation date: (10/28/01 1:23:58 PM)
*/
public GameSettings getCurrentSettings() {
copyToCurrentSettings();
return currentSettings;
}
/**
* Initialize the graphical components.
*
* Creation date: (10/27/01 11:18:17 PM)
*/
protected void initializeComponents() {
GameSettings curs = currentSettings;
JPanel everything = new JPanel();
BoxLayout boxLayout = new BoxLayout(everything, BoxLayout.Y_AXIS);
everything.setLayout(boxLayout);
JPanel bombsPanel = createBorderedPanel("Bombs per level");
bombsPerLevel = createSlider(0,curs.getMaxBombsPerLevel(),curs.getBombsPerLevel());
bombsPanel.add(bombsPerLevel);
JPanel rangePanel = createBorderedPanel("Range of robot shooting");
robotRange = createSlider(1,curs.getMaxRobotShotRange(),curs.getRobotShotRange());
robotShotDistanceFixed = new JCheckBox("Robots can only shoot the maximum distance (specified above)");
robotShotDistanceFixed.setSelected(curs.isFixedRobotShotRange());
robotShotDistanceFixed.setHorizontalAlignment(JCheckBox.LEFT);
rangePanel.add(robotRange);
rangePanel.add(robotShotDistanceFixed);
JPanel freqPanel = createBorderedPanel("Robot shooting frequency (%)");
robotShotFrequency = createSlider(0,100,curs.getRobotShootFrequency());
freqPanel.add(robotShotFrequency);
JPanel minePanel = createBorderedPanel("Robot mine dropping frequency (%)");
robotMineFrequency = createSlider(0,100,curs.getRobotMineFrequency());
minePanel.add(robotMineFrequency);
JPanel settingsPanel = createBorderedPanel("Other settings");
mouseShoots = new JCheckBox("Honestly, mice can shoot. Really!");
mouseShoots.setSelected(curs.isShootingMouse());
animatedImages = new JCheckBox("Animated images");
animatedImages.setSelected(curs.isAnimatedImages());
unlimitedLevels = new JCheckBox("Unlimited levels");
unlimitedLevels.setSelected(curs.isUnlimitedGameLevels());
unlimitedLives = new JCheckBox("Unlimited lives");
unlimitedLives.setSelected(curs.isUnlimitedLives());
shieldedRobots = new JCheckBox("Are robots shielded?");
shieldedRobots.setSelected(curs.isShieldedRobots());
settingsPanel.add(mouseShoots);
settingsPanel.add(shieldedRobots);
settingsPanel.add(animatedImages);
settingsPanel.add(unlimitedLevels);
settingsPanel.add(unlimitedLives);
JPanel predefinedPanel = createBorderedPanel("Predefined game settings");
predefinedPanel.setLayout(new GridLayout(3,1));
JButton easyButton = createImageButton("EasyButton.gif", EASY);
JButton defaultButton = createImageButton("DefaultButton.gif", DEFAULT);
JButton hardButton = createImageButton("HardButton.gif", HARD);
predefinedPanel.add(easyButton);
predefinedPanel.add(defaultButton);
predefinedPanel.add(hardButton);
JPanel comboPanel = new JPanel(new GridLayout(1,2));
comboPanel.add(predefinedPanel);
comboPanel.add(settingsPanel);
everything.add(bombsPanel);
everything.add(rangePanel);
everything.add(freqPanel);
everything.add(minePanel);
everything.add(comboPanel);
// apparantly these need to be separate panels...
JPanel dividerPanel = new JPanel();
JPanel dividerPanel2 = new JPanel();
JPanel dividerPanel3 = new JPanel();
JPanel dividerPanel4 = new JPanel();
this.setLayout(new BorderLayout());
this.add(dividerPanel, BorderLayout.WEST);
this.add(dividerPanel2, BorderLayout.EAST);
this.add(dividerPanel3, BorderLayout.SOUTH);
this.add(dividerPanel4, BorderLayout.NORTH);
this.add(everything, BorderLayout.CENTER);
}
/**
* Initialize the predefined Settings.
*
* Creation date: (10/27/01 11:20:00 PM)
*/
protected void initializeSettings() {
currentSettings = new GameSettings(MazeDomain.getInstance().getGameSettings());
easySettings = new GameSettings();
easySettings.load("easy.properties");
hardSettings = new GameSettings();
hardSettings.load("hard.properties");
defaultSettings = new GameSettings();
defaultSettings.load("default.properties");
}
/**
* Set the current game settings.
*
* Creation date: (10/28/01 1:23:14 PM)
*/
public void setCurrentSettings(GameSettings gameSettings) {
currentSettings = new GameSettings(gameSettings);
copyFromCurrentSettings();
}
}

View File

@ -0,0 +1,325 @@
package a2geek.games.mousemaze2001;
import java.io.*;
import java.awt.image.*;
import java.net.*;
import java.awt.*;
import javax.swing.*;
import a2geek.games.mousemaze2001.images.*;
/**
* Insert the type's description here.
*
* Creation date: (10/16/01 10:28:58 PM)
* @author: <a href='mailto:greener@charter.net'>Rob Greene</a>
* @version: RJG 10/31/2001 22:12:32
*/
public class IntroPanel extends JPanel {
private static IntroPanel instance = new IntroPanel();
private String[] imageNames = {
"OriginalMouseMazeLogo.gif",
"OriginalMouseMazeHelp.gif",
"OriginalMouseMazeGameShot.gif",
"OriginalMouseMazeWin.gif"
};
private Image[] scaledImages;
private int ticker;
private int stage;
private String[] story = {
"A long time ago,",
"when life was much different,",
"I wrote my first game called...",
"",
"&1",
"",
"",
"This a rewrite.",
"",
"",
"The Apple ][,",
"simple graphics,",
"small computers,",
"All Gone!",
"",
"",
"The original help screen:",
"&2",
"",
"A game in progress:",
"&3",
"",
"The winners' screen:",
"&4"
};
private Image marquee;
private Thread creationThread;
/**
* IntroPanel constructor comment.
*/
protected IntroPanel() {
super();
initialize();
}
public static IntroPanel getInstance() {
return instance;
}
protected int getMaxStage() {
return 2;
}
public void incrementTicker() {
ticker++;
}
private void initialize() {
setMinimumSize(new Dimension(560,384));
setMaximumSize(new Dimension(560*2,384*2));
setPreferredSize(new Dimension(560,384));
// load original images
Image originalImages[] = new Image[imageNames.length];
ImageManager imageManager = ImageManager.getInstance();
for (int i=0; i<imageNames.length; i++) {
originalImages[i] = imageManager.getImage(imageNames[i]);
}
// create scaled images (except #0)
MediaTracker tracker = new MediaTracker(this);
scaledImages = new Image[originalImages.length];
for (int i=0; i<originalImages.length; i++) {
Image scaled = originalImages[i];
int width = scaled.getWidth(null) / 2;
if (i > 0) {
scaled = scaled.getScaledInstance(width, -1, Image.SCALE_FAST);
}
tracker.addImage(scaled, i);
scaledImages[i] = scaled;
}
try {
tracker.waitForAll();
} catch (InterruptedException ex) {
}
}
/**
* This method will layout the marquee on the given grapics context - which can be
* the screen as well as an off-screen image.
*
* Creation date: (10/19/01 11:16:17 PM)
*/
protected int layoutMarquee(Image layoutImage) {
Graphics g = layoutImage.getGraphics();
Font font = new Font(g.getFont().getFontName(), Font.BOLD, 20);
g.setFont(font);
FontMetrics metrics = g.getFontMetrics();
int fontHeight = metrics.getHeight();
int lines = story.length;
int screenHeight = layoutImage.getHeight(null);
int screenWidth = layoutImage.getWidth(null);
g.setColor(Color.black);
g.fillRect(0,0,screenWidth,screenHeight);
int y = fontHeight + 10; // just a buffer
for (int i=0; i<lines; i++) {
String line = story[i];
if (line.startsWith("&")) {
int shape = Integer.parseInt(line.substring(1))-1;
if (shape >= 0 && shape < scaledImages.length) {
Image image = scaledImages[shape];
int shapeWidth = image.getWidth(null);
int shapeHeight = image.getHeight(null);
int x = (screenWidth - shapeWidth) / 2;
int yPos = y - fontHeight+10;
g.setColor(Color.blue);
g.fillRoundRect(x-5,yPos-5,shapeWidth+10,shapeHeight+10,5,5);
g.drawImage(image,x,yPos,null);
y+= shapeHeight+10;
}
} else {
int stringWidth = metrics.stringWidth(line);
int x = (screenWidth - stringWidth) / 2;
g.setColor(Color.lightGray);
g.drawString(line, x, y);
y+= fontHeight;
}
}
return y + 10;
}
private void nextStage() {
stage++;
if (stage >= getMaxStage()) {
stage = 0;
}
resetTicker();
}
public void paint(Graphics g) {
Font oldFont = g.getFont();
int screenHeight = getHeight();
int screenWidth = getWidth();
g.setColor(Color.black);
g.fillRect(0,0,screenWidth,screenHeight);
switch (stage) {
case 0: paintMarquee(g);
break;
case 1: paintSectionTwo(g);
break;
}
g.setFont(oldFont); // not sure if this needs to be done..
}
/**
* Paint the scrolling marquee.
* The marquee image creation is placed here since the initialize method apparantly
* cannot create a Graphics object from an Image; thus the marquee cannot be rendered
* from the constructor. The marquee image itself is laid out twice - once to get the
* height (allows it to remain somewhat dynamic) and then to generate the real image.
* The rest of the logic here is just to draw the image on the physical screen.
*
* Creation date: (10/19/01 11:13:58 PM)
*/
public void paintMarquee(Graphics g) {
if (marquee == null) {
if (creationThread == null) {
creationThread = new Thread() {
public void run() {
int width = 500;
int height = 800;
Image layoutImage = createImage(width,height);
height = layoutMarquee(layoutImage);
Image marqueeTemp = createImage(width, height);
layoutMarquee(marqueeTemp);
marquee = marqueeTemp;
resetTicker();
};
};
creationThread.setDaemon(true);
creationThread.start();
}
}
int screenHeight = getHeight();
int screenWidth = getWidth();
if (marquee == null) {
String message = "Please wait...";
Font font = new Font(g.getFont().getFontName(), Font.BOLD, 20);
g.setFont(font);
FontMetrics metrics = g.getFontMetrics();
int fontHeight = metrics.getHeight();
int stringWidth = metrics.stringWidth(message);
int x = (screenWidth - stringWidth) / 2;
int y = (screenHeight - fontHeight) / 2;
g.setColor(Color.green);
g.drawString(message, x, y);
} else {
int y = screenHeight - ticker;;
int shapeWidth = marquee.getWidth(null);
int shapeHeight = marquee.getHeight(null);
int x = (screenWidth - shapeWidth) / 2;
g.drawImage(marquee,x,y,null);
y+= shapeHeight;
if (y < 0) {
nextStage();
}
}
}
public void paintSectionTwo(Graphics g) {
Font font = new Font(g.getFont().getFontName(), Font.BOLD, 20);
g.setFont(font);
g.setColor(Color.blue);
FontMetrics metrics = g.getFontMetrics();
int fontHeight = metrics.getHeight();
int fontAscent = metrics.getAscent();
int screenHeight = getHeight();
int screenWidth = getWidth();
int y = (screenHeight - fontHeight*8) / 2;
String title = "Controlling Mouse Maze";
int stringWidth = metrics.stringWidth(title);
g.drawString(title, (screenWidth - stringWidth) / 2, y);
int saveY = y;
int x;
String[] keys;
for (int z=0; z<2; z++) {
if (z == 0) {
y = saveY;
x = (screenWidth / 4);
title = "To Shoot:";
keys = new String[] { "Q", "W", "E", "A", null, "D", "Z", "X", "C" };
} else {
y = saveY;
x= (screenWidth / 2);
title = "To Move:";
keys = new String[] { "Home", "Up", "PgUp", "Left", null, "Right", "End", "Down", "PgDn" };
}
g.setColor(Color.blue);
y+= fontHeight * 2;
g.drawString(title, x, y);
y+= fontHeight;
int maxWidth = 0;
for (int i=0; i<keys.length; i++) {
String key = keys[i];
if (key != null) {
int width = metrics.stringWidth(key);
if (width > maxWidth) maxWidth = width;
}
}
int padding = 6;
for (int i=0; i<keys.length; i++) {
String key = keys[i];
if (key != null) {
int x0 = x + (i%3)*(maxWidth + padding*2);
g.setColor(new Color(0xafafaf));
g.fillRoundRect(x0-padding,y-padding,maxWidth+padding,fontHeight+padding,padding*2,padding*2);
g.setColor(Color.white);
g.drawRoundRect(x0-padding,y-padding,maxWidth+padding,fontHeight+padding,padding*2,padding*2);
g.setColor(Color.black);
int width = metrics.stringWidth(key);
x0 += (maxWidth - width) / 2;
g.drawString(key, x0-(padding/2), y+fontAscent-(padding/2));
if (i%3 == 2) {
y+= fontHeight + padding*2;
}
}
}
}
y+= fontHeight;
g.setColor(Color.blue);
title = "Press Escape to end game";
stringWidth = metrics.stringWidth(title);
g.drawString(title, (screenWidth - stringWidth) / 2, y);
y+= fontHeight;
title = "Press 'P' to pause the game";
stringWidth = metrics.stringWidth(title);
g.drawString(title, (screenWidth - stringWidth) / 2, y);
if (ticker > 1000) {
nextStage();
}
}
public void resetTicker() {
ticker= 0;
}
}

View File

@ -0,0 +1,138 @@
package a2geek.games.mousemaze2001;
import java.awt.*;
import javax.swing.*;
import a2geek.games.mousemaze2001.domain.*;
import a2geek.games.mousemaze2001.mazeobjects.*;
/**
* Insert the type's description here.
*
* Creation date: (10/11/01 10:13:35 PM)
* @author: <a href='mailto:greener@charter.net'>Rob Greene</a>
* @version: RJG 10/31/2001 22:12:32
*/
public class MazeGridPanel extends JPanel {
private int gridWidth = 14;
private int gridHeight = 9;
// the following keep an aspect ratio of 1.33333:1 for w:h
private int minCellHeight = 16;
private int minCellWidth = 15;
private int prefCellWidth = 32;
private int prefCellHeight = 30;
private int maxCellWidth = 64;
private int maxCellHeight = 60;
/**
* MazeGridPanel constructor comment.
*/
public MazeGridPanel() {
super();
initialize();
}
/**
* MazeGridPanel constructor comment.
* @param layout java.awt.LayoutManager
*/
public MazeGridPanel(java.awt.LayoutManager layout) {
super(layout);
initialize();
}
/**
* MazeGridPanel constructor comment.
* @param layout java.awt.LayoutManager
* @param isDoubleBuffered boolean
*/
public MazeGridPanel(java.awt.LayoutManager layout, boolean isDoubleBuffered) {
super(layout, isDoubleBuffered);
initialize();
}
/**
* MazeGridPanel constructor comment.
* @param isDoubleBuffered boolean
*/
public MazeGridPanel(boolean isDoubleBuffered) {
super(isDoubleBuffered);
initialize();
}
protected void initialize() {
setMinimumSize(new Dimension(gridWidth * minCellWidth, gridHeight * minCellHeight));
setMaximumSize(new Dimension(gridWidth * maxCellWidth, gridHeight * maxCellHeight));
setPreferredSize(new Dimension(gridWidth * prefCellWidth, gridHeight * prefCellHeight));
}
public void paint(Graphics g) {
//System.out.println(new java.util.Date() + " - painting screen");
int screenWidth = getWidth();
int screenHeight = getHeight();
g.setColor(Color.black);
g.fillRect(0, 0, screenWidth, screenHeight);
g.setColor(Color.white);
screenWidth -= 2;
screenHeight -= 2;
for (int x=0; x <= gridWidth; x++) {
int xPos = (screenWidth * x) / gridWidth;
g.drawLine(xPos, 0, xPos, screenHeight);
xPos++;
g.drawLine(xPos, 0, xPos, screenHeight);
}
for (int y=0; y <= gridHeight; y++) {
int yPos = (screenHeight * y) / gridHeight;
g.drawLine(0, yPos, screenWidth, yPos);
yPos++;
g.drawLine(0, yPos, screenWidth, yPos);
}
MazeDomain maze = MazeDomain.getInstance();
if (maze.getMap() == null) return;
int cellWidth = screenWidth / gridWidth - 2;
int cellHeight = screenHeight / gridHeight - 2;
for (int x=0; x<maze.getMapWidth(); x++) {
int x0 = (screenWidth * x) / gridWidth + 2;
for (int y=0; y<maze.getMapHeight(); y++) {
int y0 = (screenHeight * y) / gridHeight + 2;
MazeObject object = maze.getMazeObject(x,y);
if (object != null) {
Graphics cell = g.create(x0,y0,cellWidth+1,cellHeight+1);
if (object instanceof AnimatedRobot) {
AnimatedRobot robot = (AnimatedRobot) object;
if (robot.isAlive() == false) continue;
}
object.paint(cell);
}
}
}
String message = maze.getPauseMessage();
if (maze.isPaused()) {
//System.out.println(new java.util.Date() + " - showing message = " + message);
Font font = new Font(g.getFont().getName(), Font.BOLD, 20);
g.setFont(font);
FontMetrics metrics = g.getFontMetrics();
int fontHeight = metrics.getAscent();
int stringWidth = metrics.stringWidth(message);
int xText = (screenWidth - stringWidth) / 2;
int yText = (screenHeight - fontHeight) / 2;
int xBox = xText - 15;
int yBox = yText - 15;
int xWidth = stringWidth + 30;
int yHeight = fontHeight + 30;
g.setColor(Color.blue);
g.fillRoundRect(xBox,yBox,xWidth,yHeight,15,15);
g.setColor(Color.white);
g.drawRoundRect(xBox,yBox,xWidth,yHeight,15,15);
g.setColor(Color.white);
g.drawString(message, xText, yText + fontHeight);
}
}
}

View File

@ -0,0 +1,42 @@
package a2geek.games.mousemaze2001;
import java.awt.*;
import javax.swing.*;
import a2geek.games.mousemaze2001.domain.*;
import a2geek.games.mousemaze2001.mazeobjects.*;
/**
* Display the number of lives graphically.
*
* Creation date: (10/27/01 12:42:11 AM)
* @author: <a href='mailto:greener@charter.net'>Rob Greene</a>
* @version: RJG 10/27/2001 01:02:48
*/
public class MouseLivesPanel extends JPanel {
InvertedMouse mouse = new InvertedMouse();
/**
* MouseLivesPanel constructor comment.
*/
public MouseLivesPanel() {
super();
}
/**
* Display the number of mouse lives.
*
* Creation date: (10/27/01 12:43:13 AM)
*/
public void paint(Graphics g) {
super.paint(g);
Rectangle rect = g.getClipBounds();
int lives = MazeDomain.getInstance().getLives();
for (int i=0; i<lives; i++) {
int x = mouse.getWidth() * i;
int y = ((int)rect.getHeight() - mouse.getHeight()) / 2;
Graphics mg = g.create(x,y,mouse.getWidth(),mouse.getHeight());
mouse.paint(mg);
}
}
}

View File

@ -0,0 +1,535 @@
package a2geek.games.mousemaze2001;
import java.awt.*;
import javax.swing.*;
import a2geek.games.mousemaze2001.domain.*;
import a2geek.games.mousemaze2001.images.*;
import a2geek.games.mousemaze2001.threads.*;
import java.awt.event.*;
/**
* Mouse Maze 2001!
*
* Creation date: (10/9/01 10:02:39 PM)
* @author: <a href='mailto:greener@charter.net'>Rob Greene</a>
* @version: RJG 11/05/2001 22:35:58
*/
public class MouseMaze2001 extends JFrame implements ActionListener, KeyListener, DomainListener {
private static MouseMaze2001 instance = new MouseMaze2001();
private static final String OK = "ok";
private static final String CANCEL = "cancel";
private static final String START = "start";
private static final String QUIT = "quit";
private static final String PREFERENCES = "preferences";
private JPanel infoPanel = null;
private CardLayout infoCardPages = null;
private JPanel infoCardPanel = null;
private JPanel logoPanel = null;
private JPanel controlPanel = null;
private JPanel gameInfoPanel = null;
private JPanel gameCardPanel = null;
private MouseLivesPanel mouseLivesPanel = null;
private JLabel robotsCountLabel = null;
private JLabel levelCountLabel = null;
private IntroPanel introPanel = null;
private MazeGridPanel mazePanel = null;
private CardLayout gameCardPages = null;
private IntroThread introThread = new IntroThread();
private GameThread gameThread = new GameThread();
private RepaintThread repaintThread = null;
private JPanel preferencesControlPanel = null;
private GameSettingsPanel gameSettingsPanel = null;
private ImageManager imageManager = null;
/**
* MouseMaze2001Layout constructor comment.
*/
public MouseMaze2001() {
Package pkg = getClass().getPackage();
String title = pkg.getImplementationTitle();
if (title == null) {
title = "Mouse Maze 2001";
}
String version = pkg.getImplementationVersion();
if (version == null) {
version = "PROTOTYPE";
}
setTitle(String.format("%s - %s", title, version));
setResizable(false);
setSize(500,200);
centerWindow();
ImageManager.getInstance(); // toggle image loading
getContentPane().add(new Component() {
public void paint(Graphics g) {
String message = "Please wait, loading images...";
int screenHeight = getHeight();
int screenWidth = getWidth();
Font font = new Font(g.getFont().getFontName(), Font.BOLD, 20);
g.setFont(font);
FontMetrics metrics = g.getFontMetrics();
int fontHeight = metrics.getHeight();
int stringWidth = metrics.stringWidth(message);
int x = (screenWidth - stringWidth) / 2;
int y = (screenHeight - fontHeight) / 2 + fontHeight;
g.setColor(Color.black);
g.fillRect(0,0,screenWidth,screenHeight);
g.setColor(Color.green);
g.drawString(message, x, y);
}
});
Thread thread = new Thread() {
public void run() {
ImageManager imageManager = ImageManager.getInstance();
while (imageManager.isDoneLoading() == false) {
try {
sleep(100);
} catch (InterruptedException ex) {
}
}
layoutScreen();
}
};
thread.start();
}
/**
* Invoked when an action occurs.
*/
public void actionPerformed(ActionEvent e) {
String command = START; // default if called from elsewhere (yup, a hack)
MazeDomain domain = MazeDomain.getInstance();
if (e != null) {
command = e.getActionCommand();
}
if (START.equals(command)) {
if (introThread.isPaused()) {
gameThread.suspend();
introThread.resume();
gameCardPages.show(gameCardPanel, getPreviewPanelName());
infoCardPages.show(infoCardPanel, getPreviewPanelName());
domain.clear();
} else {
if (!gameThread.isRunning()) {
gameThread.start(); // yes, a total hack
gameThread.suspend();
domain.addDomainListener(this);
}
introThread.suspend();
gameThread.resume();
gameCardPages.show(gameCardPanel, getPlayPanelName());
infoCardPages.show(infoCardPanel, getPlayPanelName());
mazePanel.requestFocus();
domain.newGame();
if (domain.getGameSettings().isAnimatedImages()) {
AnimationThread animationThread = new AnimationThread();
animationThread.start();
}
}
} else if (PREFERENCES.equals(command)) {
infoCardPages.show(infoCardPanel, getPreferencesPanelName());
gameCardPages.show(gameCardPanel, getPreferencesPanelName());
gameSettingsPanel.setCurrentSettings(MazeDomain.getInstance().getGameSettings());
} else if (OK.equals(command)) {
domain.setGameSettings(gameSettingsPanel.getCurrentSettings());
infoCardPages.show(infoCardPanel, getPreviewPanelName());
gameCardPages.show(gameCardPanel, getPreviewPanelName());
} else if (CANCEL.equals(command)) {
infoCardPages.show(infoCardPanel, getPreviewPanelName());
gameCardPages.show(gameCardPanel, getPreviewPanelName());
}
}
/**
* Center the current window.
*
* Creation date: (10/31/01 10:02:47 PM)
*/
public void centerWindow() {
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Dimension windowSize = getSize();
Point point = new Point();
point.x = (screenSize.width - windowSize.width) / 2;
point.y = (screenSize.height - windowSize.height) / 2;
setLocation(point);
}
protected void createControlPanel() {
JButton startButton = createImageButton("StartButton.gif", START);
JButton preferencesButton = createImageButton("PreferencesButton.gif", PREFERENCES);
JPanel topButtons = new JPanel(new GridLayout(2,1));
topButtons.add(startButton);
topButtons.add(preferencesButton);
JButton quitButton = createImageButton("QuitButton.gif", QUIT, new WindowCloseAdapter());
controlPanel = new JPanel(new BorderLayout());
controlPanel.add(topButtons, BorderLayout.NORTH);
controlPanel.add(quitButton, BorderLayout.SOUTH);
controlPanel.setBackground(Color.white);
}
protected void createGameInfoPanel() {
JLabel aHackForTheDamnFontName = new JLabel();
String theDamnFontName = aHackForTheDamnFontName.getFont().getName();
Font font = new Font(theDamnFontName, Font.BOLD, 20);
JLabel miceText = new JLabel("Mice:");
miceText.setFont(font);
miceText.setForeground(Color.blue);
JLabel levelText = new JLabel("Level:");
levelText.setFont(font);
levelText.setForeground(Color.blue);
JLabel robotsText = new JLabel("Robots:");
robotsText.setFont(font);
robotsText.setForeground(Color.blue);
mouseLivesPanel = new MouseLivesPanel();
mouseLivesPanel.setBackground(Color.white);
levelCountLabel = new JLabel("0");
levelCountLabel.setFont(font);
levelCountLabel.setForeground(Color.blue);
robotsCountLabel = new JLabel("0");
robotsCountLabel.setFont(font);
robotsCountLabel.setForeground(Color.blue);
gameInfoPanel = new JPanel(new GridLayout(3,2));
gameInfoPanel.add(miceText);
gameInfoPanel.add(mouseLivesPanel);
gameInfoPanel.add(levelText);
gameInfoPanel.add(levelCountLabel);
gameInfoPanel.add(robotsText);
gameInfoPanel.add(robotsCountLabel);
gameInfoPanel.setBackground(Color.white);
}
/**
* Create a standard image button.
*
* Creation date: (10/27/01 3:05:07 PM)
*/
protected JButton createImageButton(String resourceName, String commandString) {
return createImageButton(resourceName, commandString, this);
}
/**
* Create a standard image button.
*
* Creation date: (10/27/01 3:05:07 PM)
*/
protected JButton createImageButton(String resourceName, String commandString, ActionListener actionListener) {
JButton button = new JButton(new ImageIcon(imageManager.getImage(resourceName)));
button.setActionCommand(commandString);
button.setBackground(Color.white);
button.addActionListener(actionListener);
return button;
}
protected void createInfoPanel() {
createLogoPanel();
createControlPanel();
createGameInfoPanel();
createPreferencesControlPanel();
infoCardPages = new CardLayout();
infoCardPanel = new JPanel(infoCardPages);
infoCardPanel.add(getPreviewPanelName(), controlPanel);
infoCardPanel.add(getPlayPanelName(), gameInfoPanel);
infoCardPanel.add(getPreferencesPanelName(), preferencesControlPanel);
JPanel nestedPanel = new JPanel(new BorderLayout());
nestedPanel.setBackground(Color.white);
nestedPanel.add(logoPanel, BorderLayout.NORTH);
nestedPanel.add(infoCardPanel, BorderLayout.CENTER);
// apparantly these need to be separate panels...
JPanel dividerPanel = new JPanel();
dividerPanel.setBackground(Color.white);
JPanel dividerPanel2 = new JPanel();
dividerPanel2.setBackground(Color.white);
JPanel dividerPanel3 = new JPanel();
dividerPanel3.setBackground(Color.white);
JPanel dividerPanel4 = new JPanel();
dividerPanel4.setBackground(Color.white);
Dimension size = new Dimension(logoPanel.getWidth(), -1);
infoPanel = new JPanel(new BorderLayout());
infoPanel.setMaximumSize(size);
infoPanel.add(dividerPanel, BorderLayout.WEST);
infoPanel.add(dividerPanel2, BorderLayout.EAST);
infoPanel.add(dividerPanel3, BorderLayout.SOUTH);
infoPanel.add(dividerPanel4, BorderLayout.NORTH);
infoPanel.add(nestedPanel, BorderLayout.CENTER);
}
protected void createLogoPanel() {
logoPanel = new JPanel(new FlowLayout());
ImageCanvas logo = new ImageCanvas("MouseMazeLogo.gif");
logo.setColor(Color.white);
logoPanel.add(logo);
logoPanel.setBackground(Color.white);
}
protected void createPreferencesControlPanel() {
JButton okButton = createImageButton("OkButton.gif", OK);
JButton cancelButton = createImageButton("CancelButton.gif", CANCEL);
preferencesControlPanel = new JPanel(new BorderLayout());
preferencesControlPanel.add(okButton, BorderLayout.NORTH);
preferencesControlPanel.add(cancelButton, BorderLayout.SOUTH);
preferencesControlPanel.setBackground(Color.white);
}
/**
* Act upon domain changed events.
*
* Creation date: (10/22/01 10:06:09 PM)
*/
public void domainChanged(DomainEvent domainEvent) {
String event = domainEvent.getEvent();
MazeDomain domain = MazeDomain.getInstance();
if ("terminate".equals(event)) {
actionPerformed(null); // cheap game over
}
if ("robotShot".equals(event) || "newGame".equals(event)) {
robotsCountLabel.setText(Integer.toString(domain.getKills()));
robotsCountLabel.repaint();
}
if ("mouseKilled".equals(event)) {
mouseLivesPanel.repaint();
GameDelayThread thread = new GameDelayThread("Ouch!",500);
thread.start();
}
if ("level".equals(event)) {
//GameDelayThread thread = new GameDelayThread("Welcome to level " + domain.getLevel() + "!",1000);
//thread.start();
levelCountLabel.setText(Integer.toString(domain.getLevel()));
levelCountLabel.repaint();
}
if ("newGame".equals(event)) {
GameDelayThread thread = new GameDelayThread("Good Luck!",500);
thread.start();
levelCountLabel.setText(Integer.toString(domain.getLevel()));
levelCountLabel.repaint();
mouseLivesPanel.repaint();
}
if ("gameOver".equals(event)) {
GameDelayThread thread = new GameDelayThread("Game Over",2000);
thread.start();
mouseLivesPanel.repaint();
} else if ("gameWon".equals(event)) {
GameDelayThread thread = new GameDelayThread("You have won Mouse Maze!",3000);
thread.start();
}
repaintNeeded();
}
public static MouseMaze2001 getInstance() {
return instance;
}
protected String getPlayPanelName() {
return "play";
}
protected String getPreferencesPanelName() {
return "preferences";
}
protected String getPreviewPanelName() {
return "preview";
}
/**
* Invoked when a key has been pressed.
*/
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_LEFT:
MazeDomain.getInstance().moveMouse(-1,0);
repaintNeeded();
break;
case KeyEvent.VK_RIGHT:
MazeDomain.getInstance().moveMouse(1,0);
repaintNeeded();
break;
case KeyEvent.VK_UP:
MazeDomain.getInstance().moveMouse(0,-1);
repaintNeeded();
break;
case KeyEvent.VK_DOWN:
MazeDomain.getInstance().moveMouse(0,1);
repaintNeeded();
break;
case KeyEvent.VK_HOME:
MazeDomain.getInstance().moveMouse(-1,-1);
repaintNeeded();
break;
case KeyEvent.VK_PAGE_UP:
MazeDomain.getInstance().moveMouse(1,-1);
repaintNeeded();
break;
case KeyEvent.VK_END:
MazeDomain.getInstance().moveMouse(-1,1);
repaintNeeded();
break;
case KeyEvent.VK_PAGE_DOWN:
MazeDomain.getInstance().moveMouse(1,1);
repaintNeeded();
break;
}
}
/**
* Invoked when a key has been released.
*/
public void keyReleased(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_ESCAPE:
MazeDomain.getInstance().endGame();
break;
}
}
/**
* Invoked when a key has been typed.
* This event occurs when a key press is followed by a key release.
*/
public void keyTyped(KeyEvent e) {
char ch = Character.toUpperCase(e.getKeyChar());
MazeDomain domain = MazeDomain.getInstance();
int dx = 0;
int dy = 0;
if (domain.canMouseShoot()) {
switch (ch) {
case 'Q': dx = -1;
dy = -1;
break;
case 'W': dx = 0;
dy = -1;
break;
case 'E': dx = 1;
dy = -1;
break;
case 'A': dx = -1;
dy = 0;
break;
case 'D': dx = 1;
dy = 0;
break;
case 'Z': dx = -1;
dy = 1;
break;
case 'X': dx = 0;
dy = 1;
break;
case 'C': dx = 1;
dy = 1;
break;
}
}
switch (ch) {
case 'P': if (domain.isPaused()) {
domain.setPause(null);
} else {
domain.setPause("Game is paused");
}
repaintNeeded();
break;
}
if (dx != 0 || dy != 0) {
Point pt = new Point(domain.getMouseLocation());
pt.translate(dx,dy);
if (domain.isValidPoint(pt)) {
Thread explosion = new ExplosionThread(pt);
explosion.start();
}
}
}
/**
* Layout the actual MouseMaze screen.
*
* Creation date: (10/31/01 9:38:13 PM)
*/
protected void layoutScreen() {
setVisible(false);
MazeDomain domain = MazeDomain.getInstance();
imageManager = ImageManager.getInstance();
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
addWindowListener(new WindowCloseAdapter());
createInfoPanel();
introPanel = IntroPanel.getInstance();
mazePanel = new MazeGridPanel();
gameSettingsPanel = new GameSettingsPanel();
gameCardPages = new CardLayout();
gameCardPanel = new JPanel(gameCardPages);
gameCardPanel.add(getPreviewPanelName(), introPanel);
gameCardPanel.add(getPlayPanelName(), mazePanel);
gameCardPanel.add(getPreferencesPanelName(), gameSettingsPanel);
getContentPane().removeAll();
getContentPane().setLayout(new BorderLayout());
getContentPane().add(BorderLayout.CENTER, gameCardPanel);
getContentPane().add(BorderLayout.EAST, infoPanel);
pack();
centerWindow();
setVisible(true);
mazePanel.addKeyListener(this);
introThread.start();
repaintThread = new RepaintThread(mazePanel);
repaintThread.start();
}
/**
* Start the program
*
* Creation date: (10/9/01 10:04:11 PM)
* @param args java.lang.String[]
*/
public static void main(String[] args) {
instance.show();
}
/**
* Tell the RepaintThread that a repaint is needed.
*
* Creation date: (10/24/01 9:20:23 PM)
*/
public void repaintNeeded() {
//System.out.println(new java.util.Date() + " - repaint requested");
repaintThread.repaintNeeded();
}
}

View File

@ -0,0 +1,38 @@
package a2geek.games.mousemaze2001;
import java.awt.event.*;
import javax.swing.event.*;
/**
* Generic adapter which shuts down the application.
* <p>
* Creation date: (10/6/01 11:29:16 PM)
* @author: <a href='mailto:greener@charter.net'>Rob Greene</a>
* @version: RJG 10/08/2001 00:10:56
*/
public class WindowCloseAdapter extends WindowAdapter implements ActionListener {
/**
* WindowCloseAdapter constructor comment.
*/
public WindowCloseAdapter() {
super();
}
/**
* Perform the close action.
*
* Creation date: (10/6/01 11:32:38 PM)
*/
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
/**
* Close the system down.
*
* Creation date: (10/6/01 11:29:36 PM)
*/
public void windowClosed(WindowEvent e) {
System.exit(0);
}
}

View File

@ -0,0 +1,41 @@
package a2geek.games.mousemaze2001.domain;
/**
* A DomainEvent is passed to DomainListeners.
*
* Creation date: (10/22/01 9:58:14 PM)
* @author: <a href='mailto:greener@charter.net'>Rob Greene</a>
* @version: RJG 10/22/2001 23:31:31
*/
public class DomainEvent {
private Object source;
private String event;
/**
* DomainEvent constructor comment.
*/
public DomainEvent(Object theSource, String theEvent) {
super();
source = theSource;
event = theEvent;
}
/**
* Retrieve the event that occurred.
*
* Creation date: (10/22/01 10:00:08 PM)
*/
public String getEvent() {
return event;
}
/**
* Retrieve the source of this DomainEvent.
*
* Creation date: (10/22/01 9:59:45 PM)
*/
public Object getSource() {
return source;
}
}

View File

@ -0,0 +1,18 @@
package a2geek.games.mousemaze2001.domain;
/**
* A DomainListener identifies an object that wants to know that
* something has happened in the domain.
*
* Creation date: (10/22/01 9:55:37 PM)
* @author: <a href='mailto:greener@charter.net'>Rob Greene</a>
* @version: RJG 10/22/2001 23:31:31
*/
public interface DomainListener {
/**
* A DomainListener will receive a domainChanged event
* when the domain state has been modified.
*
* Creation date: (10/22/01 9:56:33 PM)
*/
public void domainChanged(DomainEvent domainEvent);
}

View File

@ -0,0 +1,439 @@
package a2geek.games.mousemaze2001.domain;
import java.io.*;
import java.util.*;
/**
* Represents all the configurable information of the game.
*
* Creation date: (10/27/01 2:39:27 PM)
* @author: <a href='mailto:greener@charter.net'>Rob Greene</a>
* @version: RJG 10/29/2001 22:40:54
*/
public class GameSettings {
private static final String BASE_PATH = "/settings/%s";
/*
* Indicates if the mouse is able to shoot.
*/
private boolean shootingMouse;
/*
* Number of bombs added per level. Set to 0 for none.
*/
private int bombsPerLevel;
/*
* Maximum number of bombs to have per level.
* Note: Not used by game itself, used by preferences screen.
*/
private int maxBombsPerLevel;
/*
* Range that robots can "see" or target the mouse. When the mouse
* is within this range, the robot may shoot.
*/
private int robotVisibilityRange;
/*
* Maximum robot visibility range.
* Note: Not used by game itself, used by preferences screen.
*/
private int maxRobotVisibilityRange;
/*
* Longest shot that a robot can take.
*/
private int robotShotRange;
/*
* Maximum shot range that can be chosen.
* Note: Not used by game itself, used by preferences screen.
*/
private int maxRobotShotRange;
/*
* Can robots only shoot at their maximum range?
* (For example, maybe the mouse gets "too close" and under the gun.)
*/
private boolean fixedRobotShotRange;
/*
* When the mouse is within shooting range, this is the percent chance that
* the robot will actually shoot.
*/
private int robotShootFrequency;
/*
* Should the game use animated images, or does that annoy the player?
*/
private boolean animatedImages;
/*
* How frequently should the robot drop mines?
*/
private int robotMineFrequency;
/*
* Cheat: Game is too short, lets make it go on forever!
*/
private boolean unlimitedGameLevels;
/*
* Cheat: Game is too hard, mouse is always reincarnated.
*/
private boolean unlimitedLives;
/*
* Allow robots have shielding.
*/
private boolean shieldedRobots;
/**
* GameSettings constructor comment.
*/
public GameSettings() {
super();
}
/**
* GameSettings constructor comment.
*/
public GameSettings(GameSettings other) {
super();
this.setAnimatedImages(other.isAnimatedImages());
this.setBombsPerLevel(other.getBombsPerLevel());
this.setFixedRobotShotRange(other.isFixedRobotShotRange());
this.setMaxBombsPerLevel(other.getMaxBombsPerLevel());
this.setMaxRobotShotRange(other.getMaxRobotShotRange());
this.setMaxRobotVisibilityRange(other.getMaxRobotVisibilityRange());
this.setRobotMineFrequency(other.getRobotMineFrequency());
this.setRobotShootFrequency(other.getRobotShootFrequency());
this.setRobotShotRange(other.getRobotShotRange());
this.setRobotVisibilityRange(other.getRobotVisibilityRange());
this.setShootingMouse(other.isShootingMouse());
this.setUnlimitedGameLevels(other.isUnlimitedGameLevels());
this.setUnlimitedLives(other.isUnlimitedLives());
this.setShieldedRobots(other.isShieldedRobots());
}
/**
* Retrieve the number of bombs per level.
*
* Creation date: (10/27/01 2:51:10 PM)
* @return int
*/
public int getBombsPerLevel() {
return bombsPerLevel;
}
/**
* Get the maximum bombs per level.
*
* Creation date: (10/27/01 2:51:10 PM)
* @return int
*/
public int getMaxBombsPerLevel() {
return maxBombsPerLevel;
}
/**
* Get the maximum robot shot range.
*
* Creation date: (10/27/01 2:51:10 PM)
* @return int
*/
public int getMaxRobotShotRange() {
return maxRobotShotRange;
}
/**
* Get the maximum robot visibility range.
*
* Creation date: (10/27/01 2:51:10 PM)
* @return int
*/
public int getMaxRobotVisibilityRange() {
return maxRobotVisibilityRange;
}
/**
* Get the robot mining frequency.
*
* Creation date: (10/27/01 2:51:10 PM)
* @return int
*/
public int getRobotMineFrequency() {
return robotMineFrequency;
}
/**
* Get the robot shooting frequency.
*
* Creation date: (10/27/01 2:51:10 PM)
* @return int
*/
public int getRobotShootFrequency() {
return robotShootFrequency;
}
/**
* Get the range of a robot shot.
*
* Creation date: (10/27/01 2:51:10 PM)
* @return int
*/
public int getRobotShotRange() {
return robotShotRange;
}
/**
* Get the range a robot can see.
*
* Creation date: (10/27/01 2:51:10 PM)
* @return int
*/
public int getRobotVisibilityRange() {
return robotVisibilityRange;
}
/**
* Are there animated images?
*
* Creation date: (10/27/01 2:51:10 PM)
* @return boolean
*/
public boolean isAnimatedImages() {
return animatedImages;
}
/**
* Do the robots have a fixed shot range?
*
* Creation date: (10/27/01 2:51:10 PM)
* @return boolean
*/
public boolean isFixedRobotShotRange() {
return fixedRobotShotRange;
}
/**
* Answer if the robots have shielding.
*
* Creation date: (10/29/01 10:05:30 PM)
*/
public boolean isShieldedRobots() {
return shieldedRobots;
}
/**
* Can this mouse shoot?
*
* Creation date: (10/27/01 2:51:10 PM)
* @return boolean
*/
public boolean isShootingMouse() {
return shootingMouse;
}
/**
* Are we too good for the game?
*
* Creation date: (10/27/01 2:51:10 PM)
* @return boolean
*/
public boolean isUnlimitedGameLevels() {
return unlimitedGameLevels;
}
/**
* Are we cheating?
*
* Creation date: (10/27/01 2:51:10 PM)
* @return boolean
*/
public boolean isUnlimitedLives() {
return unlimitedLives;
}
/**
* Load the game settings from a Properties file.
*
* Creation date: (10/27/01 11:21:59 PM)
*/
public void load(String filename) {
Properties props = new Properties();
try {
props.load(getClass().getResourceAsStream(String.format(BASE_PATH,filename)));
} catch (IOException ex) {
// ignore - default settings are set
}
setAnimatedImages(new Boolean(props.getProperty("animatedImages","true")).booleanValue());
setBombsPerLevel(Integer.parseInt(props.getProperty("bombsPerLevel","2")));
setFixedRobotShotRange(new Boolean(props.getProperty("fixedRobotShotRange","true")).booleanValue());
setMaxBombsPerLevel(Integer.parseInt(props.getProperty("maxBombsPerLevel","5")));
setMaxRobotShotRange(Integer.parseInt(props.getProperty("maxRobotShotRange","4")));
setMaxRobotVisibilityRange(Integer.parseInt(props.getProperty("maxRobotVisibilityRange","5")));
setRobotMineFrequency(Integer.parseInt(props.getProperty("robotMineFrequency","20")));
setRobotShootFrequency(Integer.parseInt(props.getProperty("robotShootFrequency","80")));
setRobotShotRange(Integer.parseInt(props.getProperty("robotShotRange","2")));
setRobotVisibilityRange(Integer.parseInt(props.getProperty("robotVisibilityRange","4")));
setShootingMouse(new Boolean(props.getProperty("shootingMouse","true")).booleanValue());
setUnlimitedGameLevels(new Boolean(props.getProperty("unlimitedGameLevels","false")).booleanValue());
setUnlimitedLives(new Boolean(props.getProperty("unlimitedLives","false")).booleanValue());
setShieldedRobots(new Boolean(props.getProperty("shieldedRobots","false")).booleanValue());
}
/**
* Set the animated images flag.
*
* Creation date: (10/27/01 2:51:10 PM)
* @param newAnimatedImages boolean
*/
public void setAnimatedImages(boolean newAnimatedImages) {
animatedImages = newAnimatedImages;
}
/**
* Set the number of bombs per level.
*
* Creation date: (10/27/01 2:51:10 PM)
* @param newBombsPerLevel int
*/
public void setBombsPerLevel(int newBombsPerLevel) {
bombsPerLevel = newBombsPerLevel;
}
/**
* Set the fixed range of the robots.
*
* Creation date: (10/27/01 2:51:10 PM)
* @param newFixedRobotShotRange boolean
*/
public void setFixedRobotShotRange(boolean newFixedRobotShotRange) {
fixedRobotShotRange = newFixedRobotShotRange;
}
/**
* Set the maximum bombs allowed per level.
*
* Creation date: (10/27/01 2:51:10 PM)
* @param newMaxBombsPerLevel int
*/
public void setMaxBombsPerLevel(int newMaxBombsPerLevel) {
maxBombsPerLevel = newMaxBombsPerLevel;
}
/**
* Set the maximum robot shot range.
*
* Creation date: (10/27/01 2:51:10 PM)
* @param newMaxRobotShotRange int
*/
public void setMaxRobotShotRange(int newMaxRobotShotRange) {
maxRobotShotRange = newMaxRobotShotRange;
}
/**
* Set the maximum robot visibility range.
*
* Creation date: (10/27/01 2:51:10 PM)
* @param newMaxRobotVisibilityRange int
*/
public void setMaxRobotVisibilityRange(int newMaxRobotVisibilityRange) {
maxRobotVisibilityRange = newMaxRobotVisibilityRange;
}
/**
* Set the robot mining frequency.
*
* Creation date: (10/27/01 2:51:10 PM)
* @param newRobotMineFrequency int
*/
public void setRobotMineFrequency(int newRobotMineFrequency) {
robotMineFrequency = newRobotMineFrequency;
}
/**
* Set the robot shooting frequency.
*
* Creation date: (10/27/01 2:51:10 PM)
* @param newRobotShootFrequency int
*/
public void setRobotShootFrequency(int newRobotShootFrequency) {
robotShootFrequency = newRobotShootFrequency;
}
/**
* Set the robot shooting distance.
*
* Creation date: (10/27/01 2:51:10 PM)
* @param newRobotShotRange int
*/
public void setRobotShotRange(int newRobotShotRange) {
robotShotRange = newRobotShotRange;
}
/**
* Set the robot visibility range.
*
* Creation date: (10/27/01 2:51:10 PM)
* @param newRobotVisibilityRange int
*/
public void setRobotVisibilityRange(int newRobotVisibilityRange) {
robotVisibilityRange = newRobotVisibilityRange;
}
/**
* Set if the robots have shielding.
*
* Creation date: (10/29/01 10:05:57 PM)
*/
public void setShieldedRobots(boolean newShieldedRobots) {
shieldedRobots = newShieldedRobots;
}
/**
* Tell me if this mouse is Rambo.
*
* Creation date: (10/27/01 2:51:10 PM)
* @param newShootingMouse boolean
*/
public void setShootingMouse(boolean newShootingMouse) {
shootingMouse = newShootingMouse;
}
/**
* Way cool game, but way too easy.
*
* Creation date: (10/27/01 2:51:10 PM)
* @param newUnlimitedGameLevels boolean
*/
public void setUnlimitedGameLevels(boolean newUnlimitedGameLevels) {
unlimitedGameLevels = newUnlimitedGameLevels;
}
/**
* Way cool game, but way too hard.
*
* Creation date: (10/27/01 2:51:10 PM)
* @param newUnlimitedLives boolean
*/
public void setUnlimitedLives(boolean newUnlimitedLives) {
unlimitedLives = newUnlimitedLives;
}
}

View File

@ -0,0 +1,735 @@
package a2geek.games.mousemaze2001.domain;
import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.*;
import java.util.*;
import javax.swing.event.ChangeListener;
import a2geek.games.mousemaze2001.mazeobjects.*;
import a2geek.games.mousemaze2001.threads.*;
/**
* Contain the MouseMaze domain in a singleton instance.
* Basically, all map related items are here.
*
* Creation date: (10/14/01 9:35:03 PM)
* @author: <a href='mailto:greener@charter.net'>Rob Greene</a>
* @version: RJG 11/29/2001 22:42:21
*/
public class MazeDomain {
private static final String BASE_PATH = "/sounds/%s";
private static MazeDomain instance = null;
private MazeObject[][] map = null;
private int mapWidth = 14;
private int mapHeight = 9;
private int mapLevel = 1;
private int totalMice = 3;
private int lives;
private int kills;
private Point mousePoint = new Point();
private Point exitPoint = new Point();
private Vector robots = new Vector();
private MazeObject mouse = new AnimatedMouse();
private MazeObject bomb = new AnimatedBomb();
private MazeObject exit = new Exit();
private MazeObject mine = new Mine();
private Vector domainListeners = new Vector();
private String pauseMessage = null;
private boolean paused = false;
private int animationSequence = 0;
private GameSettings gameSettings;
private AudioClip moveSound;
private AudioClip hitSound;
/**
* MazeDomain constructor comment.
*/
protected MazeDomain() {
super();
moveSound = Applet.newAudioClip(getClass().getResource(String.format(BASE_PATH,"clickfast.wav")));
hitSound = Applet.newAudioClip(getClass().getResource(String.format(BASE_PATH,"boing.wav")));
}
/**
* Add a DomainListener.
*
* Creation date: (10/22/01 9:49:44 PM)
*/
public void addDomainListener(DomainListener domainListener) {
domainListeners.add(domainListener);
}
/**
* Determine if there are any explosions on the screen.
* After explosions have disappered, checks to see if the terminate
* message should be sent. This allows the message to be displayed
* stating that the game is over.
*
* Creation date: (10/26/01 12:12:54 PM)
*/
public boolean areExplosionsPresent() {
for (int x=0; x<getMapWidth(); x++) {
for (int y=0; y<getMapHeight(); y++) {
MazeObject mazeObject = getMazeObject(x,y);
if (mazeObject != null && mazeObject.isExplosion()) return true;
}
}
// no explosions, check on mouse -- if dead, send terminate message
// yes, it is a bit of a hack.
if (getLives() <= 0) {
notifyDomainListeners("terminate");
}
// if we are at the end of the game, terminate also
if (!gameSettings.isUnlimitedGameLevels() && getLevel() > 5) {
notifyDomainListeners("terminate");
}
return false;
}
/**
* Answer if a mouse is able to shoot in this game.
*
* Creation date: (10/28/01 1:32:27 PM)
*/
public boolean canMouseShoot() {
return gameSettings.isShootingMouse();
}
/**
* Erase current domain as it relates to a specific game.
*
* Creation date: (11/5/01 10:29:06 PM)
*/
public void clear() {
map = null;
mapLevel = 1;
lives = 0;
kills = 0;
mousePoint = new Point();
exitPoint = new Point();
robots = new Vector();
pauseMessage = null;
paused = false;
animationSequence = 0;
}
/**
* Initiate the game over sequence.
*
* Creation date: (10/26/01 12:54:32 PM)
*/
public void endGame() {
lives = 0;
notifyDomainListeners("gameOver");
}
/**
* Provide random bomb explosions.
*
* Creation date: (10/26/01 12:38:22 PM)
*/
public void explodeBombsRandomly() {
if (isPaused()) return;
Random random = new Random();
int x = random.nextInt(getMapWidth()-1);
int y = random.nextInt(getMapHeight()-1);
if (isBomb(x,y)) {
setMazeObject(x,y,null);
BombExplosionThread bombExplosion = new BombExplosionThread(new Point(x,y));
bombExplosion.start();
}
}
/**
* Generate a map.
*
* Creation date: (10/14/01 10:01:32 PM)
*/
public void generateMap() {
if (mapWidth > 0 && mapHeight > 0 && mapLevel > 0) {
setPause(true);
// setup information
MazeObject[][] oldMap = map;
map = new MazeObject[mapWidth][mapHeight];
int midPoint = (mapHeight + 1) / 2 - 1;
// place mouse
setMazeObject(0, midPoint, mouse);
// place exit
exitPoint = new Point(mapWidth-1, midPoint);
setMazeObject(exitPoint, exit);
// place robots
if (getLevel() >= 5) {
placeRobot(0, 0);
placeRobot(0, mapHeight-1);
}
for (int i=1; i<=Math.min(getLevel(),4); i++) {
placeRobot(mapWidth-1, midPoint-i);
placeRobot(mapWidth-1, midPoint+i);
}
// place bombs
int bombs = mapLevel * gameSettings.getBombsPerLevel();
Random random = new Random();
while (bombs > 0) {
int x = random.nextInt(mapWidth);
int y = random.nextInt(mapHeight);
if (getMazeObject(x,y) == null) {
setMazeObject(x,y,bomb);
bombs--;
}
}
if (oldMap != null) {
LevelTranslationThread thread = new LevelTranslationThread("Welcome to level " + getLevel() + "!", map);
map = oldMap;
thread.start();
}
}
}
/**
* Retrieve the current animation sequence.
*
* Creation date: (10/26/01 10:59:35 PM)
*/
public int getAnimationSequence() {
return animationSequence;
}
/**
* Get game settings.
*
* Creation date: (10/28/01 12:43:41 PM)
*/
public GameSettings getGameSettings() {
if (gameSettings == null) {
gameSettings = new GameSettings();
gameSettings.load("default.properties");
}
return gameSettings;
}
/**
* Retrieve the singleton instance.
*
* Creation date: (10/14/01 9:36:19 PM)
*/
public static MazeDomain getInstance() {
if (instance == null) {
instance = new MazeDomain();
}
return instance;
}
/**
* Retrieve the number of robots killed.
*
* Creation date: (10/25/01 10:47:06 PM)
*/
public int getKills() {
return kills;
}
public int getLevel() {
return mapLevel;
}
/**
* Return the number of mouse lives left.
*
* Creation date: (10/25/01 11:24:01 PM)
*/
public int getLives() {
return lives;
}
/**
* Retrieve the current map.
*
* Creation date: (10/14/01 9:35:25 PM)
*/
public MazeObject[][] getMap() {
return map;
}
/**
* Retrieve map height.
*
* Creation date: (10/14/01 10:11:27 PM)
*/
public int getMapHeight() {
return mapHeight;
}
/**
* Retrieve map width.
*
* Creation date: (10/14/01 10:11:53 PM)
*/
public int getMapWidth() {
return mapWidth;
}
/**
* Get MazeObject.
*
* Creation date: (10/14/01 10:10:05 PM)
*/
public MazeObject getMazeObject(int x, int y) {
MazeObject mazeObject = null;
if (map != null) {
mazeObject = map[x][y];
}
return mazeObject;
}
/**
* Get a MazeObject.
*
* Creation date: (10/21/01 3:49:44 PM)
*/
public MazeObject getMazeObject(Point pt) {
return getMazeObject(pt.x,pt.y);
}
public Point getMouseLocation() {
return mousePoint;
}
public String getPauseMessage() {
return pauseMessage;
}
/**
* Return the number of living robots.
*
* Creation date: (10/22/01 10:45:58 PM)
*/
public int getRobotCount() {
if (robots == null) return 0;
return robots.size();
}
/**
* Retrieve the number of mouse lives.
*
* Creation date: (10/24/01 10:27:45 PM)
* @return int
*/
public int getTotalMice() {
return totalMice;
}
/**
* Increment the animation sequence.
*
* Creation date: (10/26/01 10:59:55 PM)
*/
public void incrementAnimationSequence() {
animationSequence++;
}
/**
* Test if a cell has a bomb.
*
* Creation date: (10/23/01 10:24:36 PM)
*/
public boolean isBomb(int x, int y) {
return getMazeObject(x,y) == bomb;
}
/**
* Answers true if the game has ended.
* This is used by other threads to force termination.
*
* Creation date: (10/26/01 11:05:40 PM)
*/
public boolean isGameOver() {
return (lives < 1);
}
public boolean isPaused() {
return paused;
}
/**
* Test if a point is a valid cell location.
*
* Creation date: (10/23/01 10:26:22 PM)
*/
public boolean isValidPoint(int x, int y) {
return (x >= 0 && x < mapWidth && y >= 0 && y < mapHeight);
}
/**
* Test if a point is a valid cell location.
*
* Creation date: (10/23/01 10:26:22 PM)
*/
public boolean isValidPoint(Point pt) {
return isValidPoint(pt.x, pt.y);
}
public void moveMouse(int dx, int dy) {
if (isPaused()) return;
if (mousePoint == null) return;
Point pt = new Point(mousePoint);
pt.translate(dx,dy);
if (isValidPoint(pt) == false) return;
if (getMazeObject(pt) == exit) { // end of level
moveSound.play();
setMazeObject(mousePoint, null);
mousePoint = null;
if (gameSettings.isUnlimitedGameLevels() || getLevel() <= 5) {
setLevel(getLevel()+1);
generateMap();
} else {
notifyDomainListeners("gameWon");
}
} else if (getMazeObject(pt) == null) { // a valid move
moveSound.play();
setMazeObject(mousePoint, null);
setMazeObject(pt, mouse);
} else if (getMazeObject(pt) == mine) { // ouch, that hurts!
setMazeObject(mousePoint, null);
setMazeObject(pt, mouse);
Thread explosion = new ExplosionThread(pt);
explosion.start();
} else {
hitSound.play();
}
}
/**
* Provide robot AI.
* An external thread will trigger this logic.
*
* Creation date: (10/22/01 10:47:15 PM)
* @return moved status (true == moved)
*/
public boolean moveRobot(AnimatedRobot robot) {
if (isPaused()) return true;
if (mousePoint == null) return false;
Point robotPoint = robot.getLocation();
int dx = (mousePoint.x < robotPoint.x ? -1 : 0) + (mousePoint.x > robotPoint.x ? 1 : 0);
int dy = (mousePoint.y < robotPoint.y ? -1 : 0) + (mousePoint.y > robotPoint.y ? 1 : 0);
Random random = new Random();
// determine if the robot will drop a mine
boolean willDropMine = (random.nextInt(100) < gameSettings.getRobotMineFrequency());
MazeObject replacementObject = (willDropMine ? mine : null);
// try real move
Point pt = new Point(robotPoint);
pt.translate(dx,dy);
if (isValidPoint(pt) && getMazeObject(pt) == null) {
setMazeObject(robotPoint, replacementObject);
robotPoint.translate(dx,dy); // need to keep object intact!
setMazeObject(robotPoint, robot);
notifyDomainListeners("robot");
// attempt to shoot...
robotShoot(robotPoint);
return true;
} else if (isValidPoint(pt) && getMazeObject(pt) == mouse) {
return false;
}
// try random move
dx = random.nextInt(3) - 1;
dy = random.nextInt(3) - 1;
pt = new Point(robotPoint);
pt.translate(dx,dy);
if (isValidPoint(pt) && getMazeObject(pt) == null) {
setMazeObject(robotPoint, replacementObject);
robotPoint.translate(dx,dy); // need to keep object intact!
setMazeObject(robotPoint, robot);
notifyDomainListeners("robot");
// attempt to shoot...
robotShoot(robotPoint);
return true;
}
// shucks...
return false;
}
/**
* Invoke this method to start a new game.
*
* Creation date: (10/22/01 10:12:50 PM)
*/
public void newGame() {
setLevel(1);
lives = getTotalMice();
kills = 0;
notifyDomainListeners("newGame");
generateMap();
}
/**
* Notify all change listeners.
*
* Creation date: (10/22/01 9:51:10 PM)
*/
protected void notifyDomainListeners(String event) {
Enumeration listeners = domainListeners.elements();
DomainEvent domainEvent = new DomainEvent(this, event);
while (listeners.hasMoreElements()) {
DomainListener listener = (DomainListener) listeners.nextElement();
listener.domainChanged(domainEvent);
}
}
/**
* Place a robot onto the maze. Used as a helper by generateMap.
*
* Creation date: (10/30/01 9:46:21 PM)
*/
protected void placeRobot(int x, int y) {
//System.out.println("Creating new robot at " + x + "," + y + ".");
int shieldLevels = (getGameSettings().isShieldedRobots() ? 2 : 0);
Point point = new Point(x, y);
AnimatedRobot robot = new AnimatedRobot(point, shieldLevels);
setMazeObject(point, robot);
robots.add(robot);
}
/**
* Remove a DomainListener.
*
* Creation date: (10/22/01 9:50:42 PM)
*/
public void removeDomainListener(DomainListener domainListener) {
domainListeners.remove(domainListener);
}
/**
* Control robot shooting.
*
* Creation date: (10/28/01 1:43:21 PM)
*/
protected void robotShoot(Point robotPoint) {
Random random = new Random();
int distance = (int)robotPoint.distance(mousePoint);
boolean closeEnough = distance < gameSettings.getRobotVisibilityRange();
boolean randomChance = random.nextInt(100) < gameSettings.getRobotShootFrequency();
if (closeEnough && randomChance) {
int range;
if (gameSettings.isFixedRobotShotRange()) {
range = gameSettings.getRobotShotRange();
} else {
range = random.nextInt(gameSettings.getRobotShotRange());
}
int dx = (mousePoint.x < robotPoint.x ? -range : 0) + (mousePoint.x > robotPoint.x ? range : 0);
int dy = (mousePoint.y < robotPoint.y ? -range : 0) + (mousePoint.y > robotPoint.y ? range : 0);
Point pt = new Point(robotPoint);
pt.translate(dx,dy);
if (isValidPoint(pt)) {
MazeObject mazeObject = getMazeObject(pt);
if (mazeObject != null && mazeObject.isRobot() == false) {
Thread explosion = new ExplosionThread(pt);
explosion.start();
}
}
}
}
/**
* Set the game settings.
*
* Creation date: (10/28/01 12:44:51 PM)
*/
public void setGameSettings(GameSettings newSettings) {
gameSettings = newSettings;
}
/**
* Choose a level.
*
* Creation date: (10/14/01 10:00:05 PM)
*/
public void setLevel(int level) {
// set new level
mapLevel = level;
notifyDomainListeners("level");
// kill off any robots
if (robots != null) {
for (int i=0; i<robots.size(); i++) {
AnimatedRobot robot = (AnimatedRobot) robots.elementAt(i);
robot.kill();
}
}
// erase existing locations
robots = new Vector();
mousePoint = new Point();
}
/**
* Set the current map.
*
* Creation date: (10/14/01 9:35:25 PM)
*/
public void setMap(MazeObject[][] newMap) {
map = newMap;
}
/**
* Place a MazeObject into the map.
*
* Creation date: (10/30/01 9:37:53 PM)
*/
public synchronized void setMazeObject(int x, int y, MazeObject mazeObject) {
if (mazeObject == mouse) mousePoint.setLocation(x,y);
map[x][y] = mazeObject;
}
public void setMazeObject(Point pt, MazeObject mazeObject) {
setMazeObject(pt.x,pt.y,mazeObject);
}
/**
* Set maze size.
*
* Creation date: (10/14/01 9:56:04 PM)
*/
public void setMazeSize(int width, int height) {
mapWidth = width;
mapHeight = height;
}
public void setPause(String message) {
//System.out.println(new java.util.Date() + " - pause message = " + message);
setPause(message != null);
pauseMessage = message;
}
/**
* Set the paused flag.
*
* Creation date: (11/5/01 10:20:27 PM)
*/
public void setPause(boolean pausedFlag) {
paused = pausedFlag;
}
/**
* Set the number of mouse lives.
*
* Creation date: (10/24/01 10:27:45 PM)
* @param newMice int
*/
public void setTotalMice(int newTotalMice) {
totalMice = newTotalMice;
}
/**
* Shoot in a particular direction.
*
* Creation date: (10/22/01 11:12:01 PM)
*/
protected Point shoot(int dx, int dy) {
if (mousePoint == null) return null;
Point pt = new Point(mousePoint);
pt.translate(dx,dy);
return shoot(pt);
}
/**
* Shoot at specified cell.
* This is used by the ExplosionThread when a Robot is hit.
*
* Creation date: (10/23/01 10:56:57 PM)
*/
public Point shoot(Point pt) {
if (!isPaused() && isValidPoint(pt)) {
MazeObject mazeObject = getMazeObject(pt);
if (mazeObject == null) {
// ignore these!
} else if (mazeObject.isRobot()) {
AnimatedRobot robot = (AnimatedRobot) mazeObject;
robot.decreaseShieldLevel();
if (robot.isAlive() == false) {
robots.remove(mazeObject);
setMazeObject(pt,null);
kills++;
notifyDomainListeners("robotShot");
}
} else if (mazeObject.isBomb()) {
setMazeObject(pt, null);
BombExplosionThread bombExplosion = new BombExplosionThread(pt);
bombExplosion.start();
} else if (mazeObject.isMouse()) {
if (!gameSettings.isUnlimitedLives()) lives--;
if (lives > 0) {
setMazeObject(pt, null);
mousePoint = new Point(0,mapHeight/2);
setMazeObject(mousePoint, mouse);
notifyDomainListeners("mouseKilled");
} else {
endGame();
}
}
}
return pt;
}
/**
* Ensure that map is in sync.
*
* Creation date: (10/29/01 10:28:31 PM)
*/
public void synchronizeMap() {
if (getLives() > 0) setMazeObject(mousePoint, mouse);
setMazeObject(exitPoint, exit);
for (int i=0; i<robots.size(); i++) {
AnimatedRobot robot = (AnimatedRobot) robots.elementAt(i);
setMazeObject(robot.getLocation(), robot);
}
}
}

View File

@ -0,0 +1,40 @@
package a2geek.games.mousemaze2001.images;
import java.awt.*;
import java.awt.image.*;
import a2geek.games.mousemaze2001.images.*;
public class ImageCanvas extends Canvas {
private Image fImage;
private int fWidth;
private int fHeight;
private Color color;
public void setColor(Color newColor) {
color = newColor;
}
public ImageCanvas(String filename) {
fImage = ImageManager.getInstance().getImage(filename);
if (fImage != null) {
fWidth = fImage.getWidth(this);
fHeight = fImage.getHeight(this);
} else {
fWidth = 20;
fHeight = 20;
}
setSize(fWidth, fHeight);
}
public void paint(Graphics g) {
paintBackground(g);
if (fImage != null) {
g.drawImage(fImage, 0, 0, fWidth, fHeight, this);
}
}
public void paintBackground(java.awt.Graphics g) {
g.setColor(color);
g.fillRect(0, 0, getBounds().width, getBounds().height);
}
}

View File

@ -0,0 +1,137 @@
package a2geek.games.mousemaze2001.images;
import java.awt.image.ImageProducer;
import java.net.URL;
import java.awt.Toolkit;
import java.awt.Image;
import java.awt.MediaTracker;
import java.util.*;
import java.io.*;
/**
* Provide Image management for a system.
* This brings two benefits: All images are centrally located within this class and
* do not go away with a discarded class. The Image manager can be configured to preload
* images in a threaded background process.
* All images are keyed by filename.
*
* Creation date: (10/31/01 7:30:21 PM)
* @author: <a href='mailto:greener@charter.net'>Rob Greene</a>
* @version: RJG 10/31/2001 22:12:32
*/
public class ImageManager {
private static final String BASE_PATH = "/images/%s";
private static ImageManager instance = null;
private Hashtable images = new Hashtable();
/**
* ImageManager constructor comment.
*/
protected ImageManager() {
super();
}
/**
* Retrieve an image from the images table.
* If the image has not been loaded, it is loaded.
*
* Creation date: (10/31/01 8:51:13 PM)
*/
public Image getImage(String imageName) {
Image image = (Image) images.get(imageName);
if (image == null) {
image = loadImage(imageName);
}
return image;
}
/**
* Retrieve the singleton instance of this class and
* initialize the class.
*
* Creation date: (10/31/01 7:34:49 PM)
*/
public static synchronized ImageManager getInstance() {
if (instance == null) {
instance = new ImageManager();
instance.initialize();
}
return instance;
}
/**
* Initialize the class by preloading images.
*
* Creation date: (10/31/01 7:36:07 PM)
*/
protected void initialize() {
Properties properties = new Properties();
String resourceName = String.format(BASE_PATH, "ImageManager.properties");
InputStream inputStream = getClass().getResourceAsStream(resourceName);
if (inputStream != null) {
try {
properties.load(inputStream);
Enumeration elements = properties.keys();
while (elements.hasMoreElements()) {
String imageName = (String) elements.nextElement();
//if (imageName.startsWith("#") == false && imageName.length() > 0) {
loadImage(imageName);
//}
}
} catch (IOException ex) {
log("initialize", "Unable to load " + resourceName, ex);
}
}
}
/**
* Test if the requested images have completed loading.
*
* Creation date: (10/31/01 8:52:50 PM)
*/
public boolean isDoneLoading() {
Toolkit toolkit = Toolkit.getDefaultToolkit();
Enumeration elements = images.elements();
while (elements.hasMoreElements()) {
Image image = (Image) elements.nextElement();
if (image.getHeight(null) == -1 || image.getWidth(null) == -1) {
return false;
}
}
return true;
}
/**
* Load an image into the images table.
*
* Creation date: (10/31/01 7:36:40 PM)
*/
protected Image loadImage(String imageName) {
Toolkit toolkit = Toolkit.getDefaultToolkit();
URL url = getClass().getResource(String.format(BASE_PATH,imageName));
Image image = null;
try {
image = toolkit.createImage((ImageProducer) url.getContent());
images.put(imageName, image);
} catch (IOException ex) {
log("loadImage", "Unable to load " + imageName, ex);
}
return image;
}
/**
* Log errors.
*
* Creation date: (10/31/01 9:07:18 PM)
*/
protected void log(String methodName, String description, Exception exception) {
System.out.println(new Date() + " ImageManager." + methodName + ":");
System.out.println(" " + description);
exception.printStackTrace(System.out);
}
}

View File

@ -0,0 +1,41 @@
package a2geek.games.mousemaze2001.mazeobjects;
/**
* Provide an animated bomb.
*
* Creation date: (10/26/01 11:01:35 PM)
* @author: <a href='mailto:greener@charter.net'>Rob Greene</a>
* @version: RJG 10/27/2001 01:02:48
*/
public class AnimatedBomb extends AnimatedMouseMazeImageObject {
/**
* AnimatedMine constructor comment.
*/
public AnimatedBomb() {
super();
}
/**
* Answers with the image names for this object.
*
* Creation date: (10/26/01 11:01:35 PM)
*/
protected String[] getImageNames() {
return new String[] {
"OriginalBomb0.gif",
"OriginalBomb1.gif",
"OriginalBomb2.gif",
"OriginalBomb3.gif"
};
}
/**
* Returns true if this is a bomb.
*
* Creation date: (10/14/01 9:43:56 PM)
*/
public boolean isBomb() {
return true;
}
}

View File

@ -0,0 +1,70 @@
package a2geek.games.mousemaze2001.mazeobjects;
import java.net.*;
import a2geek.games.mousemaze2001.images.ImageManager;
import java.io.*;
import java.awt.image.*;
import java.awt.*;
/**
* Represents a MazeObject which is Image based and is animated. (Basically, a 'tile'.)
*
* Creation date: (10/23/01 9:31:27 PM)
* @author: <a href='mailto:greener@charter.net'>Rob Greene</a>
* @version: RJG 10/31/2001 22:12:32
*/
public abstract class AnimatedMazeImageObject extends MazeObject {
private Image[] images = null;
/**
* MazeImageObject constructor comment.
*/
public AnimatedMazeImageObject() {
super();
ImageManager imageManager = ImageManager.getInstance();
String[] names = getImageNames();
images = new Image[names.length];
for (int i=0; i<names.length; i++) {
images[i] = imageManager.getImage(names[i]);
}
}
/**
* Provides the animation sequence.
* This just needs to be an integer - not necessarily in the valid range, as
* modulo arithmetic will be used.
*
* Creation date: (10/26/01 10:55:18 PM)
*/
protected abstract int getAnimationSequence();
/**
* Answers with the image names for this object.
*
* Creation date: (10/14/01 9:41:15 PM)
*/
protected abstract String[] getImageNames();
/**
* Draw image on screen.
* It is expected that the region to be drawn has been clipped.
* See Graphics.create for more details.
*
* Creation date: (10/14/01 9:45:16 PM)
*/
public void paint(Graphics g) {
if (images == null) return;
int sequence = getAnimationSequence() % images.length;
Image image = images[sequence];
if (image != null) {
Rectangle rect = g.getClipBounds();
int x = (rect.width - image.getWidth(null)) / 2;
int y = (rect.height - image.getHeight(null)) / 2;
g.drawImage(image, x, y, null);
}
}
}

View File

@ -0,0 +1,41 @@
package a2geek.games.mousemaze2001.mazeobjects;
/**
* Represents the animated mouse.
*
* Creation date: (10/27/01 12:22:59 AM)
* @author: <a href='mailto:greener@charter.net'>Rob Greene</a>
* @version: RJG 10/27/2001 01:02:48
*/
public class AnimatedMouse extends AnimatedMouseMazeImageObject {
/**
* AnimatedMouse constructor comment.
*/
public AnimatedMouse() {
super();
}
/**
* Answers with the image names for this object.
*
* Creation date: (10/27/01 12:22:59 AM)
*/
protected String[] getImageNames() {
return new String[] {
"OriginalMouse0.gif",
"OriginalMouse1.gif",
"OriginalMouse2.gif",
"OriginalMouse3.gif"
};
}
/**
* Returns true if this is the mouse.
*
* Creation date: (10/14/01 9:43:11 PM)
*/
public boolean isMouse() {
return true;
}
}

View File

@ -0,0 +1,31 @@
package a2geek.games.mousemaze2001.mazeobjects;
import a2geek.games.mousemaze2001.domain.MazeDomain;
/**
* Provides the generic base-class for the MouseMaze 2001 games.
*
* Creation date: (10/26/01 10:58:46 PM)
* @author: <a href='mailto:greener@charter.net'>Rob Greene</a>
* @version: RJG 10/27/2001 01:02:48
*/
public abstract class AnimatedMouseMazeImageObject extends AnimatedMazeImageObject {
/**
* AnimatedMouseMazeImageObject constructor comment.
*/
public AnimatedMouseMazeImageObject() {
super();
}
/**
* Provides the animation sequence.
* This just needs to be an integer - not necessarily in the valid range, as
* modulo arithmetic will be used.
*
* Creation date: (10/26/01 10:55:18 PM)
*/
protected int getAnimationSequence() {
return MazeDomain.getInstance().getAnimationSequence();
}
}

View File

@ -0,0 +1,192 @@
package a2geek.games.mousemaze2001.mazeobjects;
import java.awt.Point;
import a2geek.games.mousemaze2001.domain.MazeDomain;
/**
* Represents the animated robot.
*
* Creation date: (10/27/01 12:08:56 AM)
* @author: <a href='mailto:greener@charter.net'>Rob Greene</a>
* @version: RJG 10/31/2001 22:12:32
*/
public class AnimatedRobot extends AnimatedMouseMazeImageObject {
private static int idCounter = 0;
private int id;
private Point location;
private int shieldLevel;
private Thread controlThread;
/**
* AnimatedRobot constructor comment.
*/
public AnimatedRobot(Point location, int shieldLevel) {
super();
id = idCounter++;
setLocation(location);
setShieldLevel(shieldLevel);
createControlThread();
controlThread.start();
}
/**
* Create the control thread.
*
* Creation date: (10/29/01 10:55:38 PM)
*/
protected void createControlThread() {
controlThread = new Thread() {
private void log(String message) {
//System.out.println(new java.util.Date() + " (" + id + ") - " + message);
}
public void run() {
MazeDomain domain = MazeDomain.getInstance();
log("Robot thread started.");
while (getInstance().isAlive()) {
if (domain.isGameOver()) break;
log("Robot alive at " + location.x + "," + location.y);
try {
if (getInstance() != null) {
domain.moveRobot(getInstance());
sleep(1250);
}
} catch (InterruptedException ex) {
ex.printStackTrace(System.out);
}
}
log("Robot died.");
}
};
controlThread.setDaemon(true);
}
/**
* Decrease the robots shield level.
*
* Creation date: (10/29/01 7:48:53 PM)
*/
public void decreaseShieldLevel() {
shieldLevel--;
}
/**
* Provides the animation sequence.
* This just needs to be an integer - not necessarily in the valid range, as
* modulo arithmetic will be used.
*
* Creation date: (10/26/01 10:55:18 PM)
*/
protected int getAnimationSequence() {
return (super.getAnimationSequence() % 4) + (shieldLevel * 4);
}
/**
* Answers with the image names for this object.
*
* Creation date: (10/27/01 12:08:56 AM)
*/
protected java.lang.String[] getImageNames() {
return new String[] {
"OriginalRobot0.gif",
"OriginalRobot1.gif",
"OriginalRobot2.gif",
"OriginalRobot3.gif",
"OriginalRobot0shield1.gif",
"OriginalRobot1shield1.gif",
"OriginalRobot2shield1.gif",
"OriginalRobot3shield1.gif",
"OriginalRobot0shield2.gif",
"OriginalRobot1shield2.gif",
"OriginalRobot2shield2.gif",
"OriginalRobot3shield2.gif"
};
}
/**
* Internal hook for control thread.
*
* Creation date: (10/29/01 11:00:57 PM)
*/
protected AnimatedRobot getInstance() {
return this;
}
/**
* Retrieve the Robots current position.
*
* Creation date: (10/29/01 7:47:51 PM)
* @return java.awt.Point
*/
public Point getLocation() {
return location;
}
/**
* Retrieve the robots current shield level.
*
* Creation date: (10/29/01 7:47:51 PM)
* @return int
*/
public int getShieldLevel() {
return shieldLevel;
}
/**
* Answers true if this robot is still alive.
*
* Creation date: (10/29/01 9:38:38 PM)
*/
public boolean isAlive() {
return (shieldLevel >= 0);
}
/**
* Returns true if this is a robot.
*
* Creation date: (10/14/01 9:42:51 PM)
*/
public boolean isRobot() {
return true;
}
/**
* Kill this robot.
*
* Creation date: (10/29/01 11:04:18 PM)
*/
public void kill() {
shieldLevel = -1;
}
/**
* Set the robots current location.
*
* Creation date: (10/29/01 7:47:51 PM)
* @param newLocation java.awt.Point
*/
public void setLocation(Point newLocation) {
location = newLocation;
}
/**
* Set the robots current shield level.
*
* Creation date: (10/29/01 7:47:51 PM)
* @param newShieldLevel int
*/
public void setShieldLevel(int newShieldLevel) {
shieldLevel = newShieldLevel;
}
}

View File

@ -0,0 +1,42 @@
package a2geek.games.mousemaze2001.mazeobjects;
import java.awt.*;
/**
* Will draw the MazeObject in a solid color.
*
* Creation date: (10/23/01 9:37:10 PM)
* @author: <a href='mailto:greener@charter.net'>Rob Greene</a>
* @version: RJG 10/23/2001 23:16:23
*/
public abstract class ColoredMazeObject extends MazeObject {
/**
* ColoredMazeObject constructor comment.
*/
public ColoredMazeObject() {
super();
}
/**
* Returns true if this is an explosion.
*
* Creation date: (10/14/01 9:42:51 PM)
*/
public boolean isExplosion() {
return true;
}
/**
* Draw image on screen.
* It is expected that the region to be drawn has been clipped.
* See Graphics.create for more details.
*
* Creation date: (10/14/01 9:45:16 PM)
*/
public void paint(Graphics g) {
Rectangle rect = g.getClipBounds();
g.setColor(getBackground());
g.fillRect(0, 0, rect.width, rect.height);
}
}

View File

@ -0,0 +1,52 @@
package a2geek.games.mousemaze2001.mazeobjects;
import java.awt.*;
/**
* Represents the exit.
*
* Creation date: (10/14/01 10:32:40 PM)
* @author: <a href='mailto:greener@charter.net'>Rob Greene</a>
* @version: RJG 10/24/2001 22:58:13
*/
public class Exit extends MazeImageObject {
/**
* Exit constructor comment.
*/
public Exit() {
super();
}
/**
* Answers with the image name of this object.
*
* Creation date: (10/14/01 10:32:40 PM)
*/
protected String getImageName() {
return "OriginalExit.gif";
}
/**
* Returns true if this is an exit.
*
* Creation date: (10/14/01 9:43:27 PM)
*/
public boolean isExit() {
return true;
}
/**
* Draw image on screen.
* It is expected that the region to be drawn has been clipped.
* See Graphics.create for more details.
*
* Creation date: (10/14/01 9:45:16 PM)
*/
public void paint(Graphics g) {
Rectangle rect = g.getClipBounds();
g.setColor(Color.white);
g.fillRect(0,0,rect.width,rect.height);
super.paint(g);
}
}

View File

@ -0,0 +1,27 @@
package a2geek.games.mousemaze2001.mazeobjects;
import java.awt.*;
/**
* Insert the type's description here.
*
* Creation date: (10/23/01 9:38:56 PM)
* @author: <a href='mailto:greener@charter.net'>Rob Greene</a>
* @version: RJG 10/23/2001 23:16:23
*/
public class GreenTile extends ColoredMazeObject {
/**
* GreenTile constructor comment.
*/
public GreenTile() {
super();
}
/**
* Retrieve the background color of this tile.
*
* Creation date: (10/23/01 9:50:07 PM)
*/
public Color getBackground() {
return Color.green;
}
}

View File

@ -0,0 +1,39 @@
package a2geek.games.mousemaze2001.mazeobjects;
import a2geek.games.mousemaze2001.mazeobjects.*;
/**
* Represents the inverted mouse image used for the life indicator.
*
* Creation date: (10/27/01 12:56:35 AM)
* @author: <a href='mailto:greener@charter.net'>Rob Greene</a>
* @version: RJG 10/29/2001 23:31:16
*/
public class InvertedMouse extends MazeImageObject {
/**
* InvertedMouse constructor comment.
*/
public InvertedMouse() {
super();
}
/**
* Answers with the image name of this object.
*
* Creation date: (10/14/01 10:31:56 PM)
*/
protected String getImageName() {
return "InvertedMouse.gif";
}
/**
* Returns true if this is the mouse.
*
* Creation date: (10/14/01 9:43:11 PM)
*/
public boolean isMouse() {
return true;
}
}

View File

@ -0,0 +1,72 @@
package a2geek.games.mousemaze2001.mazeobjects;
import java.net.*;
import a2geek.games.mousemaze2001.images.ImageManager;
import java.io.*;
import java.awt.image.*;
import java.awt.*;
/**
* Represents a MazeObject which is Image based. (Basically, a 'tile'.)
*
* Creation date: (10/23/01 9:31:27 PM)
* @author: <a href='mailto:greener@charter.net'>Rob Greene</a>
* @version: RJG 10/31/2001 22:12:32
*/
public abstract class MazeImageObject extends MazeObject {
private Image image = null;
/**
* MazeImageObject constructor comment.
*/
public MazeImageObject() {
super();
image = ImageManager.getInstance().getImage(getImageName());
}
/**
* Return the height of the image.
*
* Creation date: (10/27/01 12:47:15 AM)
*/
public int getHeight() {
return image.getHeight(null);
}
/**
* Answers with the image name of this object.
*
* Creation date: (10/14/01 9:41:15 PM)
*/
protected abstract String getImageName();
/**
* Return the width of the image.
*
* Creation date: (10/27/01 12:47:15 AM)
*/
public int getWidth() {
return image.getWidth(null);
}
/**
* Draw image on screen.
* It is expected that the region to be drawn has been clipped.
* See Graphics.create for more details.
*
* Creation date: (10/14/01 9:45:16 PM)
*/
public void paint(Graphics g) {
if (image != null) {
Rectangle rect = g.getClipBounds();
int x = (rect.width - image.getWidth(null)) / 2;
int y = (rect.height - image.getHeight(null)) / 2;
g.drawImage(image, x, x, null);
}
}
}

View File

@ -0,0 +1,89 @@
package a2geek.games.mousemaze2001.mazeobjects;
import java.awt.*;
/**
* Represents a maze object.
*
* Creation date: (10/14/01 9:38:50 PM)
* @author: <a href='mailto:greener@charter.net'>Rob Greene</a>
* @version: RJG 10/23/2001 23:16:23
*/
public abstract class MazeObject extends Canvas {
/**
* MazeObject constructor comment.
*/
public MazeObject() {
super();
}
/**
* Returns true if this is a bomb.
*
* Creation date: (10/14/01 9:43:27 PM)
*/
public boolean isBomb() {
return false;
}
/**
* Returns true if this is an exit.
*
* Creation date: (10/14/01 9:43:27 PM)
*/
public boolean isExit() {
return false;
}
/**
* Returns true if this is an explosion.
*
* Creation date: (10/14/01 9:42:51 PM)
*/
public boolean isExplosion() {
return false;
}
/**
* Returns true if this is a mine.
*
* Creation date: (10/14/01 9:43:56 PM)
*/
public boolean isMine() {
return false;
}
/**
* Returns true if this is the mouse.
*
* Creation date: (10/14/01 9:43:11 PM)
*/
public boolean isMouse() {
return false;
}
/**
* Returns true if this is a robot.
*
* Creation date: (10/14/01 9:42:51 PM)
*/
public boolean isRobot() {
return false;
}
/**
* Draw image on screen.
* It is expected that the region to be drawn has been clipped.
* See Graphics.create for more details.
*
* Creation date: (10/14/01 9:45:16 PM)
*/
public void paint(Graphics g) {
}
}

View File

@ -0,0 +1,36 @@
package a2geek.games.mousemaze2001.mazeobjects;
/**
* Represents a mine.
*
* Creation date: (10/22/01 11:23:56 PM)
* @author: <a href='mailto:greener@charter.net'>Rob Greene</a>
* @version: RJG 10/23/2001 23:16:23
*/
public class Mine extends MazeImageObject {
/**
* Mine constructor comment.
*/
public Mine() {
super();
}
/**
* Answers with the image name of this object.
*
* Creation date: (10/22/01 11:23:56 PM)
*/
protected String getImageName() {
return "OriginalMine.gif";
}
/**
* Returns true if this is a mine.
*
* Creation date: (10/14/01 9:43:56 PM)
*/
public boolean isMine() {
return true;
}
}

View File

@ -0,0 +1,29 @@
package a2geek.games.mousemaze2001.mazeobjects;
import java.awt.*;
/**
* Purple (cyan) explosion tile.
*
* Creation date: (10/23/01 9:39:30 PM)
* @author: <a href='mailto:greener@charter.net'>Rob Greene</a>
* @version: RJG 10/23/2001 23:16:23
*/
public class PurpleTile extends ColoredMazeObject {
/**
* PurpleTile constructor comment.
*/
public PurpleTile() {
super();
setBackground(Color.cyan);
}
/**
* Retrieve the background color of this tile.
*
* Creation date: (10/23/01 9:50:07 PM)
*/
public Color getBackground() {
return Color.magenta;
}
}

View File

@ -0,0 +1,39 @@
package a2geek.games.mousemaze2001.threads;
import a2geek.games.mousemaze2001.MouseMaze2001;
import a2geek.games.mousemaze2001.domain.MazeDomain;
/**
* Insert the type's description here.
*
* Creation date: (10/27/01 12:38:44 AM)
* @author: <a href='mailto:greener@charter.net'>Rob Greene</a>
* @version: RJG 10/27/2001 01:02:48
*/
public class AnimationThread extends Thread {
/**
* AnimationThread constructor comment.
*/
public AnimationThread() {
super("AnimationThread");
}
/**
* Provide animation.
*
* Creation date: (10/27/01 12:38:59 AM)
*/
public void run() {
MazeDomain domain = MazeDomain.getInstance();
MouseMaze2001 game = MouseMaze2001.getInstance();
while (domain.isGameOver() == false) {
try {
sleep(250);
} catch (InterruptedException ex) {
}
domain.incrementAnimationSequence();
game.repaintNeeded();
}
}
}

View File

@ -0,0 +1,58 @@
package a2geek.games.mousemaze2001.threads;
import java.util.*;
import a2geek.games.mousemaze2001.domain.MazeDomain;
import java.awt.*;
/**
* This thread sets up the bomb explosion and creates multiple explosion threads.
*
* Creation date: (10/23/01 10:08:07 PM)
* @author: <a href='mailto:greener@charter.net'>Rob Greene</a>
* @version: RJG 10/24/2001 22:58:13
*/
public class BombExplosionThread extends Thread {
private int delay = 400;
private Point pt = null;
private int maxSize = 4;
/**
* ExplosionThread constructor comment.
*/
public BombExplosionThread(Point pt) {
super("BombExplosionThread");
this.pt = pt;
}
/**
* Perform the threadded process to generate bomb explosions.
* Generates the initial bomb explosion and then delayed rings around that point.
* <p>
* Creation date: (10/23/01 10:08:07 PM)
*/
public void run() {
try {
MazeDomain domain = MazeDomain.getInstance();
Random random = new Random();
int size = random.nextInt(maxSize-2)+2;
for (int i=0; i<size; i++) {
for (int dx=-i; dx<=i; dx++) {
for (int dy=-i; dy<=i; dy++) {
if (dx == i || dx == -i || dy == i || dy == -i) {
Point at = new Point(pt);
at.translate(dx,dy);
if (domain.isValidPoint(at)) {
ExplosionThread explosion = new ExplosionThread(at);
explosion.start();
}
}
}
}
sleep(delay);
}
} catch (InterruptedException ex) {
}
}
}

View File

@ -0,0 +1,169 @@
package a2geek.games.mousemaze2001.threads;
/**
* A ControlledThread is a pseudo-Thread which allows thread-safe suspending/resuming and
* stoppping/restarting. Technically, this class implements runnable. All methods, except
* process are marked as final because it is assumed that you do not want to mess around
* with the threading.
* <p>
* To implement a pausable thread, extend the ControlledThread and implement process.
* Don't forget to set a default delay in your constructor, if appropriate!
* <p>
* Creation date: (10/20/01 9:08:13 PM)
* @author: <a href='mailto:greener@charter.net'>Rob Greene</a>
* @version: RJG 10/29/2001 22:40:54
*/
public abstract class ControlledThread implements Runnable {
private boolean running = false;
private boolean paused = false;
private Thread thread;
private long delay;
/**
* ControlledThread constructor.
*/
public ControlledThread() {
super();
thread = new Thread(this, getThreadName());
thread.setDaemon(true);
}
/**
* Retrieve the delay that the thread will use.
* <p>
* Creation date: (10/20/01 9:42:01 PM)
* @return long
*/
public final long getDelay() {
return delay;
}
/**
* Returns the name of this thread. By default, it will be the class name.
*
* Creation date: (10/21/01 2:24:36 PM)
*/
protected String getThreadName() {
String className = getClass().getName();
int pos = className.lastIndexOf(".") + 1;
if (pos > -1) return className.substring(pos);
else return className;
}
/**
* Returns true if the thread is paused.
* Note that this does not indicate if the thread is actually running.
* <p>
* Creation date: (10/20/01 10:20:37 PM)
*/
public final boolean isPaused() {
return paused;
}
/**
* Returns true if this thread is actively running.
* Note that this does not indicate if the thread has been paused.
* <p>
* Creation date: (10/20/01 10:21:07 PM)
*/
public final boolean isRunning() {
return running;
}
/**
* Perform the threadded process.
* <p>
* Creation date: (10/20/01 10:21:40 PM)
*/
protected abstract void process();
/**
* Resume a paused thread.
* Note that the thread must be in a running state.
* <p>
* Creation date: (10/20/01 10:22:13 PM)
*/
public synchronized final void resume() {
paused = false;
notifyAll();
}
/**
* This is the thread control loop.
* To customize, implement the process method.
* <p>
* Creation date: (10/20/01 10:22:32 PM)
*/
public final void run() {
while (isRunning()) {
try {
process(); // <-- customize here!!
synchronized(this) {
while (isRunning() && isPaused()) {
wait();
}
}
thread.sleep(getDelay());
} catch (Exception ex) {
System.out.println("Exception in " + getThreadName());
ex.printStackTrace(System.out);
}
}
paused = false;
running = false;
}
/**
* Set the delay used in the control thread.
* <p>
* Creation date: (10/20/01 9:42:01 PM)
* @param newDelay long
*/
public final void setDelay(long newDelay) {
delay = newDelay;
}
/**
* Start the thread.
* <p>
* Creation date: (10/20/01 10:24:37 PM)
*/
public final void start() {
if (isRunning()) {
resume();
} else {
running = true;
paused = false;
thread.start();
}
}
/**
* Stop the thread.
* <p>
* Creation date: (10/20/01 10:24:46 PM)
*/
public synchronized final void stop() {
running = false;
notifyAll();
}
/**
* Suspend the thread.
* <p>
* Creation date: (10/20/01 10:24:58 PM)
*/
public final void suspend() {
paused = true;
}
}

View File

@ -0,0 +1,55 @@
package a2geek.games.mousemaze2001.threads;
import java.awt.*;
import a2geek.games.mousemaze2001.MouseMaze2001;
import a2geek.games.mousemaze2001.domain.MazeDomain;
import a2geek.games.mousemaze2001.mazeobjects.*;
/**
* This thread runs until the explosion effect is done.
*
* Creation date: (10/23/01 10:08:07 PM)
* @author: <a href='mailto:greener@charter.net'>Rob Greene</a>
* @version: RJG 10/29/2001 22:40:54
*/
public class ExplosionThread extends Thread {
private int delay = 100;
private int loops = 3;
private Point pt = null;
/**
* ExplosionThread constructor comment.
*/
public ExplosionThread(Point pt) {
super("ExplosionThread");
this.pt = pt;
this.setPriority(2);
}
/**
* Perform the threadded process.
* <p>
* Creation date: (10/23/01 10:08:07 PM)
*/
public void run() {
try {
MazeDomain domain = MazeDomain.getInstance();
domain.shoot(pt);
for (int i=0; i<loops; i++) {
domain.setMazeObject(pt, new GreenTile());
MouseMaze2001.getInstance().repaintNeeded();
sleep(delay);
domain.setMazeObject(pt, new PurpleTile());
MouseMaze2001.getInstance().repaintNeeded();
sleep(delay);
}
domain.setMazeObject(pt, null);
// ensure map is put back in order... specifically, if the mouse
// was shot in its starting square, it needs to be placed there!
domain.synchronizeMap();
MouseMaze2001.getInstance().repaintNeeded();
} catch (InterruptedException ex) {
}
}
}

View File

@ -0,0 +1,53 @@
package a2geek.games.mousemaze2001.threads;
import a2geek.games.mousemaze2001.MouseMaze2001;
import a2geek.games.mousemaze2001.domain.MazeDomain;
/**
* This thread will pause the game for a short period of time, displaying a message
* on the screen.
*
* Creation date: (10/25/01 11:45:57 PM)
* @author: <a href='mailto:greener@charter.net'>Rob Greene</a>
* @version: RJG 10/31/2001 22:12:32
*/
public class GameDelayThread extends Thread {
private int delay;
/**
* GameDelayThread constructor comment.
*/
public GameDelayThread(String message) {
this(message, 250);
}
/**
* GameDelayThread constructor comment.
*/
public GameDelayThread(String message, int delay) {
super();
MazeDomain.getInstance().setPause(message);
MouseMaze2001.getInstance().repaintNeeded();
this.delay = delay;
}
/**
* Pause for a short period of time and then disable the game pause.
*
* Creation date: (10/25/01 11:49:16 PM)
*/
public void run() {
try {
sleep(delay);
while (MazeDomain.getInstance().areExplosionsPresent()) {
sleep(50);
}
} catch (InterruptedException ex) {
int i = 0;
// ignore
}
MazeDomain.getInstance().setPause(null);
}
}

View File

@ -0,0 +1,32 @@
package a2geek.games.mousemaze2001.threads;
import java.awt.Point;
import java.util.*;
import a2geek.games.mousemaze2001.domain.MazeDomain;
/**
* Provide AI for MouseMaze game.
*
* Creation date: (10/21/01 2:00:35 PM)
* @author: <a href='mailto:greener@charter.net'>Rob Greene</a>
* @version: RJG 10/29/2001 23:31:16
*/
public class GameThread extends ControlledThread {
/**
* GameThread constructor comment.
*/
public GameThread() {
super();
setDelay(300);
}
/**
* Perform the threadded process.
* <p>
* Creation date: (10/21/01 2:00:35 PM)
*/
protected void process() {
MazeDomain.getInstance().explodeBombsRandomly();
}
}

View File

@ -0,0 +1,32 @@
package a2geek.games.mousemaze2001.threads;
import a2geek.games.mousemaze2001.IntroPanel;
/**
* Manage the Intro (demo) control thread.
* <p>
* Creation date: (10/20/01 9:08:13 PM)
* @author: <a href='mailto:greener@charter.net'>Rob Greene</a>
* @version: RJG 10/23/2001 23:16:23
*/
public class IntroThread extends ControlledThread {
/**
* IntroThread constructor comment.
*/
public IntroThread() {
super();
setDelay(15);
}
/**
* Instruct the IntroPanel to perform another "tick".
* <p>
* Creation date: (10/20/01 10:25:15 PM)
*/
protected void process() {
IntroPanel introPanel = IntroPanel.getInstance();
introPanel.incrementTicker();
introPanel.repaint();
}
}

View File

@ -0,0 +1,68 @@
package a2geek.games.mousemaze2001.threads;
import a2geek.games.mousemaze2001.MouseMaze2001;
import a2geek.games.mousemaze2001.domain.MazeDomain;
import a2geek.games.mousemaze2001.mazeobjects.*;
/**
* This thread will pause the game while the map is redrawn; semi artistically.
*
* Creation date: (10/25/01 11:45:57 PM)
* @author: <a href='mailto:greener@charter.net'>Rob Greene</a>
* @version: RJG 11/05/2001 22:35:58
*/
public class LevelTranslationThread extends Thread {
private int delay;
private MazeObject[][] newMap;
/**
* LevelTranslationThread constructor comment.
*/
public LevelTranslationThread(String message, MazeObject[][] map) {
this(message, 5, map);
}
/**
* LevelTranslationThread constructor comment.
*/
public LevelTranslationThread(String message, int delay, MazeObject[][] map) {
super();
MazeDomain.getInstance().setPause(message);
MouseMaze2001.getInstance().repaintNeeded();
this.newMap = map;
this.delay = delay;
}
/**
* Pause for a short period of time and then disable the game pause.
*
* Creation date: (10/25/01 11:49:16 PM)
*/
public void run() {
MazeDomain domain = MazeDomain.getInstance();
MouseMaze2001 controller = MouseMaze2001.getInstance();
GreenTile greenTile = new GreenTile();
PurpleTile purpleTile = new PurpleTile();
try {
for (int x=0; x<domain.getMapWidth(); x++) {
for (int y=0; y<domain.getMapHeight(); y++) {
domain.setMazeObject(x, y, greenTile);
controller.repaint();
sleep(delay);
domain.setMazeObject(x, y, purpleTile);
controller.repaint();
sleep(delay);
domain.setMazeObject(x, y, newMap[x][y]);
controller.repaint();
sleep(delay);
}
}
} catch (InterruptedException ex) {
// ignore
}
domain.setMap(newMap); // in case thread was interrupted
domain.setPause(null);
}
}

View File

@ -0,0 +1,98 @@
package a2geek.games.mousemaze2001.threads;
import java.awt.Component;
/**
* A RepaintThread manages repainting of the screen. This gives all threads in a program
* the ability to repaint the screen without having multiple threads repainting at the same
* time. In addition, the RepaintThread will pause for a short period of time after a
* screen has been repainted to ensure that the CPU is not over-taxed.
*
* Creation date: (10/24/01 9:09:07 PM)
* @author: <a href='mailto:greener@charter.net'>Rob Greene</a>
* @version: RJG 10/31/2001 22:12:32
*/
public class RepaintThread implements Runnable {
private Component component;
private Thread thread;
private int delay;
private boolean repaintNeeded;
/**
* RepaintThread constructor.
*/
public RepaintThread(Component theComponent) {
super();
thread = new Thread(this, "RepaintThread");
thread.setDaemon(true);
component = theComponent;
delay = 50;
thread.setPriority(thread.getPriority()-1);
}
/**
* Retrieve the current delay used by the RepaintThread.
*
* Creation date: (10/24/01 9:12:16 PM)
* @return int
*/
public int getDelay() {
return delay;
}
/**
* Tell the RepaintThread that a repaint needs to occur.
*
* Creation date: (10/24/01 9:19:23 PM)
*/
public synchronized void repaintNeeded() {
//System.out.println(new java.util.Date() + " + repaint received");
repaintNeeded = true;
notifyAll();
}
/**
* Control the RepaintThread.
*
* Creation date: (10/24/01 9:15:14 PM)
*/
public void run() {
while (true) {
try {
if (repaintNeeded) {
repaintNeeded = false;
component.repaint();
}
thread.sleep(getDelay());
synchronized(this) {
wait();
}
} catch (Exception ex) {
break;
}
}
}
/**
* Set the delay to be used by the RepaintThread.
*
* Creation date: (10/24/01 9:12:16 PM)
* @param newDelay int
*/
public void setDelay(int newDelay) {
delay = newDelay;
}
/**
* Start the thread.
* <p>
* Creation date: (10/20/01 10:24:37 PM)
*/
public void start() {
thread.start();
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,52 @@
# Logo
MouseMazeLogo.gif
# Buttons
CancelButton.gif
DefaultButton.gif
EasyButton.gif
HardButton.gif
OkButton.gif
PreferencesButton.gif
QuitButton.gif
StartButton.gif
# Intro sequence images
OriginalMouseMazeGameShot.gif
OriginalMouseMazeHelp.gif
OriginalMouseMazeLogo.gif
OriginalMouseMazeWin.gif
# Mouse used for lives left
InvertedMouse.gif
# Static game images
OriginalBomb.gif
OriginalExit.gif
OriginalMine.gif
OriginalMouse.gif
OriginalRobot.gif
OriginalSkull.gif
# Animated game image sequences
OriginalBomb0.gif
OriginalBomb1.gif
OriginalBomb2.gif
OriginalBomb3.gif
OriginalMouse0.gif
OriginalMouse1.gif
OriginalMouse2.gif
OriginalMouse3.gif
OriginalMouse4.gif
OriginalRobot0.gif
OriginalRobot0shield1.gif
OriginalRobot0shield2.gif
OriginalRobot1.gif
OriginalRobot1shield1.gif
OriginalRobot1shield2.gif
OriginalRobot2.gif
OriginalRobot2shield1.gif
OriginalRobot2shield2.gif
OriginalRobot3.gif
OriginalRobot3shield1.gif
OriginalRobot3shield2.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 914 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 941 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 941 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 947 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 956 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 950 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 895 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 889 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 914 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 914 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 910 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 911 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 909 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 913 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 903 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 924 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 926 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 979 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 979 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 931 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 979 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 979 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 933 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 979 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 979 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 927 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 976 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 976 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 941 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@ -0,0 +1,14 @@
animatedImages=true
bombsPerLevel=2
fixedRobotShotRange=true
maxBombsPerLevel=5
maxRobotShotRange=4
maxRobotVisibilityRange=5
robotMineFrequency=10
robotShootFrequency=80
robotShotRange=2
robotVisibilityRange=4
shootingMouse=true
unlimitedGameLevels=false
unlimitedLives=false
shieldedRobots=true

View File

@ -0,0 +1,14 @@
animatedImages=true
bombsPerLevel=1
fixedRobotShotRange=true
maxBombsPerLevel=5
maxRobotShotRange=4
maxRobotVisibilityRange=5
robotMineFrequency=5
robotShootFrequency=30
robotShotRange=1
robotVisibilityRange=2
shootingMouse=true
unlimitedGameLevels=false
unlimitedLives=false
shieldedRobots=false

View File

@ -0,0 +1,14 @@
animatedImages=true
bombsPerLevel=4
fixedRobotShotRange=false
maxBombsPerLevel=5
maxRobotShotRange=4
maxRobotVisibilityRange=5
robotMineFrequency=40
robotShootFrequency=90
robotShotRange=3
robotVisibilityRange=4
shootingMouse=true
unlimitedGameLevels=false
unlimitedLives=false
shieldedRobots=true

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.