diff --git a/pacman-java/App.class b/pacman-java/App.class
deleted file mode 100644
index 2dc99e2..0000000
Binary files a/pacman-java/App.class and /dev/null differ
diff --git a/pacman-java/PacMan$Block.class b/pacman-java/PacMan$Block.class
deleted file mode 100644
index 122d1f4..0000000
Binary files a/pacman-java/PacMan$Block.class and /dev/null differ
diff --git a/pacman-java/PacMan.class b/pacman-java/PacMan.class
deleted file mode 100644
index bff251d..0000000
Binary files a/pacman-java/PacMan.class and /dev/null differ
diff --git a/pacman-java/desktop.ini b/pacman-java/desktop.ini
deleted file mode 100644
index e65e49d..0000000
Binary files a/pacman-java/desktop.ini and /dev/null differ
diff --git a/pacman-java/out/desktop.ini b/pacman-java/out/desktop.ini
deleted file mode 100644
index e65e49d..0000000
Binary files a/pacman-java/out/desktop.ini and /dev/null differ
diff --git a/pacman-java/out/production/desktop.ini b/pacman-java/out/production/desktop.ini
deleted file mode 100644
index e65e49d..0000000
Binary files a/pacman-java/out/production/desktop.ini and /dev/null differ
diff --git a/pacman-java/out/production/pacman-java/App.class b/pacman-java/out/production/pacman-java/App.class
deleted file mode 100644
index 1977983..0000000
Binary files a/pacman-java/out/production/pacman-java/App.class and /dev/null differ
diff --git a/pacman-java/out/production/pacman-java/PacMan$Block.class b/pacman-java/out/production/pacman-java/PacMan$Block.class
deleted file mode 100644
index d37d321..0000000
Binary files a/pacman-java/out/production/pacman-java/PacMan$Block.class and /dev/null differ
diff --git a/pacman-java/out/production/pacman-java/PacMan.class b/pacman-java/out/production/pacman-java/PacMan.class
deleted file mode 100644
index a7bff52..0000000
Binary files a/pacman-java/out/production/pacman-java/PacMan.class and /dev/null differ
diff --git a/pacman-java/out/production/pacman-java/blueGhost.png b/pacman-java/out/production/pacman-java/blueGhost.png
deleted file mode 100644
index e1ee979..0000000
Binary files a/pacman-java/out/production/pacman-java/blueGhost.png and /dev/null differ
diff --git a/pacman-java/out/production/pacman-java/cherry.png b/pacman-java/out/production/pacman-java/cherry.png
deleted file mode 100644
index 45c4f31..0000000
Binary files a/pacman-java/out/production/pacman-java/cherry.png and /dev/null differ
diff --git a/pacman-java/out/production/pacman-java/cherry2.png b/pacman-java/out/production/pacman-java/cherry2.png
deleted file mode 100644
index 6dea0ca..0000000
Binary files a/pacman-java/out/production/pacman-java/cherry2.png and /dev/null differ
diff --git a/pacman-java/out/production/pacman-java/desktop.ini b/pacman-java/out/production/pacman-java/desktop.ini
deleted file mode 100644
index e65e49d..0000000
Binary files a/pacman-java/out/production/pacman-java/desktop.ini and /dev/null differ
diff --git a/pacman-java/out/production/pacman-java/orangeGhost.png b/pacman-java/out/production/pacman-java/orangeGhost.png
deleted file mode 100644
index bcd1cb8..0000000
Binary files a/pacman-java/out/production/pacman-java/orangeGhost.png and /dev/null differ
diff --git a/pacman-java/out/production/pacman-java/pacman-java.iml b/pacman-java/out/production/pacman-java/pacman-java.iml
deleted file mode 100644
index 1de981c..0000000
--- a/pacman-java/out/production/pacman-java/pacman-java.iml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/pacman-java/pacman-java.iml b/pacman-java/pacman-java.iml
deleted file mode 100644
index 1de981c..0000000
--- a/pacman-java/pacman-java.iml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/pacman-java/pacmanDown.png b/pacman-java/pacmanDown.png
deleted file mode 100644
index 2c24dbe..0000000
Binary files a/pacman-java/pacmanDown.png and /dev/null differ
diff --git a/pacman-java/pacmanLeft.png b/pacman-java/pacmanLeft.png
deleted file mode 100644
index 168f495..0000000
Binary files a/pacman-java/pacmanLeft.png and /dev/null differ
diff --git a/pacman-java/pacmanRight.png b/pacman-java/pacmanRight.png
deleted file mode 100644
index 7e370a0..0000000
Binary files a/pacman-java/pacmanRight.png and /dev/null differ
diff --git a/pacman-java/pacmanUp.png b/pacman-java/pacmanUp.png
deleted file mode 100644
index 9f4a39b..0000000
Binary files a/pacman-java/pacmanUp.png and /dev/null differ
diff --git a/pacman-java/pinkGhost.png b/pacman-java/pinkGhost.png
deleted file mode 100644
index 12c3f84..0000000
Binary files a/pacman-java/pinkGhost.png and /dev/null differ
diff --git a/pacman-java/powerFood.png b/pacman-java/powerFood.png
deleted file mode 100644
index 3e91ad9..0000000
Binary files a/pacman-java/powerFood.png and /dev/null differ
diff --git a/pacman-java/redGhost.png b/pacman-java/redGhost.png
deleted file mode 100644
index cfd374e..0000000
Binary files a/pacman-java/redGhost.png and /dev/null differ
diff --git a/pacman-java/scaredGhost.png b/pacman-java/scaredGhost.png
deleted file mode 100644
index 9e26fff..0000000
Binary files a/pacman-java/scaredGhost.png and /dev/null differ
diff --git a/pacman-java/wall.png b/pacman-java/wall.png
deleted file mode 100644
index ab12c87..0000000
Binary files a/pacman-java/wall.png and /dev/null differ
diff --git a/pacman-java/App.java b/src/game/App.java
similarity index 88%
rename from pacman-java/App.java
rename to src/game/App.java
index a82e6c5..e380cc4 100644
--- a/pacman-java/App.java
+++ b/src/game/App.java
@@ -1,33 +1,35 @@
-import javax.swing.*;
-import java.awt.*;
-import java.awt.event.ComponentAdapter;
-import java.awt.event.ComponentEvent;
-
-public class App {
- public static void main(String[] args) throws Exception {
- int rowCount = 21;
- int columnCount = 19;
- int tileSize = 32;
- int boardWidth = columnCount * tileSize;
- int boardHeight = rowCount * tileSize;
-
- JFrame frame = new JFrame("Pac Man");
-
-// Set icon for taskbar and title bar.
- ImageIcon icon = new ImageIcon(App.class.getResource("pacmanRight.png"));
- frame.setIconImage(icon.getImage());
-
- // frame.setVisible(true);
- frame.setSize(boardWidth, boardHeight);
- frame.setLocationRelativeTo(null);
- frame.setResizable(false);
- frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
-
- PacMan pacmanGame = new PacMan();
- frame.add(pacmanGame);
- frame.pack();
- pacmanGame.requestFocus();
- frame.setVisible(true);
-
- }
-}
+package game;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+
+public class App {
+ public static void main(String[] args) throws Exception {
+ int rowCount = 21;
+ int columnCount = 19;
+ int tileSize = 32;
+ int boardWidth = columnCount * tileSize;
+ int boardHeight = rowCount * tileSize;
+
+ JFrame frame = new JFrame("Pac Man");
+
+// Set icon for taskbar and title bar.
+ ImageIcon icon = new ImageIcon(App.class.getResource("../resources/pacmanRight.png"));
+ frame.setIconImage(icon.getImage());
+
+ // frame.setVisible(true);
+ frame.setSize(boardWidth, boardHeight);
+ frame.setLocationRelativeTo(null);
+ frame.setResizable(false);
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+ PacMan pacmanGame = new PacMan();
+ frame.add(pacmanGame);
+ frame.pack();
+ pacmanGame.requestFocus();
+ frame.setVisible(true);
+
+ }
+}
diff --git a/pacman-java/PacMan.java b/src/game/PacMan.java
similarity index 93%
rename from pacman-java/PacMan.java
rename to src/game/PacMan.java
index 4b4eb54..dd7aad0 100644
--- a/pacman-java/PacMan.java
+++ b/src/game/PacMan.java
@@ -1,415 +1,416 @@
-import java.awt.*;
-import java.awt.event.*;
-import java.util.HashSet;
-import java.util.Random;
-import javax.swing.*;
-
-public class PacMan extends JPanel implements ActionListener, KeyListener {
-
- class Block {
- int x;
- int y;
- int width;
- int height;
- Image image;
-
- int startX;
- int startY;
- char direction = 'U'; // U D L R
- int velocityX = 0;
- int velocityY = 0;
-
- Block(Image image, int x, int y, int width, int height) {
- this.image = image;
- this.x = x;
- this.y = y;
- this.width = width;
- this.height = height;
- this.startX = x;
- this.startY = y;
- }
-
- void updateDirection(char direction) {
- char prevDirection = this.direction;
- this.direction = direction;
- updateVelocity();
- this.x += this.velocityX;
- this.y += this.velocityY;
- for (Block wall : walls) {
- if (collision(this, wall)) {
- this.x -= this.velocityX;
- this.y -= this.velocityY;
- this.direction = prevDirection;
- updateVelocity();
- }
- }
- }
-
- void updateVelocity() {
- if (this.direction == 'U') {
- this.velocityX = 0;
- this.velocityY = -tileSize/4;
- }
- else if (this.direction == 'D') {
- this.velocityX = 0;
- this.velocityY = tileSize/4;
- }
- else if (this.direction == 'L') {
- this.velocityX = -tileSize/4;
- this.velocityY = 0;
- }
- else if (this.direction == 'R') {
- this.velocityX = tileSize/4;
- this.velocityY = 0;
- }
- }
-
- void reset() {
- this.x = this.startX;
- this.y = this.startY;
- }
- }
-
- private int rowCount = 21;
- private int columnCount = 19;
- private int tileSize = 32;
- private int boardWidth = columnCount * tileSize;
- private int boardHeight = rowCount * tileSize;
-
- private Image wallImage;
- private Image blueGhostImage;
- private Image orangeGhostImage;
- private Image pinkGhostImage;
- private Image redGhostImage;
-
- private Image pacmanUpImage;
- private Image pacmanDownImage;
- private Image pacmanLeftImage;
- private Image pacmanRightImage;
-
- //X = wall, O = skip, P = pac man, ' ' = food
- //Ghosts: b = blue, o = orange, p = pink, r = red
- private String[] tileMap = {
- "XXXXXXXXXXXXXXXXXXX",
- "X X X",
- "X XX XXX X XXX XX X",
- "X X",
- "X XX X XXXXX X XX X",
- "X X X X",
- "XXXX XXXX XXXX XXXX",
- "OOOX X X XOOO",
- "XXXX X XXrXX X XXXX",
- "X bpo X",
- "XXXX X XXXXX X XXXX",
- "OOOX X X XOOO",
- "XXXX X XXXXX X XXXX",
- "X X X",
- "X XX XXX X XXX XX X",
- "X X P X X",
- "XX X X XXXXX X X XX",
- "X X X X X",
- "X XXXXXX X XXXXXX X",
- "X X",
- "XXXXXXXXXXXXXXXXXXX"
- };
-
- HashSet walls;
- HashSet foods;
- HashSet ghosts;
- Block pacman;
-
- Timer gameLoop;
- char[] directions = {'U', 'D', 'L', 'R'}; //up down left right
- Random random = new Random();
- int score = 0;
- int lives = 3;
- boolean gameOver = false;
- boolean showInstructions = true;
-
- PacMan() {
- setPreferredSize(new Dimension(boardWidth, boardHeight));
- setBackground(Color.BLACK);
- addKeyListener(this);
- setFocusable(true);
-
- //load images
- wallImage = new ImageIcon(getClass().getResource("./wall.png")).getImage();
- blueGhostImage = new ImageIcon(getClass().getResource("./blueGhost.png")).getImage();
- orangeGhostImage = new ImageIcon(getClass().getResource("./orangeGhost.png")).getImage();
- pinkGhostImage = new ImageIcon(getClass().getResource("./pinkGhost.png")).getImage();
- redGhostImage = new ImageIcon(getClass().getResource("./redGhost.png")).getImage();
-
- pacmanUpImage = new ImageIcon(getClass().getResource("./pacmanUp.png")).getImage();
- pacmanDownImage = new ImageIcon(getClass().getResource("./pacmanDown.png")).getImage();
- pacmanLeftImage = new ImageIcon(getClass().getResource("./pacmanLeft.png")).getImage();
- pacmanRightImage = new ImageIcon(getClass().getResource("./pacmanRight.png")).getImage();
-
- loadMap();
- for (Block ghost : ghosts) {
- char newDirection = directions[random.nextInt(4)];
- ghost.updateDirection(newDirection);
- }
- //how long it takes to start timer, milliseconds gone between frames
- gameLoop = new Timer(50, this); //20fps (1000/50)
- gameLoop.start();
-
- }
-
- public void loadMap() {
- walls = new HashSet();
- foods = new HashSet();
- ghosts = new HashSet();
-
- for (int r = 0; r < rowCount; r++) {
- for (int c = 0; c < columnCount; c++) {
- String row = tileMap[r];
- char tileMapChar = row.charAt(c);
-
- int x = c*tileSize;
- int y = r*tileSize;
-
- if (tileMapChar == 'X') { //block wall
- Block wall = new Block(wallImage, x, y, tileSize, tileSize);
- walls.add(wall);
- }
- else if (tileMapChar == 'b') { //blue ghost
- Block ghost = new Block(blueGhostImage, x, y, tileSize, tileSize);
- ghosts.add(ghost);
- }
- else if (tileMapChar == 'o') { //orange ghost
- Block ghost = new Block(orangeGhostImage, x, y, tileSize, tileSize);
- ghosts.add(ghost);
- }
- else if (tileMapChar == 'p') { //pink ghost
- Block ghost = new Block(pinkGhostImage, x, y, tileSize, tileSize);
- ghosts.add(ghost);
- }
- else if (tileMapChar == 'r') { //red ghost
- Block ghost = new Block(redGhostImage, x, y, tileSize, tileSize);
- ghosts.add(ghost);
- }
- else if (tileMapChar == 'P') { //pacman
- pacman = new Block(pacmanRightImage, x, y, tileSize, tileSize);
- }
- else if (tileMapChar == ' ') { //food
- Block food = new Block(null, x + 14, y + 14, 4, 4);
- foods.add(food);
- }
- }
- }
- }
-
- public void paintComponent(Graphics g) {
- super.paintComponent(g);
- draw(g);
- }
-
- public void draw(Graphics g) {
- g.drawImage(pacman.image, pacman.x, pacman.y, pacman.width, pacman.height, null);
-
- for (Block ghost : ghosts) {
- g.drawImage(ghost.image, ghost.x, ghost.y, ghost.width, ghost.height, null);
- }
-
- for (Block wall : walls) {
- g.drawImage(wall.image, wall.x, wall.y, wall.width, wall.height, null);
- }
-
- g.setColor(Color.WHITE);
- for (Block food : foods) {
- g.fillRect(food.x, food.y, food.width, food.height);
- }
- //score
- g.setFont(new Font("Arial", Font.PLAIN, 18));
- if (gameOver) {
- g.drawString("Game Over: " + String.valueOf(score), tileSize/2, tileSize/2);
- }
- else {
- g.drawString("x" + String.valueOf(lives) + " Score: " + String.valueOf(score), tileSize/2, tileSize/2);
- }
-
- if (showInstructions) {
- g.setColor(new Color(0, 0, 0, 210));
- g.fillRect(0, 0, boardWidth, boardHeight);
-
- String title = "PAC-MAN";
- String controlsTitle = "HOW TO PLAY";
- String controls = "↑ ↓ ← → Arrow Keys to Move";
- String objMsg = "Eat all the food, avoid the ghosts!";
- String startMsg = "Press ANY KEY to Start!";
-
- // Title with shadow
- g.setFont(new Font("Arial", Font.BOLD, 50));
- FontMetrics fm = g.getFontMetrics();
- g.setColor(Color.BLUE);
- g.drawString(title, (boardWidth - fm.stringWidth(title)) / 2 + 4, boardHeight / 2 - 146);
- g.setColor(Color.YELLOW);
- g.drawString(title, (boardWidth - fm.stringWidth(title)) / 2, boardHeight / 2 - 150);
-
- // Draw game sprites for decoration
- int imgY = boardHeight / 2 - 110;
- g.drawImage(pacmanRightImage, boardWidth / 2 - 90, imgY, tileSize + 10, tileSize + 10, null);
- g.drawImage(redGhostImage, boardWidth / 2 - 30, imgY, tileSize + 10, tileSize + 10, null);
- g.drawImage(blueGhostImage, boardWidth / 2 + 30, imgY, tileSize + 10, tileSize + 10, null);
- g.drawImage(pinkGhostImage, boardWidth / 2 + 90, imgY, tileSize + 10, tileSize + 10, null);
-
- g.setColor(Color.WHITE);
- g.setFont(new Font("Arial", Font.BOLD, 26));
- fm = g.getFontMetrics();
- g.drawString(controlsTitle, (boardWidth - fm.stringWidth(controlsTitle)) / 2, boardHeight / 2 - 20);
-
- g.setColor(Color.CYAN);
- g.setFont(new Font("Arial", Font.PLAIN, 22));
- fm = g.getFontMetrics();
- g.drawString(controls, (boardWidth - fm.stringWidth(controls)) / 2, boardHeight / 2 + 20);
-
- g.setColor(Color.PINK);
- g.setFont(new Font("Arial", Font.PLAIN, 20));
- fm = g.getFontMetrics();
- g.drawString(objMsg, (boardWidth - fm.stringWidth(objMsg)) / 2, boardHeight / 2 + 60);
-
- // Blinking start message
- if ((System.currentTimeMillis() / 500) % 2 == 0) {
- g.setColor(Color.ORANGE);
- g.setFont(new Font("Arial", Font.BOLD, 24));
- fm = g.getFontMetrics();
- g.drawString(startMsg, (boardWidth - fm.stringWidth(startMsg)) / 2, boardHeight / 2 + 130);
- }
- }
- }
-
- public void move() {
- pacman.x += pacman.velocityX;
- pacman.y += pacman.velocityY;
-
- //check wall collisions
- for (Block wall : walls) {
- if (collision(pacman, wall)) {
- pacman.x -= pacman.velocityX;
- pacman.y -= pacman.velocityY;
- break;
- }
- }
-
- //check ghost collisions
- for (Block ghost : ghosts) {
- if (collision(ghost, pacman)) {
- lives -= 1;
- if (lives == 0) {
- gameOver = true;
- return;
- }
- resetPositions();
- }
-
- if (ghost.y == tileSize*9 && ghost.direction != 'U' && ghost.direction != 'D') {
- ghost.updateDirection('U');
- }
- ghost.x += ghost.velocityX;
- ghost.y += ghost.velocityY;
- for (Block wall : walls) {
- if (collision(ghost, wall) || ghost.x <= 0 || ghost.x + ghost.width >= boardWidth) {
- ghost.x -= ghost.velocityX;
- ghost.y -= ghost.velocityY;
- char newDirection = directions[random.nextInt(4)];
- ghost.updateDirection(newDirection);
- }
- }
- }
-
- //check food collision
- Block foodEaten = null;
- for (Block food : foods) {
- if (collision(pacman, food)) {
- foodEaten = food;
- score += 10;
- }
- }
- foods.remove(foodEaten);
-
- if (foods.isEmpty()) {
- loadMap();
- resetPositions();
- }
- }
-
- public boolean collision(Block a, Block b) {
- return a.x < b.x + b.width &&
- a.x + a.width > b.x &&
- a.y < b.y + b.height &&
- a.y + a.height > b.y;
- }
-
- public void resetPositions() {
- pacman.reset();
- pacman.velocityX = 0;
- pacman.velocityY = 0;
- for (Block ghost : ghosts) {
- ghost.reset();
- char newDirection = directions[random.nextInt(4)];
- ghost.updateDirection(newDirection);
- }
- }
-
- @Override
- public void actionPerformed(ActionEvent e) {
- if (showInstructions) {
- repaint();
- return;
- }
- move();
- repaint();
- if (gameOver) {
- gameLoop.stop();
- }
- }
-
- @Override
- public void keyTyped(KeyEvent e) {}
-
- @Override
- public void keyPressed(KeyEvent e) {}
-
- @Override
- public void keyReleased(KeyEvent e) {
- if (showInstructions) {
- showInstructions = false;
- return;
- }
- if (gameOver) {
- loadMap();
- resetPositions();
- lives = 3;
- score = 0;
- gameOver = false;
- gameLoop.start();
- }
- // System.out.println("KeyEvent: " + e.getKeyCode());
- if (e.getKeyCode() == KeyEvent.VK_UP) {
- pacman.updateDirection('U');
- }
- else if (e.getKeyCode() == KeyEvent.VK_DOWN) {
- pacman.updateDirection('D');
- }
- else if (e.getKeyCode() == KeyEvent.VK_LEFT) {
- pacman.updateDirection('L');
- }
- else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
- pacman.updateDirection('R');
- }
-
- if (pacman.direction == 'U') {
- pacman.image = pacmanUpImage;
- }
- else if (pacman.direction == 'D') {
- pacman.image = pacmanDownImage;
- }
- else if (pacman.direction == 'L') {
- pacman.image = pacmanLeftImage;
- }
- else if (pacman.direction == 'R') {
- pacman.image = pacmanRightImage;
- }
- }
-}
-
+package game;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.HashSet;
+import java.util.Random;
+import javax.swing.*;
+
+public class PacMan extends JPanel implements ActionListener, KeyListener {
+
+ class Block {
+ int x;
+ int y;
+ int width;
+ int height;
+ Image image;
+
+ int startX;
+ int startY;
+ char direction = 'U'; // U D L R
+ int velocityX = 0;
+ int velocityY = 0;
+
+ Block(Image image, int x, int y, int width, int height) {
+ this.image = image;
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+ this.startX = x;
+ this.startY = y;
+ }
+
+ void updateDirection(char direction) {
+ char prevDirection = this.direction;
+ this.direction = direction;
+ updateVelocity();
+ this.x += this.velocityX;
+ this.y += this.velocityY;
+ for (Block wall : walls) {
+ if (collision(this, wall)) {
+ this.x -= this.velocityX;
+ this.y -= this.velocityY;
+ this.direction = prevDirection;
+ updateVelocity();
+ }
+ }
+ }
+
+ void updateVelocity() {
+ if (this.direction == 'U') {
+ this.velocityX = 0;
+ this.velocityY = -tileSize/4;
+ }
+ else if (this.direction == 'D') {
+ this.velocityX = 0;
+ this.velocityY = tileSize/4;
+ }
+ else if (this.direction == 'L') {
+ this.velocityX = -tileSize/4;
+ this.velocityY = 0;
+ }
+ else if (this.direction == 'R') {
+ this.velocityX = tileSize/4;
+ this.velocityY = 0;
+ }
+ }
+
+ void reset() {
+ this.x = this.startX;
+ this.y = this.startY;
+ }
+ }
+
+ private int rowCount = 21;
+ private int columnCount = 19;
+ private int tileSize = 32;
+ private int boardWidth = columnCount * tileSize;
+ private int boardHeight = rowCount * tileSize;
+
+ private Image wallImage;
+ private Image blueGhostImage;
+ private Image orangeGhostImage;
+ private Image pinkGhostImage;
+ private Image redGhostImage;
+
+ private Image pacmanUpImage;
+ private Image pacmanDownImage;
+ private Image pacmanLeftImage;
+ private Image pacmanRightImage;
+
+ //X = wall, O = skip, P = pac man, ' ' = food
+ //Ghosts: b = blue, o = orange, p = pink, r = red
+ private String[] tileMap = {
+ "XXXXXXXXXXXXXXXXXXX",
+ "X X X",
+ "X XX XXX X XXX XX X",
+ "X X",
+ "X XX X XXXXX X XX X",
+ "X X X X",
+ "XXXX XXXX XXXX XXXX",
+ "OOOX X X XOOO",
+ "XXXX X XXrXX X XXXX",
+ "X bpo X",
+ "XXXX X XXXXX X XXXX",
+ "OOOX X X XOOO",
+ "XXXX X XXXXX X XXXX",
+ "X X X",
+ "X XX XXX X XXX XX X",
+ "X X P X X",
+ "XX X X XXXXX X X XX",
+ "X X X X X",
+ "X XXXXXX X XXXXXX X",
+ "X X",
+ "XXXXXXXXXXXXXXXXXXX"
+ };
+
+ HashSet walls;
+ HashSet foods;
+ HashSet ghosts;
+ Block pacman;
+
+ Timer gameLoop;
+ char[] directions = {'U', 'D', 'L', 'R'}; //up down left right
+ Random random = new Random();
+ int score = 0;
+ int lives = 3;
+ boolean gameOver = false;
+ boolean showInstructions = true;
+
+ PacMan() {
+ setPreferredSize(new Dimension(boardWidth, boardHeight));
+ setBackground(Color.BLACK);
+ addKeyListener(this);
+ setFocusable(true);
+
+ //load images
+ wallImage = new ImageIcon(getClass().getResource("../resources/wall.png")).getImage();
+ blueGhostImage = new ImageIcon(getClass().getResource("../resources/blueGhost.png")).getImage();
+ orangeGhostImage = new ImageIcon(getClass().getResource("../resources/orangeGhost.png")).getImage();
+ pinkGhostImage = new ImageIcon(getClass().getResource("../resources/pinkGhost.png")).getImage();
+ redGhostImage = new ImageIcon(getClass().getResource("../resources/redGhost.png")).getImage();
+
+ pacmanUpImage = new ImageIcon(getClass().getResource("../resources/pacmanUp.png")).getImage();
+ pacmanDownImage = new ImageIcon(getClass().getResource("../resources/pacmanDown.png")).getImage();
+ pacmanLeftImage = new ImageIcon(getClass().getResource("../resources/pacmanLeft.png")).getImage();
+ pacmanRightImage = new ImageIcon(getClass().getResource("../resources/pacmanRight.png")).getImage();
+
+ loadMap();
+ for (Block ghost : ghosts) {
+ char newDirection = directions[random.nextInt(4)];
+ ghost.updateDirection(newDirection);
+ }
+ //how long it takes to start timer, milliseconds gone between frames
+ gameLoop = new Timer(50, this); //20fps (1000/50)
+ gameLoop.start();
+
+ }
+
+ public void loadMap() {
+ walls = new HashSet();
+ foods = new HashSet();
+ ghosts = new HashSet();
+
+ for (int r = 0; r < rowCount; r++) {
+ for (int c = 0; c < columnCount; c++) {
+ String row = tileMap[r];
+ char tileMapChar = row.charAt(c);
+
+ int x = c*tileSize;
+ int y = r*tileSize;
+
+ if (tileMapChar == 'X') { //block wall
+ Block wall = new Block(wallImage, x, y, tileSize, tileSize);
+ walls.add(wall);
+ }
+ else if (tileMapChar == 'b') { //blue ghost
+ Block ghost = new Block(blueGhostImage, x, y, tileSize, tileSize);
+ ghosts.add(ghost);
+ }
+ else if (tileMapChar == 'o') { //orange ghost
+ Block ghost = new Block(orangeGhostImage, x, y, tileSize, tileSize);
+ ghosts.add(ghost);
+ }
+ else if (tileMapChar == 'p') { //pink ghost
+ Block ghost = new Block(pinkGhostImage, x, y, tileSize, tileSize);
+ ghosts.add(ghost);
+ }
+ else if (tileMapChar == 'r') { //red ghost
+ Block ghost = new Block(redGhostImage, x, y, tileSize, tileSize);
+ ghosts.add(ghost);
+ }
+ else if (tileMapChar == 'P') { //pacman
+ pacman = new Block(pacmanRightImage, x, y, tileSize, tileSize);
+ }
+ else if (tileMapChar == ' ') { //food
+ Block food = new Block(null, x + 14, y + 14, 4, 4);
+ foods.add(food);
+ }
+ }
+ }
+ }
+
+ public void paintComponent(Graphics g) {
+ super.paintComponent(g);
+ draw(g);
+ }
+
+ public void draw(Graphics g) {
+ g.drawImage(pacman.image, pacman.x, pacman.y, pacman.width, pacman.height, null);
+
+ for (Block ghost : ghosts) {
+ g.drawImage(ghost.image, ghost.x, ghost.y, ghost.width, ghost.height, null);
+ }
+
+ for (Block wall : walls) {
+ g.drawImage(wall.image, wall.x, wall.y, wall.width, wall.height, null);
+ }
+
+ g.setColor(Color.WHITE);
+ for (Block food : foods) {
+ g.fillRect(food.x, food.y, food.width, food.height);
+ }
+ //score
+ g.setFont(new Font("Arial", Font.PLAIN, 18));
+ if (gameOver) {
+ g.drawString("Game Over: " + String.valueOf(score), tileSize/2, tileSize/2);
+ }
+ else {
+ g.drawString("x" + String.valueOf(lives) + " Score: " + String.valueOf(score), tileSize/2, tileSize/2);
+ }
+
+ if (showInstructions) {
+ g.setColor(new Color(0, 0, 0, 210));
+ g.fillRect(0, 0, boardWidth, boardHeight);
+
+ String title = "PAC-MAN";
+ String controlsTitle = "HOW TO PLAY";
+ String controls = "↑ ↓ ← → Arrow Keys to Move";
+ String objMsg = "Eat all the food, avoid the ghosts!";
+ String startMsg = "Press ANY KEY to Start!";
+
+ // Title with shadow
+ g.setFont(new Font("Arial", Font.BOLD, 50));
+ FontMetrics fm = g.getFontMetrics();
+ g.setColor(Color.BLUE);
+ g.drawString(title, (boardWidth - fm.stringWidth(title)) / 2 + 4, boardHeight / 2 - 146);
+ g.setColor(Color.YELLOW);
+ g.drawString(title, (boardWidth - fm.stringWidth(title)) / 2, boardHeight / 2 - 150);
+
+ // Draw game sprites for decoration
+ int imgY = boardHeight / 2 - 110;
+ g.drawImage(pacmanRightImage, boardWidth / 2 - 90, imgY, tileSize + 10, tileSize + 10, null);
+ g.drawImage(redGhostImage, boardWidth / 2 - 30, imgY, tileSize + 10, tileSize + 10, null);
+ g.drawImage(blueGhostImage, boardWidth / 2 + 30, imgY, tileSize + 10, tileSize + 10, null);
+ g.drawImage(pinkGhostImage, boardWidth / 2 + 90, imgY, tileSize + 10, tileSize + 10, null);
+
+ g.setColor(Color.WHITE);
+ g.setFont(new Font("Arial", Font.BOLD, 26));
+ fm = g.getFontMetrics();
+ g.drawString(controlsTitle, (boardWidth - fm.stringWidth(controlsTitle)) / 2, boardHeight / 2 - 20);
+
+ g.setColor(Color.CYAN);
+ g.setFont(new Font("Arial", Font.PLAIN, 22));
+ fm = g.getFontMetrics();
+ g.drawString(controls, (boardWidth - fm.stringWidth(controls)) / 2, boardHeight / 2 + 20);
+
+ g.setColor(Color.PINK);
+ g.setFont(new Font("Arial", Font.PLAIN, 20));
+ fm = g.getFontMetrics();
+ g.drawString(objMsg, (boardWidth - fm.stringWidth(objMsg)) / 2, boardHeight / 2 + 60);
+
+ // Blinking start message
+ if ((System.currentTimeMillis() / 500) % 2 == 0) {
+ g.setColor(Color.ORANGE);
+ g.setFont(new Font("Arial", Font.BOLD, 24));
+ fm = g.getFontMetrics();
+ g.drawString(startMsg, (boardWidth - fm.stringWidth(startMsg)) / 2, boardHeight / 2 + 130);
+ }
+ }
+ }
+
+ public void move() {
+ pacman.x += pacman.velocityX;
+ pacman.y += pacman.velocityY;
+
+ //check wall collisions
+ for (Block wall : walls) {
+ if (collision(pacman, wall)) {
+ pacman.x -= pacman.velocityX;
+ pacman.y -= pacman.velocityY;
+ break;
+ }
+ }
+
+ //check ghost collisions
+ for (Block ghost : ghosts) {
+ if (collision(ghost, pacman)) {
+ lives -= 1;
+ if (lives == 0) {
+ gameOver = true;
+ return;
+ }
+ resetPositions();
+ }
+
+ if (ghost.y == tileSize*9 && ghost.direction != 'U' && ghost.direction != 'D') {
+ ghost.updateDirection('U');
+ }
+ ghost.x += ghost.velocityX;
+ ghost.y += ghost.velocityY;
+ for (Block wall : walls) {
+ if (collision(ghost, wall) || ghost.x <= 0 || ghost.x + ghost.width >= boardWidth) {
+ ghost.x -= ghost.velocityX;
+ ghost.y -= ghost.velocityY;
+ break;
+ }
+ }
+ }
+
+ //check food collision
+ Block foodEaten = null;
+ for (Block food : foods) {
+ if (collision(pacman, food)) {
+ foodEaten = food;
+ score += 10;
+ }
+ }
+ foods.remove(foodEaten);
+
+ if (foods.isEmpty()) {
+ loadMap();
+ resetPositions();
+ }
+ }
+
+ public boolean collision(Block a, Block b) {
+ return a.x < b.x + b.width &&
+ a.x + a.width > b.x &&
+ a.y < b.y + b.height &&
+ a.y + a.height > b.y;
+ }
+
+ public void resetPositions() {
+ pacman.reset();
+ pacman.velocityX = 0;
+ pacman.velocityY = 0;
+ for (Block ghost : ghosts) {
+ ghost.reset();
+ char newDirection = directions[random.nextInt(4)];
+ ghost.updateDirection(newDirection);
+ }
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if (showInstructions) {
+ repaint();
+ return;
+ }
+ move();
+ repaint();
+ if (gameOver) {
+ gameLoop.stop();
+ }
+ }
+
+ @Override
+ public void keyTyped(KeyEvent e) {}
+
+ @Override
+ public void keyPressed(KeyEvent e) {}
+
+ @Override
+ public void keyReleased(KeyEvent e) {
+ if (showInstructions) {
+ showInstructions = false;
+ return;
+ }
+ if (gameOver) {
+ loadMap();
+ resetPositions();
+ lives = 3;
+ score = 0;
+ gameOver = false;
+ gameLoop.start();
+ }
+ // System.out.println("KeyEvent: " + e.getKeyCode());
+ if (e.getKeyCode() == KeyEvent.VK_UP) {
+ pacman.updateDirection('U');
+ }
+ else if (e.getKeyCode() == KeyEvent.VK_DOWN) {
+ pacman.updateDirection('D');
+ }
+ else if (e.getKeyCode() == KeyEvent.VK_LEFT) {
+ pacman.updateDirection('L');
+ }
+ else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
+ pacman.updateDirection('R');
+ }
+
+ if (pacman.direction == 'U') {
+ pacman.image = pacmanUpImage;
+ }
+ else if (pacman.direction == 'D') {
+ pacman.image = pacmanDownImage;
+ }
+ else if (pacman.direction == 'L') {
+ pacman.image = pacmanLeftImage;
+ }
+ else if (pacman.direction == 'R') {
+ pacman.image = pacmanRightImage;
+ }
+ }
+}
+
diff --git a/pacman-java/blueGhost.png b/src/resources/blueGhost.png
similarity index 100%
rename from pacman-java/blueGhost.png
rename to src/resources/blueGhost.png
diff --git a/pacman-java/cherry.png b/src/resources/cherry.png
similarity index 100%
rename from pacman-java/cherry.png
rename to src/resources/cherry.png
diff --git a/pacman-java/cherry2.png b/src/resources/cherry2.png
similarity index 100%
rename from pacman-java/cherry2.png
rename to src/resources/cherry2.png
diff --git a/pacman-java/orangeGhost.png b/src/resources/orangeGhost.png
similarity index 100%
rename from pacman-java/orangeGhost.png
rename to src/resources/orangeGhost.png
diff --git a/pacman-java/out/production/pacman-java/pacmanDown.png b/src/resources/pacmanDown.png
similarity index 100%
rename from pacman-java/out/production/pacman-java/pacmanDown.png
rename to src/resources/pacmanDown.png
diff --git a/pacman-java/out/production/pacman-java/pacmanLeft.png b/src/resources/pacmanLeft.png
similarity index 100%
rename from pacman-java/out/production/pacman-java/pacmanLeft.png
rename to src/resources/pacmanLeft.png
diff --git a/pacman-java/out/production/pacman-java/pacmanRight.png b/src/resources/pacmanRight.png
similarity index 100%
rename from pacman-java/out/production/pacman-java/pacmanRight.png
rename to src/resources/pacmanRight.png
diff --git a/pacman-java/out/production/pacman-java/pacmanUp.png b/src/resources/pacmanUp.png
similarity index 100%
rename from pacman-java/out/production/pacman-java/pacmanUp.png
rename to src/resources/pacmanUp.png
diff --git a/pacman-java/out/production/pacman-java/pinkGhost.png b/src/resources/pinkGhost.png
similarity index 100%
rename from pacman-java/out/production/pacman-java/pinkGhost.png
rename to src/resources/pinkGhost.png
diff --git a/pacman-java/out/production/pacman-java/powerFood.png b/src/resources/powerFood.png
similarity index 100%
rename from pacman-java/out/production/pacman-java/powerFood.png
rename to src/resources/powerFood.png
diff --git a/pacman-java/out/production/pacman-java/redGhost.png b/src/resources/redGhost.png
similarity index 100%
rename from pacman-java/out/production/pacman-java/redGhost.png
rename to src/resources/redGhost.png
diff --git a/pacman-java/out/production/pacman-java/scaredGhost.png b/src/resources/scaredGhost.png
similarity index 100%
rename from pacman-java/out/production/pacman-java/scaredGhost.png
rename to src/resources/scaredGhost.png
diff --git a/pacman-java/out/production/pacman-java/wall.png b/src/resources/wall.png
similarity index 100%
rename from pacman-java/out/production/pacman-java/wall.png
rename to src/resources/wall.png