Преглед на файлове

Neustrukturierung, mehr dem MVC Model angepasst, anfang von Datenspeicherung

Jan преди 7 месеца
родител
ревизия
8b3369cf5d

+ 118 - 1
src/main/java/controller/GameController.java

@@ -1,4 +1,121 @@
 package controller;
 
-public class GameController {
+import model.GameModel;
+import model.Item;
+import model.items.ITEM_NAME;
+import util.GAMESTATE;
+import view.GamePanel;
+
+import java.io.Serializable;
+
+public class GameController implements Runnable, Serializable {
+    private KeyHandler keyHandler;
+    private GameModel gameModel;
+
+    private transient Thread gameThread; // transient to avoid serialization
+    private GamePanel view;
+    private boolean running = true;
+    private int fps = 60;
+
+    public GameController() {
+        this.keyHandler = new KeyHandler(this);
+        this.gameModel = new GameModel();
+        this.view = new GamePanel(this);
+        setStartInventory();
+    }
+
+    private void setStartInventory() {
+        gameModel.getInventory().addToInventory(new Item(ITEM_NAME.STONE));
+        gameModel.getInventory().addToInventory(new Item(ITEM_NAME.WATER));
+        gameModel.getInventory().addToInventory(new Item(ITEM_NAME.WOOD));
+    }
+
+    public void setView(GamePanel gp){
+        view = gp;
+    }
+    public void handleInventoryClick(int x, int y) {
+        int slot = view.getInventoryView().getClickedInventorySlot(x, y);
+        gameModel.getInventory().select(slot);
+    }
+
+    public void startGameLoop() {
+        gameThread = new Thread(this);
+        gameThread.start();
+    }
+
+    public void stopGameLoop() {
+        running = false;
+    }
+
+    public void update() {
+        if (view.gameState == GAMESTATE.PLAY || view.gameState == GAMESTATE.INVENTORY) {
+            view.camera.update();
+        }
+    }
+
+    @Override
+    public void run() {
+        double drawInterval = 1_000_000_000.0 / fps;
+        double delta = 0;
+        long lastTime = System.nanoTime();
+        long currentTime;
+        long timer = 0;
+        int drawCount = 0;
+
+        while (running) {
+            currentTime = System.nanoTime();
+            delta += (currentTime - lastTime) / drawInterval;
+            timer += (currentTime - lastTime);
+            lastTime = currentTime;
+
+            if (delta >= 1) {
+                update();           // Logic update
+                view.repaint();     // Triggers paintComponent in view
+                delta--;
+                drawCount++;
+            }
+
+            if (timer >= 1_000_000_000) {
+                drawCount = 0;
+                timer = 0;
+            }
+        }
+    }
+    public GamePanel getView(){
+        return view;
+    }
+    public void zoomIn() {
+        view.zoomInOut(1);
+    }
+
+    public void zoomOut() {
+        view.zoomInOut(-1);
+    }
+
+    public void togglePauseOrExitInventory() {
+        if (view.gameState == GAMESTATE.INVENTORY) {
+            view.gameState = GAMESTATE.PLAY;
+        } else if (view.gameState == GAMESTATE.PLAY) {
+            view.gameState = GAMESTATE.PAUSED;
+        } else if (view.gameState == GAMESTATE.PAUSED) {
+            view.gameState = GAMESTATE.PLAY;
+        }
+    }
+
+    public void toggleInventory() {
+        if (view.gameState == GAMESTATE.INVENTORY) {
+            view.gameState = GAMESTATE.PLAY;
+            gameModel.getInventory().deselect();
+        } else if (view.gameState == GAMESTATE.PLAY) {
+            view.gameState = GAMESTATE.INVENTORY;
+        }
+    }
+
+    public GameModel getModel() {
+        return gameModel;
+    }
+
+    public KeyHandler getKeyHandler() {
+        return keyHandler;
+    }
 }

+ 20 - 52
src/main/java/controller/KeyHandler.java

@@ -8,74 +8,42 @@ import java.awt.event.KeyListener;
 
 public class KeyHandler implements KeyListener {
 
-    public boolean upPressed, downPressed, leftPressed, rightPressed;
+    private GameController controller;
 
-    GamePanel gp;
+    public boolean upPressed, downPressed, leftPressed, rightPressed;
 
-    public KeyHandler(GamePanel gp){
-        this.gp = gp;
+    public KeyHandler(GameController controller) {
+        this.controller = controller;
     }
 
     @Override
-    public void keyTyped(KeyEvent e) {
-
-    }
+    public void keyTyped(KeyEvent e) {}
 
     @Override
     public void keyPressed(KeyEvent e) {
         int code = e.getKeyCode();
-        if(code == KeyEvent.VK_W){
-            upPressed = true;
-        }
-        if(code == KeyEvent.VK_A){
-            leftPressed = true;
-        }
-        if(code == KeyEvent.VK_S){
-            downPressed = true;
-        }
-        if(code == KeyEvent.VK_D){
-            rightPressed = true;
-        }
-        if(code == KeyEvent.VK_UP){
-            gp.zoomInOut(1);
-        }
-        if(code == KeyEvent.VK_DOWN){
-            gp.zoomInOut(-1);
-        }
-
-        if(code == KeyEvent.VK_ESCAPE){
-            if(gp.gameState == GAMESTATE.INVENTORY){
-                gp.gameState = GAMESTATE.PLAY;
-            }else if(gp.gameState == GAMESTATE.PLAY){
-                gp.gameState = GAMESTATE.PAUSED;
-            }else if(gp.gameState == GAMESTATE.PAUSED){
-                gp.gameState = GAMESTATE.PLAY;
-            }
-        }
 
-        if(code == KeyEvent.VK_E){
-            if(gp.gameState == GAMESTATE.INVENTORY){
-                gp.gameState = GAMESTATE.PLAY;
-            }else if(gp.gameState == GAMESTATE.PLAY){
-                gp.gameState = GAMESTATE.INVENTORY;
-            }
+        switch (code) {
+            case KeyEvent.VK_W -> upPressed = true;
+            case KeyEvent.VK_A -> leftPressed = true;
+            case KeyEvent.VK_S -> downPressed = true;
+            case KeyEvent.VK_D -> rightPressed = true;
+            case KeyEvent.VK_UP -> controller.zoomIn();
+            case KeyEvent.VK_DOWN -> controller.zoomOut();
+            case KeyEvent.VK_ESCAPE -> controller.togglePauseOrExitInventory();
+            case KeyEvent.VK_E -> controller.toggleInventory();
         }
     }
 
     @Override
     public void keyReleased(KeyEvent e) {
         int code = e.getKeyCode();
-        if(code == KeyEvent.VK_W){
-            upPressed = false;
-        }
-        if(code == KeyEvent.VK_A){
-            leftPressed = false;
-        }
-        if(code == KeyEvent.VK_S){
-            downPressed = false;
-        }
-        if(code == KeyEvent.VK_D){
-            rightPressed = false;
+
+        switch (code) {
+            case KeyEvent.VK_W -> upPressed = false;
+            case KeyEvent.VK_A -> leftPressed = false;
+            case KeyEvent.VK_S -> downPressed = false;
+            case KeyEvent.VK_D -> rightPressed = false;
         }
     }
 }

+ 13 - 3
src/main/java/controller/MouseListener.java

@@ -1,5 +1,6 @@
 package controller;
 
+import model.Inventory;
 import model.Tile;
 import util.GAMESTATE;
 import view.Camera;
@@ -19,10 +20,14 @@ public class MouseListener extends MouseMotionAdapter implements java.awt.event.
     TileManager tileManager;
     GamePanel gp;
     InventoryView iView;
-    public MouseListener(GamePanel gp, Camera camera, TileManager tm, InventoryView inventoryView){
+    Inventory inventory;
+    GameController controller;
+
+    public MouseListener(GameController controller, GamePanel gp, Camera camera, TileManager tm) {
+        this.controller = controller;
+        this.gp = gp;
         this.camera = camera;
         this.tileManager = tm;
-        this.gp = gp;
     }
     @Override
     public void mouseDragged(MouseEvent e) {
@@ -42,8 +47,13 @@ public class MouseListener extends MouseMotionAdapter implements java.awt.event.
 
     @Override
     public void mouseClicked(MouseEvent e) {
+        if (gp.gameState == GAMESTATE.INVENTORY && e.getButton() == MouseEvent.BUTTON1) {
+            controller.handleInventoryClick(e.getX(), e.getY());
+        }
         if(gp.gameState == GAMESTATE.INVENTORY && e.getButton() == 1){
-            gp.inventory.select(e.getX(), e.getY());
+            controller.handleInventoryClick(e.getX(), e.getY());
+        }else if(gp.gameState == GAMESTATE.PAUSED){
+            gp.ui.handleClick(e.getX(), e.getY());
         }
     }
 

+ 6 - 2
src/main/java/main/Main.java

@@ -1,18 +1,22 @@
 package main;
 
+import controller.GameController;
+import model.GameModel;
 import view.GamePanel;
 
 import javax.swing.*;
 
 public class Main {
     public static void main(String[] args) {
+        GameController gameController = new GameController();
+        GamePanel gamePanel = gameController.getView();
+
         System.out.println("Starte Spiel...");
         JFrame window = new JFrame();
         window.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
         window.setResizable(false);
         window.setTitle("Tiny Settlement");
 
-        GamePanel gamePanel = new GamePanel();
         window.setPreferredSize(gamePanel.getPreferredSize());
         window.add(gamePanel);
 
@@ -21,6 +25,6 @@ public class Main {
         window.setLocationRelativeTo(null);
         window.setVisible(true);
 
-        gamePanel.startGameThread();
+        gameController.startGameLoop();
     }
 }

+ 7 - 22
src/main/java/model/Entity.java

@@ -8,19 +8,17 @@ import java.awt.*;
 import java.io.IOException;
 
 public abstract class Entity {
-    private GamePanel gp;
-    private KeyHandler keyH;
+    public GamePanel gp;
 
     private Image optionalPlayerImage;
 
-    private int worldX, worldY;
-    private int speed;
+    public int worldX, worldY;
+    public int speed;
 
-    public final int screenX, screenY;
+    public int screenX, screenY;
 
-    public Entity(GamePanel gamePanel, KeyHandler keyHandler){
+    public Entity(GamePanel gamePanel){
         gp = gamePanel;
-        keyH = keyHandler;
         screenX = gp.screenWidth/2 - gamePanel.tileSize/2;
         screenY = gp.screenHeight/2 - gamePanel.tileSize/2;
 
@@ -40,23 +38,10 @@ public abstract class Entity {
         worldX += x;
     }
 
-    public void update(){
-        if(keyH.upPressed){
-            worldY -= speed;
-        }
-        if(keyH.downPressed){
-            worldY += speed;
-        }
-        if(keyH.leftPressed){
-            worldX -= speed;
-        }
-        if(keyH.rightPressed){
-            worldX += speed;
-        }
-    }
+    public abstract void update();
+
     public void draw(Graphics2D g2){
         g2.setColor(Color.WHITE);
-
         g2.drawImage(optionalPlayerImage, screenX, screenY, gp.tileSize, gp.tileSize, null);
     }
 }

+ 13 - 0
src/main/java/model/GameModel.java

@@ -0,0 +1,13 @@
+package model;
+
+public class GameModel {
+    private Inventory inventory;
+
+    public GameModel() {
+        inventory = new Inventory();
+    }
+
+    public Inventory getInventory() {
+        return inventory;
+    }
+}

+ 39 - 0
src/main/java/model/GameSaver.java

@@ -0,0 +1,39 @@
+package model;
+
+import controller.GameController;
+import view.GamePanel;
+
+import java.io.*;
+
+public class GameSaver {
+    private static final String SAVE_FILE = "game.dat";
+    private GameSaver(){
+
+    }
+    public static void saveGame(GameController controller) {
+        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(SAVE_FILE))) {
+            oos.writeObject(controller);
+            System.out.println("Game saved.");
+        } catch (IOException e) {
+            System.out.println("Failed to save game.");
+            e.printStackTrace();
+        }
+    }
+    public static GameController loadGame() {
+        File file = new File(SAVE_FILE);
+
+        if (!file.exists()) {
+            // File doesn't exist → return a new GameController
+            System.out.println("Save file not found. Starting a new game...");
+            return new GameController(); // Assumes a default constructor exists
+        }
+
+        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) {
+            return (GameController) ois.readObject();
+        } catch (Exception e) {
+            System.out.println("Failed to load save file. Starting a new game...");
+            e.printStackTrace();
+            return new GameController(); // Fallback if file is corrupt or incompatible
+        }
+    }
+}

+ 8 - 9
src/main/java/model/Inventory.java

@@ -11,16 +11,10 @@ import java.util.List;
 public class Inventory {
     private int uniqueItemsCount;
     private HashMap<ITEM_NAME, Item> itemHashMap;
-    private GamePanel gp;
-    public Inventory(GamePanel gamePanel) {
-        gp = gamePanel;
+    public Inventory() {
         uniqueItemsCount = 0;
         itemHashMap = new HashMap<>();
 
-        //test
-        addToInventory(new Item(ITEM_NAME.STONE));
-        addToInventory(new Item(ITEM_NAME.WOOD));
-        addToInventory(new Item(ITEM_NAME.WOOD));
     }
 
     public Item addToInventory(Item item){
@@ -49,8 +43,7 @@ public class Inventory {
         return uniqueItemsCount;
     }
 
-    public void select(int x, int y) {
-        int clickedSlot = gp.inventoryView.getClickedInventorySlot(x, y);
+    public void select(int clickedSlot) {
         if(clickedSlot != -1){
             getItemList().forEach((item) -> {
                 item.setSelected(false);
@@ -58,4 +51,10 @@ public class Inventory {
             getItemList().get(clickedSlot).setSelected();
         }
     }
+
+    public void deselect() {
+        getItemList().forEach((item) -> {
+            item.setSelected(false);
+        });
+    }
 }

+ 1 - 1
src/main/java/util/GAMESTATE.java

@@ -3,5 +3,5 @@ package util;
 public enum GAMESTATE {
     PLAY,
     PAUSED,
-    INVENTORY,
+    INVENTORY, QUIT,
 }

+ 3 - 4
src/main/java/view/Camera.java

@@ -1,14 +1,13 @@
 package view;
 
-import view.entity.Entity;
 import controller.KeyHandler;
+import model.Entity;
 
 import javax.imageio.ImageIO;
 import java.awt.*;
 import java.io.IOException;
 
 public class Camera extends Entity {
-    private GamePanel gp;
     private KeyHandler keyH;
 
     private Image optionalPlayerImage;
@@ -17,8 +16,8 @@ public class Camera extends Entity {
     public final int screenY;
 
     public Camera(GamePanel gamePanel, KeyHandler keyHandler){
-        gp = gamePanel;
-        keyH = keyHandler;
+        super(gamePanel);
+        this.keyH = keyHandler;
         screenX = gp.screenWidth/2 - gamePanel.tileSize/2;
         screenY = gp.screenHeight/2 - gamePanel.tileSize/2;
         //getPlayerImage();

+ 27 - 60
src/main/java/view/GamePanel.java

@@ -1,7 +1,9 @@
 package view;
 
+import controller.GameController;
 import controller.MouseListener;
 import controller.MouseWheelZoom;
+import model.GameSaver;
 import model.Inventory;
 import view.tile.TileManager;
 import util.GAMESTATE;
@@ -11,7 +13,7 @@ import view.util.screenCoordinatesToWorld;
 import javax.swing.*;
 import java.awt.*;
 
-public class GamePanel extends JPanel implements Runnable, screenCoordinatesToWorld {
+public class GamePanel extends JPanel implements screenCoordinatesToWorld {
 
     //Screen Settings
     final static int originalTileSize = 16;
@@ -19,8 +21,7 @@ public class GamePanel extends JPanel implements Runnable, screenCoordinatesToWo
 
     int fps = 60;
 
-    public Inventory inventory;
-
+    public GameController gameController;
     public static int static_TileSize = originalTileSize * scale;
 
     public int tileSize = originalTileSize * scale;
@@ -44,16 +45,18 @@ public class GamePanel extends JPanel implements Runnable, screenCoordinatesToWo
 
 
     TileManager tileManager = new TileManager(this);
-    KeyHandler keyH = new KeyHandler(this);
-    Thread gameThread;
-    public InventoryView inventoryView = new InventoryView(this);
-    public Camera camera = new Camera(this, keyH);
+    private InventoryView inventoryView;
+    public Camera camera;
+
 
+    public GamePanel(GameController controller) {
+        this.gameController = controller; // get from controller
+        this.camera = new Camera(this, controller.getKeyHandler());
 
-    public GamePanel(){
-        inventory = new Inventory(this);
+        Inventory inventory = gameController.getModel().getInventory();
+        this.inventoryView = new InventoryView(inventory);
 
-        MouseListener mdl = new MouseListener(this, camera, tileManager, inventoryView);
+        MouseListener mdl = new MouseListener(controller, this, camera, tileManager);
         this.addMouseListener(mdl);
         this.addMouseMotionListener(mdl);
         this.addMouseWheelListener(new MouseWheelZoom(this));
@@ -61,13 +64,10 @@ public class GamePanel extends JPanel implements Runnable, screenCoordinatesToWo
         this.setPreferredSize(new Dimension(screenWidth, screenHeight));
         this.setBackground(Color.BLACK);
         this.setDoubleBuffered(true);
-        this.addKeyListener(keyH);
+        this.addKeyListener(controller.getKeyHandler()); // now safe
         this.setFocusable(true);
 
         gameState = GAMESTATE.PLAY;
-
-        System.out.println("Screen Width: " + screenWidth);
-        System.out.println("Screen Height: " + screenHeight);
     }
 
     public void zoomInOut(int i){
@@ -85,31 +85,29 @@ public class GamePanel extends JPanel implements Runnable, screenCoordinatesToWo
         double newCameraWorldX = camera.worldX * multiplier;
         double newCameraWorldY = camera.worldY * multiplier;
 
-        camera.worldX = newCameraWorldX;
-        camera.worldY = newCameraWorldY;
+        camera.worldX = (int) newCameraWorldX;
+        camera.worldY = (int) newCameraWorldY;
     }
-
-    public void startGameThread(){
-        gameThread = new Thread(this);
-        gameThread.start();
+    public InventoryView getInventoryView(){
+        return inventoryView;
     }
-
-    public void clearAll(Graphics g){
-        super.paintComponent(g);
-    }
-
-    public void paintComponent(Graphics g){
+    @Override
+    public void paintComponent(Graphics g) {
         super.paintComponent(g);
-
         Graphics2D g2 = (Graphics2D) g;
 
         tileManager.draw(g2);
         camera.draw(g2);
 
-        if(gameState == GAMESTATE.INVENTORY){
+        if (gameState == GAMESTATE.INVENTORY) {
             inventoryView.drawInventoryOverlay(g2);
         }
-        // UI
+
+        if (gameState == GAMESTATE.QUIT) {
+            GameSaver.saveGame(gameController);
+            System.exit(0);
+        }
+
         ui.draw(g2);
         g2.dispose();
     }
@@ -119,34 +117,6 @@ public class GamePanel extends JPanel implements Runnable, screenCoordinatesToWo
         }
     }
 
-    @Override
-    public void run() {
-        double drawInterval = 1000000000/fps;
-        double delta = 0;
-        long lastTime = System.nanoTime();
-        long currentTime;
-        long timer = 0;
-        int drawCount = 0;
-        while (gameThread != null){
-            currentTime = System.nanoTime();
-
-            delta += (currentTime - lastTime) / drawInterval;
-            timer += (currentTime - lastTime);
-            lastTime = currentTime;
-            if(delta >= 1){
-                update();
-                repaint();
-                delta--;
-                drawCount++;
-            }
-            if(timer >= 1000000000){
-                //System.out.println("FPS: " + drawCount);
-                drawCount = 0;
-                timer = 0;
-            }
-        }
-    }
-
     public int x(int screenX){
         return (int) (camera.worldX + screenX / (double) tileSize);
     }
@@ -155,7 +125,4 @@ public class GamePanel extends JPanel implements Runnable, screenCoordinatesToWo
         return (int) (camera.worldY + screenY / (double) tileSize);
     }
 
-    public void highlightTile(int screenX, int screenY) {
-        System.out.println("Highlight X: " + screenX/tileSize+" Y: "+screenY/tileSize);
-    }
 }

+ 8 - 24
src/main/java/view/InventoryView.java

@@ -6,18 +6,17 @@ import util.TextUtil;
 import java.awt.*;
 
 public class InventoryView {
-    private GamePanel gp;
-    private int inventoryHeight, inventoryWidth, inventoryY, inventoryX;
+    private Inventory inventory;
     int overlayX = 20;
     int overlayY = 20;
     int slotSize = 48;
     int slotSpacing = 8;
     int slotCount = 0;
-    public InventoryView(GamePanel gamePanel){
-        this.gp = gamePanel;
+    public InventoryView(Inventory inventory){
+        this.inventory = inventory;
     }
     public void drawInventoryOverlay(Graphics2D g2) {
-        slotCount = gp.inventory.getUniqueItemsCount();
+        slotCount = inventory.getUniqueItemsCount();
 
         int overlayWidth = slotSize + 2* slotSpacing;
         int overlayHeight = (slotSize + slotSpacing) * slotCount + slotSpacing;
@@ -28,8 +27,8 @@ public class InventoryView {
 
         // Draw slots
         for (int i = 0; i < slotCount; i++) {
-            if(gp.inventory.getItemList().get(i).isSelected()){
-                g2.setColor(Color.CYAN);
+            if(inventory.getItemList().get(i).isSelected()){
+                g2.setColor(Color.WHITE);
             }else{
                 g2.setColor(Color.LIGHT_GRAY);
             }
@@ -39,12 +38,12 @@ public class InventoryView {
 
             g2.setColor(Color.DARK_GRAY);
 
-            String itemName = gp.inventory.getItemList().get(i).getItemName().toString();
+            String itemName = inventory.getItemList().get(i).getItemName().toString();
 
             TextUtil.setFontAppropriateToSize(itemName, slotSize - slotSpacing/2, g2);
 
             g2.drawString(itemName, x + slotSpacing/4, y + slotSize / 2 + 5);
-            g2.drawString( "" + gp.inventory.getItemList().get(i).getCount() , x + slotSize - slotSize/5, y + slotSize -2);
+            g2.drawString( "" + inventory.getItemList().get(i).getCount() , x + slotSize - slotSize/5, y + slotSize -2);
 
             g2.setColor(Color.LIGHT_GRAY); // reset color for next slot
         }
@@ -62,19 +61,4 @@ public class InventoryView {
         }
         return -1; // No slot was clicked
     }
-    public int getInventoryHeight() {
-        return inventoryHeight;
-    }
-
-    public int getInventoryWidth() {
-        return inventoryWidth;
-    }
-
-    public int getInventoryY() {
-        return inventoryY;
-    }
-
-    public int getInventoryX() {
-        return inventoryX;
-    }
 }

+ 29 - 22
src/main/java/view/UI.java

@@ -1,37 +1,43 @@
 package view;
 
 import util.GAMESTATE;
+import view.components.Button;
 
 import java.awt.*;
+import java.util.ArrayList;
 
 public class UI {
     private GamePanel gp;
-    private Graphics2D g2; //test
+    private Graphics2D g2;
     private Font arial_40;
-    private String message = "";
-    private boolean messageOn;
+    private ArrayList<Button> activeButtons = new ArrayList<>();
 
     public UI(GamePanel gp){
         this.gp = gp;
         arial_40 = new Font("Arial", Font.PLAIN, 80);
     }
 
-    public void showMessage(String text){
-        message = text;
-        messageOn = true;
-    }
-
     public void draw(Graphics2D g2){
         this.g2 = g2;
         g2.setFont(arial_40);
         g2.setColor(Color.white);
 
         if(gp.gameState == GAMESTATE.PAUSED){
-            drawBlackScreenWithMessage(g2, "Spiel Pausiert");
+            drawPauseScreen(g2, "Spiel Pausiert");
+        }
+    }
+
+    public void handleClick(int screenX, int screenY) {
+        for (Button button : activeButtons) {
+            if (button.wasClicked(screenX, screenY)) {
+                button.click();
+                break;
+            }
         }
     }
+    private void drawPauseScreen(Graphics2D g2, String message) {
+
 
-    private void drawBlackScreenWithMessage(Graphics2D g2, String message) {
         // Background overlay
         g2.setColor(new Color(0, 0, 0, 150));
         g2.fillRect(0, 0, gp.screenWidth, gp.screenHeight);
@@ -60,18 +66,19 @@ public class UI {
         int buttonX = gp.screenWidth / 2 - buttonWidth / 2;
         int resumeY = boxY + 100;
         int exitY = resumeY + buttonHeight + spacing;
-
-        // Resume button
-        g2.setColor(new Color(200, 200, 200));
-        g2.fillRoundRect(buttonX, resumeY, buttonWidth, buttonHeight, 15, 15);
-        g2.setColor(Color.BLACK);
-        g2.drawString("Fortsetzen", buttonX + 11, resumeY + 30);
-
-        // Exit button
-        g2.setColor(new Color(200, 200, 200));
-        g2.fillRoundRect(buttonX, exitY, buttonWidth, buttonHeight, 15, 15);
-        g2.setColor(Color.BLACK);
-        g2.drawString("Beenden", buttonX + 22, exitY + 30);
+        Button resumeButton = new Button(buttonHeight, buttonWidth, "Fortsetzen", () -> {
+            gp.gameState = GAMESTATE.PLAY;
+        });
+        resumeButton.setScreenCoordinates(buttonX, resumeY);
+        resumeButton.draw(g2);
+        activeButtons.add(resumeButton);
+
+        Button exitButton = new Button(buttonHeight, buttonWidth, "Beenden", () -> {
+            gp.gameState = GAMESTATE.QUIT; // or custom exit logic
+        });
+        exitButton.setScreenCoordinates(buttonX, exitY);
+        exitButton.draw(g2);
+        activeButtons.add(exitButton);
     }
 
 

+ 49 - 0
src/main/java/view/components/Button.java

@@ -0,0 +1,49 @@
+package view.components;
+
+import java.awt.*;
+
+public class Button {
+    int screenX, screenY;
+    private int height;
+    private int width;
+    private String text;
+    private Runnable runnable;
+
+    public Button(int height, int width, String text, Runnable c){
+        this.height = height;
+        this.width = width;
+        this.text = text;
+        runnable = c;
+    }
+    public Button(int height, int width, int screenX, int screenY, String text, Runnable c){
+        this.height = height;
+        this.width = width;
+        this.text = text;
+        this.screenY = screenY;
+        this.screenX = screenX;
+        runnable = c;
+    }
+    public void click(){
+        runnable.run();
+    }
+    public boolean wasClicked(int clickX, int clickY){
+        if(clickX >= screenX && clickX <= screenX + width && clickY >= screenY && clickY <= screenY + height){
+            return true;
+        }else return false;
+    }
+    public void draw(Graphics2D g2){
+        g2.setColor(new Color(200, 200, 200));
+        g2.fillRoundRect(screenX, screenY, width, height, 15, 15);
+        g2.setColor(Color.BLACK);
+        g2.drawString(text, screenX + 11, screenY + 30);
+    }
+    public void setDimensions(int height, int width){
+        this.height = height;
+        this.width = width;
+    }
+    public void setScreenCoordinates(int x, int y){
+        this.screenX = x;
+        this.screenY = y;
+    }
+
+}