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