From 666f0ac6aa281002fb22e3aa85195fc17e94b8c5 Mon Sep 17 00:00:00 2001 From: Andres Cruz <1912548@stud.hs-mannheim.de> Date: Sun, 29 Dec 2024 21:12:00 +0100 Subject: [PATCH] =?UTF-8?q?Letzte=20=C3=9Cbung=20:)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Uebung_05_Andres/Design.java | 21 ++ src/main/java/Uebung_05_Andres/Ghost.java | 71 +++++ src/main/java/Uebung_05_Andres/Pacman.java | 33 +++ .../java/Uebung_05_Andres/PacmanGame.java | 272 ++++++++++++++++++ 4 files changed, 397 insertions(+) create mode 100644 src/main/java/Uebung_05_Andres/Design.java create mode 100644 src/main/java/Uebung_05_Andres/Ghost.java create mode 100644 src/main/java/Uebung_05_Andres/Pacman.java create mode 100644 src/main/java/Uebung_05_Andres/PacmanGame.java diff --git a/src/main/java/Uebung_05_Andres/Design.java b/src/main/java/Uebung_05_Andres/Design.java new file mode 100644 index 0000000..dfc344d --- /dev/null +++ b/src/main/java/Uebung_05_Andres/Design.java @@ -0,0 +1,21 @@ +package Uebung_05_Andres; + +import java.awt.Color; + +public class Design { + // Konstante für die Bildschirmbreite + public static final int SCREEN_WIDTH = 400; + // Konstante für die Bildschirmhöhe + public static final int SCREEN_HEIGHT = 400; + // Konstante für die Größe eines Feldes des Labyrinths + public static final int CELL_SIZE = 40; + // Definierte Farben für das Spiel + public static final Color YELLOW = new Color(255, 255, 0); + public static final Color RED = new Color(255, 0, 0); + public static final Color WHITE = new Color(255, 255, 255); + public static final Color BLUE = new Color(0, 0, 255); + public static final Color BLACK = new Color(0, 0, 0); + public static final Color GREEN = new Color(0, 100, 0); + public static final Color ORANGE = new Color(255, 140, 0); + public static final Color PINK = new Color(255, 192, 203); +} diff --git a/src/main/java/Uebung_05_Andres/Ghost.java b/src/main/java/Uebung_05_Andres/Ghost.java new file mode 100644 index 0000000..21a11c8 --- /dev/null +++ b/src/main/java/Uebung_05_Andres/Ghost.java @@ -0,0 +1,71 @@ +package Uebung_05_Andres; + +import java.awt.Color; +import java.awt.Graphics; + +import javax.swing.Timer; + +public class Ghost { + int x; + int y; + boolean isEatable; + + private Color color; + private final Color EATABLE_COLOR = Design.BLUE; + private Timer timer; + + // Konstruktor für den Geist + public Ghost(int x, int y, Color color) { + this.x = x; + this.y = y; + this.color = color; + this.isEatable = false; + } + + public void makeGhostEatable() { + //Extend duration if pacman eats multiple power pills quickly + if (isEatable) { + timer.restart(); + } + + this.isEatable = true; + + // After 10 seconds, set isEatable to false + timer = new Timer(10000, e -> { + this.isEatable = false; + }); + + timer.setRepeats(false); // This ensures the timer only runs once + timer.start(); + } + + public void gotEaten() { + this.isEatable = false; + //Teleport ghost to ghost-box + this.x = 9; + this.y = 5; + } + + // Zeichne den Geist + public void draw(Graphics g) { + g.setColor(isEatable ? EATABLE_COLOR : color); + String[] ghostPixels = { + " #### ", + "######", + "## # #", + "######", + "######", + "# # # " + }; + int pixelSize = Design.CELL_SIZE / ghostPixels.length; + for (int rowIdx = 0; rowIdx < ghostPixels.length; rowIdx++) { + for (int colIdx = 0; colIdx < ghostPixels[rowIdx].length(); colIdx++) { + if (ghostPixels[rowIdx].charAt(colIdx) == '#') { + int pixelX = x * Design.CELL_SIZE + colIdx * pixelSize; + int pixelY = y * Design.CELL_SIZE + rowIdx * pixelSize; + g.fillRect(pixelX, pixelY, pixelSize, pixelSize); + } + } + } + } +} diff --git a/src/main/java/Uebung_05_Andres/Pacman.java b/src/main/java/Uebung_05_Andres/Pacman.java new file mode 100644 index 0000000..b95cbd3 --- /dev/null +++ b/src/main/java/Uebung_05_Andres/Pacman.java @@ -0,0 +1,33 @@ +package Uebung_05_Andres; + +import java.awt.Graphics; + +public class Pacman { + int x; + int y; + + // Konstruktor für Pacman + public Pacman(int x, int y) { + this.x = x; + this.y = y; + } + + // Zeichne Pacman + public void draw(Graphics g) { + g.setColor(Design.YELLOW); + + // Angle for the mouth (for animation) + int startAngle = (int)(Math.sin(System.currentTimeMillis() / 200.0) * 45); // Animating the mouth to open and close + int arcAngle = 270 - startAngle * 2; // The size of the mouth opening + + // Draw Pac-Man with an open mouth + g.fillArc( + x * Design.CELL_SIZE, + y * Design.CELL_SIZE, + Design.CELL_SIZE, + Design.CELL_SIZE, + startAngle + 30, + arcAngle + 30 + ); + } +} diff --git a/src/main/java/Uebung_05_Andres/PacmanGame.java b/src/main/java/Uebung_05_Andres/PacmanGame.java new file mode 100644 index 0000000..935e49d --- /dev/null +++ b/src/main/java/Uebung_05_Andres/PacmanGame.java @@ -0,0 +1,272 @@ +package Uebung_05_Andres; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +// Hauptklasse für das Pacman-Spiel +public class PacmanGame extends JPanel implements KeyListener, ActionListener { + // Timer für das Fortschreiten des Spiels + private Timer timer; + + /** + * Labyrinth definition: + * # -> wall + * * -> power pill + * / -> teleportation point + * . -> cookie + * _ -> empty space for practical purposes + */ + private String[] labyrinth = { + "###################", + "#..........##....*#", + "#.##.###.#.##.###.#", + "#.##.#............#", + "#*...#.##-##.#.#..#", + "##.#....# #..#.#.##", + "##.#.##.###.##.#.##", + "/_.#.##..*..##.#._/", + "##.#....###....#.##", + "##.#############.##", + "#.................#", + "#.###.##...##.###.#", + "#.###....#....###.#", + "#.....##.*.##.....#", + "###################" + }; + + // Anzahl der Zeilen und Spalten im Labyrinth + private int ROWS = labyrinth.length; + private int COLS = labyrinth[0].length(); + + // Referenzen für Pacman und einen Geist + private Pacman pacman; + private Ghost[] ghosts = new Ghost[4]; + + // Konstruktor für das Pacman-Spiel + public PacmanGame() { + // Setze Dimensionen des Spielfelds + setPreferredSize(new Dimension(COLS * Design.CELL_SIZE, ROWS * Design.CELL_SIZE)); + // Setze Hintergrundfarbe + setBackground(Design.BLACK); + // Füge KeyListener hinzu + addKeyListener(this); + // Ermögliche die Fokussierung auf das JPanel + setFocusable(true); + + // Initialisiere Pacman und Geist + pacman = new Pacman(1, 1); + ghosts[0] = new Ghost(1, ROWS - 5, Design.RED); + ghosts[1] = new Ghost(COLS - 2, ROWS - 2, Design.ORANGE); + ghosts[2] = new Ghost(9, 7, Design.PINK); + ghosts[3] = new Ghost(COLS - 2, 4, Design.GREEN); + + // Starte Timer mit 500ms Intervall + timer = new Timer(500, this); + timer.start(); + } + + // Reagiere auf Timer-Events + @Override + public void actionPerformed(ActionEvent e) { + // Bewege den Geist + for (Ghost ghost: ghosts) { + moveGhost(ghost); + } + + // Prüfe auf Kollisionen + for (Ghost ghost : ghosts) { + checkCollisions(ghost); + } + + // Aktualisiere die Darstellung + repaint(); + } + + // Override für das Zeichnen des Komponenten + @Override + protected void paintComponent(Graphics g) { + super.paintComponent(g); + // Zeichne das Labyrinth + drawLabyrinth(g); + // Zeichne Pacman + pacman.draw(g); + // Zeichne den Geist + for (Ghost ghost : ghosts) { + ghost.draw(g); + } + } + + // Zeichne das Labyrinth + private void drawLabyrinth(Graphics g) { + for (int y = 0; y < ROWS; y++) { + for (int x = 0; x < COLS; x++) { + + switch (labyrinth[y].charAt(x)) { + case '#': //Wall + g.setColor(Design.BLUE); + g.fillRect( + x * Design.CELL_SIZE, + y * Design.CELL_SIZE, + Design.CELL_SIZE, + Design.CELL_SIZE + ); + break; + + case '.': //Point + g.setColor(Design.WHITE); + g.fillOval( + x * Design.CELL_SIZE + Design.CELL_SIZE / 2 - 5, + y * Design.CELL_SIZE + Design.CELL_SIZE / 2 - 5, + 10, + 10 + ); + break; + + case '*': //Power pill + g.setColor(Design.WHITE); + g.fillOval( + x * Design.CELL_SIZE + Design.CELL_SIZE / 2 - 10, + y * Design.CELL_SIZE + Design.CELL_SIZE / 2 - 10, + 20, + 20 + ); + break; + + case '-': //Ghost spawn barrier + g.setColor(Design.WHITE); + g.fillRect( + x * Design.CELL_SIZE, + y * Design.CELL_SIZE, + Design.CELL_SIZE, + 10 + ); + break; + } + } + } + } + + // Bewege Pacman, falls möglich + private void movePacman(int dx, int dy) { + int newX = pacman.x + dx; + int newY = pacman.y + dy; + + //Check if pacman should be teleported. Same row teleportation only! + if (labyrinth[newY].charAt(newX) == '/') { + pacman.x = newX == 0 ? labyrinth[newY].length()-2 : 1; + pacman.y = newY; + } + // Überprüfe, ob das neue Feld kein Wand ist, bevor Pacman bewegt wird + else if (labyrinth[newY].charAt(newX) != '#' && labyrinth[newY].charAt(newX) != '-') { + pacman.x = newX; + pacman.y = newY; + } + } + + // Bewege den Geist in Richtung von Pacman + private void moveGhost(Ghost ghost) { + if (ghost.x < pacman.x && labyrinth[ghost.y].charAt(ghost.x + 1) != '#') { + ghost.x += 1; + } else if (ghost.x > pacman.x && labyrinth[ghost.y].charAt(ghost.x - 1) != '#') { + ghost.x -= 1; + } else if (ghost.y < pacman.y && labyrinth[ghost.y + 1].charAt(ghost.x) != '#') { + ghost.y += 1; + } else if (ghost.y > pacman.y && labyrinth[ghost.y - 1].charAt(ghost.x) != '#') { + ghost.y -= 1; + } + } + + // Prüfe Kollisionen und Spielstatus + private void checkCollisions(Ghost ghost) { + // Kollision zwischen Pacman und Geist + if (pacman.x == ghost.x && pacman.y == ghost.y) { + if (ghost.isEatable) { + ghost.gotEaten(); + } else { + JOptionPane.showMessageDialog(this, "Game Over! The ghost caught Pacman."); + System.exit(0); + } + } + + // Kollision Pacman mit einem Punkt + if (labyrinth[pacman.y].charAt(pacman.x) == '.') { + labyrinth[pacman.y] = labyrinth[pacman.y].substring(0, pacman.x) + " " + labyrinth[pacman.y].substring(pacman.x + 1); + } + + // Kollision Pacman mit einem Power Pill + if (labyrinth[pacman.y].charAt(pacman.x) == '*') { + labyrinth[pacman.y] = labyrinth[pacman.y].substring(0, pacman.x) + " " + labyrinth[pacman.y].substring(pacman.x + 1); + triggerPowerUp(); + } + + + // Überprüfen, ob alle Punkte gegessen sind + if (isAllCookiesEaten()) { + JOptionPane.showMessageDialog(this, "You Win! Pacman ate all the cookies."); + System.exit(0); + } + } + + private void triggerPowerUp() { + for (Ghost ghost: ghosts) { + ghost.makeGhostEatable(); + } + } + + // Überprüfe, ob alle Punkte gegessen wurden + private boolean isAllCookiesEaten() { + for (String row : labyrinth) { + if (row.contains(".")) { + return false; + } + } + return true; + } + + // Erforderliche, aber nicht genutzte Methode von KeyListener + @Override + public void keyTyped(KeyEvent e) {} + + // Reagiere auf Tastendrücke + @Override + public void keyPressed(KeyEvent e) { + int key = e.getKeyCode(); + // Steuere Pacman mit den Pfeiltasten + if (key == KeyEvent.VK_LEFT) { + movePacman(-1, 0); + } else if (key == KeyEvent.VK_RIGHT) { + movePacman(1, 0); + } else if (key == KeyEvent.VK_UP) { + movePacman(0, -1); + } else if (key == KeyEvent.VK_DOWN) { + movePacman(0, 1); + } + // Prüfe Kollisionen nach der Bewegung + for (Ghost ghost : ghosts) { + checkCollisions(ghost); + } + // Aktualisiere die Darstellung + repaint(); + } + + // Erforderliche, aber nicht genutzte Methode von KeyListener + @Override + public void keyReleased(KeyEvent e) {} + + // Hauptmethode zum Starten des Spiels + public static void main(String[] args) { + SwingUtilities.invokeLater(() -> { + JFrame frame = new JFrame("Pacman by Andres :v"); + PacmanGame game = new PacmanGame(); + frame.add(game); + frame.pack(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + }); + } +} \ No newline at end of file