Skip to content
Snippets Groups Projects
Verified Commit 661bbde3 authored by Christopher Bohn's avatar Christopher Bohn :thinking:
Browse files

Added starter code for Lab 9

parent 88897382
No related branches found
No related tags found
No related merge requests found
Showing
with 2586 additions and 0 deletions
# Mac file finder metadata
.DS_Store
# Windows file metadata
._*
# Thumbnail image caches
Thumbs.db
ethumbs.db
# MS Office temporary file
~*
# Emacs backup file
*~
# Common
[Bb]in/
[Bb]uild/
[Oo]bj/
[Oo]ut/
[Tt]mp/
[Xx]86/
[Ii][Aa]32/
[Xx]64/
[Xx]86_64/
[Xx]86-64/
[Aa]rm
[Aa]32
[Tt]32
[Aa]64
*.tmp
*.bak
*.bk
*.swp
# Java files
*.class
javadoc/
# Maven
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
# JetBrains (IntelliJ IDEA, PyCharm, etc) files
.idea/
cmake-build-*/
*.iml
*.iws
*.ipr
# Eclipse files
.settings/
.project
.classpath
.buildpath
.loadpath
.factorypath
local.properties
This diff is collapsed.
This code is a modification of ["Intelligent Java Pacman"](https://sourceforge.net/projects/javaipacman/) by
[Junyang Gu](https://sourceforge.net/u/mikejyg/profile/).
"Intelligent Java Pacman" is free software released under the GNU General Public
License version 3.0 (GPLv3); see LICENSE for details.
Maze Layout
===========
The maze's X coordinates go from 0 (left) to 20 (right).
The maze's Y coordinates go from 0 (top) to 15 (bottom).
The maze has no dead ends.
Ghost Behavior (as implemented in the turn method of edu.unl.cse.soft160.pacman.Ghost)
======================================================================================
A ghost may never go into a wall.
A ghost may never reverse direction; it can only go straight, turn left, or turn right.
If a ghost is:
in the center box ("caged") and
able to move in the same direction as the player,
it should:
move in the same direction as the player.
If a ghost is:
in the center box ("caged") and
not able to move in the same direction as the player,
it should:
move in the first available direction from the list [north, east, west, south].
If a ghost is:
outside the center box and inedible ("hunting"),
it should:
choose the highest rated legal move, where the rating of a move is the sum of:
the number of squares from the ghost to the player in that direction and
a ten-point bonus if the player is moving in the same direction.
If a ghost is:
outside the center box and edible ("edible"),
it should:
choose the highest rated legal move, where the rating of a move is:
the number of squares from the ghost to the player in the opposite direction.
If a ghost is:
outside the center box and recovering from being eaten ("eaten"),
it should:
choose the highest rated legal move, where the rating of a move is the sum of:
the number of squares from the ghost to the player in the opposite direction and
a ten-point bonus if the player is moving in the same direction.
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>edu.unl.cse.soft160.pacman</groupId>
<artifactId>pacman</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>pacman</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
/**
* Copyright (C) 1997-2010 Junyang Gu <mikejyg@gmail.com>
*
* This file is part of javaiPacman.
*
* javaiPacman is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* javaiPacman is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with javaiPacman. If not, see <http://www.gnu.org/licenses/>.
*/
package edu.unl.cse.soft160.pacman;
/**
* the tables are used to speed up computation
*/
public class Constants {
// for direction computation
public static final int[] DIRECTION_X_COMPONENTS = {1, 0, -1, 0};
public static final int[] DIRECTION_Y_COMPONENTS = {0, -1, 0, 1};
public static final int[] iDirection = {-1, // 0:
1, // 1: x=0, y=-1
-1, // 2:
-1, // 3:
2, // 4: x=-1, y=0
-1, // 5:
0, // 6: x=1, y=0
-1, // 7
-1, // 8
3 // 9: x=0, y=1
};
// backward direction
public static final int[] iBack = {2, 3, 0, 1};
// direction code
public enum Direction {
EAST,
NORTH,
WEST,
SOUTH,
}
// the maze definition string
public static final String[] MazeDefine = {
"XXXXXXXXXXXXXXXXXXXXX", // 1
"X.........X.........X", // 2
"XOXXX.XXX.X.XXX.XXXOX", // 3
"X......X..X.........X", // 4
"XXX.XX.X.XXX.XX.X.X.X", // 5
"X....X..........X.X.X", // 6
"X.XX.X.XXXXX-X.XX.X.X", // 7
"X.XX.X.X X......X", // 8
"X.XX...X X.XXXX.X", // 9
"X.XX.X.XXXXXXX.XXXX.X", // 10
"X....X.... .........X", // 11
"XXX.XX.XXXXXXX.X.X.XX", // 12
"X.........X....X....X", // 13
"XOXXXXXXX.X.XXXXXXXOX", // 14
"X...................X", // 15
"XXXXXXXXXXXXXXXXXXXXX", // 16
};
}
/**
* Copyright (C) 1997-2010 Junyang Gu <mikejyg@gmail.com>
*
* This file is part of javaiPacman.
*
* javaiPacman is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* javaiPacman is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with javaiPacman. If not, see <http://www.gnu.org/licenses/>.
*/
package edu.unl.cse.soft160.pacman;
import static edu.unl.cse.soft160.pacman.Constants.Direction;
import java.awt.*;
public class Ghost {
public enum Status {
CAGED, HUNTING, EDIBLE, EATEN,
};
private final int[] STEPS = { 7, 7, 1, 1 }; // indexed by status
private final int[] FRAMES = { 8, 8, 2, 1 }; // indexed by status
private final int MAXIMUM_EDIBILITY_DURATION = 600; // frames
private int edibilityDuration; // frames
private Speed speed = new Speed();
private Status status;
private int edibilityRemaining;
private boolean blinking;
private Direction direction;
private int x, y;
// the applet this object is associated to
private Window applet;
private Graphics graphics;
// the maze the ghosts knows
private Maze maze;
// the ghost images
java.awt.Image imageGhost;
java.awt.Image imageEdible;
java.awt.Image imageEye;
Ghost(Window applet, Graphics graphics, Maze maze, Color color) {
this.applet = applet;
this.graphics = graphics;
this.maze = maze;
imageGhost = applet.createImage(18, 18);
Image.drawGhost(imageGhost, 0, color);
imageEdible = applet.createImage(18, 18);
Image.drawGhost(imageEdible, 1, Color.white);
imageEye = applet.createImage(18, 18);
Image.drawGhost(imageEye, 2, Color.lightGray);
}
public void start(int initialPosition, int round) {
x = (8 + initialPosition + (initialPosition >= 2 ? 1 : 0)) * 16;
y = 8 * 16;
direction = Direction.NORTH;
status = Status.CAGED;
edibilityDuration = MAXIMUM_EDIBILITY_DURATION / ((round + 1) / 2);
speed.start(STEPS[status.ordinal()], FRAMES[status.ordinal()]);
}
public void draw() {
maze.DrawDot(x / 16, y / 16);
maze.DrawDot(x / 16 + (x % 16 > 0 ? 1 : 0), y / 16 + (y % 16 > 0 ? 1 : 0));
if (status == Status.EDIBLE && blinking && edibilityRemaining % 32 < 16) {
graphics.drawImage(imageGhost, x - 1, y - 1, applet);
} else if (status == Status.HUNTING || status == Status.CAGED) {
graphics.drawImage(imageGhost, x - 1, y - 1, applet);
} else if (status == Status.EDIBLE) {
graphics.drawImage(imageEdible, x - 1, y - 1, applet);
} else {
graphics.drawImage(imageEye, x - 1, y - 1, applet);
}
}
public static Direction turn(Status status, int gridX, int gridY, Direction direction, int playerGridX, int playerGridY,
Direction playerDirection, boolean eastBlocked, boolean northBlocked, boolean westBlocked, boolean southBlocked) {
int reverse = (direction.ordinal() + 2) % 4;
int dx = playerGridX - gridX;
int dy = playerGridY - gridY;
boolean[] blocked = { eastBlocked, northBlocked, westBlocked, southBlocked };
Direction candidate;
candidate = Direction.EAST;
int eastScore = 0;
if (status == Status.CAGED && candidate == playerDirection) {
eastScore = 1;
} else {
int towardsPlayer = Math.max(
dx * Constants.DIRECTION_X_COMPONENTS[candidate.ordinal()] + dy * Constants.DIRECTION_Y_COMPONENTS[candidate.ordinal()],
0);
if (status == Status.HUNTING) {
eastScore += towardsPlayer;
} else {
eastScore -= towardsPlayer;
}
}
if (status != Status.EDIBLE && candidate == playerDirection) {
eastScore += 10;
}
if (candidate.ordinal() == reverse || blocked[candidate.ordinal()]) {
eastScore = Integer.MIN_VALUE;
}
candidate = Direction.NORTH;
int northScore = 0;
if (status == Status.CAGED && candidate == playerDirection) {
northScore = 1;
} else {
int towardsPlayer = Math.max(
dx * Constants.DIRECTION_X_COMPONENTS[candidate.ordinal()] + dy * Constants.DIRECTION_Y_COMPONENTS[candidate.ordinal()],
0);
if (status == Status.HUNTING) {
northScore += towardsPlayer;
} else {
northScore -= towardsPlayer;
}
}
if (status != Status.EDIBLE && candidate == playerDirection) {
northScore += 10;
}
if (candidate.ordinal() == reverse || blocked[candidate.ordinal()]) {
northScore = Integer.MIN_VALUE;
}
candidate = Direction.WEST;
int westScore = 0;
if (status == Status.CAGED && candidate == playerDirection) {
westScore = 1;
} else {
int towardsPlayer = Math.max(
dx * Constants.DIRECTION_X_COMPONENTS[candidate.ordinal()] + dy * Constants.DIRECTION_Y_COMPONENTS[candidate.ordinal()],
0);
if (status == Status.HUNTING) {
westScore += towardsPlayer;
} else {
westScore -= towardsPlayer;
}
}
if (status != Status.EDIBLE && candidate == playerDirection) {
westScore += 10;
}
if (candidate.ordinal() == reverse || blocked[candidate.ordinal()]) {
westScore = Integer.MIN_VALUE;
}
candidate = Direction.SOUTH;
int southScore = 0;
if (status == Status.CAGED && candidate == playerDirection) {
southScore = 1;
} else {
int towardsPlayer = Math.max(
dx * Constants.DIRECTION_X_COMPONENTS[candidate.ordinal()] + dy * Constants.DIRECTION_Y_COMPONENTS[candidate.ordinal()],
0);
if (status == Status.HUNTING) {
southScore += towardsPlayer;
} else {
southScore -= towardsPlayer;
}
}
if (status != Status.EDIBLE && candidate == playerDirection) {
southScore += 10;
}
if (candidate.ordinal() == reverse || blocked[candidate.ordinal()]) {
southScore = Integer.MIN_VALUE;
}
if (status == Status.CAGED) {
++northScore;
}
Direction result = direction;
int score = Integer.MIN_VALUE;
if (eastScore > score) {
result = Direction.EAST;
score = eastScore;
}
if (northScore > score) {
result = Direction.NORTH;
score = northScore;
}
if (westScore > score) {
result = Direction.WEST;
score = westScore;
}
if (southScore > score) {
result = Direction.SOUTH;
score = southScore;
}
return result;
}
private boolean isDoor(int gridX, int gridY) {
int square = maze.grid[gridY][gridX];
return square == Maze.DOOR;
}
private boolean isBlocked(int gridX, int gridY) {
int square = maze.grid[gridY][gridX];
return square == Maze.WALL || square == Maze.DOOR && status != Status.CAGED;
}
private void move(int playerX, int playerY, Direction playerDirection) {
if (x % 16 == 0 && y % 16 == 0) {
int gridX = x / 16;
int gridY = y / 16;
if (status == Status.CAGED && isDoor(gridX, gridY)) {
status = Status.HUNTING;
}
direction = turn(status, gridX, gridY, direction, playerX / 16, playerY / 16, playerDirection,
isBlocked(gridX + 1, gridY), isBlocked(gridX, gridY - 1), isBlocked(gridX - 1, gridY),
isBlocked(gridX, gridY + 1));
}
int travelRate = (status == Status.EATEN) ? 2 : 1;
x += travelRate * Constants.DIRECTION_X_COMPONENTS[direction.ordinal()];
y += travelRate * Constants.DIRECTION_Y_COMPONENTS[direction.ordinal()];
}
public void tick(int playerX, int playerY, int playerDirection) {
if (status == Status.EDIBLE || status == Status.EATEN) {
--edibilityRemaining;
if (edibilityRemaining == 0) {
status = Status.HUNTING;
}
}
if (status == Status.EDIBLE) {
blinking = edibilityRemaining < edibilityDuration / 3;
}
if (speed.isMove() && (status != Status.EDIBLE || edibilityRemaining % 2 == 0)) {
move(playerX, playerY, Direction.values()[playerDirection]);
}
}
public void makeEdible() {
if (status == Status.EDIBLE || status == Status.HUNTING) {
status = Status.EDIBLE;
edibilityRemaining = edibilityDuration;
blinking = false;
// reverse
if (x % 16 != 0 || y % 16 != 0) {
direction = Direction.values()[Constants.iBack[direction.ordinal()]];
// a special condition:
// when ghost is leaving home, it can not go back
// while becoming edible
int square;
square = maze.grid[y / 16 + Constants.DIRECTION_Y_COMPONENTS[direction.ordinal()]][x / 16
+ Constants.DIRECTION_X_COMPONENTS[direction.ordinal()]];
if (square == Maze.DOOR)
direction = Direction.values()[Constants.iBack[direction.ordinal()]];
}
}
}
// return 1 if caught the pac!
// return 2 if being caught by pac
public int testCollision(int playerX, int playerY) {
if (x <= playerX + 2 && x >= playerX - 2 && y <= playerY + 2 && y >= playerY - 2) {
switch (status) {
case HUNTING:
return 1;
case EDIBLE:
status = Status.EATEN;
x = x / 4 * 4;
y = y / 4 * 4;
return 2;
default:
break;
}
}
// nothing
return 0;
}
}
/**
* Copyright (C) 1997-2010 Junyang Gu <mikejyg@gmail.com>
*
* This file is part of javaiPacman.
*
* javaiPacman is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* javaiPacman is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with javaiPacman. If not, see <http://www.gnu.org/licenses/>.
*/
package edu.unl.cse.soft160.pacman;
import java.awt.*;
public class Image {
public static void drawDot(java.awt.Image img) {
Graphics g = img.getGraphics();
g.setColor(Color.yellow);
g.drawRect(0, 0, 2, 2);
g.dispose();
}
public static void drawPowerDot(java.awt.Image img) {
Graphics g = img.getGraphics();
g.setColor(Color.black);
g.fillRect(0, 0, 16, 16);
g.setColor(Color.yellow);
int iCounter = 0;
short mask = 0x01;
for (int i = 0; i < 16; i++)
for (int j = 0; j < 16; j++) {
if ((power_bits[iCounter] & mask) != 0)
g.fillRect(j, i, 1, 1);
mask <<= 1;
if ((mask & 0xff) == 0) {
mask = 0x01;
iCounter++;
}
}
g.dispose();
}
public static void drawPac(java.awt.Image img, int dir, int step) {
Graphics g = img.getGraphics();
g.setColor(Color.black);
g.fillRect(0, 0, 18, 18);
g.setColor(Color.yellow);
int iCounter = 0;
short mask = 0x01;
for (int i = 0; i < 16; i++)
for (int j = 0; j < 16; j++) {
if ((pac_bits[dir][step][iCounter] & mask) != 0)
g.fillRect(j + 1, i + 1, 1, 1);
mask <<= 1;
if ((mask & 0xff) == 0) {
mask = 0x01;
iCounter++;
}
}
g.dispose();
}
public static void drawGhost(java.awt.Image img, int number, Color color) {
Graphics g = img.getGraphics();
g.setColor(Color.black);
g.fillRect(0, 0, 18, 18);
g.setColor(color);
int iCounter = 0;
short mask = 0x01;
for (int i = 0; i < 16; i++)
for (int j = 0; j < 16; j++) {
if ((ghost_bits[number][iCounter] & mask) != 0)
g.fillRect(j + 1, i + 1, 1, 1);
mask <<= 1;
if ((mask & 0xff) == 0) {
mask = 0x01;
iCounter++;
}
}
g.dispose();
}
// //////////////////////////////////////////////////////////////////////////////
// image arrays
// //////////////////////////////////////////////////////////////////////////////
static final short[][][] pac_bits = { // [4][4][32]
// right
{
{0xe0, 0x07, 0xf8, 0x1f, 0xfc, 0x0f, 0xfe, 0x07, 0xfe,
0x03, 0xff, 0x01, 0xff, 0x00, 0x7f, 0x00, 0x7f,
0x00, 0xff, 0x00, 0xff, 0x01, 0xfe, 0x03, 0xfe,
0x07, 0xfc, 0x0f, 0xf8, 0x1f, 0xe0, 0x07},
{0xe0, 0x07, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xfe,
0x3f, 0xff, 0x0f, 0xff, 0x03, 0xff, 0x00, 0xff,
0x00, 0xff, 0x03, 0xff, 0x0f, 0xfe, 0x3f, 0xfe,
0x7f, 0xfc, 0x3f, 0xf8, 0x1f, 0xe0, 0x07},
{0xe0, 0x07, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xfe,
0x7f, 0xff, 0xff, 0xff, 0x1f, 0xff, 0x01, 0xff,
0x01, 0xff, 0x1f, 0xff, 0xff, 0xfe, 0x7f, 0xfe,
0x7f, 0xfc, 0x3f, 0xf8, 0x1f, 0xe0, 0x07},
{0xe0, 0x07, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xfe,
0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe,
0x7f, 0xfc, 0x3f, 0xf8, 0x1f, 0xe0, 0x07},},
// up
{
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x06,
0x60, 0x0f, 0xf0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f,
0xfe, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe,
0x7f, 0xfc, 0x3f, 0xf8, 0x1f, 0xe0, 0x07},
{0x00, 0x00, 0x08, 0x10, 0x1c, 0x38, 0x1e, 0x78, 0x3e,
0x7c, 0x3f, 0xfc, 0x7f, 0xfe, 0x7f, 0xfe, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe,
0x7f, 0xfc, 0x3f, 0xf8, 0x1f, 0xe0, 0x07},
{0x20, 0x04, 0x38, 0x1c, 0x3c, 0x3c, 0x7e, 0x7e, 0x7e,
0x7e, 0x7f, 0xfe, 0x7f, 0xfe, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe,
0x7f, 0xfc, 0x3f, 0xf8, 0x1f, 0xe0, 0x07},
{0xe0, 0x07, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xfe,
0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe,
0x7f, 0xfc, 0x3f, 0xf8, 0x1f, 0xe0, 0x07}},
// left
{
{0xe0, 0x07, 0xf8, 0x1f, 0xf0, 0x3f, 0xe0, 0x7f, 0xc0,
0x7f, 0x80, 0xff, 0x00, 0xff, 0x00, 0xfe, 0x00,
0xfe, 0x00, 0xff, 0x80, 0xff, 0xc0, 0x7f, 0xe0,
0x7f, 0xf0, 0x3f, 0xf8, 0x1f, 0xe0, 0x07},
{0xe0, 0x07, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xfc,
0x7f, 0xf0, 0xff, 0xc0, 0xff, 0x00, 0xff, 0x00,
0xff, 0xc0, 0xff, 0xf0, 0xff, 0xfc, 0x7f, 0xfe,
0x7f, 0xfc, 0x3f, 0xf8, 0x1f, 0xe0, 0x07},
{0xe0, 0x07, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xfe,
0x7f, 0xff, 0xff, 0xf8, 0xff, 0x80, 0xff, 0x80,
0xff, 0xf8, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe,
0x7f, 0xfc, 0x3f, 0xf8, 0x1f, 0xe0, 0x07},
{0xe0, 0x07, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xfe,
0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe,
0x7f, 0xfc, 0x3f, 0xf8, 0x1f, 0xe0, 0x07}},
// down
{
{0xe0, 0x07, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xfe,
0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0x3f,
0xfc, 0x1f, 0xf8, 0x0f, 0xf0, 0x06, 0x60, 0x02,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0xe0, 0x07, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xfe,
0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
0xfe, 0x7f, 0xfe, 0x3f, 0xfc, 0x3e, 0x7c, 0x1e,
0x78, 0x1c, 0x38, 0x08, 0x10, 0x00, 0x00},
{0xe0, 0x07, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xfe,
0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x7f, 0xfe, 0x7f, 0xfe, 0x7e, 0x7e, 0x7e,
0x7e, 0x3c, 0x3c, 0x38, 0x1c, 0x20, 0x04},
{0xe0, 0x07, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xfe,
0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe,
0x7f, 0xfc, 0x3f, 0xf8, 0x1f, 0xe0, 0x07}}};
static final short[][] ghost_bits = { // [3][32]
{0xe0, 0x07, 0xf8, 0x1f, 0xcc, 0x33, 0xbc, 0x3d, 0xfe, 0x7f, 0xde,
0x7b, 0x8e, 0x71, 0x9e, 0x79, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe,
0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0x76, 0x6e, 0x76, 0x6e, 0x24,
0x24},
{0xe0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x04, 0x20, 0x32, 0x4c, 0x4a,
0x52, 0x8a, 0x51, 0x8a, 0x51, 0x72, 0x4e, 0x02, 0x40, 0x02,
0x40, 0x02, 0x40, 0x8a, 0x51, 0x56, 0x6a, 0x52, 0x4a, 0x24,
0x24},
// blind
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0c, 0x48,
0x12, 0x88, 0x11, 0x88, 0x11, 0x70, 0x0e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00}};
static final short[] power_bits =
// [32]
// show
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f,
0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf0, 0x0f, 0xe0,
0x07, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
}
/**
* Copyright (C) 1997-2010 Junyang Gu <mikejyg@gmail.com>
*
* This file is part of javaiPacman.
*
* javaiPacman is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* javaiPacman is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with javaiPacman. If not, see <http://www.gnu.org/licenses/>.
*/
package edu.unl.cse.soft160.pacman;
import java.awt.*;
public class Interface {
// frames to wait after eaten a dot
final int DOT_WAIT = 4;
int iDotWait;
// current position
int iX, iY;
// current direction
int iDir;
// the applet this object is associated to
Window applet;
Graphics graphics;
// the pac image
java.awt.Image[][] imagePac;
// the knowledge of the maze
Maze maze;
// the knowledge of the power dots
PowerDot powerDot;
Interface(Window a, Graphics g, Maze m, PowerDot p) {
applet = a;
graphics = g;
maze = m;
powerDot = p;
// initialize pac and pac image
imagePac = new java.awt.Image[4][4];
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++) {
imagePac[i][j] = applet.createImage(18, 18);
Image.drawPac(imagePac[i][j], i, j);
}
}
public void start() {
iX = 10 * 16;
iY = 10 * 16;
iDir = 1; // downward, illegal and won't move
iDotWait = 0;
}
public void draw() {
maze.DrawDot(iX / 16, iY / 16);
maze.DrawDot(iX / 16 + (iX % 16 > 0 ? 1 : 0), iY / 16
+ (iY % 16 > 0 ? 1 : 0));
int iImageStep = (iX % 16 + iY % 16) / 2; // determine shape of PAc
if (iImageStep < 4)
iImageStep = 3 - iImageStep;
else
iImageStep -= 4;
graphics.drawImage(imagePac[iDir][iImageStep], iX - 1, iY - 1, applet);
}
// return 1 if eat a dot
// return 2 if eat power dot
public int move(int iNextDir) {
int eaten = 0;
// iNextDir=cAuto.GetNextDir();
if (iNextDir != -1 && iNextDir != iDir) // not set or same
// change direction
{
if (iX % 16 != 0 || iY % 16 != 0) {
// only check go back
if (iNextDir % 2 == iDir % 2)
iDir = iNextDir;
} else // need to see whether ahead block is OK
{
if (mazeOK(
iX / 16 + Constants.DIRECTION_X_COMPONENTS[iNextDir],
iY / 16 + Constants.DIRECTION_Y_COMPONENTS[iNextDir])) {
iDir = iNextDir;
iNextDir = -1;
}
}
}
if (iX % 16 == 0 && iY % 16 == 0) {
// see whether has eaten something
switch (maze.grid[iY / 16][iX / 16]) {
case Maze.DOT :
eaten = 1;
maze.grid[iY / 16][iX / 16] = Maze.BLANK; // eat dot
maze.iTotalDotcount--;
iDotWait = DOT_WAIT;
break;
case Maze.POWER_DOT :
eaten = 2;
powerDot.eat(iX / 16, iY / 16);
maze.grid[iY / 16][iX / 16] = Maze.BLANK;
break;
}
if (maze.grid[iY / 16 + Constants.DIRECTION_Y_COMPONENTS[iDir]][iX
/ 16 + Constants.DIRECTION_X_COMPONENTS[iDir]] == 1) {
return (eaten); // not valid move
}
}
if (iDotWait == 0) {
iX += Constants.DIRECTION_X_COMPONENTS[iDir];
iY += Constants.DIRECTION_Y_COMPONENTS[iDir];
} else
iDotWait--;
return (eaten);
}
boolean mazeOK(int iRow, int icol) {
if ((maze.grid[icol][iRow] & (Maze.WALL | Maze.DOOR)) == 0)
return (true);
return (false);
}
}
/**
* Copyright (C) 1997-2010 Junyang Gu <mikejyg@gmail.com>
*
* This file is part of javaiPacman.
*
* javaiPacman is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* javaiPacman is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with javaiPacman. If not, see <http://www.gnu.org/licenses/>.
*/
package edu.unl.cse.soft160.pacman;
import static edu.unl.cse.soft160.pacman.Constants.Direction;
import java.awt.*;
/* define the maze */
public class Maze {
// constant definitions
static final int BLANK = 0;
static final int WALL = 1;
static final int DOOR = 2;
static final int DOT = 4;
static final int POWER_DOT = 8;
static final int HEIGHT = 16;
static final int WIDTH = 21;
static final int height = HEIGHT * 16;
static final int width = WIDTH * 16;
// the applet the object associate with
Window applet;
// the graphics it will be using
Graphics graphics;
// the maze image
java.awt.Image imageMaze;
// the dot image
java.awt.Image imageDot;
// total dots left
int iTotalDotcount;
// the status of maze
int[][] grid;
// initialize the maze
Maze(Window a, Graphics g) {
// setup associations
applet = a;
graphics = g;
imageMaze = applet.createImage(width, height);
imageDot = applet.createImage(2, 2);
// create data
grid = new int[HEIGHT][WIDTH];
}
public void start() {
int i, j, k;
iTotalDotcount = 0;
for (i = 0; i < HEIGHT; i++)
for (j = 0; j < WIDTH; j++) {
switch (Constants.MazeDefine[i].charAt(j)) {
case ' ' :
k = BLANK;
break;
case 'X' :
k = WALL;
break;
case '.' :
k = DOT;
iTotalDotcount++;
break;
case 'O' :
k = POWER_DOT;
break;
case '-' :
k = DOOR;
break;
default :
k = DOT;
iTotalDotcount++;
break;
}
grid[i][j] = k;
}
// create initial maze image
createImage();
}
public void draw() {
graphics.drawImage(imageMaze, 0, 0, applet);
drawDots();
}
void drawDots() // on the offscreen
{
int i, j;
for (i = 0; i < HEIGHT; i++)
for (j = 0; j < WIDTH; j++) {
if (grid[i][j] == DOT)
graphics.drawImage(imageDot, j * 16 + 7, i * 16 + 7, applet);
}
}
void createImage() {
// create the image of a dot
Image.drawDot(imageDot);
// create the image of the maze
Graphics gmaze = imageMaze.getGraphics();
// background
gmaze.setColor(Color.black);
gmaze.fillRect(0, 0, width, height);
DrawWall(gmaze);
}
public void DrawDot(int icol, int iRow) {
if (grid[iRow][icol] == DOT)
graphics.drawImage(imageDot, icol * 16 + 7, iRow * 16 + 7, applet);
}
void DrawWall(Graphics g) {
int i, j;
int iDir;
g.setColor(Color.green);
for (i = 0; i < HEIGHT; i++) {
for (j = 0; j < WIDTH; j++) {
for (iDir = Direction.EAST.ordinal(); iDir <= Direction.SOUTH.ordinal(); iDir++) {
if (grid[i][j] == DOOR) {
g.drawLine(j * 16, i * 16 + 8, j * 16 + 16, i * 16 + 8);
continue;
}
if (grid[i][j] != WALL)
continue;
switch (Direction.values()[iDir]) {
case NORTH :
if (i == 0)
break;
if (grid[i - 1][j] == WALL)
break;
DrawBoundary(g, j, i - 1, Direction.SOUTH.ordinal());
break;
case EAST :
if (j == WIDTH - 1)
break;
if (grid[i][j + 1] == WALL)
break;
DrawBoundary(g, j + 1, i, Direction.WEST.ordinal());
break;
case SOUTH :
if (i == HEIGHT - 1)
break;
if (grid[i + 1][j] == WALL)
break;
DrawBoundary(g, j, i + 1, Direction.NORTH.ordinal());
break;
case WEST :
if (j == 0)
break;
if (grid[i][j - 1] == WALL)
break;
DrawBoundary(g, j - 1, i, Direction.EAST.ordinal());
break;
default :
}
}
}
}
}
void DrawBoundary(Graphics g, int col, int row, int iDir) {
int x, y;
x = col * 16;
y = row * 16;
switch (Direction.values()[iDir]) {
case WEST :
// draw lower half segment
if (grid[row + 1][col] != WALL)
// down empty
if (grid[row + 1][col - 1] != WALL)
// left-down empty
{
g.drawArc(x - 8 - 6, y + 8 - 6, 12, 12, 270, 100);
} else {
g.drawLine(x - 2, y + 8, x - 2, y + 16);
}
else {
g.drawLine(x - 2, y + 8, x - 2, y + 17);
g.drawLine(x - 2, y + 17, x + 7, y + 17);
}
// Draw upper half segment
if (grid[row - 1][col] != WALL)
// upper empty
if (grid[row - 1][col - 1] != WALL)
// upper-left empty
{
g.drawArc(x - 8 - 6, y + 7 - 6, 12, 12, 0, 100);
} else {
g.drawLine(x - 2, y, x - 2, y + 7);
}
else {
g.drawLine(x - 2, y - 2, x - 2, y + 7);
g.drawLine(x - 2, y - 2, x + 7, y - 2);
}
break;
case EAST :
// draw lower half segment
if (grid[row + 1][col] != WALL)
// down empty
if (grid[row + 1][col + 1] != WALL)
// down-right empty
{
g.drawArc(x + 16 + 7 - 6, y + 8 - 6, 12, 12, 180, 100);
} else {
g.drawLine(x + 17, y + 8, x + 17, y + 15);
}
else {
g.drawLine(x + 8, y + 17, x + 17, y + 17);
g.drawLine(x + 17, y + 8, x + 17, y + 17);
}
// Draw upper half segment
if (grid[row - 1][col] != WALL)
// upper empty
if (grid[row - 1][col + 1] != WALL)
// upper-right empty
{
g.drawArc(x + 16 + 7 - 6, y + 7 - 6, 12, 12, 90, 100);
} else {
g.drawLine(x + 17, y, x + 17, y + 7);
}
else {
g.drawLine(x + 8, y - 2, x + 17, y - 2);
g.drawLine(x + 17, y - 2, x + 17, y + 7);
}
break;
case NORTH :
// draw left half segment
if (grid[row][col - 1] != WALL)
// left empty
if (grid[row - 1][col - 1] != WALL)
// left-upper empty
{
g.drawArc(x + 7 - 6, y - 8 - 6, 12, 12, 180, 100);
} else {
g.drawLine(x, y - 2, x + 7, y - 2);
}
// Draw right half segment
if (grid[row][col + 1] != WALL)
// right empty
if (grid[row - 1][col + 1] != WALL)
// right-upper empty
{
g.drawArc(x + 8 - 6, y - 8 - 6, 12, 12, 270, 100);
} else {
g.drawLine(x + 8, y - 2, x + 16, y - 2);
}
break;
case SOUTH :
// draw left half segment
if (grid[row][col - 1] != WALL)
// left empty
if (grid[row + 1][col - 1] != WALL)
// left-down empty
{
g.drawArc(x + 7 - 6, y + 16 + 7 - 6, 12, 12, 90, 100);
} else {
g.drawLine(x, y + 17, x + 7, y + 17);
}
// Draw right half segment
if (grid[row][col + 1] != WALL)
// right empty
if (grid[row + 1][col + 1] != WALL)
// right-down empty
{
g.drawArc(x + 8 - 6, y + 16 + 7 - 6, 12, 12, 0, 100);
} else {
g.drawLine(x + 8, y + 17, x + 15, y + 17);
}
break;
}
}
}
/**
* Copyright (C) 1997-2010 Junyang Gu <mikejyg@gmail.com>
*
* This file is part of javaiPacman.
*
* javaiPacman is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* javaiPacman is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with javaiPacman. If not, see <http://www.gnu.org/licenses/>.
*/
package edu.unl.cse.soft160.pacman;
import static edu.unl.cse.soft160.pacman.Constants.Direction;
import java.awt.*;
import java.awt.event.*;
/**
* the main class of the pacman game
*/
public class PacMan extends Frame
implements
Runnable,
KeyListener,
WindowListener {
private static final long serialVersionUID = 3582431359568375379L;
// the timer
Thread timer;
int timerPeriod = 12; // in miliseconds
// the timer will increment this variable to signal a frame
int signalMove = 0;
// for graphics
final int canvasWidth = 368;
final int canvasHeight = 288 + 1;
// the canvas starting point within the frame
int topOffset;
int leftOffset;
// the draw point of maze within the canvas
final int iMazeX = 16;
final int iMazeY = 16;
// the off screen canvas for the maze
java.awt.Image offScreen;
Graphics offScreenG;
// the objects
Maze maze;
Interface pac;
PowerDot powerDot;
Ghost[] ghosts;
// game counters
final int PAcLIVE = 3;
int pacRemain;
int changePacRemain; // to signal redraw remaining pac
// score
int score;
int hiScore;
int scoreGhost; // score of eat ghost, doubles every time
int changeScore; // signal score change
int changeHiScore; // signal change of hi score
// score images
java.awt.Image imgScore;
Graphics imgScoreG;
java.awt.Image imgHiScore;
Graphics imgHiScoreG;
// game status
final int INITIMAGE = 100; // need to wait before paint anything
final int STARTWAIT = 0; // wait before running
final int RUNNING = 1;
final int DEADWAIT = 2; // wait after dead
final int SUSPENDED = 3; // suspended during game
int gameState;
final int WAITCOUNT = 100; // 100 frames for wait states
int wait; // the counter
// rounds
int round; // the round of current game;
// whether it is played in a new maze
boolean newMaze;
// the direction specified by key
int pacKeyDir;
int key = 0;
final int NONE = 0;
final int SUSPEND = 1; // stop/start
final int BOSS = 2; // boss
// //////////////////////////////////////////////
// initialize the object
// only called once at the beginning
// //////////////////////////////////////////////
public PacMan() {
super("PacMan");
// init variables
hiScore = 0;
gameState = INITIMAGE;
initGUI();
addWindowListener(this);
addKeyListener(this);
setSize(canvasWidth, canvasHeight);
setVisible(true);
}
void initGUI() {
addNotify(); // for updated inset information
}
public void initImages() {
// initialize off screen drawing canvas
offScreen = createImage(Maze.width, Maze.height);
if (offScreen == null)
System.out.println("createImage failed");
offScreenG = offScreen.getGraphics();
// initialize maze object
maze = new Maze(this, offScreenG);
// initialize ghosts object
// 4 ghosts
ghosts = new Ghost[4];
for (int i = 0; i < 4; i++) {
Color color;
if (i == 0)
color = Color.red;
else if (i == 1)
color = Color.blue;
else if (i == 2)
color = Color.white;
else
color = Color.orange;
ghosts[i] = new Ghost(this, offScreenG, maze, color);
}
// initialize power dot object
powerDot = new PowerDot(this, offScreenG, ghosts);
// initialize pac object
pac = new Interface(this, offScreenG, maze, powerDot);
// initialize the score images
imgScore = createImage(150, 16);
imgScoreG = imgScore.getGraphics();
imgHiScore = createImage(150, 16);
imgHiScoreG = imgHiScore.getGraphics();
imgHiScoreG.setColor(Color.black);
imgHiScoreG.fillRect(0, 0, 150, 16);
imgHiScoreG.setColor(Color.red);
imgHiScoreG.setFont(new Font("Helvetica", Font.BOLD, 12));
imgHiScoreG.drawString("HI SCORE", 0, 14);
imgScoreG.setColor(Color.black);
imgScoreG.fillRect(0, 0, 150, 16);
imgScoreG.setColor(Color.green);
imgScoreG.setFont(new Font("Helvetica", Font.BOLD, 12));
imgScoreG.drawString("SCORE", 0, 14);
}
void startTimer() {
// start the timer
timer = new Thread(this);
timer.start();
}
void startGame() {
pacRemain = PAcLIVE;
changePacRemain = 1;
score = 0;
changeScore = 1;
newMaze = true;
round = 1;
startRound();
}
void startRound() {
// new round for maze?
if (newMaze == true) {
maze.start();
powerDot.start();
newMaze = false;
}
maze.draw(); // draw maze in off screen buffer
pac.start();
pacKeyDir = Direction.SOUTH.ordinal();
for (int i = 0; i < 4; i++)
ghosts[i].start(i, round);
gameState = STARTWAIT;
wait = WAITCOUNT;
}
// /////////////////////////////////////////
// paint everything
// /////////////////////////////////////////
public void paint(Graphics g) {
if (gameState == INITIMAGE) {
// System.out.println("first paint(...)...");
// init images, must be done after show() because of Graphics
initImages();
// set the proper size of canvas
Insets insets = getInsets();
topOffset = insets.top;
leftOffset = insets.left;
setSize(canvasWidth + insets.left + insets.right, canvasHeight
+ insets.top + insets.bottom);
setResizable(false);
// now we can start timer
startGame();
startTimer();
}
g.setColor(Color.black);
g.fillRect(leftOffset, topOffset, canvasWidth, canvasHeight);
changeScore = 1;
changeHiScore = 1;
changePacRemain = 1;
paintUpdate(g);
}
void paintUpdate(Graphics g) {
// updating the frame
powerDot.draw();
for (int i = 0; i < 4; i++)
ghosts[i].draw();
pac.draw();
// display the offscreen
g.drawImage(offScreen, iMazeX + leftOffset, iMazeY + topOffset, this);
// display extra information
if (changeHiScore == 1) {
imgHiScoreG.setColor(Color.black);
imgHiScoreG.fillRect(70, 0, 80, 16);
imgHiScoreG.setColor(Color.red);
imgHiScoreG.drawString(Integer.toString(hiScore), 70, 14);
g.drawImage(imgHiScore, 8 + leftOffset, 0 + topOffset, this);
changeHiScore = 0;
}
if (changeScore == 1) {
imgScoreG.setColor(Color.black);
imgScoreG.fillRect(70, 0, 80, 16);
imgScoreG.setColor(Color.green);
imgScoreG.drawString(Integer.toString(score), 70, 14);
g.drawImage(imgScore, 158 + leftOffset, 0 + topOffset, this);
changeScore = 0;
}
// update pac life info
if (changePacRemain == 1) {
int i;
for (i = 1; i < pacRemain; i++) {
g.drawImage(pac.imagePac[0][0], 16 * i + leftOffset,
canvasHeight - 18 + topOffset, this);
}
g.drawImage(powerDot.imageBlank, 16 * i + leftOffset, canvasHeight
- 17 + topOffset, this);
changePacRemain = 0;
}
}
// //////////////////////////////////////////////////////////
// controls moves
// this is the routine running at the background of drawings
// //////////////////////////////////////////////////////////
void move() {
int k;
int oldScore = score;
for (int i = 0; i < 4; i++)
ghosts[i].tick(pac.iX, pac.iY, pac.iDir);
k = pac.move(pacKeyDir);
if (k == 1) // eaten a dot
{
changeScore = 1;
score += 10 * ((round + 1) / 2);
} else if (k == 2) // eaten a powerDot
{
scoreGhost = 200;
}
if (maze.iTotalDotcount == 0) {
gameState = DEADWAIT;
wait = WAITCOUNT;
newMaze = true;
round++;
return;
}
for (int i = 0; i < 4; i++) {
k = ghosts[i].testCollision(pac.iX, pac.iY);
if (k == 1) // kill pac
{
pacRemain--;
changePacRemain = 1;
gameState = DEADWAIT; // stop the game
wait = WAITCOUNT;
return;
} else if (k == 2) // caught by pac
{
score += scoreGhost * ((round + 1) / 2);
changeScore = 1;
scoreGhost *= 2;
}
}
if (score > hiScore) {
hiScore = score;
changeHiScore = 1;
}
if (changeScore == 1) {
if (score / 10000 - oldScore / 10000 > 0) {
pacRemain++; // bonus
changePacRemain = 1;
}
}
}
// /////////////////////////////////////////
// this is the routine draw each frames
// /////////////////////////////////////////
public void update(Graphics g) {
// System.out.println("update called");
if (gameState == INITIMAGE)
return;
// seperate the timer from update
if (signalMove != 0) {
signalMove = 0;
if (wait != 0) {
wait--;
return;
}
switch (gameState) {
case STARTWAIT :
gameState = RUNNING;
break;
case RUNNING :
if (key == SUSPEND)
gameState = SUSPENDED;
else
move();
break;
case DEADWAIT :
if (pacRemain > 0)
startRound();
else
startGame();
gameState = STARTWAIT;
wait = WAITCOUNT;
pacKeyDir = Direction.SOUTH.ordinal();
break;
case SUSPENDED :
if (key == SUSPEND)
gameState = RUNNING;
break;
}
key = NONE;
}
paintUpdate(g);
}
// /////////////////////////////////////
// process key input
// /////////////////////////////////////
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_RIGHT :
case KeyEvent.VK_L :
pacKeyDir = Direction.EAST.ordinal();
break;
case KeyEvent.VK_UP :
pacKeyDir = Direction.NORTH.ordinal();
break;
case KeyEvent.VK_LEFT :
pacKeyDir = Direction.WEST.ordinal();
break;
case KeyEvent.VK_DOWN :
pacKeyDir = Direction.SOUTH.ordinal();
break;
case KeyEvent.VK_S :
key = SUSPEND;
break;
case KeyEvent.VK_B :
key = BOSS;
break;
}
}
public void keyTyped(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
}
// /////////////////////////////////////////////////
// handles window event
// /////////////////////////////////////////////////
public void windowOpened(WindowEvent e) {
}
public void windowClosing(WindowEvent e) {
dispose();
}
public void windowClosed(WindowEvent e) {
}
public void windowIconified(WindowEvent e) {
}
public void windowDeiconified(WindowEvent e) {
}
public void windowActivated(WindowEvent e) {
}
public void windowDeactivated(WindowEvent e) {
}
// ///////////////////////////////////////////////
// the timer
// ///////////////////////////////////////////////
public void run() {
while (true) {
try {
Thread.sleep(timerPeriod);
} catch (InterruptedException e) {
return;
}
signalMove++;
repaint();
}
}
// for applet the check state
boolean finalized = false;
public void dispose() {
// kill the thread
timer.interrupt();
// the off screen canvas
// java.awt.Image offScreen=null;
offScreenG.dispose();
offScreenG = null;
// the objects
maze = null;
pac = null;
powerDot = null;
for (int i = 0; i < 4; i++)
ghosts[i] = null;
ghosts = null;
// score images
imgScore = null;
imgHiScore = null;
imgScoreG.dispose();
imgScoreG = null;
imgHiScoreG.dispose();
imgHiScoreG = null;
super.dispose();
finalized = true;
}
public boolean isFinalized() {
return finalized;
}
public void setFinalized(boolean finalized) {
this.finalized = finalized;
}
public static void main(String... arguments) {
new PacMan();
}
}
/**
* Copyright (C) 1997-2010 Junyang Gu <mikejyg@gmail.com>
*
* This file is part of javaiPacman.
*
* javaiPacman is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* javaiPacman is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with javaiPacman. If not, see <http://www.gnu.org/licenses/>.
*/
package edu.unl.cse.soft160.pacman;
import java.awt.*;
public class PowerDot {
final int iX[] = {1, 19, 1, 19};
final int iY[] = {2, 2, 13, 13};
final int iShowCount = 32;
final int iHideCount = 16;
int frameCount;
int showStatus;
int iValid[];
// the applet this object is associated to
Window applet;
Graphics graphics;
// the ghosts it controls
Ghost[] ghosts;
// the power dot image
java.awt.Image imagePowerDot;
// the blank image
java.awt.Image imageBlank;
PowerDot(Window a, Graphics g, Ghost[] gh) {
applet = a;
graphics = g;
ghosts = gh;
// initialize power dot and image
iValid = new int[4];
imagePowerDot = applet.createImage(16, 16);
Image.drawPowerDot(imagePowerDot);
imageBlank = applet.createImage(16, 16);
Graphics imageG = imageBlank.getGraphics();
imageG.setColor(Color.black);
imageG.fillRect(0, 0, 16, 16);
frameCount = iShowCount;
showStatus = 1; // show
}
public void start() {
// all power dots available
for (int i = 0; i < 4; i++)
iValid[i] = 1;
}
void clear(int dot) {
graphics.drawImage(imageBlank, iX[dot] * 16, iY[dot] * 16, applet);
}
void eat(int iCol, int iRow) {
for (int i = 0; i < 4; i++) {
if (iX[i] == iCol && iY[i] == iRow) {
iValid[i] = 0;
clear(i);
}
}
for (int i = 0; i < 4; i++)
ghosts[i].makeEdible();
}
public void draw() {
frameCount--;
if (frameCount == 0) {
if (showStatus == 1) {
showStatus = 0;
frameCount = iHideCount;
} else {
showStatus = 1;
frameCount = iShowCount;
}
}
for (int i = 0; i < 4; i++) {
if (iValid[i] == 1 && showStatus == 1)
graphics.drawImage(imagePowerDot, iX[i] * 16, iY[i] * 16,
applet);
else
graphics.drawImage(imageBlank, iX[i] * 16, iY[i] * 16, applet);
}
}
}
/**
* Copyright (C) 1997-2010 Junyang Gu <mikejyg@gmail.com>
*
* This file is part of javaiPacman.
*
* javaiPacman is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* javaiPacman is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with javaiPacman. If not, see <http://www.gnu.org/licenses/>.
*/
package edu.unl.cse.soft160.pacman;
/**
* speed control
*
* use init(s,f) to set the frame/step ratio NOTE: s must <= f call start() to
* reset counters call isMove per frame to see if step are to be taken
*/
public class Speed {
// move steps per frames
int steps;
int frames;
int frameCount;
int stepCount;
float frameStepRatio;
Speed() {
start(1, 1);
}
public void start(int s, int f) throws Error {
if (f < s)
throw new Error("Speed.init(...): frame must >= step");
steps = s;
frames = f;
frameStepRatio = (float) frames / (float) steps;
stepCount = steps;
frameCount = frames;
}
public boolean isMove() {
frameCount--;
float ratio = (float) frameCount / (float) stepCount;
if (frameCount == 0)
frameCount = frames;
if (ratio < frameStepRatio) {
stepCount--;
if (stepCount == 0)
stepCount = steps;
return true;
}
return false;
}
}
/**
* Copyright (C) 1997-2010 Junyang Gu <mikejyg@gmail.com>
*
* This file is part of javaiPacman.
*
* javaiPacman is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* javaiPacman is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with javaiPacman. If not, see <http://www.gnu.org/licenses/>.
*/
package edu.unl.cse.soft160.pacman;
/**
* provide some global public utility functions
*/
public class Utility {
public static int RandDo(int iOdds)
// see if it happens within a probability of 1/odds
{
if (Math.random() * iOdds < 1)
return (1);
return (0);
}
// return a random number within [0..iTotal)
public static int RandSelect(int iTotal) {
double a;
a = Math.random();
a = a * iTotal;
return ((int) a);
}
public static int IntSign(int iD) {
if (iD == 0)
return (0);
if (iD > 0)
return (1);
else
return (-1);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment