Browse Source

Villager angefangen und einfache Logik dafür

Jan 6 months ago
parent
commit
25e1f2a259

+ 33 - 5
src/main/java/controller/GameController.java

@@ -1,9 +1,12 @@
 package controller;
 
+import controller.entity.EntityController;
+import controller.entity.VillagerController;
 import controller.tiles.interactive.*;
 import controller.tiles.interactive.upgradeable.*;
 import model.GameModel;
 import model.GameSaver;
+import model.entity.EntityModel;
 import model.items.Item;
 import model.items.ITEM_NAME;
 import model.tiles.InteractiveTileModel;
@@ -17,27 +20,28 @@ public class GameController implements Runnable, Serializable {
     public final String worldPath = "gamefiles/worlds/world_0.txt";
     private GameModel gameModel;
     private boolean running = true;
-    private int fps = 60;
+    public final int fps = 60;
 
 
     private transient KeyHandler keyHandler;
     private transient Thread gameThread;
     private transient GamePanel view;
+    public transient ArrayList<EntityController> entityControllers;
     public transient ArrayList<InteractiveTileController> interactiveTileControllers;
 
     public GameController() {
         this.keyHandler = new KeyHandler(this);
         this.gameModel = new GameModel();
         this.view = new GamePanel(this);
+        entityControllers = new ArrayList<>();
         interactiveTileControllers = new ArrayList<>();
         setStartInventory();
         setupInteractiveTiles();
+        setupEntities();
         view.loadMap(worldPath);
     }
 
     private void setupInteractiveTiles() {
-
-
         LighthouseController lighthouse = new LighthouseController(this, setupInteractiveTileModel(24, 20));
         addInteractiveTile(lighthouse);
 
@@ -55,16 +59,30 @@ public class GameController implements Runnable, Serializable {
 
         SawmillController sawmillController = new SawmillController(this, setupInteractiveTileModel(29, 20));
         addInteractiveTile(sawmillController);
+    }
 
+    private void setupEntities(){
+        VillagerController villager = new VillagerController(this, setupEntityModel(22,20));
+        addEntity(villager);
+    }
+
+    private void addEntity(EntityController entityController) {
+        entityControllers.add(entityController);
     }
 
     private void addInteractiveTile(InteractiveTileController controller) {
-        getView().tileManager.addInteractiveTile(controller);
+        interactiveTileControllers.add(controller);
+    }
+
+    private EntityModel setupEntityModel(int worldX, int worldY) {
+        EntityModel model = new EntityModel(worldX, worldY, getView().tileSize, getView().tileSize);
+        gameModel.addEntityModel(model);
+        return model;
     }
 
     public InteractiveTileModel setupInteractiveTileModel(int worldGridX, int worldGridY){
         InteractiveTileModel model = new InteractiveTileModel(worldGridX, worldGridY, getView().tileSize, getView().tileSize);
-        gameModel.addModel(model);
+        gameModel.addInteractiveTileModel(model);
         return model;
     }
     private void setStartInventory() {
@@ -76,6 +94,7 @@ public class GameController implements Runnable, Serializable {
     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);
@@ -119,6 +138,7 @@ public class GameController implements Runnable, Serializable {
             if (delta >= 1) {
                 update();           // Logic update
                 view.repaint();     // Triggers paintComponent in view
+                moveEntities();
                 delta--;
                 drawCount++;
             }
@@ -129,6 +149,13 @@ public class GameController implements Runnable, Serializable {
             }
         }
     }
+
+    private void moveEntities() {
+        for(EntityController entityController : entityControllers){
+            entityController.convertRepaintSpeedToMovementLogic();
+        }
+    }
+
     public void zoomInOut(int i) {
         view.zoomInOut(i);
         view.closeMenus();
@@ -174,6 +201,7 @@ public class GameController implements Runnable, Serializable {
         interactiveTileControllers = new ArrayList<>();
         setupInteractiveTiles();
     }
+
     public void loadWorld(){
         if(view == null) this.view = new GamePanel(this);
         view.loadMap(worldPath);

+ 20 - 0
src/main/java/controller/InteractiveController.java

@@ -0,0 +1,20 @@
+package controller;
+
+import view.Camera;
+import view.popUpMenu.PopupMenu;
+import view.tile.ONCLICKTYPE;
+
+public interface InteractiveController {
+
+    boolean getClicked();
+
+    ONCLICKTYPE getOnClickType();
+
+    PopupMenu getPopupMenu();
+
+    void unClick();
+
+    boolean isClicked(int screenX, int screenY, Camera camera);
+
+    void click(int screenX, int screenY);
+}

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

@@ -13,15 +13,13 @@ public class MouseListener extends MouseMotionAdapter implements java.awt.event.
     private int startY;
 
     Camera camera;
-    TileManager tileManager;
     GamePanel gamePanel;
     GameController controller;
 
-    public MouseListener(GameController controller, GamePanel gamePanel, Camera camera, TileManager tm) {
+    public MouseListener(GameController controller, GamePanel gamePanel, Camera camera) {
         this.controller = controller;
         this.gamePanel = gamePanel;
         this.camera = camera;
-        this.tileManager = tm;
     }
     @Override
     public void mouseDragged(MouseEvent e) {

+ 0 - 2
src/main/java/controller/MouseWheelZoom.java

@@ -1,7 +1,5 @@
 package controller;
 
-import view.GamePanel;
-
 import java.awt.event.MouseWheelEvent;
 import java.awt.event.MouseWheelListener;
 

+ 0 - 4
src/main/java/controller/VillagerController.java

@@ -1,4 +0,0 @@
-package controller;
-
-public class VillagerController {
-}

+ 123 - 0
src/main/java/controller/entity/EntityController.java

@@ -0,0 +1,123 @@
+package controller.entity;
+
+import controller.GameController;
+import controller.InteractiveController;
+import model.entity.EntityModel;
+import view.Camera;
+import view.entity.EntityView;
+import view.popUpMenu.PopupMenu;
+import view.tile.ONCLICKTYPE;
+
+import java.awt.*;
+
+public abstract class EntityController implements InteractiveController {
+    private GameController gameController;
+    private EntityView view;
+    private EntityModel model;
+    protected ONCLICKTYPE onclicktype;
+
+    private boolean clicked = false;
+    private int screenXClick, screenYClick;
+    private int updateCount;
+
+    public EntityController(EntityModel model, EntityView view, GameController gameController){
+        this.view = view;
+        this.model = model;
+        this.gameController =  gameController;
+    }
+    public void move(int x, int y){
+        model.move(x,y);
+    }
+
+    public void setModel(EntityModel model){
+        this.model = model;
+    }
+
+    public void setView(EntityView view){
+        this.view = view;
+    }
+
+    public boolean isClicked(int mouseScreenX, int mouseScreenY, Camera camera) {
+        double mouseWorldGridX = (camera.worldX + mouseScreenX - camera.screenX) / view.entityController.getTileSize();
+        double mouseWorldGridY = (camera.worldY + mouseScreenY - camera.screenY) / view.entityController.getTileSize();
+
+        return mouseWorldGridX == model.getWorldGridX() &&  mouseWorldGridY == model.getWorldGridY();
+    }
+
+    public int getTileSize(){
+        return gameController.getView().tileSize;
+    }
+
+    public void updateCoordinates(int screenX, int screenY){
+        view.updateCoordinates(screenX, screenY);
+    }
+
+    public void setOnClick(Runnable onClick){
+        onclicktype = ONCLICKTYPE.RUNNABLE;
+        view.setOnClick(onClick);
+    }
+
+    public PopupMenu getPopupMenu(){
+        return view.getPopupMenu();
+    }
+
+    public void setPopupOnClick(PopupMenu popup){
+        onclicktype = ONCLICKTYPE.POPUP;
+        view.setPopupOnClick(popup);
+    }
+
+    public void click(int screenX, int screenY) {
+        if(onclicktype == ONCLICKTYPE.RUNNABLE){
+            view.runOnClick();
+        }else{
+            screenXClick = screenX;
+            screenYClick = screenY;
+            clicked = true;
+        }
+    }
+
+    public EntityModel getModel(){
+        return model;
+    }
+
+    public ONCLICKTYPE getOnClickType(){
+        return onclicktype;
+    }
+
+    public void drawSprite(Graphics2D g2){
+        view.drawSprite(g2);
+    }
+    public void drawPopup(Graphics2D g2){
+        if(onclicktype == ONCLICKTYPE.POPUP &&  clicked == true){
+            view.drawPopUp(screenXClick, screenYClick, g2);
+        }
+    }
+
+    public boolean getClicked(){
+        return clicked;
+    }
+
+    public void unClick() {
+        clicked = false;
+    }
+
+    /**
+     * Called about every second
+     *
+     */
+    public abstract void findPath();
+
+    /**
+     * Called everytime the view is repainted <br>
+     * scales down the default frames per second the view is painted down to 1 sec to avoid too fast movement logic
+     *
+     */
+    public void convertRepaintSpeedToMovementLogic() {
+        if(updateCount >= gameController.fps){
+            findPath();
+            updateCount = 0;
+        }else{
+            updateCount++;
+        }
+    }
+}

+ 31 - 0
src/main/java/controller/entity/VillagerController.java

@@ -0,0 +1,31 @@
+package controller.entity;
+
+import controller.GameController;
+import model.entity.EntityModel;
+import util.Translator;
+import view.entity.VillagerView;
+import view.popUpMenu.EntityMenu;
+import view.popUpMenu.PopupMenu;
+
+public class VillagerController extends EntityController{
+    private int amount = 1;
+    public VillagerController(GameController controller, EntityModel model){
+        super(model, null, controller);
+        setView(new VillagerView(controller, this));
+        PopupMenu popup = new EntityMenu(100, 100, Translator.translate("popup.villager"), this);
+        setPopupOnClick(popup);
+    }
+    @Override
+    public void findPath() {
+        System.out.println("1sec");
+        switch (amount){
+            case 1: move(0, 1);
+            case 2: move(0, -1);
+        }
+        if(amount > 2){
+            amount = 0;
+        }
+        amount++;
+
+    }
+}

+ 11 - 12
src/main/java/controller/tiles/interactive/InteractiveTileController.java

@@ -1,6 +1,7 @@
 package controller.tiles.interactive;
 
 import controller.GameController;
+import controller.InteractiveController;
 import model.tiles.InteractiveTileModel;
 import view.Camera;
 import view.popUpMenu.PopupMenu;
@@ -9,7 +10,7 @@ import view.tile.interactive.InteractiveTileView;
 
 import java.awt.*;
 
-public abstract class InteractiveTileController {
+public abstract class InteractiveTileController implements InteractiveController {
     private GameController gameController;
     private InteractiveTileView view;
     private InteractiveTileModel model;
@@ -35,21 +36,16 @@ public abstract class InteractiveTileController {
     public boolean isClicked(int mouseScreenX, int mouseScreenY, Camera camera) {
         double mouseWorldGridX = (camera.worldX + mouseScreenX - camera.screenX) / view.tileManager.getTileSize();
         double mouseWorldGridY = (camera.worldY + mouseScreenY - camera.screenY) / view.tileManager.getTileSize();
-
-        return mouseWorldGridX == model.getWorldGridX() &&  mouseWorldGridY == model.getWorldGridY();
+        boolean clicked = mouseWorldGridX == model.getWorldGridX() &&  mouseWorldGridY == model.getWorldGridY();
+        return clicked;
     }
 
     public int getTileSize(){
         return gameController.getView().tileSize;
     }
 
-    public void updateCoordinates(int screenX, int screnY){
-        view.updateCoordinates(screenX, screnY);
-    }
-
-    public void setOnClick(Runnable onClick){
-        onclicktype = ONCLICKTYPE.RUNNABLE;
-        view.setOnClick(onClick);
+    public void updateCoordinates(int screenX, int screenY){
+        view.updateCoordinates(screenX, screenY);
     }
 
     public PopupMenu getPopupMenu(){
@@ -65,6 +61,7 @@ public abstract class InteractiveTileController {
         if(onclicktype == ONCLICKTYPE.RUNNABLE){
             view.runOnClick();
         }else{
+
             screenXClick = screenX;
             screenYClick = screenY;
             clicked = true;
@@ -78,12 +75,14 @@ public abstract class InteractiveTileController {
     public ONCLICKTYPE getOnClickType(){
         return onclicktype;
     }
-    public void drawTile(Graphics2D g2, Camera camera){
-        view.drawTile(g2, camera);
+    public void drawTile(Graphics2D g2){
+        view.drawTile(g2);
     }
+
     public void drawPopup(Graphics2D g2){
         if(onclicktype == ONCLICKTYPE.POPUP &&  clicked == true){
             view.drawPopUp(screenXClick, screenYClick, g2);
+
         }
     }
 

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

@@ -1,10 +1,8 @@
 package main;
 
 import controller.GameController;
-import model.GameModel;
 import model.GameSaver;
 import util.Translator;
-import util.WorldGenerator;
 import view.GamePanel;
 
 import javax.swing.*;

+ 9 - 4
src/main/java/model/GameModel.java

@@ -1,5 +1,6 @@
 package model;
 
+import model.entity.EntityModel;
 import model.tiles.InteractiveTileModel;
 
 import java.io.Serializable;
@@ -7,8 +8,8 @@ import java.util.ArrayList;
 
 public class GameModel implements Serializable {
     private Inventory inventory;
-    private ArrayList<InteractiveTileModel> models = new ArrayList<>();
-
+    private ArrayList<InteractiveTileModel> interactiveTileModels = new ArrayList<>();
+    private ArrayList<EntityModel> entityModels = new ArrayList<>();
     public GameModel() {
         inventory = new Inventory();
     }
@@ -17,7 +18,11 @@ public class GameModel implements Serializable {
         return inventory;
     }
 
-    public void addModel(InteractiveTileModel model) {
-        models.add(model);
+    public void addInteractiveTileModel(InteractiveTileModel model) {
+        interactiveTileModels.add(model);
+    }
+
+    public void addEntityModel(EntityModel model) {
+        entityModels.add(model);
     }
 }

+ 0 - 47
src/main/java/model/entity/Entity.java

@@ -1,47 +0,0 @@
-package model.entity;
-
-import controller.KeyHandler;
-import view.GamePanel;
-
-import javax.imageio.ImageIO;
-import java.awt.*;
-import java.io.IOException;
-
-public abstract class Entity {
-    public GamePanel gp;
-
-    private Image optionalPlayerImage;
-
-    public int worldX, worldY;
-    public int speed;
-
-    public int screenX, screenY;
-
-    public Entity(GamePanel gamePanel){
-        gp = gamePanel;
-        screenX = gp.screenWidth/2 - gamePanel.tileSize/2;
-        screenY = gp.screenHeight/2 - gamePanel.tileSize/2;
-
-        setDefaultValues();
-    }
-    private void getEntityImage(String filePath){
-        try{
-            optionalPlayerImage = ImageIO.read(getClass().getResourceAsStream(filePath));
-        }catch (IOException e){
-            e.printStackTrace();
-        }
-    }
-    public abstract void setDefaultValues();
-
-    public void move(int x, int y){
-        worldY += y;
-        worldX += x;
-    }
-
-    public abstract void update();
-
-    public void draw(Graphics2D g2){
-        g2.setColor(Color.WHITE);
-        g2.drawImage(optionalPlayerImage, screenX, screenY, gp.tileSize, gp.tileSize, null);
-    }
-}

+ 62 - 0
src/main/java/model/entity/EntityModel.java

@@ -0,0 +1,62 @@
+package model.entity;
+
+import view.GamePanel;
+
+import java.awt.*;
+
+public class EntityModel {
+    public GamePanel gp;
+
+    private Image optionalImage;
+
+    public int worldX, worldY;
+    public int speed;
+
+    public int screenX, screenY;
+    private boolean clicked;
+    private int height, width;
+
+    public EntityModel(double worldX, double worldY, int width, int height){
+        this.worldX = (int) worldX;
+        this.worldY = (int) worldY;
+        this.width = width;
+        this.height = height;
+    }
+
+    public double getWorldGridX() {
+        return worldX;
+    }
+
+    public double getWorldGridY() {
+        return worldY;
+    }
+
+    public int getWidth() {
+        return width;
+    }
+
+    public int getHeight() {
+        return height;
+    }
+
+    public boolean isClicked() {
+        return clicked;
+    }
+
+    public void setClicked(boolean clicked) {
+        this.clicked = clicked;
+    }
+
+
+    public void move(int x, int y){
+        worldY += y;
+        worldX += x;
+    }
+
+    public int getWorldX() {
+        return worldX;
+    }
+    public int getWorldY() {
+        return worldY;
+    }
+}

+ 17 - 29
src/main/java/view/Camera.java

@@ -1,60 +1,52 @@
 package view;
 
 import controller.KeyHandler;
-import model.entity.Entity;
+import view.entity.EntityView;
 
 import javax.imageio.ImageIO;
 import java.awt.*;
 import java.io.IOException;
 
-public class Camera extends Entity {
+public class Camera{
+    private GamePanel gamePanel;
     private KeyHandler keyH;
 
-    private Image optionalPlayerImage;
-
+    public int worldX, worldY;
+    public int speed;
     public final int screenX;
     public final int screenY;
 
     public Camera(GamePanel gamePanel, KeyHandler keyHandler){
-        super(gamePanel);
+        this.gamePanel = gamePanel;
         this.keyH = keyHandler;
-        screenX = gp.screenWidth/2;
-        screenY = gp.screenHeight/2;
-        //getPlayerImage();
+        screenX = gamePanel.screenWidth/2;
+        screenY = gamePanel.screenHeight/2;
         setDefaultValues();
     }
-
-    private void getPlayerImage(){
-        try{
-            optionalPlayerImage = ImageIO.read(getClass().getResourceAsStream("/sprites/bigrock.png"));
-        }catch (IOException e){
-            e.printStackTrace();
-        }
-    }
     public void setDefaultValues(){
-        worldX = gp.tileSize * 23;
-        worldY = gp.tileSize * 21;
+        worldX = gamePanel.tileSize * 23;
+        worldY = gamePanel.tileSize * 21;
         speed = 4;
     }
 
     public void move(int x, int y) {
         // 1. Calculate world dimensions
-        int worldWidth = gp.maxWorldCol * gp.tileSize;
-        int worldHeight = gp.maxWorldRow * gp.tileSize;
+        int worldWidth = gamePanel.maxWorldCol * gamePanel.tileSize;
+        int worldHeight = gamePanel.maxWorldRow * gamePanel.tileSize;
 
         // 2. Infer zoom factor
-        float zoom = (float) gp.tileSize / gp.originalTileSize;
+        float zoom = (float) gamePanel.tileSize / gamePanel.originalTileSize;
 
         // 3. Calculate visible screen size in world units
-        float viewWidth = gp.screenWidth +zoom;
-        float viewHeight = gp.screenHeight;
+        float viewWidth = gamePanel.screenWidth +zoom;
+        float viewHeight = gamePanel.screenHeight;
 
         float halfViewWidth = viewWidth / 2f;
         float halfViewHeight = viewHeight / 2f;
 
         // 4. Proposed new camera center position
-        float newWorldX = worldX + x;
-        float newWorldY = worldY + y;
+        float newWorldX = (float) (worldX + x);
+        float newWorldY = (float) (worldY + y);
 
         // 5. Clamp the camera to world bounds so no outside area is visible
         newWorldX = clamp(newWorldX, halfViewWidth, worldWidth - halfViewWidth);
@@ -88,8 +80,4 @@ public class Camera extends Entity {
             move(speed, 0);
         }
     }
-    public void draw(Graphics2D g2){
-        g2.setColor(Color.WHITE);
-        g2.drawImage(optionalPlayerImage, screenX, screenY, gp.tileSize, gp.tileSize, null);
-    }
 }

+ 9 - 8
src/main/java/view/GamePanel.java

@@ -5,7 +5,7 @@ import controller.MouseListener;
 import controller.MouseWheelZoom;
 import model.GameSaver;
 import model.Inventory;
-import util.WorldGenerator;
+import view.entity.EntityManager;
 import view.tile.TileManager;
 import util.GAMESTATE;
 
@@ -44,19 +44,25 @@ public class GamePanel extends JPanel{
 
 
     public TileManager tileManager;
+    public EntityManager entityManager;
+
     private InventoryView inventoryView;
     public Camera camera;
 
 
+
     public GamePanel(GameController controller) {
 
         this.gameController = controller; // get from controller
         this.camera = new Camera(this, controller.getKeyHandler());
+
         this.tileManager = new TileManager(this);
+        this.entityManager = new EntityManager(this);
+
         Inventory inventory = gameController.getModel().getInventory();
         this.inventoryView = new InventoryView(inventory);
 
-        MouseListener mdl = new MouseListener(controller, this, camera, tileManager);
+        MouseListener mdl = new MouseListener(controller, this, camera);
         this.addMouseListener(mdl);
         this.addMouseMotionListener(mdl);
         this.addMouseWheelListener(new MouseWheelZoom(controller));
@@ -116,7 +122,7 @@ public class GamePanel extends JPanel{
         g2 = (Graphics2D) g;
 
         tileManager.draw(g2);
-        camera.draw(g2);
+        entityManager.draw(g2);
 
         if (gameState == GAMESTATE.INVENTORY) {
             inventoryView.drawInventoryOverlay(g2);
@@ -129,11 +135,6 @@ public class GamePanel extends JPanel{
         ui.draw(g2);
         g2.dispose();
     }
-    public void update(){
-        if(gameState == GAMESTATE.PLAY || gameState == GAMESTATE.INVENTORY){
-            camera.update();
-        }
-    }
 
     public void generateNewWorld() {
         tileManager.generateNewWorld();

+ 23 - 15
src/main/java/view/UI.java

@@ -1,5 +1,7 @@
 package view;
 
+import controller.InteractiveController;
+import controller.entity.EntityController;
 import controller.tiles.interactive.InteractiveTileController;
 import util.GAMESTATE;
 import util.Translator;
@@ -40,24 +42,30 @@ public class UI {
     }
     public void handleClick(int screenX, int screenY){
         for (InteractiveTileController tile : gp.gameController.interactiveTileControllers) {
-
-            if(tile.getClicked() && tile.getOnClickType() == ONCLICKTYPE.POPUP){
-                PopupMenu popupMenu = tile.getPopupMenu();
-                Button clickedButton = popupMenu.getClickedButton(screenX,screenY);
-                if(clickedButton != null){
-                    clickedButton.click();
-                    tile.unClick();
-                    return;
-                }
-            }
-
-            if (tile.isClicked(screenX, screenY, gp.camera) && !tile.getClicked()) {
-                tile.click(screenX, screenY);
-            }else if(tile.getClicked()){
-                tile.unClick();
+            handleClickForController(tile, screenX, screenY);
+        }
+        for (EntityController controller : gp.gameController.entityControllers) {
+            handleClickForController(controller, screenX, screenY);
+        }
+    }
+    private void handleClickForController(InteractiveController interactiveController, int screenX, int screenY){
+        if(interactiveController.getClicked() && interactiveController.getOnClickType() == ONCLICKTYPE.POPUP){
+            PopupMenu popupMenu = interactiveController.getPopupMenu();
+            Button clickedButton = popupMenu.getClickedButton(screenX,screenY);
+            if(clickedButton != null){
+
+                clickedButton.click();
+                interactiveController.unClick();
+                return;
             }
         }
+        if (interactiveController.isClicked(screenX, screenY, gp.camera) && !interactiveController.getClicked()) {
+            interactiveController.click(screenX, screenY);
+        }else if(interactiveController.getClicked()){
+            interactiveController.unClick();
+        }
     }
+
     private void drawPauseScreen(Graphics2D g2, String message) {
 
 

+ 0 - 7
src/main/java/view/entity/Entity.java

@@ -1,7 +0,0 @@
-package view.entity;
-
-public class Entity {
-
-    public double worldX, worldY;
-    public int speed;
-}

+ 53 - 0
src/main/java/view/entity/EntityManager.java

@@ -0,0 +1,53 @@
+package view.entity;
+
+import controller.entity.EntityController;
+import model.entity.EntityModel;
+import view.GamePanel;
+
+import java.awt.*;
+import java.io.*;
+import java.util.ArrayList;
+
+public class EntityManager {
+    GamePanel gamePanel;
+    private ArrayList<EntityController> entities = new ArrayList<>();
+
+    public EntityManager(GamePanel gp){
+        this.gamePanel = gp;
+        getEntityImages();
+    }
+
+    public void draw(Graphics2D g2){
+        for (EntityController entity : gamePanel.gameController.entityControllers) {
+            EntityModel model = entity.getModel();
+            entity.updateCoordinates(worldColToScreenX(model.getWorldX()), worldRowToScreenY(model.getWorldY()));
+            entity.drawSprite(g2);
+        }
+        for (EntityController entity : gamePanel.gameController.entityControllers) {
+            entity.drawPopup(g2);
+        }
+    }
+    public int getTileSize(){
+        return gamePanel.tileSize;
+    }
+
+    public int worldColToScreenX(double worldCol) {
+        double worldX = worldCol * gamePanel.tileSize; // Reactively use tileSize
+        return (int) (worldX - gamePanel.camera.worldX + gamePanel.camera.screenX);
+    }
+
+    public int worldRowToScreenY(double worldRow) {
+
+        double worldY = worldRow * gamePanel.tileSize; // Reactively use tileSize
+        return (int) (worldY - gamePanel.camera.worldY + gamePanel.camera.screenY);
+    }
+    public void addEntity(EntityController entityController){
+        entities.add(entityController);
+    }
+    public void getEntityImages(){
+
+    }
+    private void setupEntity(EntityView entity) throws IOException {
+
+    }
+}

+ 75 - 0
src/main/java/view/entity/EntityView.java

@@ -0,0 +1,75 @@
+package view.entity;
+
+import controller.GameController;
+import controller.entity.EntityController;
+import view.GamePanel;
+import view.popUpMenu.PopupMenu;
+
+import javax.imageio.ImageIO;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+
+public abstract class EntityView {
+
+    private int width, height;
+    private EntityController controller;
+    public double worldX, worldY;
+    public int speed;
+    public GamePanel gamePanel;
+    public EntityController entityController;
+    public GameController gameController;
+    private int screenX, screenY;
+    private PopupMenu popupMenu;
+    private Runnable onClick;
+    private BufferedImage image;
+
+    public EntityView(int width, int height, GameController controller, EntityController entityController) {
+        this.screenX = 100;
+        this.screenY = 100;
+        this.entityController = entityController;
+        this.width = width;
+        this.height = height;
+        this.gameController = controller;
+    }
+    public void setImage(String imagePath) {
+        try {
+            image = ImageIO.read(getClass().getResourceAsStream(imagePath));
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public void draw(Graphics2D g2) {
+        g2.drawRect(10,10,10,10);
+    }
+
+    public void updateCoordinates(int screenX, int screenY) {
+        this.screenX =  screenX;
+        this.screenY = screenY;
+    }
+
+    public PopupMenu getPopupMenu() {
+        return popupMenu;
+    }
+
+    public void setOnClick(Runnable onClick) {
+        System.out.println("No onclick set!");
+    }
+
+    public void setPopupOnClick(PopupMenu popup) {
+        this.popupMenu = popup;
+    }
+
+    public void runOnClick() {
+
+    }
+
+    public void drawPopUp(int screenXClick, int screenYClick, Graphics2D g2) {
+        popupMenu.draw(screenXClick, screenYClick, g2);
+    }
+
+    public void drawSprite(Graphics2D g2){
+        g2.drawImage(image, screenX, screenY, gameController.getView().tileSize, gameController.getView().tileSize, null);
+    }
+}

+ 9 - 1
src/main/java/view/entity/VillagerView.java

@@ -1,4 +1,12 @@
 package view.entity;
 
-public class VillagerView {
+import controller.GameController;
+import controller.entity.EntityController;
+
+public class VillagerView extends EntityView{
+    public VillagerView(GameController controller, EntityController entityController) {
+        super( controller.getView().tileSize, controller.getView().tileSize, controller, entityController);
+        setImage("/sprites/bigrock.png");
+    }
+
 }

+ 46 - 0
src/main/java/view/popUpMenu/EntityMenu.java

@@ -0,0 +1,46 @@
+package view.popUpMenu;
+
+import controller.entity.EntityController;
+import controller.tiles.interactive.InteractiveTileController;
+import util.Translator;
+import view.components.Button;
+
+import java.awt.*;
+
+public class EntityMenu extends PopupMenu{
+    private EntityController controller;
+    public EntityMenu(int width, int height, String title, EntityController controller) {
+        super(width, height, title);
+        this.controller = controller;
+        addButton( new Button(80, 25, Translator.translate("popup.villager.lumberjack"), this::nothing), 10, 40 );
+    }
+
+    @Override
+    public void draw(int x, int y, Graphics2D g2){
+        FontMetrics fm = g2.getFontMetrics();
+        int msgWidth = fm.stringWidth(title);
+        if(overlayWidth < msgWidth) overlayWidth = msgWidth + 20;
+
+        centerButtons();
+
+        g2.setColor(Color.GRAY);
+        g2.fillRoundRect(x,y, overlayWidth, overlayHeight, 15, 15);
+        g2.setColor(Color.WHITE);
+        g2.drawRoundRect(x,y,overlayWidth,overlayHeight, 15, 15);
+
+        g2.drawString(title, x + ((overlayWidth - msgWidth )/2), y+ 20);
+
+        String levelStr = "Level: ";
+        int lvlStrWidth = fm.stringWidth(levelStr);
+        g2.drawString(levelStr, x + ((overlayWidth - lvlStrWidth )/2), y+ 35);
+        for (Button button : buttonArrayList){
+            button.setRelativeScreenCoordinates(x,y);
+            button.draw(g2);
+        }
+
+    }
+
+    public void nothing(){
+
+    }
+}

+ 4 - 3
src/main/java/view/tile/TileManager.java

@@ -1,7 +1,9 @@
 package view.tile;
 
+import controller.entity.EntityController;
 import controller.tiles.interactive.InteractiveTileController;
 import model.Tile;
+import model.entity.EntityModel;
 import model.tiles.BackgroundTile;
 import model.tiles.InteractiveTileModel;
 import util.WorldGenerator;
@@ -22,7 +24,6 @@ public class TileManager {
         tile = new Tile[10];
         mapTileNum = new int[GamePanel.maxWorldCol][GamePanel.maxWorldRow];
         getTileImage();
-
     }
     public int getTileSize(){
         return gamePanel.tileSize;
@@ -69,7 +70,7 @@ public class TileManager {
         int worldCol = 0;
         int worldRow = 0;
 
-        while (worldCol<gamePanel.maxWorldCol && worldRow < gamePanel.maxWorldRow){
+        while (worldCol< gamePanel.maxWorldCol && worldRow < gamePanel.maxWorldRow){
 
             int tileNum = mapTileNum[worldCol][worldRow];
 
@@ -99,7 +100,7 @@ public class TileManager {
         for (InteractiveTileController tile : gamePanel.gameController.interactiveTileControllers) {
             InteractiveTileModel model = tile.getModel();
             tile.updateCoordinates(worldColToScreenX(model.getWorldGridX()), worldRowToScreenY(model.getWorldGridY()));
-            tile.drawTile(g2, gamePanel.camera);
+            tile.drawTile(g2);
         }
         for (InteractiveTileController tile : gamePanel.gameController.interactiveTileControllers) {
             tile.drawPopup(g2);

+ 2 - 1
src/main/java/view/tile/interactive/InteractiveTileView.java

@@ -43,6 +43,7 @@ public abstract class InteractiveTileView extends Tile implements Serializable {
     public void runOnClick(){
         onClick.run();
     }
+
     public void setPopupOnClick(PopupMenu popup){
         this.popup = popup;
     }
@@ -51,7 +52,7 @@ public abstract class InteractiveTileView extends Tile implements Serializable {
         this.onClick = onClick;
     }
 
-    public void drawTile(Graphics2D g2, Camera camera){
+    public void drawTile(Graphics2D g2){
         g2.drawImage(image, screenX, screenY, controller.getTileSize(), controller.getTileSize(), null);
     }
 

+ 2 - 1
src/main/resources/lang/de_de.json

@@ -15,5 +15,6 @@
   "popup.title.lighthouse": "Leuchtturm",
   "popup.title.iron_mine": "Eisen Mine",
   "popup.title.mine": "Steinbruch",
-  "popup.title.sawmill": "Sägewerk"
+  "popup.title.sawmill": "Sägewerk",
+  "popup.villager": "Dorfbewohner"
 }

+ 2 - 1
src/main/resources/lang/en_us.json

@@ -15,5 +15,6 @@
   "popup.title.lighthouse": "Lighthouse",
   "popup.title.iron_mine": "Iron Mine",
   "popup.title.mine": "Stone Mine",
-  "popup.title.sawmill": "Sawmill"
+  "popup.title.sawmill": "Sawmill",
+  "popup.villager": "Villager"
 }