Pārlūkot izejas kodu

Shop wird korrekt angezeigt, vorerst ohne Aktionen

Jan 6 mēneši atpakaļ
vecāks
revīzija
cbfed6b228

+ 15 - 7
src/main/java/controller/GameController.java

@@ -7,6 +7,7 @@ import controller.factories.InteractiveTileFactory;
 import controller.input.KeyHandler;
 import controller.tiles.interactive.*;
 import controller.tiles.interactive.upgradeable.*;
+import controller.ui.ShopController;
 import model.GameModel;
 import model.GameSaver;
 import model.Inventory;
@@ -18,9 +19,6 @@ import model.tiles.InteractiveTileModel;
 import model.tiles.InteractiveTileType;
 import util.GAMESTATE;
 import view.GamePanel;
-import view.tile.interactive.InteractiveTileView;
-
-import java.awt.*;
 import java.io.Serializable;
 import java.util.ArrayList;
 
@@ -38,10 +36,9 @@ public class GameController implements Runnable, Serializable {
     private transient Thread gameThread;
     private transient RessourceManager ressourceManager;
     private transient GamePanel view;
+    private transient ShopController shopController;
     public transient ArrayList<EntityController> entityControllers;
     public transient ArrayList<InteractiveTileController> interactiveTileControllers;
-    private transient InteractiveTileController draggingTile;
-    private transient int residualShiftX, residualShiftY;
     private transient boolean gameActive;
 
     /**
@@ -56,9 +53,17 @@ public class GameController implements Runnable, Serializable {
         initializeInteractiveTiles();
         initializeEntities();
         initResourceManager();
+        initShopController();
         view.loadMap(worldPath);
     }
 
+    /**
+     * Creates a new ShopController
+     */
+    private void initShopController() {
+        shopController = new ShopController();
+    }
+
     /**
      * Creates a new ResourceManager
      */
@@ -327,9 +332,8 @@ public class GameController implements Runnable, Serializable {
         if (view.gameState == GAMESTATE.INVENTORY) {
             view.gameState = GAMESTATE.PLAY;
             getModel().getInventory().deselectAll();
-        } else if (view.gameState == GAMESTATE.PLAY) {
+        } else
             view.gameState = GAMESTATE.INVENTORY;
-        }
     }
 
     /**
@@ -409,6 +413,7 @@ public class GameController implements Runnable, Serializable {
         loadInteractiveTilesFromSave();
         loadEntitiesFromSave();
         initResourceManager();
+        initShopController();
     }
 
     /**
@@ -450,5 +455,8 @@ public class GameController implements Runnable, Serializable {
     }
 
 
+    public void toggleShop() {
+        getView().toggleShop();
+    }
 }
 

+ 1 - 0
src/main/java/controller/input/KeyHandler.java

@@ -31,6 +31,7 @@ public class KeyHandler implements KeyListener {
             case KeyEvent.VK_DOWN -> controller.zoomInOut(-1);
             case KeyEvent.VK_ESCAPE -> controller.togglePauseOrExitInventory();
             case KeyEvent.VK_E -> controller.toggleInventory();
+            case KeyEvent.VK_R -> controller.toggleShop();
         }
     }
 

+ 4 - 0
src/main/java/controller/ui/ShopController.java

@@ -1,4 +1,8 @@
 package controller.ui;
 
 public class ShopController {
+    public ShopController(){
+
+    }
+
 }

+ 4 - 0
src/main/java/model/Inventory.java

@@ -56,4 +56,8 @@ public class Inventory implements Serializable {
             item.setSelected(false);
         });
     }
+
+    public boolean hasEnough(ITEM_NAME key, int comparedTo) {
+        return itemHashMap.get(key).getCount() >= comparedTo;
+    }
 }

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

@@ -5,5 +5,5 @@ public enum GAMESTATE {
     PAUSED,
     INVENTORY,
     QUIT,
-    MAIN_MENU, SAVE
+    MAIN_MENU, SHOP, SAVE
 }

+ 5 - 0
src/main/java/util/economy/EconomyInfo.java

@@ -10,6 +10,8 @@ public class EconomyInfo {
     private static final String FILE_PATH = "/economy/economy.json";
     private static final Map<InteractiveTileType, EconomyData> economyHashmap = new HashMap<>();
 
+    private EconomyInfo(){};
+
     public static void load() {
         economyHashmap.clear();
         try (InputStream is = EconomyInfo.class.getResourceAsStream(FILE_PATH);
@@ -32,6 +34,9 @@ public class EconomyInfo {
             e.printStackTrace();
         }
     }
+    public static List<InteractiveTileType> getOffers(){
+        return economyHashmap.keySet().stream().toList();
+    }
 
     private static void parseTopLevel(String json) {
         int index = 0;

+ 14 - 1
src/main/java/view/GamePanel.java

@@ -10,6 +10,7 @@ import view.popUpMenu.PopupManager;
 import view.tile.TileManager;
 import util.GAMESTATE;
 import view.ui.InventoryView;
+import view.ui.ShopView;
 import view.ui.UI;
 
 import javax.swing.*;
@@ -48,6 +49,7 @@ public class GamePanel extends JPanel{
     public EntityManager entityManager;
     private PopupManager popupManager;
     private InventoryView inventoryView;
+    private ShopView shopView;
     public Camera camera;
     private MainMenu mainMenu;
 
@@ -61,6 +63,8 @@ public class GamePanel extends JPanel{
         this.entityManager = new EntityManager(this);
         this.popupManager = new PopupManager(this, new ArrayList<>(Arrays.asList(tileManager, entityManager)));
         this.mainMenu = new MainMenu(this);
+        this.shopView = new ShopView(this);
+
         Inventory inventory = gameController.getModel().getInventory();
         this.inventoryView = new InventoryView(inventory);
 
@@ -137,7 +141,9 @@ public class GamePanel extends JPanel{
         entityManager.draw(g2);
         popupManager.drawPopups(g2);
 
-
+        if(gameState == GAMESTATE.SHOP){
+            shopView.drawOverlay(g2);
+        }
         if (gameState == GAMESTATE.INVENTORY) {
             inventoryView.drawInventoryOverlay(g2);
         }
@@ -165,4 +171,11 @@ public class GamePanel extends JPanel{
     public void handleMainMenuClick(int x, int y) {
         mainMenu.handleClick(x,y);
     }
+
+    public void toggleShop() {
+        if(gameState == GAMESTATE.SHOP){
+            gameState = GAMESTATE.PLAY;
+        }else gameState = GAMESTATE.SHOP;
+
+    }
 }

+ 1 - 1
src/main/java/view/tile/interactive/AnimalEnclosureView.java

@@ -7,6 +7,6 @@ public class AnimalEnclosureView extends InteractiveTileView {
 
     public AnimalEnclosureView(GameController gc, InteractiveTileController controller) {
         super( 1, 1, controller, gc.getView().tileManager);
-        setImage("/tiles/animalEnclosure/animalEnclosureTest.png");
+        setImage("/tiles/animal_enclosure/animal_enclosureTest.png");
     }
 }

+ 1 - 1
src/main/java/view/tile/interactive/IronMineView.java

@@ -7,6 +7,6 @@ public class IronMineView extends InteractiveTileView {
 
     public IronMineView(GameController gc, InteractiveTileController controller) {
         super( 1,1, controller, gc.getView().tileManager);
-        setImage("/tiles/mineIron/mineIronTest.png");
+        setImage("/tiles/iron_mine/iron_mineTest.png");
     }
 }

+ 1 - 0
src/main/java/view/ui/InventoryView.java

@@ -20,6 +20,7 @@ public class InventoryView {
     public InventoryView(Inventory inventory){
         this.inventory = inventory;
     }
+
     public void drawInventoryOverlay(Graphics2D g2) {
         slotCount = inventory.getUniqueItemsCount();
 

+ 121 - 0
src/main/java/view/ui/ShopView.java

@@ -1,4 +1,125 @@
 package view.ui;
 
+import model.Inventory;
+import model.items.ITEM_NAME;
+import model.tiles.InteractiveTileType;
+import util.Translator;
+import util.economy.EconomyData;
+import util.economy.EconomyInfo;
+import view.GamePanel;
+
+import javax.imageio.ImageIO;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
 public class ShopView {
+    private GamePanel gamePanel;
+    private List<InteractiveTileType> offers;
+
+    int overlayY = 80;
+    int slotSize = 128;
+    int spacing = 8;
+    int slotCount = 0;
+    int offsetX, offsetY;
+    public ShopView(GamePanel gamePanel){
+        this.gamePanel = gamePanel;
+        offers = EconomyInfo.getOffers();
+    }
+
+    public void drawOverlay(Graphics2D g2) {
+        drawShopOverlay(g2, Translator.translate("menu.shop"));
+
+        drawInventoryOverlay(g2);
+    }
+
+    private void drawInventoryOverlay(Graphics2D g2) {
+        gamePanel.getInventoryView().drawInventoryOverlay(g2);
+    }
+
+    public void drawShopOverlay(Graphics2D g2, String title){
+
+        slotCount = offers.size();
+
+        int overlayWidth = (slotSize + spacing) * slotCount + spacing;
+        int overlayHeight = slotSize + 2* spacing;
+
+        offsetX = gamePanel.getWidth()/2 - overlayWidth/2;
+        offsetY = overlayY + spacing;
+        g2.setColor(new Color(0, 0, 0, 160));
+        g2.fillRoundRect(offsetX, offsetY, overlayWidth, overlayHeight, 25,25);
+        drawTitle(g2, title);
+
+        offsetX += spacing;
+        offsetY += spacing;
+
+        for(InteractiveTileType type : offers){
+            drawOffer(g2, type);
+        }
+
+    }
+
+    private void drawOffer(Graphics2D g2, InteractiveTileType offer){
+        g2.setColor(Color.LIGHT_GRAY);
+        g2.fillRoundRect(offsetX, offsetY, slotSize, slotSize, 25, 25);
+
+        g2.setColor(Color.BLACK);
+        BufferedImage image = getImage("/tiles/" + offer.toString().toLowerCase() + "/" + offer.toString().toLowerCase() + "Test.png");
+        int imageSize = slotSize/2;
+        g2.drawImage(image, offsetX + (slotSize/2 - imageSize/2), offsetY, imageSize, imageSize,null);
+
+        EconomyData data = EconomyInfo.infoOf(offer);
+
+        int stringOffset = slotSize + imageSize;
+        List<Map.Entry<ITEM_NAME, Integer>> entries = new ArrayList<>(data.getCosts().get(1).entrySet());
+
+        for(Map.Entry<ITEM_NAME, Integer> entry : entries){
+            String needed = Translator.translate("item."+entry.getKey()) + ": " + entry.getValue();
+            int strWidth = g2.getFontMetrics().stringWidth(needed);
+            Inventory inventory = gamePanel.gameController.getModel().getInventory();
+
+            if(inventory.hasEnough(entry.getKey(), entry.getValue())){
+                g2.setColor(Color.BLACK);
+            }else{
+                g2.setColor(Color.RED);
+            }
+            g2.drawString(needed, offsetX + (slotSize/2 - strWidth/2), stringOffset);
+            stringOffset += g2.getFontMetrics().getHeight();
+        }
+        offsetX += slotSize + spacing;
+
+        if(offsetX >= gamePanel.getWidth() - slotSize*2){
+            offsetY += slotSize + spacing;
+            offsetX = slotSize + slotSize/2;
+        }
+    }
+
+
+    private void drawTitle(Graphics2D g2, String title){
+        Font defaultF = g2.getFont();
+        g2.setFont(new Font("Arial", Font.BOLD, 50));
+
+        FontMetrics fm = g2.getFontMetrics();
+        int msgWidth = fm.stringWidth(title);
+        g2.setColor(new Color(0, 0, 0, 100));
+        int offset = 100;
+
+        g2.fillRoundRect(gamePanel.screenWidth /2 - msgWidth /2 - offset/2, 40 - fm.getHeight()/2, msgWidth + offset, 50, 25, 25);
+        g2.setColor(Color.WHITE);
+        g2.drawString(title, gamePanel.screenWidth / 2 - msgWidth / 2, 50);
+        g2.setFont(defaultF);
+    }
+
+    public BufferedImage getImage(String imagePath){
+        try {
+            return ImageIO.read(getClass().getResourceAsStream(imagePath));
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
 }

+ 67 - 1
src/main/resources/economy/economy.json

@@ -2,7 +2,7 @@
   "IRON_MINE": {
     "maxLevel": 10,
     "costs": {
-      "1": { "wood": 20 },
+      "1": { "stone": 40, "wood": 20 },
       "2": { "stone": 5, "wood": 10 },
       "3": { "stone": 50, "wood": 50 },
       "4": { "stone": 500, "wood": 100 }
@@ -44,5 +44,71 @@
       "3": 25,
       "4": 20
     }
+  },
+  "BARRACKS": {
+    "maxLevel": 5,
+    "costs": {
+      "1": { "wood": 1 },
+      "2": { "stone": 54, "wood": 40 }
+    },
+    "lighthouseLevels": {
+      "1": 1,
+      "2": 3
+    },
+    "maxAmountPerLighthouseLevel": {
+      "1": 1,
+      "2": 2,
+      "3": 4
+    },
+    "productionTimeInSec": {
+      "1": 30,
+      "2": 28,
+      "3": 25,
+      "4": 20
+    }
+  },
+  "ANIMAL_ENCLOSURE": {
+    "maxLevel": 5,
+    "costs": {
+      "1": { "wood": 1 },
+      "2": { "stone": 54, "wood": 40 }
+    },
+    "lighthouseLevels": {
+      "1": 1,
+      "2": 3
+    },
+    "maxAmountPerLighthouseLevel": {
+      "1": 1,
+      "2": 2,
+      "3": 4
+    },
+    "productionTimeInSec": {
+      "1": 30,
+      "2": 28,
+      "3": 25,
+      "4": 20
+    }
+  },
+  "MINE": {
+    "maxLevel": 5,
+    "costs": {
+      "1": { "wood": 1 },
+      "2": { "stone": 54, "wood": 40 }
+    },
+    "lighthouseLevels": {
+      "1": 1,
+      "2": 3
+    },
+    "maxAmountPerLighthouseLevel": {
+      "1": 1,
+      "2": 2,
+      "3": 4
+    },
+    "productionTimeInSec": {
+      "1": 30,
+      "2": 28,
+      "3": 25,
+      "4": 20
+    }
   }
 }

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

@@ -6,6 +6,7 @@
   "menu.quit": "Beenden",
   "menu.save": "Speichern",
   "menu.main_menu": "Hauptmenu",
+  "menu.shop": "Laden",
   "popup.collect": "Sammeln",
   "popup.upgrade": "Verbessern",
   "item.wood": "Holz",

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

@@ -6,6 +6,7 @@
   "menu.quit": "Quit",
   "menu.save": "Save",
   "menu.main_menu": "Main Menu",
+  "menu.shop": "Shop",
   "popup.collect": "Collect",
   "popup.upgrade": "Upgrade",
   "item.wood": "Wood",

+ 0 - 0
src/main/resources/tiles/animalEnclosure/animalEnclosureTest.png → src/main/resources/tiles/animal_enclosure/animal_enclosureTest.png


+ 0 - 0
src/main/resources/tiles/mineIron/mineIronTest.png → src/main/resources/tiles/iron_mine/iron_mineTest.png


+ 3 - 3
src/test/java/EconomyInfoTest.java

@@ -17,7 +17,7 @@ public class EconomyInfoTest {
 
         Map<Integer, Map<ITEM_NAME, Integer>> costs = data.getCosts();
 
-        Map<ITEM_NAME, Integer> levelCosts2 = costs.get(2);
+        Map<ITEM_NAME, Integer> levelCosts2 = costs.get(1);
 
         int max = data.getMaxLevel();
 
@@ -32,8 +32,8 @@ public class EconomyInfoTest {
         Assertions.assertEquals(25, data.getProductionTime(3));
         Assertions.assertEquals(20, data.getProductionTime(4));
 
-        Assertions.assertEquals(5, stoneAmount);
-        Assertions.assertEquals(10, woodAmount);
+        Assertions.assertEquals(40, stoneAmount);
+        Assertions.assertEquals(20, woodAmount);
 
         Assertions.assertEquals(10, max);
 

+ 67 - 1
src/test/resources/economy/economy.json

@@ -2,7 +2,7 @@
   "IRON_MINE": {
     "maxLevel": 10,
     "costs": {
-      "1": { "wood": 20 },
+      "1": { "stone": 40, "wood": 20 },
       "2": { "stone": 5, "wood": 10 },
       "3": { "stone": 50, "wood": 50 },
       "4": { "stone": 500, "wood": 100 }
@@ -44,5 +44,71 @@
       "3": 25,
       "4": 20
     }
+  },
+  "BARRACKS": {
+    "maxLevel": 5,
+    "costs": {
+      "1": { "wood": 1 },
+      "2": { "stone": 54, "wood": 40 }
+    },
+    "lighthouseLevels": {
+      "1": 1,
+      "2": 3
+    },
+    "maxAmountPerLighthouseLevel": {
+      "1": 1,
+      "2": 2,
+      "3": 4
+    },
+    "productionTimeInSec": {
+      "1": 30,
+      "2": 28,
+      "3": 25,
+      "4": 20
+    }
+  },
+  "ANIMAL_ENCLOSURE": {
+    "maxLevel": 5,
+    "costs": {
+      "1": { "wood": 1 },
+      "2": { "stone": 54, "wood": 40 }
+    },
+    "lighthouseLevels": {
+      "1": 1,
+      "2": 3
+    },
+    "maxAmountPerLighthouseLevel": {
+      "1": 1,
+      "2": 2,
+      "3": 4
+    },
+    "productionTimeInSec": {
+      "1": 30,
+      "2": 28,
+      "3": 25,
+      "4": 20
+    }
+  },
+  "MINE": {
+    "maxLevel": 5,
+    "costs": {
+      "1": { "wood": 1 },
+      "2": { "stone": 54, "wood": 40 }
+    },
+    "lighthouseLevels": {
+      "1": 1,
+      "2": 3
+    },
+    "maxAmountPerLighthouseLevel": {
+      "1": 1,
+      "2": 2,
+      "3": 4
+    },
+    "productionTimeInSec": {
+      "1": 30,
+      "2": 28,
+      "3": 25,
+      "4": 20
+    }
   }
 }