Browse Source

Verbessertes Umherziehen von Tiles, fix(RessourceManager): Läuft nun nur noch wenn das Spiel aktiv ist

Jan 6 months ago
parent
commit
a1f4ef9200

+ 99 - 83
src/main/java/controller/GameController.java

@@ -4,6 +4,7 @@ import controller.entity.EntityController;
 import controller.entity.VillagerController;
 import controller.factories.EntityFactory;
 import controller.factories.InteractiveTileFactory;
+import controller.input.KeyHandler;
 import controller.tiles.interactive.*;
 import controller.tiles.interactive.upgradeable.*;
 import model.GameModel;
@@ -19,6 +20,7 @@ import util.GAMESTATE;
 import view.GamePanel;
 import view.tile.interactive.InteractiveTileView;
 
+import java.awt.*;
 import java.io.Serializable;
 import java.util.ArrayList;
 
@@ -40,7 +42,7 @@ public class GameController implements Runnable, Serializable {
     public transient ArrayList<InteractiveTileController> interactiveTileControllers;
     private transient InteractiveTileController draggingTile;
     private transient int residualShiftX, residualShiftY;
-    private boolean gameActive;
+    private transient boolean gameActive;
 
     /**
      * Constructs a GameController, sets up model, view, input, inventory, entities, and interactive tiles.
@@ -383,73 +385,92 @@ public class GameController implements Runnable, Serializable {
         getView().generateNewWorld();
     }
 
+    private int originalGridX, originalGridY;
+
     /**
-     * Handles dragging shifts in screen coordinates, converting to world-grid movement.
-     *
-     * @param dx pixel shift in x
-     * @param dy pixel shift in y
+     * Called from GameMouseListener.mousePressed when starting a drag on right-click.
      */
-    public void handleTileShift(int dx, int dy) {
-        if (draggingTile == null) {
-            return;
+    public void setDraggingTile(InteractiveTileController tile) {
+        draggingTile = tile;
+        if (draggingTile != null) {
+            InteractiveTileModel model = draggingTile.getModel();
+            originalGridX = model.getWorldGridX();
+            originalGridY = model.getWorldGridY();
+            // Optionally, ensure view's screen coords are set initially
+            InteractiveTileView view = draggingTile.getView();
+            int sx = worldColToScreenX(originalGridX);
+            int sy = worldRowToScreenY(originalGridY);
+            view.setScreenCoordinates(sx, sy);
         }
-        accumulateResidualShift(dx, dy);
-        applyGridShiftIfNeeded();
     }
 
     /**
-     * Accumulates residual pixel shifts before converting to grid movement.
-     *
-     * @param dx pixel delta x
-     * @param dy pixel delta y
+     * Called from GameMouseListener.mousePressed to clear any residual state.
+     * Retained for compatibility; residual shifting no longer used for mouse drag.
      */
-    private void accumulateResidualShift(int dx, int dy) {
-        residualShiftX += dx;
-        residualShiftY += dy;
+    public void resetResidualShift() {
+        // No-op or clear any previous state related to grid-shift dragging
+        // Previously, residualShiftX/Y were used; now smooth drag uses pixel offsets via handleTileShift
     }
 
     /**
-     * Checks if enough residual has accumulated to shift by whole tiles, and applies if valid.
+     * Entry point for dragging movement: called from GameMouseListener.mouseDragged when right mouse button.
+     * dx, dy are screen pixel deltas.
      */
-    private void applyGridShiftIfNeeded() {
-        int tileSize = getView().tileSize;
-        int gridShiftX = residualShiftX / tileSize;
-        int gridShiftY = residualShiftY / tileSize;
-        if (gridShiftX == 0 && gridShiftY == 0) {
+    public void handleTileShift(int dx, int dy) {
+        if (draggingTile == null) {
             return;
         }
-        // Remove used pixels
-        residualShiftX -= gridShiftX * tileSize;
-        residualShiftY -= gridShiftY * tileSize;
-
-        attemptTilePositionShift(gridShiftX, gridShiftY);
+        // Smooth pixel-based move: update view's screen coordinates by delta
+        InteractiveTileView view = draggingTile.getView();
+        view.setScreenCoordinates(view.getScreenX() + dx, view.getScreenY() + dy);
     }
 
     /**
-     * Attempts to shift the dragging tile model by given grid offsets. Reverts residuals if invalid.
-     *
-     * @param gridShiftX number of tiles to shift in x
-     * @param gridShiftY number of tiles to shift in y
+     * Called from GameMouseListener.mouseReleased when ending a drag.
+     * Snaps the tile to grid, validates position, reverts if invalid.
      */
-    private void attemptTilePositionShift(int gridShiftX, int gridShiftY) {
-        InteractiveTileModel model = draggingTile.getModel();
-        int oldX = model.getWorldGridX();
-        int oldY = model.getWorldGridY();
-        int newX = oldX + gridShiftX;
-        int newY = oldY + gridShiftY;
-
-        if (!isValidPosition(newX, newY)) {
-            // Revert residual since shift is invalid
-            int tileSize = getView().tileSize;
-            residualShiftX += gridShiftX * tileSize;
-            residualShiftY += gridShiftY * tileSize;
+    public void handleTileRelease(int mouseX, int mouseY) {
+        if (draggingTile == null) {
             return;
         }
+        InteractiveTileView view = draggingTile.getView();
+        InteractiveTileModel model = draggingTile.getModel();
 
-        model.setWorldGridX(newX);
-        model.setWorldGridY(newY);
-    }
+        GamePanel gp = getView();
+        int tileSize = gp.tileSize;
+        int widthTiles = view.getScaleX();
+        int heightTiles = view.getScaleY();
+
+        // Compute the screen coordinates of the tile's top-left
+        int dropScreenX = view.getScreenX();
+        int dropScreenY = view.getScreenY();
+        // Compute the center pixel position of the tile
+        int centerScreenX = dropScreenX + (widthTiles * tileSize) / 2;
+        int centerScreenY = dropScreenY + (heightTiles * tileSize) / 2;
+        // Convert center to world grid coordinate (floor)
+        int centerGridX = screenToWorldX(centerScreenX);
+        int centerGridY = screenToWorldY(centerScreenY);
+        // Compute top-left grid position so that tile center aligns to centerGrid
+        int targetGridX = centerGridX - (widthTiles / 2);
+        int targetGridY = centerGridY - (heightTiles / 2);
+
+        if (isValidPosition(targetGridX, targetGridY)) {
+            model.setWorldGridX(targetGridX);
+            model.setWorldGridY(targetGridY);
+        } else {
+            // Revert to original grid position
+            model.setWorldGridX(originalGridX);
+            model.setWorldGridY(originalGridY);
+        }
+        // After updating model, reset view’s screen coords to the snapped grid position
+        int snappedScreenX = worldColToScreenX(model.getWorldGridX());
+        int snappedScreenY = worldRowToScreenY(model.getWorldGridY());
+        view.setScreenCoordinates(snappedScreenX, snappedScreenY);
 
+        // Clear dragging state
+        draggingTile = null;
+    }
     /**
      * Checks if draggingTile can be placed at new grid coordinates without out-of-bounds or collision.
      *
@@ -483,29 +504,6 @@ public class GameController implements Runnable, Serializable {
         }
         return true;
     }
-
-    /**
-     * Converts a screen X coordinate to world grid X.
-     *
-     * @param screenX screen X in pixels
-     * @return world grid X coordinate
-     */
-    public int screenToWorldX(int screenX) {
-        GamePanel gp = getView();
-        return (gp.camera.worldX + screenX - gp.camera.screenX) / gp.tileSize;
-    }
-
-    /**
-     * Converts a screen Y coordinate to world grid Y.
-     *
-     * @param screenY screen Y in pixels
-     * @return world grid Y coordinate
-     */
-    public int screenToWorldY(int screenY) {
-        GamePanel gp = getView();
-        return (gp.camera.worldY + screenY - gp.camera.screenY) / gp.tileSize;
-    }
-
     /**
      * Returns the InteractiveTileController at the specified grid coordinates, or null if none.
      *
@@ -533,29 +531,37 @@ public class GameController implements Runnable, Serializable {
         return null;
     }
 
-    /**
-     * Sets the tile currently being dragged.
-     *
-     * @param tile the InteractiveTileController being dragged
-     */
-    public void setDraggingTile(InteractiveTileController tile) {
-        this.draggingTile = tile;
+
+    // Ensure you have utility methods:
+    private int worldColToScreenX(int worldCol) {
+        GamePanel gp = getView();
+        return gp.camera.screenX + worldCol * gp.tileSize - gp.camera.worldX;
     }
 
-    /**
-     * Resets any accumulated residual pixel shift (e.g., when drag ends).
-     */
-    public void resetResidualShift() {
-        residualShiftX = 0;
-        residualShiftY = 0;
+    private int worldRowToScreenY(int worldRow) {
+        GamePanel gp = getView();
+        return gp.camera.screenY + worldRow * gp.tileSize - gp.camera.worldY;
+    }
+
+    // screenToWorldX/Y assumed unchanged
+    public int screenToWorldX(int screenX) {
+        GamePanel gp = getView();
+        return (gp.camera.worldX + screenX - gp.camera.screenX) / gp.tileSize;
+    }
+
+    public int screenToWorldY(int screenY) {
+        GamePanel gp = getView();
+        return (gp.camera.worldY + screenY - gp.camera.screenY) / gp.tileSize;
     }
 
+
     /**
      * Loads interactive tiles and entities from the saved GameModel.
      */
     public void loadGame() {
         loadInteractiveTilesFromSave();
         loadEntitiesFromSave();
+        initResourceManager();
     }
 
     /**
@@ -588,6 +594,12 @@ public class GameController implements Runnable, Serializable {
         }
     }
 
+    /**
+     *
+     */
+    public boolean isTileDragged(InteractiveTileController controller){
+        return draggingTile == controller;
+    }
     /**
      *  Initializes the Main Menu for changing worlds etc.
      */
@@ -602,5 +614,9 @@ public class GameController implements Runnable, Serializable {
     public void addToInventory(Item collected) {
         getModel().getInventory().addToInventory(collected);
     }
+
+    public InteractiveTileController getDraggedTile() {
+        return draggingTile;
+    }
 }
 

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

@@ -1,6 +1,7 @@
 package controller;
 
 import controller.tiles.interactive.InteractiveTileController;
+import util.GAMESTATE;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -23,6 +24,8 @@ public class RessourceManager {
                 scheduler.shutdown();
                 return;
             }
+
+            if(gameController.getView().gameState == GAMESTATE.INVENTORY || gameController.getView().gameState == GAMESTATE.PLAY)
             calculateResources();
         }, 0, 1, TimeUnit.SECONDS);
     }
@@ -34,6 +37,7 @@ public class RessourceManager {
     private void calculateResources() {
         // If interactiveTileControllers can change concurrently, consider making a snapshot:
         List<InteractiveTileController> snapshot;
+
         synchronized(gameController.interactiveTileControllers) {
             snapshot = new ArrayList<>(gameController.interactiveTileControllers);
         }

+ 5 - 2
src/main/java/controller/GameMouseListener.java → src/main/java/controller/input/GameMouseListener.java

@@ -1,5 +1,6 @@
-package controller;
+package controller.input;
 
+import controller.GameController;
 import util.GAMESTATE;
 import view.Camera;
 import view.GamePanel;
@@ -79,7 +80,9 @@ public class GameMouseListener implements MouseListener, MouseMotionListener {
 
     @Override
     public void mouseReleased(MouseEvent e) {
-
+        if (SwingUtilities.isRightMouseButton(e)) {
+            controller.handleTileRelease(e.getX(), e.getY());
+        }
     }
 
     @Override

+ 3 - 1
src/main/java/controller/KeyHandler.java → src/main/java/controller/input/KeyHandler.java

@@ -1,6 +1,8 @@
-package controller;
+package controller.input;
 
 
+import controller.GameController;
+
 import java.awt.event.KeyEvent;
 import java.awt.event.KeyListener;
 

+ 3 - 1
src/main/java/controller/MouseWheelZoom.java → src/main/java/controller/input/MouseWheelZoom.java

@@ -1,4 +1,6 @@
-package controller;
+package controller.input;
+
+import controller.GameController;
 
 import java.awt.event.MouseWheelEvent;
 import java.awt.event.MouseWheelListener;

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

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

+ 1 - 6
src/main/java/view/Camera.java

@@ -1,11 +1,6 @@
 package view;
 
-import controller.KeyHandler;
-import view.entity.EntityView;
-
-import javax.imageio.ImageIO;
-import java.awt.*;
-import java.io.IOException;
+import controller.input.KeyHandler;
 
 public class Camera{
     private GamePanel gamePanel;

+ 7 - 6
src/main/java/view/GamePanel.java

@@ -1,15 +1,16 @@
 package view;
 
 import controller.GameController;
-import controller.GameMouseListener;
-import controller.InteractiveController;
-import controller.MouseWheelZoom;
+import controller.input.GameMouseListener;
+import controller.input.MouseWheelZoom;
 import model.GameSaver;
 import model.Inventory;
 import view.entity.EntityManager;
 import view.popUpMenu.PopupManager;
 import view.tile.TileManager;
 import util.GAMESTATE;
+import view.ui.InventoryView;
+import view.ui.UI;
 
 import javax.swing.*;
 import java.awt.*;
@@ -137,7 +138,6 @@ public class GamePanel extends JPanel{
         popupManager.drawPopups(g2);
 
 
-
         if (gameState == GAMESTATE.INVENTORY) {
             inventoryView.drawInventoryOverlay(g2);
         }
@@ -148,8 +148,9 @@ public class GamePanel extends JPanel{
         }
 
 
-
-        ui.draw(g2);
+        if(gameState == GAMESTATE.PAUSED){
+            ui.draw(g2);
+        }
         g2.dispose();
     }
 

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

@@ -97,12 +97,29 @@ public class TileManager implements RenderingManager {
                 worldRow++;
             }
         }
+        drawAllTiles(g2);
+    }
+
+    /**
+     * Drawing loop: update view coords from model for non-dragged tiles; draw all.
+     */
+    public void drawAllTiles(Graphics2D g2) {
+        // Optionally draw non-dragged first, then dragged to render on top
         for (InteractiveTileController tile : gamePanel.gameController.interactiveTileControllers) {
-            InteractiveTileModel model = tile.getModel();
-            tile.updateCoordinates(worldColToScreenX(model.getWorldGridX()), worldRowToScreenY(model.getWorldGridY()));
-            tile.drawTile(g2);
+            if (!gamePanel.gameController.isTileDragged(tile)) {
+                InteractiveTileModel model = tile.getModel();
+                int sx = worldColToScreenX(model.getWorldGridX());
+                int sy = worldRowToScreenY(model.getWorldGridY());
+                tile.getView().setScreenCoordinates(sx, sy);
+                tile.drawTile(g2);
+            }
+        }
+        if (gamePanel.gameController.getDraggedTile() != null) {
+            // Draw dragged tile on top
+            gamePanel.gameController.getDraggedTile().drawTile(g2);
         }
     }
+
     public int worldColToScreenX(int worldCol) {
         double worldX = worldCol * gamePanel.tileSize; // Reactively use tileSize
         return (int) (worldX - gamePanel.camera.worldX + gamePanel.camera.screenX);

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

@@ -65,6 +65,7 @@ public abstract class InteractiveTileView extends Tile implements Serializable {
         height = newTileSize * scaleY;
         width = newTileSize * scaleX;
     }
+
     public int getScreenX(){
         return screenX;
     }

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

@@ -1,4 +1,4 @@
-package view;
+package view.ui;
 
 import model.Inventory;
 import model.items.Item;

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

@@ -0,0 +1,4 @@
+package view.ui;
+
+public class ShopView {
+}

+ 3 - 4
src/main/java/view/UI.java → src/main/java/view/ui/UI.java

@@ -1,10 +1,11 @@
-package view;
+package view.ui;
 
 import controller.InteractiveController;
 import controller.entity.EntityController;
 import controller.tiles.interactive.InteractiveTileController;
 import util.GAMESTATE;
 import util.Translator;
+import view.GamePanel;
 import view.components.Button;
 import view.popUpMenu.PopupMenu;
 import view.tile.ONCLICKTYPE;
@@ -28,9 +29,7 @@ public class UI {
         g2.setFont(arial_40);
         g2.setColor(Color.white);
 
-        if(gp.gameState == GAMESTATE.PAUSED){
-            drawPauseScreen(g2, Translator.translate("menu.pause"));
-        }
+        drawPauseScreen(g2, Translator.translate("menu.pause"));
     }
     public void handleMenuClick(int screenX, int screenY) {
         for (Button button : activeButtons) {