added java docs to view
This commit is contained in:
		@@ -55,6 +55,11 @@ public class InputSynchronizer {
 | 
			
		||||
        setupInput();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Updates the rotation angle based on user input.
 | 
			
		||||
     *
 | 
			
		||||
     * @param tpf The time per frame.
 | 
			
		||||
     */
 | 
			
		||||
    public void update(float tpf) {
 | 
			
		||||
        if (isRotateLeft && isRotateRight) {
 | 
			
		||||
            return;
 | 
			
		||||
 
 | 
			
		||||
@@ -90,6 +90,10 @@ public class MdgaApp extends SimpleApplication {
 | 
			
		||||
 | 
			
		||||
    public static final int DEBUG_MULTIPLIER = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Constructs a new MdgaApp instance.
 | 
			
		||||
     * Initializes the network connection and client game logic.
 | 
			
		||||
     */
 | 
			
		||||
    public MdgaApp() {
 | 
			
		||||
        networkConnection = new NetworkSupport(this);
 | 
			
		||||
        this.clientGameLogic = new ClientGameLogic(networkConnection);
 | 
			
		||||
@@ -272,14 +276,22 @@ public NotificationSynchronizer getNotificationSynchronizer() {
 | 
			
		||||
     * Prepares the app for a new game cycle.
 | 
			
		||||
     */
 | 
			
		||||
    public void setup() {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the client game logic.
 | 
			
		||||
     *
 | 
			
		||||
     * @return the {@link ClientGameLogic} instance
 | 
			
		||||
     */
 | 
			
		||||
    public ClientGameLogic getGameLogic() {
 | 
			
		||||
        return clientGameLogic;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the executor service.
 | 
			
		||||
     *
 | 
			
		||||
     * @return the {@link ExecutorService} instance
 | 
			
		||||
     */
 | 
			
		||||
    public ExecutorService getExecutor() {
 | 
			
		||||
        if (this.executor == null) {
 | 
			
		||||
            this.executor = Executors.newCachedThreadPool();
 | 
			
		||||
@@ -288,10 +300,23 @@ public ExecutorService getExecutor() {
 | 
			
		||||
        return this.executor;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the network connection.
 | 
			
		||||
     *
 | 
			
		||||
     * @return the {@link ServerConnection} instance
 | 
			
		||||
     */
 | 
			
		||||
    public ServerConnection getNetworkSupport() {
 | 
			
		||||
        return networkConnection;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Updates the resolution settings.
 | 
			
		||||
     *
 | 
			
		||||
     * @param width the new width
 | 
			
		||||
     * @param height the new height
 | 
			
		||||
     * @param imageFactor the new image factor
 | 
			
		||||
     * @param isFullscreen whether the game is in fullscreen mode
 | 
			
		||||
     */
 | 
			
		||||
    public void updateResolution(int width, int height, float imageFactor, boolean isFullscreen) {
 | 
			
		||||
        if (isFullscreen) {
 | 
			
		||||
            int baseWidth = 1280;
 | 
			
		||||
@@ -317,6 +342,9 @@ public void updateResolution(int width, int height, float imageFactor, boolean i
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Restarts the application.
 | 
			
		||||
     */
 | 
			
		||||
    public static void restartApp() {
 | 
			
		||||
        try {
 | 
			
		||||
            String javaBin = System.getProperty("java.home") + "/bin/java";
 | 
			
		||||
@@ -335,11 +363,13 @@ public static void restartApp() {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Cleans up the application after a game.
 | 
			
		||||
     */
 | 
			
		||||
    public void afterGameCleanup() {
 | 
			
		||||
        MainView main = (MainView) mainView;
 | 
			
		||||
 | 
			
		||||
        main.getJoinDialog().disconnect();
 | 
			
		||||
        System.out.println("Disconnecting from server..." + clientGameLogic.isHost());
 | 
			
		||||
        if (clientGameLogic.isHost()) {
 | 
			
		||||
            main.getHostDialog().shutdownServer();
 | 
			
		||||
        }
 | 
			
		||||
@@ -347,14 +377,29 @@ public void afterGameCleanup() {
 | 
			
		||||
        ceremonyView.afterGameCleanup();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the game view.
 | 
			
		||||
     *
 | 
			
		||||
     * @return the {@link GameView} instance
 | 
			
		||||
     */
 | 
			
		||||
    public GameView getGameView() {
 | 
			
		||||
        return gameView;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the timer manager.
 | 
			
		||||
     *
 | 
			
		||||
     * @return the {@link TimerManager} instance
 | 
			
		||||
     */
 | 
			
		||||
    public TimerManager getTimerManager() {
 | 
			
		||||
        return timerManager;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the ceremony view.
 | 
			
		||||
     *
 | 
			
		||||
     * @return the {@link CeremonyView} instance
 | 
			
		||||
     */
 | 
			
		||||
    public CeremonyView getCeremonyView() {
 | 
			
		||||
        return ceremonyView;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,9 @@
 | 
			
		||||
import java.util.logging.Level;
 | 
			
		||||
import java.util.logging.Logger;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The ModelSynchronizer class is responsible for synchronizing the model state with the view and game logic.
 | 
			
		||||
 */
 | 
			
		||||
public class ModelSynchronizer {
 | 
			
		||||
    private static final Logger LOGGER = Logger.getLogger(ModelSynchronizer.class.getName());
 | 
			
		||||
    private MdgaApp app;
 | 
			
		||||
@@ -17,11 +20,19 @@ public class ModelSynchronizer {
 | 
			
		||||
    private BonusCard card;
 | 
			
		||||
    private boolean swap;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Constructor for ModelSynchronizer.
 | 
			
		||||
     *
 | 
			
		||||
     * @param app the MdgaApp instance
 | 
			
		||||
     */
 | 
			
		||||
    ModelSynchronizer(MdgaApp app) {
 | 
			
		||||
        this.app = app;
 | 
			
		||||
        swap = false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handles the end of an animation.
 | 
			
		||||
     */
 | 
			
		||||
    public void animationEnd() {
 | 
			
		||||
        if (app.getNotificationSynchronizer().waitForAnimation) {
 | 
			
		||||
            app.getNotificationSynchronizer().waitForAnimation = false;
 | 
			
		||||
@@ -30,13 +41,24 @@ public void animationEnd() {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Selects a piece or swap based on the current state.
 | 
			
		||||
     *
 | 
			
		||||
     * @param a the first UUID
 | 
			
		||||
     * @param b the second UUID
 | 
			
		||||
     */
 | 
			
		||||
    public void select(UUID a, UUID b) {
 | 
			
		||||
        if (swap) selectSwap(a, b);
 | 
			
		||||
        else selectPiece(a);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Selects a swap between two pieces.
 | 
			
		||||
     *
 | 
			
		||||
     * @param a the first UUID
 | 
			
		||||
     * @param b the second UUID
 | 
			
		||||
     */
 | 
			
		||||
    public void selectSwap(UUID a, UUID b) {
 | 
			
		||||
        // TODO call from somewhere
 | 
			
		||||
        LOGGER.log(Level.INFO, "selectPiece");
 | 
			
		||||
        this.a = a;
 | 
			
		||||
        this.b = b;
 | 
			
		||||
@@ -49,8 +71,12 @@ public void selectSwap(UUID a, UUID b) {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Selects a single piece.
 | 
			
		||||
     *
 | 
			
		||||
     * @param piece the UUID of the piece
 | 
			
		||||
     */
 | 
			
		||||
    public void selectPiece(UUID piece) {
 | 
			
		||||
        // TODO call from somewhere
 | 
			
		||||
        LOGGER.log(Level.INFO, "selectPiece");
 | 
			
		||||
 | 
			
		||||
        this.a = piece;
 | 
			
		||||
@@ -63,8 +89,12 @@ public void selectPiece(UUID piece) {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Selects a bonus card.
 | 
			
		||||
     *
 | 
			
		||||
     * @param card the BonusCard instance
 | 
			
		||||
     */
 | 
			
		||||
    public void selectCard(BonusCard card) {
 | 
			
		||||
        // TODO call from somewhere
 | 
			
		||||
        LOGGER.log(Level.INFO, "selectCard");
 | 
			
		||||
 | 
			
		||||
        this.card = card;
 | 
			
		||||
@@ -78,6 +108,9 @@ public void selectCard(BonusCard card) {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Confirms the current selection.
 | 
			
		||||
     */
 | 
			
		||||
    public void confirm() {
 | 
			
		||||
        LOGGER.log(Level.INFO, "confirm");
 | 
			
		||||
 | 
			
		||||
@@ -105,54 +138,106 @@ public void confirm() {
 | 
			
		||||
        gameView.hideNoPower();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Selects a TSK color.
 | 
			
		||||
     *
 | 
			
		||||
     * @param color the Color instance
 | 
			
		||||
     */
 | 
			
		||||
    public void selectTsk(Color color) {
 | 
			
		||||
        app.getGameLogic().selectTsk(color);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Unselects a TSK color.
 | 
			
		||||
     *
 | 
			
		||||
     * @param color the Color instance
 | 
			
		||||
     */
 | 
			
		||||
    public void unselectTsk(Color color) {
 | 
			
		||||
        app.getGameLogic().deselectTSK(color);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handles the event of rolling dice.
 | 
			
		||||
     */
 | 
			
		||||
    public void rolledDice() {
 | 
			
		||||
        app.getGameLogic().selectDice();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the player's name.
 | 
			
		||||
     *
 | 
			
		||||
     * @param name the player's name
 | 
			
		||||
     */
 | 
			
		||||
    public void setName(String name) {
 | 
			
		||||
        // TODO call from somewhere
 | 
			
		||||
        LOGGER.log(Level.INFO, "setName: {0}", name);
 | 
			
		||||
        app.getGameLogic().selectName(name);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the player's ready status.
 | 
			
		||||
     *
 | 
			
		||||
     * @param ready the ready status
 | 
			
		||||
     */
 | 
			
		||||
    public void setReady(boolean ready) {
 | 
			
		||||
        app.getGameLogic().selectReady(ready);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the host port.
 | 
			
		||||
     *
 | 
			
		||||
     * @param port the host port
 | 
			
		||||
     */
 | 
			
		||||
    public void setHost(int port) {
 | 
			
		||||
        app.getGameLogic().selectJoin("");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the join IP and port.
 | 
			
		||||
     *
 | 
			
		||||
     * @param ip the IP address
 | 
			
		||||
     * @param port the port number
 | 
			
		||||
     */
 | 
			
		||||
    public void setJoin(String ip, int port) {
 | 
			
		||||
        app.getGameLogic().selectJoin(ip);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handles the event of leaving the game.
 | 
			
		||||
     */
 | 
			
		||||
    public void leave() {
 | 
			
		||||
        app.getGameLogic().selectLeave();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Enters a specific game state.
 | 
			
		||||
     *
 | 
			
		||||
     * @param state the MdgaState instance
 | 
			
		||||
     */
 | 
			
		||||
    public void enter(MdgaState state) {
 | 
			
		||||
        LOGGER.log(Level.INFO, "enter: {0}", state);
 | 
			
		||||
        //app.enter(state);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Proceeds to the next game state.
 | 
			
		||||
     */
 | 
			
		||||
    public void next() {
 | 
			
		||||
        app.getGameLogic().selectNext();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the swap state.
 | 
			
		||||
     *
 | 
			
		||||
     * @param swap the swap state
 | 
			
		||||
     */
 | 
			
		||||
    public void setSwap(boolean swap) {
 | 
			
		||||
        this.swap = swap;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Forces an action.
 | 
			
		||||
     */
 | 
			
		||||
    public void force() {
 | 
			
		||||
 | 
			
		||||
        // Implementation needed
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -6,23 +6,47 @@
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The NetworkSupport class provides support for network communication between the client and server.
 | 
			
		||||
 * It implements the MessageListener and ClientStateListener interfaces to handle incoming messages
 | 
			
		||||
 * and client state changes, respectively.
 | 
			
		||||
 */
 | 
			
		||||
public class NetworkSupport implements MessageListener<Client>, ClientStateListener, ServerConnection {
 | 
			
		||||
 | 
			
		||||
    private static final System.Logger LOGGER = System.getLogger(NetworkSupport.class.getName());
 | 
			
		||||
    private final MdgaApp app;
 | 
			
		||||
    private Client client;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Constructor for NetworkSupport.
 | 
			
		||||
     *
 | 
			
		||||
     * @param app the MdgaApp instance
 | 
			
		||||
     */
 | 
			
		||||
    public NetworkSupport(MdgaApp app) {
 | 
			
		||||
        this.app = app;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the MdgaApp instance.
 | 
			
		||||
     *
 | 
			
		||||
     * @return the MdgaApp instance
 | 
			
		||||
     */
 | 
			
		||||
    public MdgaApp getApp() {
 | 
			
		||||
        return this.app;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns whether the client is connected to the server.
 | 
			
		||||
     *
 | 
			
		||||
     * @return true if the client is connected, false otherwise
 | 
			
		||||
     */
 | 
			
		||||
    public boolean isConnected() {
 | 
			
		||||
        return this.client != null && this.client.isConnected();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Connects the client to the server.
 | 
			
		||||
     */
 | 
			
		||||
    public void connect() {
 | 
			
		||||
        if (this.client != null) {
 | 
			
		||||
            throw new IllegalStateException("trying to join a game again");
 | 
			
		||||
@@ -36,6 +60,9 @@ public void connect() {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Disconnects the client from the server.
 | 
			
		||||
     */
 | 
			
		||||
    public void disconnect() {
 | 
			
		||||
        if (this.client != null) {
 | 
			
		||||
            this.client.close();
 | 
			
		||||
@@ -44,6 +71,13 @@ public void disconnect() {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Initializes the network connection to the server.
 | 
			
		||||
     *
 | 
			
		||||
     * @param host the server host
 | 
			
		||||
     * @param port the server port
 | 
			
		||||
     * @throws IOException if an I/O error occurs
 | 
			
		||||
     */
 | 
			
		||||
    public void initNetwork(String host, int port) throws IOException {
 | 
			
		||||
        if (this.client != null) {
 | 
			
		||||
            throw new IllegalStateException("trying to join a game again");
 | 
			
		||||
@@ -55,6 +89,12 @@ public void initNetwork(String host, int port) throws IOException {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handles incoming messages from the server.
 | 
			
		||||
     *
 | 
			
		||||
     * @param client the client
 | 
			
		||||
     * @param message the message
 | 
			
		||||
     */
 | 
			
		||||
    public void messageReceived(Client client, Message message) {
 | 
			
		||||
        LOGGER.log(System.Logger.Level.INFO, "message received from server: {0}", new Object[]{message});
 | 
			
		||||
        if (message instanceof ServerMessage serverMessage) {
 | 
			
		||||
@@ -63,10 +103,21 @@ public void messageReceived(Client client, Message message) {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handles client connection to the server.
 | 
			
		||||
     *
 | 
			
		||||
     * @param client the client
 | 
			
		||||
     */
 | 
			
		||||
    public void clientConnected(Client client) {
 | 
			
		||||
        LOGGER.log(System.Logger.Level.INFO, "Client connected: {0}", new Object[]{client});
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handles client disconnection from the server.
 | 
			
		||||
     *
 | 
			
		||||
     * @param client the client
 | 
			
		||||
     * @param disconnectInfo the disconnect information
 | 
			
		||||
     */
 | 
			
		||||
    public void clientDisconnected(Client client, ClientStateListener.DisconnectInfo disconnectInfo) {
 | 
			
		||||
        LOGGER.log(System.Logger.Level.INFO, "Client {0} disconnected: {1}", new Object[]{client, disconnectInfo});
 | 
			
		||||
        if (this.client != client) {
 | 
			
		||||
@@ -78,6 +129,11 @@ public void clientDisconnected(Client client, ClientStateListener.DisconnectInfo
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sends a message to the server.
 | 
			
		||||
     *
 | 
			
		||||
     * @param message the message
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    public void send(ClientMessage message) {
 | 
			
		||||
        LOGGER.log(System.Logger.Level.INFO, "sending {0}", new Object[]{message});
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,10 @@
 | 
			
		||||
import java.util.Timer;
 | 
			
		||||
import java.util.TimerTask;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The NotificationSynchronizer class is responsible for handling and synchronizing notifications
 | 
			
		||||
 * received from the game logic and updating the application state accordingly.
 | 
			
		||||
 */
 | 
			
		||||
public class NotificationSynchronizer {
 | 
			
		||||
    private final MdgaApp app;
 | 
			
		||||
 | 
			
		||||
@@ -27,10 +31,19 @@ public class NotificationSynchronizer {
 | 
			
		||||
 | 
			
		||||
    public boolean waitForAnimation = false;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Constructs a NotificationSynchronizer with the specified MdgaApp instance.
 | 
			
		||||
     *
 | 
			
		||||
     * @param app the MdgaApp instance
 | 
			
		||||
     */
 | 
			
		||||
    NotificationSynchronizer(MdgaApp app) {
 | 
			
		||||
        this.app = app;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Updates the notification synchronizer by processing notifications from the game logic.
 | 
			
		||||
     * Handles different types of notifications based on the current application state.
 | 
			
		||||
     */
 | 
			
		||||
    public void update() {
 | 
			
		||||
        while (timer.getTimeInSeconds() >= delay) {
 | 
			
		||||
            if (waitForAnimation) {
 | 
			
		||||
@@ -78,6 +91,11 @@ public void update() {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handles notifications when the application is in the MAIN state.
 | 
			
		||||
     *
 | 
			
		||||
     * @param notification the notification to handle
 | 
			
		||||
     */
 | 
			
		||||
    private void handleMain(Notification notification) {
 | 
			
		||||
        if (notification instanceof LobbyDialogNotification) {
 | 
			
		||||
            app.enter(MdgaState.LOBBY);
 | 
			
		||||
@@ -88,6 +106,11 @@ private void handleMain(Notification notification) {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handles notifications when the application is in the LOBBY state.
 | 
			
		||||
     *
 | 
			
		||||
     * @param notification the notification to handle
 | 
			
		||||
     */
 | 
			
		||||
    private void handleLobby(Notification notification) {
 | 
			
		||||
        LobbyView lobbyView = (LobbyView) app.getView();
 | 
			
		||||
 | 
			
		||||
@@ -108,6 +131,11 @@ private void handleLobby(Notification notification) {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handles notifications when the application is in the GAME state.
 | 
			
		||||
     *
 | 
			
		||||
     * @param notification the notification to handle
 | 
			
		||||
     */
 | 
			
		||||
    private void handleGame(Notification notification) {
 | 
			
		||||
        GameView gameView = (GameView) app.getView();
 | 
			
		||||
        GuiHandler guiHandler = gameView.getGuiHandler();
 | 
			
		||||
@@ -256,6 +284,11 @@ public void run() {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handles notifications when the application is in the CEREMONY state.
 | 
			
		||||
     *
 | 
			
		||||
     * @param notification the notification to handle
 | 
			
		||||
     */
 | 
			
		||||
    private void handleCeremony(Notification notification) {
 | 
			
		||||
        if (notification instanceof StartDialogNotification) {
 | 
			
		||||
            app.afterGameCleanup();
 | 
			
		||||
 
 | 
			
		||||
@@ -5,10 +5,18 @@
 | 
			
		||||
public class ActionControl extends InitControl {
 | 
			
		||||
    private final Runnable runnable;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Constructs a new ActionControl object with the specified action.
 | 
			
		||||
     *
 | 
			
		||||
     * @param runnable The action to be performed.
 | 
			
		||||
     */
 | 
			
		||||
    public ActionControl(Runnable runnable) {
 | 
			
		||||
        this.runnable = runnable;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Performs the action associated with this control.
 | 
			
		||||
     */
 | 
			
		||||
    protected void action() {
 | 
			
		||||
        if (null != runnable) {
 | 
			
		||||
            runnable.run();
 | 
			
		||||
 
 | 
			
		||||
@@ -12,6 +12,9 @@
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Random;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * MatrixAnimation class handles the animation of radar and matrix particle effects.
 | 
			
		||||
 */
 | 
			
		||||
public class MatrixAnimation extends ActionControl {
 | 
			
		||||
    private MdgaApp app;
 | 
			
		||||
    private static final Random RANDOM = new Random();
 | 
			
		||||
@@ -22,7 +25,9 @@ public class MatrixAnimation extends ActionControl {
 | 
			
		||||
    private ParticleEmitter radarEmitter = null;
 | 
			
		||||
    private float timeElapsed = 0f;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Enum representing the states of the matrix animation.
 | 
			
		||||
     */
 | 
			
		||||
    private enum MatrixState {
 | 
			
		||||
        RADAR_ON,
 | 
			
		||||
        RADAR_OFF,
 | 
			
		||||
@@ -32,12 +37,22 @@ private enum MatrixState {
 | 
			
		||||
 | 
			
		||||
    private MatrixState state;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Constructor for MatrixAnimation.
 | 
			
		||||
     *
 | 
			
		||||
     * @param app       the application instance
 | 
			
		||||
     * @param radarPos  the position of the radar
 | 
			
		||||
     * @param runnable  the runnable action to be executed
 | 
			
		||||
     */
 | 
			
		||||
    public MatrixAnimation(MdgaApp app, Vector3f radarPos, Runnable runnable) {
 | 
			
		||||
        super(runnable);
 | 
			
		||||
        this.app = app;
 | 
			
		||||
        this.radarPos = radarPos;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Initializes the spatial and sets the initial state to RADAR_ON.
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void initSpatial() {
 | 
			
		||||
        state = MatrixState.RADAR_ON;
 | 
			
		||||
@@ -46,13 +61,17 @@ protected void initSpatial() {
 | 
			
		||||
        radar();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Updates the control based on the time per frame (tpf).
 | 
			
		||||
     *
 | 
			
		||||
     * @param tpf the time per frame
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void controlUpdate(float tpf) {
 | 
			
		||||
        if (!init) return;
 | 
			
		||||
 | 
			
		||||
        timeElapsed += tpf;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        switch (state) {
 | 
			
		||||
            case RADAR_ON -> {
 | 
			
		||||
                if (timeElapsed >= 2f) {
 | 
			
		||||
@@ -72,7 +91,6 @@ protected void controlUpdate(float tpf) {
 | 
			
		||||
                    timeElapsed = 0;
 | 
			
		||||
                    matrix();
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
            case MATRIX_ON -> {
 | 
			
		||||
                if (timeElapsed >= 3f) {
 | 
			
		||||
@@ -98,12 +116,18 @@ protected void controlUpdate(float tpf) {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Turns off all active particle emitters.
 | 
			
		||||
     */
 | 
			
		||||
    private void turnOff() {
 | 
			
		||||
        for (ParticleEmitter particleEmitter : activeEmitter) {
 | 
			
		||||
            particleEmitter.setParticlesPerSec(0f);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Initializes the radar particle emitter.
 | 
			
		||||
     */
 | 
			
		||||
    private void radar() {
 | 
			
		||||
        Material mat = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Particle.j3md");
 | 
			
		||||
        mat.setTexture("Texture", app.getAssetManager().loadTexture("Images/particle/radar_beam.png"));
 | 
			
		||||
@@ -128,6 +152,9 @@ private void radar() {
 | 
			
		||||
        radarEmitter = emitter;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Initializes multiple matrix particle streams.
 | 
			
		||||
     */
 | 
			
		||||
    private void matrix() {
 | 
			
		||||
        for (int i = 0; i < 5; i++) {
 | 
			
		||||
            particleStream(
 | 
			
		||||
@@ -140,7 +167,15 @@ private void matrix() {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Creates a particle stream with the specified parameters.
 | 
			
		||||
     *
 | 
			
		||||
     * @param start     the start color of the particles
 | 
			
		||||
     * @param end       the end color of the particles
 | 
			
		||||
     * @param speedVar  the speed variation of the particles
 | 
			
		||||
     * @param pos       the position of the particles
 | 
			
		||||
     * @param spawnVar  the spawn rate variation of the particles
 | 
			
		||||
     */
 | 
			
		||||
    private void particleStream(ColorRGBA start, ColorRGBA end, float speedVar, Vector3f pos, float spawnVar) {
 | 
			
		||||
        Material mat = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Particle.j3md");
 | 
			
		||||
        mat.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
 | 
			
		||||
@@ -165,6 +200,11 @@ private void particleStream(ColorRGBA start, ColorRGBA end, float speedVar, Vect
 | 
			
		||||
        activeEmitter.add(matrix);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Generates a random position vector.
 | 
			
		||||
     *
 | 
			
		||||
     * @return a random position vector
 | 
			
		||||
     */
 | 
			
		||||
    public static Vector3f getRandomPosition() {
 | 
			
		||||
        // Generate a random angle in radians (0 to 2π)
 | 
			
		||||
        float angle = (float) (2 * Math.PI * RANDOM.nextDouble());
 | 
			
		||||
@@ -180,6 +220,13 @@ public static Vector3f getRandomPosition() {
 | 
			
		||||
        return new Vector3f(x, y, 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Generates a random float between the specified start and end values.
 | 
			
		||||
     *
 | 
			
		||||
     * @param start the start value
 | 
			
		||||
     * @param end   the end value
 | 
			
		||||
     * @return a random float between start and end
 | 
			
		||||
     */
 | 
			
		||||
    public static float getRandomFloat(float start, float end) {
 | 
			
		||||
        if (start > end) {
 | 
			
		||||
            throw new IllegalArgumentException("Start must be less than or equal to end.");
 | 
			
		||||
@@ -187,6 +234,11 @@ public static float getRandomFloat(float start, float end) {
 | 
			
		||||
        return start + RANDOM.nextFloat() * (end - start);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Generates a random color for the matrix particles.
 | 
			
		||||
     *
 | 
			
		||||
     * @return a random ColorRGBA object
 | 
			
		||||
     */
 | 
			
		||||
    public static ColorRGBA generateMatrixColor() {
 | 
			
		||||
        // Red is dominant
 | 
			
		||||
        float red = 0.8f + RANDOM.nextFloat() * 0.2f;  // Red channel: 0.8 to 1.0
 | 
			
		||||
 
 | 
			
		||||
@@ -18,19 +18,31 @@
 | 
			
		||||
 | 
			
		||||
import static com.jme3.material.Materials.LIGHTING;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * ShellAnimation class handles the animation of a shell being fired from a tank.
 | 
			
		||||
 */
 | 
			
		||||
public class ShellAnimation extends ActionControl {
 | 
			
		||||
    private static final float FLYING_DURATION = 1.25f;
 | 
			
		||||
    private static final float FLYING_HEIGHT = 12f;
 | 
			
		||||
    private TankTopControl tankTopControl;
 | 
			
		||||
    private MdgaApp app;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Constructor for ShellAnimation.
 | 
			
		||||
     *
 | 
			
		||||
     * @param tankTopControl the control for the tank top
 | 
			
		||||
     * @param app the application instance
 | 
			
		||||
     * @param actionAfter the action to perform after the animation
 | 
			
		||||
     */
 | 
			
		||||
    public ShellAnimation(TankTopControl tankTopControl, MdgaApp app, Runnable actionAfter) {
 | 
			
		||||
        super(actionAfter);
 | 
			
		||||
        this.tankTopControl = tankTopControl;
 | 
			
		||||
        this.app = app;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Initializes the spatial for the animation.
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void initSpatial() {
 | 
			
		||||
        tankTopControl.rotate(spatial.getLocalTranslation(), this::shoot);
 | 
			
		||||
@@ -38,6 +50,11 @@ protected void initSpatial() {
 | 
			
		||||
        //app.getRootNode().attachChild(createShell());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Calculates the shooting position based on the tank's turret rotation.
 | 
			
		||||
     *
 | 
			
		||||
     * @return the shooting position as a Vector3f
 | 
			
		||||
     */
 | 
			
		||||
    private Vector3f getShootPos() {
 | 
			
		||||
        Vector3f localOffset = new Vector3f(0, -5.4f, 2.9f);
 | 
			
		||||
        Quaternion turretRotation = tankTopControl.getSpatial().getLocalRotation();
 | 
			
		||||
@@ -45,6 +62,9 @@ private Vector3f getShootPos() {
 | 
			
		||||
        return tankTopControl.getSpatial().getLocalTranslation().add(transformedOffset);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handles the shooting action, including sound and visual effects.
 | 
			
		||||
     */
 | 
			
		||||
    private void shoot() {
 | 
			
		||||
        app.getAcousticHandler().playSound(MdgaSound.TANK_SHOOT);
 | 
			
		||||
        Vector3f shootPos = getShootPos();
 | 
			
		||||
@@ -74,6 +94,11 @@ private void shoot() {
 | 
			
		||||
        shell.addControl(new ShellControl(this::hitExplosion, shootPos, spatial.getLocalTranslation(), FLYING_HEIGHT, FLYING_DURATION, app.getAssetManager()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Creates the shell model and sets its initial properties.
 | 
			
		||||
     *
 | 
			
		||||
     * @return the created shell as a Spatial
 | 
			
		||||
     */
 | 
			
		||||
    private Spatial createShell() {
 | 
			
		||||
        Spatial model = app.getAssetManager().loadModel(Asset.shell.getModelPath());
 | 
			
		||||
        model.scale(.16f);
 | 
			
		||||
@@ -98,6 +123,9 @@ private Spatial createShell() {
 | 
			
		||||
        return model;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handles the explosion effect when the shell hits a target.
 | 
			
		||||
     */
 | 
			
		||||
    private void hitExplosion() {
 | 
			
		||||
        app.getAcousticHandler().playSound(MdgaSound.TANK_EXPLOSION);
 | 
			
		||||
        createEffect(
 | 
			
		||||
@@ -113,6 +141,21 @@ private void hitExplosion() {
 | 
			
		||||
        app.getTimerManager().addTask(0.8f, super::action);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Creates a particle effect at the specified position.
 | 
			
		||||
     *
 | 
			
		||||
     * @param shootPos the position to create the effect
 | 
			
		||||
     * @param image the image to use for the particles
 | 
			
		||||
     * @param x the number of columns in the texture
 | 
			
		||||
     * @param y the number of rows in the texture
 | 
			
		||||
     * @param startSize the initial size of the particles
 | 
			
		||||
     * @param endSize the final size of the particles
 | 
			
		||||
     * @param velocity the initial velocity of the particles
 | 
			
		||||
     * @param lowLife the minimum lifetime of the particles
 | 
			
		||||
     * @param highLife the maximum lifetime of the particles
 | 
			
		||||
     * @param start the starting color of the particles
 | 
			
		||||
     * @param end the ending color of the particles
 | 
			
		||||
     */
 | 
			
		||||
    private void createEffect(Vector3f shootPos,
 | 
			
		||||
                              String image,
 | 
			
		||||
                              int x, int y,
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,9 @@
 | 
			
		||||
import com.jme3.math.FastMath;
 | 
			
		||||
import com.jme3.math.Vector3f;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * ShellControl is responsible for controlling the movement and visual effects of a shell.
 | 
			
		||||
 */
 | 
			
		||||
public class ShellControl extends ActionControl {
 | 
			
		||||
    private final Vector3f shootPos;
 | 
			
		||||
    private final Vector3f endPos;
 | 
			
		||||
@@ -17,6 +20,16 @@ public class ShellControl extends ActionControl {
 | 
			
		||||
    private ParticleEmitter emitter;
 | 
			
		||||
    private AssetManager assetManager;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Constructs a new ShellControl.
 | 
			
		||||
     *
 | 
			
		||||
     * @param runnable the action to perform when the shell reaches its destination
 | 
			
		||||
     * @param shootPos the starting position of the shell
 | 
			
		||||
     * @param endPos the ending position of the shell
 | 
			
		||||
     * @param height the height of the shell's trajectory
 | 
			
		||||
     * @param duration the duration of the shell's flight
 | 
			
		||||
     * @param assetManager the asset manager to load resources
 | 
			
		||||
     */
 | 
			
		||||
    public ShellControl(Runnable runnable, Vector3f shootPos, Vector3f endPos, float height, float duration, AssetManager assetManager) {
 | 
			
		||||
        super(runnable);
 | 
			
		||||
        this.shootPos = shootPos;
 | 
			
		||||
@@ -26,6 +39,9 @@ public ShellControl(Runnable runnable, Vector3f shootPos, Vector3f endPos, float
 | 
			
		||||
        this.assetManager = assetManager;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Initializes the spatial with the necessary controls and particle emitter.
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void initSpatial() {
 | 
			
		||||
        spatial.addControl(new MoveControl(
 | 
			
		||||
@@ -47,6 +63,9 @@ protected void initSpatial() {
 | 
			
		||||
        createEmitter();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Creates and configures the particle emitter for the shell trail.
 | 
			
		||||
     */
 | 
			
		||||
    private void createEmitter() {
 | 
			
		||||
        emitter = new ParticleEmitter("ShellTrail", ParticleMesh.Type.Triangle, 200);
 | 
			
		||||
        Material mat = new Material(assetManager, "Common/MatDefs/Misc/Particle.j3md");
 | 
			
		||||
@@ -74,6 +93,11 @@ private void createEmitter() {
 | 
			
		||||
        spatial.getParent().attachChild(emitter);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Updates the control, adjusting the shell's rotation and emitter position.
 | 
			
		||||
     *
 | 
			
		||||
     * @param tpf time per frame
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void controlUpdate(float tpf) {
 | 
			
		||||
        Vector3f direction = spatial.getLocalTranslation().subtract(oldPos).normalize();
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,10 @@
 | 
			
		||||
import com.jme3.renderer.Camera;
 | 
			
		||||
import pp.mdga.client.MdgaApp;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * OutlineOEControl class extends OutlineControl to manage outline colors and widths
 | 
			
		||||
 * for own and enemy objects, including hover and select states.
 | 
			
		||||
 */
 | 
			
		||||
public class OutlineOEControl extends OutlineControl{
 | 
			
		||||
    private static final ColorRGBA OUTLINE_OWN_COLOR = ColorRGBA.White;
 | 
			
		||||
    private static final ColorRGBA OUTLINE_ENEMY_COLOR = ColorRGBA.Red;
 | 
			
		||||
@@ -16,6 +20,13 @@ public class OutlineOEControl extends OutlineControl{
 | 
			
		||||
    private static final int OUTLINE_HOVER_WIDTH = 8;
 | 
			
		||||
    private static final int OUTLINE_SELECT_WIDTH = 10;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Constructor for OutlineOEControl.
 | 
			
		||||
     *
 | 
			
		||||
     * @param app the MdgaApp instance
 | 
			
		||||
     * @param fpp the FilterPostProcessor instance
 | 
			
		||||
     * @param cam the Camera instance
 | 
			
		||||
     */
 | 
			
		||||
    public OutlineOEControl(MdgaApp app, FilterPostProcessor fpp, Camera cam){
 | 
			
		||||
        super(app, fpp, cam,
 | 
			
		||||
          OUTLINE_OWN_COLOR, OUTLINE_HIGHLIGHT_WIDTH,
 | 
			
		||||
@@ -24,6 +35,9 @@ public OutlineOEControl(MdgaApp app, FilterPostProcessor fpp, Camera cam){
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the outline colors and enables selection for own objects.
 | 
			
		||||
     */
 | 
			
		||||
    public void selectableOwn(){
 | 
			
		||||
        setHighlightColor(OUTLINE_OWN_COLOR);
 | 
			
		||||
        setHoverColor(OUTLINE_OWN_HOVER_COLOR);
 | 
			
		||||
@@ -31,6 +45,9 @@ public void selectableOwn(){
 | 
			
		||||
        selectableOn();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the outline colors and enables selection for enemy objects.
 | 
			
		||||
     */
 | 
			
		||||
    public void selectableEnemy(){
 | 
			
		||||
        setHighlightColor(OUTLINE_ENEMY_COLOR);
 | 
			
		||||
        setHoverColor(OUTLINE_ENEMY_HOVER_COLOR);
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,9 @@
 | 
			
		||||
 | 
			
		||||
import static pp.mdga.client.Util.linInt;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Controls the rotation of the tank's top part to face an enemy position.
 | 
			
		||||
 */
 | 
			
		||||
public class TankTopControl extends InitControl {
 | 
			
		||||
 | 
			
		||||
    private float timer = 0; // Time elapsed
 | 
			
		||||
@@ -16,6 +19,11 @@ public class TankTopControl extends InitControl {
 | 
			
		||||
    private float endAngle = 0;
 | 
			
		||||
    private Runnable actionAfter = null;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Updates the control each frame.
 | 
			
		||||
     *
 | 
			
		||||
     * @param tpf Time per frame
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void controlUpdate(float tpf) {
 | 
			
		||||
        if (!rotating) return;
 | 
			
		||||
@@ -43,6 +51,12 @@ protected void controlUpdate(float tpf) {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Initiates the rotation of the tank's top part to face the enemy position.
 | 
			
		||||
     *
 | 
			
		||||
     * @param enemyPos The position of the enemy
 | 
			
		||||
     * @param actionAfter The action to execute after the rotation is complete
 | 
			
		||||
     */
 | 
			
		||||
    public void rotate(Vector3f enemyPos, Runnable actionAfter) {
 | 
			
		||||
        if (spatial == null) throw new RuntimeException("spatial is null");
 | 
			
		||||
 | 
			
		||||
@@ -62,6 +76,12 @@ public void rotate(Vector3f enemyPos, Runnable actionAfter) {
 | 
			
		||||
        this.actionAfter = actionAfter; // Store the action to execute after rotation
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Calculates the angle to the enemy position.
 | 
			
		||||
     *
 | 
			
		||||
     * @param enemyPos The position of the enemy
 | 
			
		||||
     * @return The angle to the enemy in degrees
 | 
			
		||||
     */
 | 
			
		||||
    private float getEnemyAngle(Vector3f enemyPos) {
 | 
			
		||||
        // Direction to the enemy in the XY plane
 | 
			
		||||
        Vector3f direction = enemyPos.subtract(spatial.getLocalTranslation());
 | 
			
		||||
@@ -82,6 +102,11 @@ private float getEnemyAngle(Vector3f enemyPos) {
 | 
			
		||||
        return (float) Math.toDegrees(angle); // Return the absolute angle in degrees
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Calculates the tank's current angle.
 | 
			
		||||
     *
 | 
			
		||||
     * @return The tank's current angle in degrees
 | 
			
		||||
     */
 | 
			
		||||
    private float getOwnAngle() {
 | 
			
		||||
        // Tank's forward direction in the XY plane
 | 
			
		||||
        Vector3f forward = spatial.getLocalRotation().mult(Vector3f.UNIT_Y);
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,10 @@
 | 
			
		||||
import pp.mdga.client.MdgaApp;
 | 
			
		||||
import pp.mdga.client.board.OutlineControl;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * CardControl class extends OutlineControl to manage the visual representation
 | 
			
		||||
 * and behavior of a card in the game.
 | 
			
		||||
 */
 | 
			
		||||
public class CardControl extends OutlineControl {
 | 
			
		||||
 | 
			
		||||
    private static final ColorRGBA HIGHLIGHT_COLOR = ColorRGBA.Yellow;
 | 
			
		||||
@@ -24,10 +28,17 @@ public class CardControl extends OutlineControl {
 | 
			
		||||
    private static final ColorRGBA SELECT_COLOR = ColorRGBA.Blue;
 | 
			
		||||
    private static final int SELECT_WIDTH = 13;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    private Node root;
 | 
			
		||||
    private BitmapText num;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Constructor for CardControl.
 | 
			
		||||
     *
 | 
			
		||||
     * @param app  the application instance
 | 
			
		||||
     * @param fpp  the FilterPostProcessor instance
 | 
			
		||||
     * @param cam  the Camera instance
 | 
			
		||||
     * @param root the root Node
 | 
			
		||||
     */
 | 
			
		||||
    public CardControl(MdgaApp app, FilterPostProcessor fpp, Camera cam, Node root) {
 | 
			
		||||
        super(app, fpp, cam,
 | 
			
		||||
            HIGHLIGHT_COLOR, HIGHLIGHT_WIDTH,
 | 
			
		||||
@@ -37,12 +48,16 @@ public CardControl(MdgaApp app, FilterPostProcessor fpp, Camera cam, Node root)
 | 
			
		||||
 | 
			
		||||
        this.root = root;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        Node rootNum = createNum();
 | 
			
		||||
        rootNum.setLocalTranslation(new Vector3f(0.35f, 0.8f, 0));
 | 
			
		||||
        root.attachChild(rootNum);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Creates a Node containing a number and a circle geometry.
 | 
			
		||||
     *
 | 
			
		||||
     * @return the created Node
 | 
			
		||||
     */
 | 
			
		||||
    private Node createNum() {
 | 
			
		||||
        Node rootNum = new Node("root Num");
 | 
			
		||||
        Geometry circle = new Geometry("circle", new Sphere(20, 20, 1));
 | 
			
		||||
@@ -63,18 +78,30 @@ private Node createNum() {
 | 
			
		||||
        return rootNum;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the number displayed on the card.
 | 
			
		||||
     *
 | 
			
		||||
     * @param num the number to display
 | 
			
		||||
     */
 | 
			
		||||
    public void setNumCard(int num) {
 | 
			
		||||
        this.num.setText(String.valueOf(num));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the root Node of the card.
 | 
			
		||||
     *
 | 
			
		||||
     * @return the root Node
 | 
			
		||||
     */
 | 
			
		||||
    public Node getRoot() {
 | 
			
		||||
        return root;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Initializes the spatial properties of the card.
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    public void initSpatial() {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private final static Vector3f HIGHLIGHT_Y = new Vector3f(0, 0.4f, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,10 @@
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * CardLayer is an application state that manages the rendering and updating of card objects
 | 
			
		||||
 * in a separate viewport with post-processing effects.
 | 
			
		||||
 */
 | 
			
		||||
public class CardLayer extends AbstractAppState {
 | 
			
		||||
 | 
			
		||||
    public static final int SHADOWMAP_SIZE = 1024 * 8;
 | 
			
		||||
@@ -40,7 +44,13 @@ public class CardLayer extends AbstractAppState {
 | 
			
		||||
    DirectionalLight sun;
 | 
			
		||||
    ComposeFilter compose;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Constructs a new CardLayer with the specified post-processor, camera, and background texture.
 | 
			
		||||
     *
 | 
			
		||||
     * @param fpp the FilterPostProcessor to use for post-processing effects
 | 
			
		||||
     * @param overlayCam the Camera to use for the overlay
 | 
			
		||||
     * @param backTexture the Texture2D to use as the background texture
 | 
			
		||||
     */
 | 
			
		||||
    public CardLayer(FilterPostProcessor fpp, Camera overlayCam, Texture2D backTexture) {
 | 
			
		||||
        this.overlayCam = overlayCam;
 | 
			
		||||
        this.fpp = fpp;
 | 
			
		||||
@@ -58,6 +68,12 @@ public CardLayer(FilterPostProcessor fpp, Camera overlayCam, Texture2D backTextu
 | 
			
		||||
        root = new Node("Under gui viewport Root");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Initializes the CardLayer, setting up the viewport, filters, and lighting.
 | 
			
		||||
     *
 | 
			
		||||
     * @param stateManager the AppStateManager managing this state
 | 
			
		||||
     * @param app the Application instance
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    public void initialize(AppStateManager stateManager, Application app) {
 | 
			
		||||
        this.app = app;
 | 
			
		||||
@@ -84,26 +100,35 @@ public void initialize(AppStateManager stateManager, Application app) {
 | 
			
		||||
        if (!init) init = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Shuts down the CardLayer, removing filters, lights, and clearing buffers.
 | 
			
		||||
     */
 | 
			
		||||
    public void shutdown() {
 | 
			
		||||
//        view.clearProcessors();
 | 
			
		||||
        fpp.removeFilter(dlsf);
 | 
			
		||||
        dlsf = null;
 | 
			
		||||
        root.removeLight(sun);
 | 
			
		||||
        fpp.removeFilter(fxaaFilter);
 | 
			
		||||
//        fpp.removeFilter(compose);
 | 
			
		||||
        view.detachScene(root);
 | 
			
		||||
//        app.getRenderManager().removeMainView(view);
 | 
			
		||||
 | 
			
		||||
        cardBuffer.clear();
 | 
			
		||||
        root.detachAllChildren();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Renders the CardLayer, updating the geometric state of the root node.
 | 
			
		||||
     *
 | 
			
		||||
     * @param rm the RenderManager handling the rendering
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    public void render(RenderManager rm) {
 | 
			
		||||
        root.updateGeometricState();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Updates the CardLayer, attaching buffered cards to the root node and updating its logical state.
 | 
			
		||||
     *
 | 
			
		||||
     * @param tpf time per frame
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    public void update(float tpf) {
 | 
			
		||||
        if (init && !cardBuffer.isEmpty()) {
 | 
			
		||||
@@ -115,19 +140,39 @@ public void update(float tpf) {
 | 
			
		||||
        root.updateLogicalState(tpf);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Adds a spatial card to the CardLayer.
 | 
			
		||||
     *
 | 
			
		||||
     * @param card the Spatial card to add
 | 
			
		||||
     */
 | 
			
		||||
    public void addSpatial(Spatial card) {
 | 
			
		||||
        if (root == null) cardBuffer.add(card);
 | 
			
		||||
        else root.attachChild(card);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Deletes a spatial card from the CardLayer.
 | 
			
		||||
     *
 | 
			
		||||
     * @param spatial the Spatial card to delete
 | 
			
		||||
     */
 | 
			
		||||
    public void deleteSpatial(Spatial spatial) {
 | 
			
		||||
        root.detachChild(spatial);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the overlay camera used by the CardLayer.
 | 
			
		||||
     *
 | 
			
		||||
     * @return the overlay camera
 | 
			
		||||
     */
 | 
			
		||||
    public Camera getOverlayCam() {
 | 
			
		||||
        return overlayCam;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the root node of the CardLayer.
 | 
			
		||||
     *
 | 
			
		||||
     * @return the root node
 | 
			
		||||
     */
 | 
			
		||||
    public Node getRootNode() {
 | 
			
		||||
        return root;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,9 @@
 | 
			
		||||
 | 
			
		||||
import java.util.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Handles the card layer in the GUI, including card management and dice control.
 | 
			
		||||
 */
 | 
			
		||||
public class CardLayerHandler {
 | 
			
		||||
    private static final Vector3f START = new Vector3f(-1.8f, -3.5f, 0);
 | 
			
		||||
    private static final Vector3f MARGIN = new Vector3f(1.8f, 0, 0);
 | 
			
		||||
@@ -36,12 +39,21 @@ public class CardLayerHandler {
 | 
			
		||||
    private BonusCard cardSelect = null;
 | 
			
		||||
    private boolean show = false;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Constructs a CardLayerHandler.
 | 
			
		||||
     *
 | 
			
		||||
     * @param app the application instance
 | 
			
		||||
     * @param backTexture the background texture
 | 
			
		||||
     */
 | 
			
		||||
    public CardLayerHandler(MdgaApp app, Texture2D backTexture) {
 | 
			
		||||
        this.app = app;
 | 
			
		||||
        this.fpp = new FilterPostProcessor(app.getAssetManager());
 | 
			
		||||
        this.backTexture = backTexture;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Initializes the card layer and dice control.
 | 
			
		||||
     */
 | 
			
		||||
    public void init() {
 | 
			
		||||
        cardLayerCamera = createOverlayCam();
 | 
			
		||||
        cardLayer = new CardLayer(fpp, cardLayerCamera, backTexture);
 | 
			
		||||
@@ -51,6 +63,9 @@ public void init() {
 | 
			
		||||
        diceControl.create(new Vector3f(0, 0, 0), 1f, false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Shuts down the card layer and clears selectable cards.
 | 
			
		||||
     */
 | 
			
		||||
    public void shutdown() {
 | 
			
		||||
        clearSelectableCards();
 | 
			
		||||
        if (cardLayer != null) {
 | 
			
		||||
@@ -60,11 +75,20 @@ public void shutdown() {
 | 
			
		||||
        cardLayer = null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Rolls the dice with a specified number and action to perform after rolling.
 | 
			
		||||
     *
 | 
			
		||||
     * @param rollNum the number to roll (must be between 1 and 6)
 | 
			
		||||
     * @param actionAfter the action to perform after rolling
 | 
			
		||||
     */
 | 
			
		||||
    public void rollDice(int rollNum, Runnable actionAfter) {
 | 
			
		||||
        if (!(1 <= rollNum && rollNum <= 6)) throw new RuntimeException("rollNum is not in the range [1,6]");
 | 
			
		||||
        diceControl.rollDice(rollNum, actionAfter);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Shows the dice on the card layer.
 | 
			
		||||
     */
 | 
			
		||||
    public void showDice() {
 | 
			
		||||
        if (show) return;
 | 
			
		||||
        show = true;
 | 
			
		||||
@@ -72,11 +96,19 @@ public void showDice() {
 | 
			
		||||
        diceControl.spin();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Hides the dice from the card layer.
 | 
			
		||||
     */
 | 
			
		||||
    public void hideDice() {
 | 
			
		||||
        show = false;
 | 
			
		||||
        diceControl.hide();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Adds a card to the card layer.
 | 
			
		||||
     *
 | 
			
		||||
     * @param card the card to add
 | 
			
		||||
     */
 | 
			
		||||
    public void addCard(BonusCard card) {
 | 
			
		||||
        if (card == BonusCard.HIDDEN) throw new RuntimeException("Can't add hidden card to GUI");
 | 
			
		||||
 | 
			
		||||
@@ -90,6 +122,11 @@ public void addCard(BonusCard card) {
 | 
			
		||||
        updateCard();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Removes a card from the card layer.
 | 
			
		||||
     *
 | 
			
		||||
     * @param card the card to remove
 | 
			
		||||
     */
 | 
			
		||||
    public void removeCard(BonusCard card) {
 | 
			
		||||
        if (bonusCardControlMap.containsKey(card)) {
 | 
			
		||||
            bonusCardIntegerMap.put(card, bonusCardIntegerMap.get(card) - 1);
 | 
			
		||||
@@ -102,6 +139,9 @@ public void removeCard(BonusCard card) {
 | 
			
		||||
        } else throw new RuntimeException("card is not in bonusCardControlMap");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Clears all selectable cards.
 | 
			
		||||
     */
 | 
			
		||||
    public void clearSelectableCards() {
 | 
			
		||||
        for (CardControl control : selectableCards) {
 | 
			
		||||
            control.selectableOff();
 | 
			
		||||
@@ -110,6 +150,9 @@ public void clearSelectableCards() {
 | 
			
		||||
        cardSelect = null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Updates the card layer with the current cards.
 | 
			
		||||
     */
 | 
			
		||||
    private void updateCard() {
 | 
			
		||||
        for (BonusCard card : bonusCardControlMap.keySet()) {
 | 
			
		||||
            CardControl control = bonusCardControlMap.get(card);
 | 
			
		||||
@@ -126,6 +169,11 @@ private void updateCard() {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the selectable cards.
 | 
			
		||||
     *
 | 
			
		||||
     * @param select the list of cards to set as selectable
 | 
			
		||||
     */
 | 
			
		||||
    public void setSelectableCards(List<BonusCard> select) {
 | 
			
		||||
        for (BonusCard card : select) {
 | 
			
		||||
            selectableCards.add(bonusCardControlMap.get(card));
 | 
			
		||||
@@ -135,6 +183,11 @@ public void setSelectableCards(List<BonusCard> select) {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Selects a card control.
 | 
			
		||||
     *
 | 
			
		||||
     * @param cardControl the card control to select
 | 
			
		||||
     */
 | 
			
		||||
    public void selectCard(CardControl cardControl) {
 | 
			
		||||
        if (cardControl.isSelected()) {
 | 
			
		||||
            cardControl.selectOff();
 | 
			
		||||
@@ -150,28 +203,48 @@ public void selectCard(CardControl cardControl) {
 | 
			
		||||
        app.getModelSynchronize().selectCard(cardSelect);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the card layer camera.
 | 
			
		||||
     *
 | 
			
		||||
     * @return the card layer camera
 | 
			
		||||
     */
 | 
			
		||||
    public Camera getCardLayerCamera() {
 | 
			
		||||
        return cardLayerCamera;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Adds a shield symbol to the card layer.
 | 
			
		||||
     */
 | 
			
		||||
    public void shield() {
 | 
			
		||||
        SymbolControl control = createSymbol(Asset.shieldSymbol);
 | 
			
		||||
        cardLayer.addSpatial(control.getSpatial());
 | 
			
		||||
        control.shield();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Adds a swap symbol to the card layer.
 | 
			
		||||
     */
 | 
			
		||||
    public void swap() {
 | 
			
		||||
        SymbolControl control = createSymbol(Asset.swapSymbol);
 | 
			
		||||
        cardLayer.addSpatial(control.getSpatial());
 | 
			
		||||
        control.swap();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Adds a turbo symbol to the card layer.
 | 
			
		||||
     */
 | 
			
		||||
    public void turbo() {
 | 
			
		||||
        SymbolControl control = createSymbol(Asset.turboSymbol);
 | 
			
		||||
        cardLayer.addSpatial(control.getSpatial());
 | 
			
		||||
        control.turbo();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Converts a bonus card to its corresponding asset.
 | 
			
		||||
     *
 | 
			
		||||
     * @param card the bonus card
 | 
			
		||||
     * @return the corresponding asset
 | 
			
		||||
     */
 | 
			
		||||
    private Asset bonusToAsset(BonusCard card) {
 | 
			
		||||
        return switch (card) {
 | 
			
		||||
            case TURBO -> Asset.turboCard;
 | 
			
		||||
@@ -181,10 +254,21 @@ private Asset bonusToAsset(BonusCard card) {
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Calculates the next position for a card.
 | 
			
		||||
     *
 | 
			
		||||
     * @param i the index of the card
 | 
			
		||||
     * @return the next position vector
 | 
			
		||||
     */
 | 
			
		||||
    private Vector3f nextPos(int i) {
 | 
			
		||||
        return START.add(MARGIN.mult(i));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Creates an overlay camera for the card layer.
 | 
			
		||||
     *
 | 
			
		||||
     * @return the created overlay camera
 | 
			
		||||
     */
 | 
			
		||||
    private Camera createOverlayCam() {
 | 
			
		||||
        Camera originalCam = app.getCamera();
 | 
			
		||||
        Camera overlayCam = new Camera(originalCam.getWidth(), originalCam.getHeight());
 | 
			
		||||
@@ -197,6 +281,15 @@ private Camera createOverlayCam() {
 | 
			
		||||
        return overlayCam;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the key associated with a value in a map.
 | 
			
		||||
     *
 | 
			
		||||
     * @param map the map to search
 | 
			
		||||
     * @param value the value to find the key for
 | 
			
		||||
     * @param <K> the type of keys in the map
 | 
			
		||||
     * @param <V> the type of values in the map
 | 
			
		||||
     * @return the key associated with the value, or null if not found
 | 
			
		||||
     */
 | 
			
		||||
    private <K, V> K getKeyByValue(Map<K, V> map, V value) {
 | 
			
		||||
        for (Map.Entry<K, V> entry : map.entrySet()) {
 | 
			
		||||
            if (entry.getValue().equals(value)) {
 | 
			
		||||
@@ -206,6 +299,9 @@ private <K, V> K getKeyByValue(Map<K, V> map, V value) {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Test method to add sample cards to the card layer.
 | 
			
		||||
     */
 | 
			
		||||
    public void test() {
 | 
			
		||||
        addCard(BonusCard.SHIELD);
 | 
			
		||||
        addCard(BonusCard.SHIELD);
 | 
			
		||||
@@ -213,6 +309,13 @@ public void test() {
 | 
			
		||||
        addCard(BonusCard.SWAP);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Creates a card control for a given asset and position.
 | 
			
		||||
     *
 | 
			
		||||
     * @param card the asset representing the card
 | 
			
		||||
     * @param pos the position to place the card
 | 
			
		||||
     * @return the created card control
 | 
			
		||||
     */
 | 
			
		||||
    private CardControl createCard(Asset card, Vector3f pos) {
 | 
			
		||||
        Node rootCard = new Node("Root Card");
 | 
			
		||||
        Spatial spatial = app.getAssetManager().loadModel(card.getModelPath());
 | 
			
		||||
@@ -229,6 +332,12 @@ private CardControl createCard(Asset card, Vector3f pos) {
 | 
			
		||||
        return control;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Creates a symbol control for a given asset.
 | 
			
		||||
     *
 | 
			
		||||
     * @param asset the asset representing the symbol
 | 
			
		||||
     * @return the created symbol control
 | 
			
		||||
     */
 | 
			
		||||
    private SymbolControl createSymbol(Asset asset) {
 | 
			
		||||
        Spatial spatial = app.getAssetManager().loadModel(asset.getModelPath());
 | 
			
		||||
        Material mat = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
 | 
			
		||||
@@ -241,6 +350,11 @@ private SymbolControl createSymbol(Asset asset) {
 | 
			
		||||
        return control;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the card layer.
 | 
			
		||||
     *
 | 
			
		||||
     * @return the card layer
 | 
			
		||||
     */
 | 
			
		||||
    public CardLayer getCardLayer() {
 | 
			
		||||
        return cardLayer;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -16,6 +16,9 @@
 | 
			
		||||
import static com.jme3.material.Materials.LIGHTING;
 | 
			
		||||
import static com.jme3.material.Materials.UNSHADED;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * DiceControl class handles the rolling and spinning behavior of a dice in the game.
 | 
			
		||||
 */
 | 
			
		||||
public class DiceControl extends AbstractControl {
 | 
			
		||||
    private Quaternion targetRotation;
 | 
			
		||||
    private final Vector3f angularVelocity = new Vector3f();
 | 
			
		||||
@@ -31,11 +34,20 @@ public class DiceControl extends AbstractControl {
 | 
			
		||||
    private final AssetManager assetManager;
 | 
			
		||||
    private Runnable actionAfter;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Constructor for DiceControl.
 | 
			
		||||
     *
 | 
			
		||||
     * @param assetManager the asset manager to load models and textures
 | 
			
		||||
     */
 | 
			
		||||
    public DiceControl(AssetManager assetManager) {
 | 
			
		||||
        this.assetManager = assetManager;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Updates the control each frame.
 | 
			
		||||
     *
 | 
			
		||||
     * @param tpf time per frame
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void controlUpdate(float tpf) {
 | 
			
		||||
        float clampedTpf = Math.min(tpf, 0.05f); // Max 50 ms per frame
 | 
			
		||||
@@ -56,7 +68,6 @@ protected void controlUpdate(float tpf) {
 | 
			
		||||
            } else {
 | 
			
		||||
                timeElapsed += clampedTpf * rollDuration;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                if (timeElapsed > 1.0f) timeElapsed = 1.0f;
 | 
			
		||||
                Quaternion interpolated = spatial.getLocalRotation().clone();
 | 
			
		||||
                interpolated.slerp(targetRotation, timeElapsed);
 | 
			
		||||
@@ -74,6 +85,11 @@ protected void controlUpdate(float tpf) {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Applies rotational velocity to the dice.
 | 
			
		||||
     *
 | 
			
		||||
     * @param tpf time per frame
 | 
			
		||||
     */
 | 
			
		||||
    private void spinWithAngularVelocity(float tpf) {
 | 
			
		||||
        Quaternion currentRotation = spatial.getLocalRotation();
 | 
			
		||||
        Quaternion deltaRotation = new Quaternion();
 | 
			
		||||
@@ -85,11 +101,22 @@ private void spinWithAngularVelocity(float tpf) {
 | 
			
		||||
        spatial.setLocalRotation(currentRotation.mult(deltaRotation));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Renders the control.
 | 
			
		||||
     *
 | 
			
		||||
     * @param rm the render manager
 | 
			
		||||
     * @param vp the viewport
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void controlRender(RenderManager rm, ViewPort vp) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Initiates the dice roll.
 | 
			
		||||
     *
 | 
			
		||||
     * @param diceNum the number on the dice to roll to
 | 
			
		||||
     * @param actionAfter the action to perform after the roll
 | 
			
		||||
     */
 | 
			
		||||
    public void rollDice(int diceNum, Runnable actionAfter) {
 | 
			
		||||
        if (isRolling) return;
 | 
			
		||||
        spin = false;
 | 
			
		||||
@@ -107,6 +134,12 @@ public void rollDice(int diceNum, Runnable actionAfter) {
 | 
			
		||||
        isRolling = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the target rotation for a given dice number.
 | 
			
		||||
     *
 | 
			
		||||
     * @param diceNum the number on the dice
 | 
			
		||||
     * @return the target rotation as a Quaternion
 | 
			
		||||
     */
 | 
			
		||||
    private Quaternion getRotationForDiceNum(int diceNum) {
 | 
			
		||||
        return switch (diceNum) {
 | 
			
		||||
            case 1 -> new Quaternion().fromAngleAxis((float) (1 * (Math.PI / 2)), Vector3f.UNIT_X);
 | 
			
		||||
@@ -119,10 +152,19 @@ private Quaternion getRotationForDiceNum(int diceNum) {
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Linear interpolation function.
 | 
			
		||||
     *
 | 
			
		||||
     * @param t the interpolation factor
 | 
			
		||||
     * @return the interpolated value
 | 
			
		||||
     */
 | 
			
		||||
    public static float lerp(float t) {
 | 
			
		||||
        return (float) Math.sqrt(1 - Math.pow(t - 1, 2));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets a random rotation for the dice.
 | 
			
		||||
     */
 | 
			
		||||
    public void randomRotation() {
 | 
			
		||||
        Quaternion randomRotation = new Quaternion();
 | 
			
		||||
        randomRotation.fromAngles(
 | 
			
		||||
@@ -133,11 +175,17 @@ public void randomRotation() {
 | 
			
		||||
        spatial.setLocalRotation(randomRotation);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Initiates the dice spin.
 | 
			
		||||
     */
 | 
			
		||||
    public void spin() {
 | 
			
		||||
        angularVelocity.set(ANGULAR_SPIN, ANGULAR_SPIN, ANGULAR_SPIN);
 | 
			
		||||
        spin = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Hides the dice by removing it from the parent node.
 | 
			
		||||
     */
 | 
			
		||||
    public void hide() {
 | 
			
		||||
        spatial.removeFromParent();
 | 
			
		||||
        spin = false;
 | 
			
		||||
@@ -145,6 +193,13 @@ public void hide() {
 | 
			
		||||
        slerp = false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Creates the dice model and sets its initial properties.
 | 
			
		||||
     *
 | 
			
		||||
     * @param pos the position to place the dice
 | 
			
		||||
     * @param scale the scale of the dice
 | 
			
		||||
     * @param shadow whether the dice should cast and receive shadows
 | 
			
		||||
     */
 | 
			
		||||
    public void create(Vector3f pos, float scale, boolean shadow) {
 | 
			
		||||
        Spatial spatial = assetManager.loadModel(Asset.dice.getModelPath());
 | 
			
		||||
        Material mat;
 | 
			
		||||
@@ -163,6 +218,11 @@ public void create(Vector3f pos, float scale, boolean shadow) {
 | 
			
		||||
        spatial.addControl(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the position of the dice.
 | 
			
		||||
     *
 | 
			
		||||
     * @param pos the new position
 | 
			
		||||
     */
 | 
			
		||||
    public void setPos(Vector3f pos) {
 | 
			
		||||
        spatial.setLocalTranslation(pos);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,9 @@
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Handles the GUI elements and interactions for the game.
 | 
			
		||||
 */
 | 
			
		||||
public class GuiHandler {
 | 
			
		||||
    private final MdgaApp app;
 | 
			
		||||
    private final CardLayerHandler cardLayerHandler;
 | 
			
		||||
@@ -20,6 +23,12 @@ public class GuiHandler {
 | 
			
		||||
 | 
			
		||||
    private FrameBuffer backFrameBuffer;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Constructs a new GuiHandler.
 | 
			
		||||
     *
 | 
			
		||||
     * @param app the application instance
 | 
			
		||||
     * @param guiNode the GUI node
 | 
			
		||||
     */
 | 
			
		||||
    public GuiHandler(MdgaApp app, Node guiNode) {
 | 
			
		||||
        this.app = app;
 | 
			
		||||
        this.ownColor = ownColor;
 | 
			
		||||
@@ -34,6 +43,11 @@ public GuiHandler(MdgaApp app, Node guiNode) {
 | 
			
		||||
        actionTextHandler = new ActionTextHandler(guiNode, app.getAssetManager(), app.getContext().getSettings());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Initializes the GUI handler with the player's color.
 | 
			
		||||
     *
 | 
			
		||||
     * @param ownColor the player's color
 | 
			
		||||
     */
 | 
			
		||||
    public void init(Color ownColor) {
 | 
			
		||||
        cardLayerHandler.init();
 | 
			
		||||
        playerNameHandler.show();
 | 
			
		||||
@@ -41,11 +55,20 @@ public void init(Color ownColor) {
 | 
			
		||||
        app.getViewPort().setOutputFrameBuffer(backFrameBuffer);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Shuts down the GUI handler.
 | 
			
		||||
     */
 | 
			
		||||
    public void shutdown() {
 | 
			
		||||
        cardLayerHandler.shutdown();
 | 
			
		||||
        app.getViewPort().setOutputFrameBuffer(null);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Rolls the dice and handles the result.
 | 
			
		||||
     *
 | 
			
		||||
     * @param rollNum the number rolled
 | 
			
		||||
     * @param mult the multiplier
 | 
			
		||||
     */
 | 
			
		||||
    public void rollDice(int rollNum, int mult) {
 | 
			
		||||
        cardLayerHandler.rollDice(rollNum, () -> {
 | 
			
		||||
            if (mult == -1) actionTextHandler.ownDice(rollNum);
 | 
			
		||||
@@ -56,43 +79,82 @@ public void rollDice(int rollNum, int mult) {
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Shows the rolled dice with a multiplier for a specific player.
 | 
			
		||||
     *
 | 
			
		||||
     * @param rollNum the number rolled
 | 
			
		||||
     * @param mult the multiplier
 | 
			
		||||
     * @param color the player's color
 | 
			
		||||
     */
 | 
			
		||||
    public void showRolledDiceMult(int rollNum, int mult, Color color) {
 | 
			
		||||
        String name = playerNameHandler.getName(color);
 | 
			
		||||
        if (mult == -1) actionTextHandler.diceNum(rollNum, name, color);
 | 
			
		||||
        else actionTextHandler.diceNumMult(rollNum, mult, name, color);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Shows the rolled dice for a specific player.
 | 
			
		||||
     *
 | 
			
		||||
     * @param rollNum the number rolled
 | 
			
		||||
     * @param color the player's color
 | 
			
		||||
     */
 | 
			
		||||
    public void showRolledDice(int rollNum, Color color) {
 | 
			
		||||
        actionTextHandler.diceNum(rollNum, playerNameHandler.getName(color), color);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Displays the dice on the screen.
 | 
			
		||||
     */
 | 
			
		||||
    public void showDice() {
 | 
			
		||||
        cardLayerHandler.showDice();
 | 
			
		||||
        actionTextHandler.diceNow();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Hides the dice from the screen.
 | 
			
		||||
     */
 | 
			
		||||
    public void hideDice() {
 | 
			
		||||
        cardLayerHandler.hideDice();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //add own handCard
 | 
			
		||||
    /**
 | 
			
		||||
     * Adds a card to the player's hand.
 | 
			
		||||
     *
 | 
			
		||||
     * @param card the card to add
 | 
			
		||||
     */
 | 
			
		||||
    public void addCardOwn(BonusCard card) {
 | 
			
		||||
        cardLayerHandler.addCard(card);
 | 
			
		||||
        playerNameHandler.addCard(ownColor);
 | 
			
		||||
        actionTextHandler.drawCardOwn(ownColor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Plays a card from the player's hand.
 | 
			
		||||
     *
 | 
			
		||||
     * @param card the card to play
 | 
			
		||||
     */
 | 
			
		||||
    public void playCardOwn(BonusCard card) {
 | 
			
		||||
        getEffectByCard(card);
 | 
			
		||||
        cardLayerHandler.removeCard(card);
 | 
			
		||||
        playerNameHandler.removeCard(ownColor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Plays a card from an enemy player's hand.
 | 
			
		||||
     *
 | 
			
		||||
     * @param color the enemy player's color
 | 
			
		||||
     * @param card the card to play
 | 
			
		||||
     */
 | 
			
		||||
    public void playCardEnemy(Color color, BonusCard card) {
 | 
			
		||||
        getEffectByCard(card);
 | 
			
		||||
        playerNameHandler.removeCard(color);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the effect of a card and applies it.
 | 
			
		||||
     *
 | 
			
		||||
     * @param bonus the card to get the effect from
 | 
			
		||||
     */
 | 
			
		||||
    private void getEffectByCard(BonusCard bonus) {
 | 
			
		||||
        switch (bonus) {
 | 
			
		||||
            case SWAP -> swap();
 | 
			
		||||
@@ -102,30 +164,64 @@ private void getEffectByCard(BonusCard bonus) {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Clears all selectable cards.
 | 
			
		||||
     */
 | 
			
		||||
    public void clearSelectableCards() {
 | 
			
		||||
        cardLayerHandler.clearSelectableCards();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the selectable cards.
 | 
			
		||||
     *
 | 
			
		||||
     * @param select the list of selectable cards
 | 
			
		||||
     */
 | 
			
		||||
    public void setSelectableCards(List<BonusCard> select) {
 | 
			
		||||
        cardLayerHandler.setSelectableCards(select);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Selects a card.
 | 
			
		||||
     *
 | 
			
		||||
     * @param cardControl the card control to select
 | 
			
		||||
     */
 | 
			
		||||
    public void selectCard(CardControl cardControl) {
 | 
			
		||||
        cardLayerHandler.selectCard(cardControl);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the camera for the card layer.
 | 
			
		||||
     *
 | 
			
		||||
     * @return the card layer camera
 | 
			
		||||
     */
 | 
			
		||||
    public Camera getCardLayerCamera() {
 | 
			
		||||
        return cardLayerHandler.getCardLayerCamera();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the root node for the card layer.
 | 
			
		||||
     *
 | 
			
		||||
     * @return the card layer root node
 | 
			
		||||
     */
 | 
			
		||||
    public Node getCardLayerRootNode() {
 | 
			
		||||
        return cardLayerHandler.getCardLayer().getRootNode();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Adds a player to the game.
 | 
			
		||||
     *
 | 
			
		||||
     * @param color the player's color
 | 
			
		||||
     * @param name the player's name
 | 
			
		||||
     */
 | 
			
		||||
    public void addPlayer(Color color, String name) {
 | 
			
		||||
        playerNameHandler.addPlayer(color, name, color == ownColor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the active player.
 | 
			
		||||
     *
 | 
			
		||||
     * @param color the active player's color
 | 
			
		||||
     */
 | 
			
		||||
    public void setActivePlayer(Color color) {
 | 
			
		||||
        playerNameHandler.setActivePlayer(color);
 | 
			
		||||
 | 
			
		||||
@@ -133,38 +229,63 @@ public void setActivePlayer(Color color) {
 | 
			
		||||
        else actionTextHandler.activePlayer(playerNameHandler.getName(color), color);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Applies the shield effect.
 | 
			
		||||
     */
 | 
			
		||||
    public void shield() {
 | 
			
		||||
        cardLayerHandler.shield();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Applies the swap effect.
 | 
			
		||||
     */
 | 
			
		||||
    public void swap() {
 | 
			
		||||
        cardLayerHandler.swap();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Applies the turbo effect.
 | 
			
		||||
     */
 | 
			
		||||
    public void turbo() {
 | 
			
		||||
        cardLayerHandler.turbo();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Hides the action text.
 | 
			
		||||
     */
 | 
			
		||||
    public void hideText() {
 | 
			
		||||
        actionTextHandler.hide();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //addCard Enemy (DrawCardNotification)
 | 
			
		||||
    /**
 | 
			
		||||
     * Draws a card for an enemy player.
 | 
			
		||||
     *
 | 
			
		||||
     * @param color the enemy player's color
 | 
			
		||||
     */
 | 
			
		||||
    public void drawCard(Color color) {
 | 
			
		||||
        //Color != ownColor
 | 
			
		||||
        actionTextHandler.drawCard(playerNameHandler.getName(color), color);
 | 
			
		||||
        playerNameHandler.addCard(color);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Displays the finish text for a player.
 | 
			
		||||
     *
 | 
			
		||||
     * @param color the player's color
 | 
			
		||||
     */
 | 
			
		||||
    public void finish(Color color) {
 | 
			
		||||
        if (ownColor == color) actionTextHandler.finishTextOwn(color);
 | 
			
		||||
        else actionTextHandler.finishText(playerNameHandler.getName(color), color);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Displays the ranking result for a player.
 | 
			
		||||
     *
 | 
			
		||||
     * @param color the player's color
 | 
			
		||||
     * @param eye the ranking result
 | 
			
		||||
     */
 | 
			
		||||
    public void rollRankingResult(Color color, int eye) {
 | 
			
		||||
        if (ownColor == color) actionTextHandler.rollRankingResultOwn(color, eye);
 | 
			
		||||
        else actionTextHandler.rollRankingResult(playerNameHandler.getName(color), color, eye);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,9 @@
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Handles the display and management of player names and their associated data.
 | 
			
		||||
 */
 | 
			
		||||
public class PlayerNameHandler {
 | 
			
		||||
    private final BitmapFont playerFont;
 | 
			
		||||
    private final Node playerNameNode;
 | 
			
		||||
@@ -37,6 +40,13 @@ public class PlayerNameHandler {
 | 
			
		||||
 | 
			
		||||
    private final Node guiNode;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Constructs a PlayerNameHandler.
 | 
			
		||||
     *
 | 
			
		||||
     * @param guiNode the GUI node to attach player names to
 | 
			
		||||
     * @param assetManager the asset manager to load resources
 | 
			
		||||
     * @param appSettings the application settings
 | 
			
		||||
     */
 | 
			
		||||
    public PlayerNameHandler(Node guiNode, AssetManager assetManager, AppSettings appSettings) {
 | 
			
		||||
        this.guiNode = guiNode;
 | 
			
		||||
 | 
			
		||||
@@ -49,18 +59,26 @@ public PlayerNameHandler(Node guiNode, AssetManager assetManager, AppSettings ap
 | 
			
		||||
        this.assetManager = assetManager;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Shows the player names on the GUI.
 | 
			
		||||
     */
 | 
			
		||||
    public void show() {
 | 
			
		||||
        guiNode.attachChild(playerNameNode);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Hides the player names from the GUI.
 | 
			
		||||
     */
 | 
			
		||||
    public void hide() {
 | 
			
		||||
        guiNode.detachChild(playerNameNode);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Draws the player names and their associated data on the GUI.
 | 
			
		||||
     */
 | 
			
		||||
    private void drawPlayers() {
 | 
			
		||||
        playerNameNode.detachAllChildren();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        for (int i = 0; i < playerOrder.size(); i++) {
 | 
			
		||||
            Color color = playerOrder.get(i);
 | 
			
		||||
            if (!colorNameMap.containsKey(color)) throw new RuntimeException(color + " isn't mapped to a name");
 | 
			
		||||
@@ -79,6 +97,14 @@ private void drawPlayers() {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Creates a BitmapText object to display the number of cards a player has.
 | 
			
		||||
     *
 | 
			
		||||
     * @param num the number of cards
 | 
			
		||||
     * @param lastWidth the width of the last element
 | 
			
		||||
     * @param lastX the x position of the last element
 | 
			
		||||
     * @return a BitmapText object displaying the number of cards
 | 
			
		||||
     */
 | 
			
		||||
    private Spatial createCardNum(int num, float lastWidth, float lastX) {
 | 
			
		||||
        BitmapText hudText = new BitmapText(playerFont);
 | 
			
		||||
        //renderedSize = 45
 | 
			
		||||
@@ -89,6 +115,12 @@ private Spatial createCardNum(int num, float lastWidth, float lastX) {
 | 
			
		||||
        return hudText;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Creates a Picture object to display a hand card image.
 | 
			
		||||
     *
 | 
			
		||||
     * @param width the width of the previous element
 | 
			
		||||
     * @return a Picture object displaying a hand card image
 | 
			
		||||
     */
 | 
			
		||||
    private Picture createHandCard(float width) {
 | 
			
		||||
        Picture pic = new Picture("HUD Picture");
 | 
			
		||||
        pic.setImage(assetManager, "./Images/handcard.png", true);
 | 
			
		||||
@@ -98,6 +130,12 @@ private Picture createHandCard(float width) {
 | 
			
		||||
        return pic;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the image path for a given color.
 | 
			
		||||
     *
 | 
			
		||||
     * @param color the color to get the image path for
 | 
			
		||||
     * @return the image path for the given color
 | 
			
		||||
     */
 | 
			
		||||
    private String imagePath(Color color) {
 | 
			
		||||
        String root = "./Images/name_pictures/";
 | 
			
		||||
        return switch (color) {
 | 
			
		||||
@@ -109,6 +147,12 @@ private String imagePath(Color color) {
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Creates a Picture object to display a color image.
 | 
			
		||||
     *
 | 
			
		||||
     * @param color the color to create the image for
 | 
			
		||||
     * @return a Picture object displaying the color image
 | 
			
		||||
     */
 | 
			
		||||
    private Spatial createColor(Color color) {
 | 
			
		||||
        Picture pic = new Picture("HUD Picture");
 | 
			
		||||
        pic.setImage(assetManager, imagePath(color), true);
 | 
			
		||||
@@ -118,7 +162,14 @@ private Spatial createColor(Color color) {
 | 
			
		||||
        return pic;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Creates a BitmapText object to display a player's name.
 | 
			
		||||
     *
 | 
			
		||||
     * @param name the player's name
 | 
			
		||||
     * @param first whether the player is the first in the list
 | 
			
		||||
     * @param own whether the player is the current user
 | 
			
		||||
     * @return a BitmapText object displaying the player's name
 | 
			
		||||
     */
 | 
			
		||||
    private BitmapText createName(String name, boolean first, boolean own) {
 | 
			
		||||
        BitmapText hudText = new BitmapText(playerFont);
 | 
			
		||||
        //renderedSize = 45
 | 
			
		||||
@@ -129,6 +180,13 @@ private BitmapText createName(String name, boolean first, boolean own) {
 | 
			
		||||
        return hudText;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Adds a player to the handler.
 | 
			
		||||
     *
 | 
			
		||||
     * @param color the color associated with the player
 | 
			
		||||
     * @param name the name of the player
 | 
			
		||||
     * @param own whether the player is the current user
 | 
			
		||||
     */
 | 
			
		||||
    public void addPlayer(Color color, String name, boolean own) {
 | 
			
		||||
        if (own) ownColor = color;
 | 
			
		||||
        colorNameMap.put(color, name);
 | 
			
		||||
@@ -136,6 +194,11 @@ public void addPlayer(Color color, String name, boolean own) {
 | 
			
		||||
        drawPlayers();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the active player.
 | 
			
		||||
     *
 | 
			
		||||
     * @param color the color associated with the active player
 | 
			
		||||
     */
 | 
			
		||||
    public void setActivePlayer(Color color) {
 | 
			
		||||
        if (playerOrder.get(0) == color) return;
 | 
			
		||||
        Color oldFirst = playerOrder.remove(0);
 | 
			
		||||
@@ -146,16 +209,32 @@ public void setActivePlayer(Color color) {
 | 
			
		||||
        drawPlayers();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the name of a player by their color.
 | 
			
		||||
     *
 | 
			
		||||
     * @param color the color associated with the player
 | 
			
		||||
     * @return the name of the player
 | 
			
		||||
     */
 | 
			
		||||
    public String getName(Color color) {
 | 
			
		||||
        if (!colorNameMap.containsKey(color)) throw new RuntimeException("color is not in colorNameMap");
 | 
			
		||||
        return colorNameMap.get(color);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Adds a card to a player.
 | 
			
		||||
     *
 | 
			
		||||
     * @param color the color associated with the player
 | 
			
		||||
     */
 | 
			
		||||
    public void addCard(Color color) {
 | 
			
		||||
        colorCardMap.put(color, colorCardMap.getOrDefault(color, 0) + 1);
 | 
			
		||||
        drawPlayers();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Removes a card from a player.
 | 
			
		||||
     *
 | 
			
		||||
     * @param color the color associated with the player
 | 
			
		||||
     */
 | 
			
		||||
    public void removeCard(Color color) {
 | 
			
		||||
        if (colorCardMap.containsKey(color)) {
 | 
			
		||||
            colorCardMap.put(color, colorCardMap.getOrDefault(color, 0) - 1);
 | 
			
		||||
@@ -163,6 +242,4 @@ public void removeCard(Color color) {
 | 
			
		||||
        }
 | 
			
		||||
        drawPlayers();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -11,17 +11,34 @@
 | 
			
		||||
import com.jme3.texture.FrameBuffer;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * OutlineFilter is a custom filter for rendering outlines around objects.
 | 
			
		||||
 */
 | 
			
		||||
public class OutlineFilter extends Filter {
 | 
			
		||||
 | 
			
		||||
    private OutlinePreFilter outlinePreFilter;
 | 
			
		||||
    private ColorRGBA outlineColor = new ColorRGBA(0, 1, 0, 1);
 | 
			
		||||
    private float outlineWidth = 1;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Constructs an OutlineFilter with the specified OutlinePreFilter.
 | 
			
		||||
     *
 | 
			
		||||
     * @param outlinePreFilter the pre-filter used for outlining
 | 
			
		||||
     */
 | 
			
		||||
    public OutlineFilter(OutlinePreFilter outlinePreFilter) {
 | 
			
		||||
        super("OutlineFilter");
 | 
			
		||||
        this.outlinePreFilter = outlinePreFilter;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Initializes the filter with the given parameters.
 | 
			
		||||
     *
 | 
			
		||||
     * @param assetManager the asset manager
 | 
			
		||||
     * @param renderManager the render manager
 | 
			
		||||
     * @param vp the viewport
 | 
			
		||||
     * @param w the width of the viewport
 | 
			
		||||
     * @param h the height of the viewport
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void initFilter(AssetManager assetManager, RenderManager renderManager, ViewPort vp, int w, int h) {
 | 
			
		||||
        MaterialDef matDef = (MaterialDef) assetManager.loadAsset("MatDefs/SelectObjectOutliner/Outline.j3md");
 | 
			
		||||
@@ -31,6 +48,11 @@ protected void initFilter(AssetManager assetManager, RenderManager renderManager
 | 
			
		||||
        material.setFloat("OutlineWidth", outlineWidth);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Called before each frame is rendered.
 | 
			
		||||
     *
 | 
			
		||||
     * @param tpf time per frame
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void preFrame(float tpf) {
 | 
			
		||||
        super.preFrame(tpf);
 | 
			
		||||
@@ -38,6 +60,14 @@ protected void preFrame(float tpf) {
 | 
			
		||||
//		System.out.println("OutlineFilter.preFrame()");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Called after each frame is rendered.
 | 
			
		||||
     *
 | 
			
		||||
     * @param renderManager the render manager
 | 
			
		||||
     * @param viewPort the viewport
 | 
			
		||||
     * @param prevFilterBuffer the previous filter buffer
 | 
			
		||||
     * @param sceneBuffer the scene buffer
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void postFrame(RenderManager renderManager, ViewPort viewPort, FrameBuffer prevFilterBuffer, FrameBuffer sceneBuffer) {
 | 
			
		||||
        super.postFrame(renderManager, viewPort, prevFilterBuffer, sceneBuffer);
 | 
			
		||||
@@ -45,15 +75,30 @@ protected void postFrame(RenderManager renderManager, ViewPort viewPort, FrameBu
 | 
			
		||||
//		System.out.println("OutlineFilter.postFrame()");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the material used by this filter.
 | 
			
		||||
     *
 | 
			
		||||
     * @return the material
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    protected Material getMaterial() {
 | 
			
		||||
        return material;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the outline color.
 | 
			
		||||
     *
 | 
			
		||||
     * @return the outline color
 | 
			
		||||
     */
 | 
			
		||||
    public ColorRGBA getOutlineColor() {
 | 
			
		||||
        return outlineColor;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the outline color.
 | 
			
		||||
     *
 | 
			
		||||
     * @param outlineColor the new outline color
 | 
			
		||||
     */
 | 
			
		||||
    public void setOutlineColor(ColorRGBA outlineColor) {
 | 
			
		||||
        this.outlineColor = outlineColor;
 | 
			
		||||
        if (material != null) {
 | 
			
		||||
@@ -61,10 +106,20 @@ public void setOutlineColor(ColorRGBA outlineColor) {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the outline width.
 | 
			
		||||
     *
 | 
			
		||||
     * @return the outline width
 | 
			
		||||
     */
 | 
			
		||||
    public float getOutlineWidth() {
 | 
			
		||||
        return outlineWidth;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the outline width.
 | 
			
		||||
     *
 | 
			
		||||
     * @param outlineWidth the new outline width
 | 
			
		||||
     */
 | 
			
		||||
    public void setOutlineWidth(float outlineWidth) {
 | 
			
		||||
        this.outlineWidth = outlineWidth;
 | 
			
		||||
        if (material != null) {
 | 
			
		||||
@@ -72,6 +127,11 @@ public void setOutlineWidth(float outlineWidth) {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the OutlinePreFilter used by this filter.
 | 
			
		||||
     *
 | 
			
		||||
     * @return the OutlinePreFilter
 | 
			
		||||
     */
 | 
			
		||||
    public OutlinePreFilter getOutlinePreFilter() {
 | 
			
		||||
        return outlinePreFilter;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -12,23 +12,36 @@
 | 
			
		||||
import com.jme3.texture.Texture;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * OutlinePreFilter is a custom filter used to apply an outline effect to objects.
 | 
			
		||||
 */
 | 
			
		||||
public class OutlinePreFilter extends Filter {
 | 
			
		||||
 | 
			
		||||
    private Pass normalPass;
 | 
			
		||||
    private RenderManager renderManager;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Creates a OutlinePreFilter
 | 
			
		||||
     * Creates an OutlinePreFilter.
 | 
			
		||||
     */
 | 
			
		||||
    public OutlinePreFilter() {
 | 
			
		||||
        super("OutlinePreFilter");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Indicates that this filter requires a depth texture.
 | 
			
		||||
     *
 | 
			
		||||
     * @return true, indicating that a depth texture is required.
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    protected boolean isRequiresDepthTexture() {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Called after the render queue is processed.
 | 
			
		||||
     *
 | 
			
		||||
     * @param queue the render queue.
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void postQueue(RenderQueue queue) {
 | 
			
		||||
        Renderer r = renderManager.getRenderer();
 | 
			
		||||
@@ -36,21 +49,47 @@ protected void postQueue(RenderQueue queue) {
 | 
			
		||||
        renderManager.getRenderer().clearBuffers(true, true, false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Called after the frame is rendered.
 | 
			
		||||
     *
 | 
			
		||||
     * @param renderManager the render manager.
 | 
			
		||||
     * @param viewPort the viewport.
 | 
			
		||||
     * @param prevFilterBuffer the previous filter buffer.
 | 
			
		||||
     * @param sceneBuffer the scene buffer.
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void postFrame(RenderManager renderManager, ViewPort viewPort, FrameBuffer prevFilterBuffer, FrameBuffer sceneBuffer) {
 | 
			
		||||
        super.postFrame(renderManager, viewPort, prevFilterBuffer, sceneBuffer);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the material used by this filter.
 | 
			
		||||
     *
 | 
			
		||||
     * @return the material.
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    protected Material getMaterial() {
 | 
			
		||||
        return material;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the texture containing the outline.
 | 
			
		||||
     *
 | 
			
		||||
     * @return the outline texture.
 | 
			
		||||
     */
 | 
			
		||||
    public Texture getOutlineTexture() {
 | 
			
		||||
        return normalPass.getRenderedTexture();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Initializes the filter.
 | 
			
		||||
     *
 | 
			
		||||
     * @param manager the asset manager.
 | 
			
		||||
     * @param renderManager the render manager.
 | 
			
		||||
     * @param vp the viewport.
 | 
			
		||||
     * @param w the width.
 | 
			
		||||
     * @param h the height.
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void initFilter(AssetManager manager, RenderManager renderManager, ViewPort vp, int w, int h) {
 | 
			
		||||
        this.renderManager = renderManager;
 | 
			
		||||
@@ -59,6 +98,11 @@ protected void initFilter(AssetManager manager, RenderManager renderManager, Vie
 | 
			
		||||
        material = new Material(manager, "MatDefs/SelectObjectOutliner/OutlinePre.j3md");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Cleans up the filter.
 | 
			
		||||
     *
 | 
			
		||||
     * @param r the renderer.
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void cleanUpFilter(Renderer r) {
 | 
			
		||||
        normalPass.cleanup(r);
 | 
			
		||||
 
 | 
			
		||||
@@ -10,17 +10,34 @@
 | 
			
		||||
import com.jme3.renderer.ViewPort;
 | 
			
		||||
import com.jme3.texture.FrameBuffer;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * OutlineProFilter is a custom filter for rendering outlines around objects.
 | 
			
		||||
 */
 | 
			
		||||
public class OutlineProFilter extends Filter {
 | 
			
		||||
 | 
			
		||||
    private OutlinePreFilter outlinePreFilter;
 | 
			
		||||
    private ColorRGBA outlineColor = new ColorRGBA(0, 1, 0, 1);
 | 
			
		||||
    private float outlineWidth = 1;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Constructs an OutlineProFilter with the specified OutlinePreFilter.
 | 
			
		||||
     *
 | 
			
		||||
     * @param outlinePreFilter the pre-filter used for outlining
 | 
			
		||||
     */
 | 
			
		||||
    public OutlineProFilter(OutlinePreFilter outlinePreFilter) {
 | 
			
		||||
        super("OutlineFilter");
 | 
			
		||||
        this.outlinePreFilter = outlinePreFilter;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Initializes the filter with the given parameters.
 | 
			
		||||
     *
 | 
			
		||||
     * @param assetManager the asset manager
 | 
			
		||||
     * @param renderManager the render manager
 | 
			
		||||
     * @param vp the viewport
 | 
			
		||||
     * @param w the width of the viewport
 | 
			
		||||
     * @param h the height of the viewport
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void initFilter(AssetManager assetManager, RenderManager renderManager, ViewPort vp, int w, int h) {
 | 
			
		||||
        MaterialDef matDef = (MaterialDef) assetManager.loadAsset("MatDefs/SelectObjectOutliner/OutlinePro.j3md");
 | 
			
		||||
@@ -30,29 +47,54 @@ protected void initFilter(AssetManager assetManager, RenderManager renderManager
 | 
			
		||||
        material.setFloat("OutlineWidth", outlineWidth);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Called before rendering each frame.
 | 
			
		||||
     *
 | 
			
		||||
     * @param tpf time per frame
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void preFrame(float tpf) {
 | 
			
		||||
        super.preFrame(tpf);
 | 
			
		||||
        material.setTexture("OutlineDepthTexture", outlinePreFilter.getOutlineTexture());
 | 
			
		||||
//		System.out.println("OutlineFilter.preFrame()");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Called after rendering each frame.
 | 
			
		||||
     *
 | 
			
		||||
     * @param renderManager the render manager
 | 
			
		||||
     * @param viewPort the viewport
 | 
			
		||||
     * @param prevFilterBuffer the previous filter buffer
 | 
			
		||||
     * @param sceneBuffer the scene buffer
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void postFrame(RenderManager renderManager, ViewPort viewPort, FrameBuffer prevFilterBuffer, FrameBuffer sceneBuffer) {
 | 
			
		||||
        super.postFrame(renderManager, viewPort, prevFilterBuffer, sceneBuffer);
 | 
			
		||||
//		material.setTexture("OutlineDepthTexture", outlinePreFilter.getDefaultPassDepthTexture());
 | 
			
		||||
//		System.out.println("OutlineFilter.postFrame()");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the material used by this filter.
 | 
			
		||||
     *
 | 
			
		||||
     * @return the material
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    protected Material getMaterial() {
 | 
			
		||||
        return material;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the outline color.
 | 
			
		||||
     *
 | 
			
		||||
     * @return the outline color
 | 
			
		||||
     */
 | 
			
		||||
    public ColorRGBA getOutlineColor() {
 | 
			
		||||
        return outlineColor;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the outline color.
 | 
			
		||||
     *
 | 
			
		||||
     * @param outlineColor the new outline color
 | 
			
		||||
     */
 | 
			
		||||
    public void setOutlineColor(ColorRGBA outlineColor) {
 | 
			
		||||
        this.outlineColor = outlineColor;
 | 
			
		||||
        if (material != null) {
 | 
			
		||||
@@ -60,10 +102,20 @@ public void setOutlineColor(ColorRGBA outlineColor) {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the outline width.
 | 
			
		||||
     *
 | 
			
		||||
     * @return the outline width
 | 
			
		||||
     */
 | 
			
		||||
    public float getOutlineWidth() {
 | 
			
		||||
        return outlineWidth;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the outline width.
 | 
			
		||||
     *
 | 
			
		||||
     * @param outlineWidth the new outline width
 | 
			
		||||
     */
 | 
			
		||||
    public void setOutlineWidth(float outlineWidth) {
 | 
			
		||||
        this.outlineWidth = outlineWidth;
 | 
			
		||||
        if (material != null) {
 | 
			
		||||
@@ -71,9 +123,13 @@ public void setOutlineWidth(float outlineWidth) {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the OutlinePreFilter.
 | 
			
		||||
     *
 | 
			
		||||
     * @return the OutlinePreFilter
 | 
			
		||||
     */
 | 
			
		||||
    public OutlinePreFilter getOutlinePreFilter() {
 | 
			
		||||
        return outlinePreFilter;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -9,6 +9,9 @@
 | 
			
		||||
import com.jme3.scene.Spatial;
 | 
			
		||||
import pp.mdga.client.MdgaApp;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This class is responsible for outlining selected objects in the scene.
 | 
			
		||||
 */
 | 
			
		||||
public class SelectObjectOutliner {
 | 
			
		||||
 | 
			
		||||
    private final FilterPostProcessor fpp;
 | 
			
		||||
@@ -21,6 +24,15 @@ public class SelectObjectOutliner {
 | 
			
		||||
    private OutlineProFilter outlineFilter = null;
 | 
			
		||||
    private final MdgaApp app;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Constructor for SelectObjectOutliner.
 | 
			
		||||
     *
 | 
			
		||||
     * @param fpp the FilterPostProcessor
 | 
			
		||||
     * @param renderManager the RenderManager
 | 
			
		||||
     * @param assetManager the AssetManager
 | 
			
		||||
     * @param cam the Camera
 | 
			
		||||
     * @param app the MdgaApp instance
 | 
			
		||||
     */
 | 
			
		||||
    public SelectObjectOutliner(FilterPostProcessor fpp, RenderManager renderManager, AssetManager assetManager, Camera cam, MdgaApp app) {
 | 
			
		||||
        this.selected = false;
 | 
			
		||||
        this.fpp = fpp;
 | 
			
		||||
@@ -30,6 +42,11 @@ public SelectObjectOutliner(FilterPostProcessor fpp, RenderManager renderManager
 | 
			
		||||
        this.app = app;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Deselects the currently selected object, removing the outline effect.
 | 
			
		||||
     *
 | 
			
		||||
     * @param model the Spatial model to deselect
 | 
			
		||||
     */
 | 
			
		||||
    public void deselect(Spatial model) {
 | 
			
		||||
        if (selected) {
 | 
			
		||||
            selected = false;
 | 
			
		||||
@@ -37,6 +54,12 @@ public void deselect(Spatial model) {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
//    /**
 | 
			
		||||
//     * Selects an object and applies an outline effect.
 | 
			
		||||
//     *
 | 
			
		||||
//     * @param model the Spatial model to select
 | 
			
		||||
//     * @param color the ColorRGBA for the outline
 | 
			
		||||
//     */
 | 
			
		||||
//    public void select(Spatial model, ColorRGBA color) {
 | 
			
		||||
//        if (!selected) {
 | 
			
		||||
//            selected = true;
 | 
			
		||||
@@ -44,6 +67,13 @@ public void deselect(Spatial model) {
 | 
			
		||||
//        }
 | 
			
		||||
//    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Selects an object and applies an outline effect.
 | 
			
		||||
     *
 | 
			
		||||
     * @param model the Spatial model to select
 | 
			
		||||
     * @param color the ColorRGBA for the outline
 | 
			
		||||
     * @param width the width of the outline
 | 
			
		||||
     */
 | 
			
		||||
    public void select(Spatial model, ColorRGBA color, int width) {
 | 
			
		||||
        if (!selected) {
 | 
			
		||||
            selected = true;
 | 
			
		||||
@@ -51,6 +81,11 @@ public void select(Spatial model, ColorRGBA color, int width) {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Hides the outline effect from the selected object.
 | 
			
		||||
     *
 | 
			
		||||
     * @param model the Spatial model to hide the outline effect from
 | 
			
		||||
     */
 | 
			
		||||
    private void hideOutlineFilterEffect(Spatial model) {
 | 
			
		||||
        outlineFilter.setEnabled(false);
 | 
			
		||||
        outlineFilter.getOutlinePreFilter().setEnabled(false);
 | 
			
		||||
@@ -61,6 +96,13 @@ private void hideOutlineFilterEffect(Spatial model) {
 | 
			
		||||
        outlineViewport = null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Shows the outline effect on the selected object.
 | 
			
		||||
     *
 | 
			
		||||
     * @param model the Spatial model to show the outline effect on
 | 
			
		||||
     * @param width the width of the outline
 | 
			
		||||
     * @param color the ColorRGBA for the outline
 | 
			
		||||
     */
 | 
			
		||||
    private void showOutlineFilterEffect(Spatial model, int width, ColorRGBA color) {
 | 
			
		||||
        outlineViewport = renderManager.createPreView("outlineViewport", cam);
 | 
			
		||||
        FilterPostProcessor outlineFpp = new FilterPostProcessor(assetManager);
 | 
			
		||||
 
 | 
			
		||||
@@ -59,7 +59,7 @@ public MdgaServer(int port) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     *
 | 
			
		||||
     * Main method to start the server.
 | 
			
		||||
     */
 | 
			
		||||
    public void run() {
 | 
			
		||||
        startServer();
 | 
			
		||||
@@ -87,6 +87,9 @@ private void startServer() {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Process the next message in the queue.
 | 
			
		||||
     */
 | 
			
		||||
    private void processNextMessage() {
 | 
			
		||||
        try {
 | 
			
		||||
            ReceivedMessage message = pendingMessages.take(); // This is a blocking call
 | 
			
		||||
@@ -97,6 +100,9 @@ private void processNextMessage() {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Register serializable classes.
 | 
			
		||||
     */
 | 
			
		||||
    private void initializeSerializables() {
 | 
			
		||||
 | 
			
		||||
        Serializer.registerClass(UUID.class, new UUIDSerializer());
 | 
			
		||||
@@ -170,6 +176,9 @@ private void initializeSerializables() {
 | 
			
		||||
        Serializer.registerClass(BonusCard.class, new EnumSerializer());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Register listeners for the server.
 | 
			
		||||
     */
 | 
			
		||||
    private void registerListeners() {
 | 
			
		||||
        myServer.addMessageListener(this, AnimationEndMessage.class);
 | 
			
		||||
        myServer.addMessageListener(this, ClientStartGameMessage.class);
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,16 @@
 | 
			
		||||
import pp.mdga.message.client.ClientInterpreter;
 | 
			
		||||
import pp.mdga.message.client.ClientMessage;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Represents a message received from the server.
 | 
			
		||||
 */
 | 
			
		||||
public record ReceivedMessage(ClientMessage msg, int from) {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Processes the received message using the specified client interpreter.
 | 
			
		||||
     *
 | 
			
		||||
     * @param interpreter the client interpreter to use for processing the message
 | 
			
		||||
     */
 | 
			
		||||
    void process(ClientInterpreter interpreter) {
 | 
			
		||||
        msg.accept(interpreter, from);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,20 @@
 | 
			
		||||
import java.nio.ByteBuffer;
 | 
			
		||||
import java.util.UUID;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Serializer for UUID objects to be used with jME3 networking.
 | 
			
		||||
 */
 | 
			
		||||
public class UUIDSerializer extends Serializer {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Reads a UUID object from the given ByteBuffer.
 | 
			
		||||
     *
 | 
			
		||||
     * @param data the ByteBuffer containing the serialized UUID
 | 
			
		||||
     * @param c the class type of the object to be read
 | 
			
		||||
     * @param <T> the type of the object to be read
 | 
			
		||||
     * @return the deserialized UUID object, or null if the UUID is a placeholder
 | 
			
		||||
     * @throws IOException if an I/O error occurs
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    public <T> T readObject(ByteBuffer data, Class<T> c) throws IOException {
 | 
			
		||||
        byte[] uuid = new byte[36];
 | 
			
		||||
@@ -19,6 +32,13 @@ public <T> T readObject(ByteBuffer data, Class<T> c) throws IOException {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Writes a UUID object to the given ByteBuffer.
 | 
			
		||||
     *
 | 
			
		||||
     * @param buffer the ByteBuffer to write the serialized UUID to
 | 
			
		||||
     * @param object the UUID object to be serialized
 | 
			
		||||
     * @throws IOException if an I/O error occurs
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    public void writeObject(ByteBuffer buffer, Object object) throws IOException {
 | 
			
		||||
        UUID uuid = (UUID) object;
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,13 @@
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * CeremonyView class handles the display and interaction of the ceremony view in the application.
 | 
			
		||||
 */
 | 
			
		||||
public class CeremonyView extends MdgaView {
 | 
			
		||||
    /**
 | 
			
		||||
     * Enum representing the sub-states of the CeremonyView.
 | 
			
		||||
     */
 | 
			
		||||
    private enum SubState {
 | 
			
		||||
        AWARD_CEREMONY,
 | 
			
		||||
        STATISTICS,
 | 
			
		||||
@@ -39,6 +45,11 @@ private enum SubState {
 | 
			
		||||
 | 
			
		||||
    private AmbientLight ambient = new AmbientLight();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Constructor for CeremonyView.
 | 
			
		||||
     *
 | 
			
		||||
     * @param app The application instance.
 | 
			
		||||
     */
 | 
			
		||||
    public CeremonyView(MdgaApp app) {
 | 
			
		||||
        super(app);
 | 
			
		||||
 | 
			
		||||
@@ -52,6 +63,9 @@ public CeremonyView(MdgaApp app) {
 | 
			
		||||
        ambient.setColor(new ColorRGBA(0.3f, 0.3f, 0.3f, 1));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Method called when entering the CeremonyView.
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onEnter() {
 | 
			
		||||
        rootNode.addLight(ambient);
 | 
			
		||||
@@ -98,6 +112,9 @@ public void onEnter() {
 | 
			
		||||
        enterSub(SubState.AWARD_CEREMONY);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Method called when leaving the CeremonyView.
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onLeave() {
 | 
			
		||||
        backButton.hide();
 | 
			
		||||
@@ -116,6 +133,11 @@ public void onLeave() {
 | 
			
		||||
        rootNode.detachChild(background);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Method called when entering an overlay.
 | 
			
		||||
     *
 | 
			
		||||
     * @param overlay The overlay being entered.
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void onEnterOverlay(Overlay overlay) {
 | 
			
		||||
        if (rootNode.hasChild(podest)) {
 | 
			
		||||
@@ -123,11 +145,21 @@ protected void onEnterOverlay(Overlay overlay) {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Method called when leaving an overlay.
 | 
			
		||||
     *
 | 
			
		||||
     * @param overlay The overlay being left.
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void onLeaveOverlay(Overlay overlay) {
 | 
			
		||||
        enterSub(state);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Method called to update the CeremonyView.
 | 
			
		||||
     *
 | 
			
		||||
     * @param tpf Time per frame.
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void onUpdate(float tpf) {
 | 
			
		||||
        for (CeremonyButton c : ceremonyButtons) {
 | 
			
		||||
@@ -135,6 +167,9 @@ protected void onUpdate(float tpf) {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handles the award ceremony sub-state.
 | 
			
		||||
     */
 | 
			
		||||
    private void awardCeremony() {
 | 
			
		||||
        continueButton.show();
 | 
			
		||||
 | 
			
		||||
@@ -145,6 +180,9 @@ private void awardCeremony() {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handles the statistics sub-state.
 | 
			
		||||
     */
 | 
			
		||||
    private void statistics() {
 | 
			
		||||
        //background = createBackground("Images/b2.png");
 | 
			
		||||
        //guiNode.attachChild(background);
 | 
			
		||||
@@ -154,6 +192,11 @@ private void statistics() {
 | 
			
		||||
        ceremonyDialog.show();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Enters a sub-state of the CeremonyView.
 | 
			
		||||
     *
 | 
			
		||||
     * @param state The sub-state to enter.
 | 
			
		||||
     */
 | 
			
		||||
    private void enterSub(SubState state) {
 | 
			
		||||
        this.state = state;
 | 
			
		||||
 | 
			
		||||
@@ -178,6 +221,9 @@ private void enterSub(SubState state) {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handles the forward button action.
 | 
			
		||||
     */
 | 
			
		||||
    public void forward() {
 | 
			
		||||
        switch (state) {
 | 
			
		||||
            case AWARD_CEREMONY:
 | 
			
		||||
@@ -189,6 +235,9 @@ public void forward() {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handles the back button action.
 | 
			
		||||
     */
 | 
			
		||||
    private void back() {
 | 
			
		||||
        switch (state) {
 | 
			
		||||
            case AWARD_CEREMONY:
 | 
			
		||||
@@ -200,6 +249,13 @@ private void back() {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Adds a participant to the ceremony.
 | 
			
		||||
     *
 | 
			
		||||
     * @param color The color of the participant.
 | 
			
		||||
     * @param pos The position of the participant.
 | 
			
		||||
     * @param name The name of the participant.
 | 
			
		||||
     */
 | 
			
		||||
    public void addCeremonyParticipant(Color color, int pos, String name) {
 | 
			
		||||
        CeremonyButton button = new CeremonyButton(app, guiNode, rootNode, color, CeremonyButton.Pos.values()[pos - 1], name);
 | 
			
		||||
 | 
			
		||||
@@ -211,6 +267,17 @@ public void addCeremonyParticipant(Color color, int pos, String name) {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Adds a row of statistics.
 | 
			
		||||
     *
 | 
			
		||||
     * @param name The name of the row.
 | 
			
		||||
     * @param v1 Value 1.
 | 
			
		||||
     * @param v2 Value 2.
 | 
			
		||||
     * @param v3 Value 3.
 | 
			
		||||
     * @param v4 Value 4.
 | 
			
		||||
     * @param v5 Value 5.
 | 
			
		||||
     * @param v6 Value 6.
 | 
			
		||||
     */
 | 
			
		||||
    public void addStatisticsRow(String name, int v1, int v2, int v3, int v4, int v5, int v6) {
 | 
			
		||||
        ceremonyDialog.addStatisticsRow(name, v1, v2, v3, v4, v5, v6);
 | 
			
		||||
 | 
			
		||||
@@ -218,6 +285,9 @@ public void addStatisticsRow(String name, int v1, int v2, int v3, int v4, int v5
 | 
			
		||||
        ceremonyDialog.show();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Cleans up after the game.
 | 
			
		||||
     */
 | 
			
		||||
    public void afterGameCleanup() {
 | 
			
		||||
        ceremonyDialog.prepare();
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -12,6 +12,9 @@
 | 
			
		||||
import pp.mdga.client.gui.GuiHandler;
 | 
			
		||||
import pp.mdga.game.Color;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Represents the view for the game.
 | 
			
		||||
 */
 | 
			
		||||
public class GameView extends MdgaView {
 | 
			
		||||
    private BoardHandler boardHandler;
 | 
			
		||||
    private CameraHandler camera;
 | 
			
		||||
@@ -33,6 +36,11 @@ public class GameView extends MdgaView {
 | 
			
		||||
 | 
			
		||||
    private Node guiHandlerNode = new Node();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Constructs a new GameView.
 | 
			
		||||
     *
 | 
			
		||||
     * @param app the application instance
 | 
			
		||||
     */
 | 
			
		||||
    public GameView(MdgaApp app) {
 | 
			
		||||
        super(app);
 | 
			
		||||
 | 
			
		||||
@@ -53,6 +61,9 @@ public GameView(MdgaApp app) {
 | 
			
		||||
        guiNode.attachChild(guiHandlerNode);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Called when entering the view.
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onEnter() {
 | 
			
		||||
        camera.init(ownColor);
 | 
			
		||||
@@ -64,24 +75,36 @@ public void onEnter() {
 | 
			
		||||
        app.getAcousticHandler().playSound(MdgaSound.START);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Called when leaving the view.
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onLeave() {
 | 
			
		||||
        boardHandler.shutdown();
 | 
			
		||||
        guiHandler.shutdown();
 | 
			
		||||
        camera.shutdown();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        confirmButton.hide();
 | 
			
		||||
        noPowerButton.hide();
 | 
			
		||||
 | 
			
		||||
        app.getViewPort().removeProcessor(fpp);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Called to update the view.
 | 
			
		||||
     *
 | 
			
		||||
     * @param tpf time per frame
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onUpdate(float tpf) {
 | 
			
		||||
        camera.update(app.getInputSynchronize().getScroll(), app.getInputSynchronize().getRotation());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Called when entering an overlay.
 | 
			
		||||
     *
 | 
			
		||||
     * @param overlay the overlay being entered
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void onEnterOverlay(Overlay overlay) {
 | 
			
		||||
        if (overlay == Overlay.SETTINGS) {
 | 
			
		||||
@@ -89,6 +112,11 @@ protected void onEnterOverlay(Overlay overlay) {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Called when leaving an overlay.
 | 
			
		||||
     *
 | 
			
		||||
     * @param overlay the overlay being left
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void onLeaveOverlay(Overlay overlay) {
 | 
			
		||||
        if (overlay == Overlay.SETTINGS) {
 | 
			
		||||
@@ -96,26 +124,52 @@ protected void onLeaveOverlay(Overlay overlay) {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Leaves the game.
 | 
			
		||||
     */
 | 
			
		||||
    private void leaveGame() {
 | 
			
		||||
        app.getModelSynchronize().leave();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the board handler.
 | 
			
		||||
     *
 | 
			
		||||
     * @return the board handler
 | 
			
		||||
     */
 | 
			
		||||
    public BoardHandler getBoardHandler() {
 | 
			
		||||
        return boardHandler;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the GUI handler.
 | 
			
		||||
     *
 | 
			
		||||
     * @return the GUI handler
 | 
			
		||||
     */
 | 
			
		||||
    public GuiHandler getGuiHandler() {
 | 
			
		||||
        return guiHandler;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the player's color.
 | 
			
		||||
     *
 | 
			
		||||
     * @param ownColor the player's color
 | 
			
		||||
     */
 | 
			
		||||
    public void setOwnColor(Color ownColor) {
 | 
			
		||||
        this.ownColor = ownColor;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the player's color.
 | 
			
		||||
     *
 | 
			
		||||
     * @return the player's color
 | 
			
		||||
     */
 | 
			
		||||
    public Color getOwnColor() {
 | 
			
		||||
        return ownColor;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Shows the confirm button and hides the no power button.
 | 
			
		||||
     */
 | 
			
		||||
    public void needConfirm() {
 | 
			
		||||
        noPowerButton.hide();
 | 
			
		||||
        confirmButton.show();
 | 
			
		||||
@@ -123,12 +177,18 @@ public void needConfirm() {
 | 
			
		||||
        needConfirm = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Hides the confirm button.
 | 
			
		||||
     */
 | 
			
		||||
    public void noConfirm() {
 | 
			
		||||
        confirmButton.hide();
 | 
			
		||||
 | 
			
		||||
        needConfirm = false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Shows the no power button and hides the confirm button.
 | 
			
		||||
     */
 | 
			
		||||
    public void showNoPower() {
 | 
			
		||||
        confirmButton.hide();
 | 
			
		||||
        noPowerButton.show();
 | 
			
		||||
@@ -136,11 +196,19 @@ public void showNoPower() {
 | 
			
		||||
        needNoPower = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Hides the no power button.
 | 
			
		||||
     */
 | 
			
		||||
    public void hideNoPower() {
 | 
			
		||||
        noPowerButton.hide();
 | 
			
		||||
        needNoPower = false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Enters the interrupt state with the specified color.
 | 
			
		||||
     *
 | 
			
		||||
     * @param color the color to set
 | 
			
		||||
     */
 | 
			
		||||
    public void enterInterrupt(Color color) {
 | 
			
		||||
        enterOverlay(Overlay.INTERRUPT);
 | 
			
		||||
 | 
			
		||||
@@ -153,6 +221,9 @@ public void enterInterrupt(Color color) {
 | 
			
		||||
        interruptDialog.show();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Leaves the interrupt state.
 | 
			
		||||
     */
 | 
			
		||||
    public void leaveInterrupt() {
 | 
			
		||||
        leaveOverlay(Overlay.INTERRUPT);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,9 @@
 | 
			
		||||
import pp.mdga.client.button.LobbyButton;
 | 
			
		||||
import pp.mdga.game.Color;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Represents the lobby view in the game.
 | 
			
		||||
 */
 | 
			
		||||
public class LobbyView extends MdgaView {
 | 
			
		||||
    private Geometry background;
 | 
			
		||||
 | 
			
		||||
@@ -33,6 +36,11 @@ public class LobbyView extends MdgaView {
 | 
			
		||||
 | 
			
		||||
    private Color own = null;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Constructs a new LobbyView.
 | 
			
		||||
     *
 | 
			
		||||
     * @param app the application instance
 | 
			
		||||
     */
 | 
			
		||||
    public LobbyView(MdgaApp app) {
 | 
			
		||||
        super(app);
 | 
			
		||||
 | 
			
		||||
@@ -48,6 +56,9 @@ public LobbyView(MdgaApp app) {
 | 
			
		||||
        ambient.setColor(new ColorRGBA(0.3f, 0.3f, 0.3f, 1));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Called when entering the lobby view.
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onEnter() {
 | 
			
		||||
        app.getCamera().setParallelProjection(true);
 | 
			
		||||
@@ -92,6 +103,9 @@ public void onEnter() {
 | 
			
		||||
        rootNode.attachChild(background);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Called when leaving the lobby view.
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onLeave() {
 | 
			
		||||
        leaveButton.hide();
 | 
			
		||||
@@ -130,6 +144,11 @@ public void onLeave() {
 | 
			
		||||
        rootNode.detachChild(background);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Called on each frame update.
 | 
			
		||||
     *
 | 
			
		||||
     * @param tpf time per frame
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void onUpdate(float tpf) {
 | 
			
		||||
        airforceButton.update(tpf);
 | 
			
		||||
@@ -140,14 +159,22 @@ protected void onUpdate(float tpf) {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void onEnterOverlay(Overlay overlay) {
 | 
			
		||||
 | 
			
		||||
        // No implementation needed
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void onLeaveOverlay(Overlay overlay) {
 | 
			
		||||
 | 
			
		||||
        // No implementation needed
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the taken status of a color.
 | 
			
		||||
     *
 | 
			
		||||
     * @param color the color
 | 
			
		||||
     * @param isTaken whether the color is taken
 | 
			
		||||
     * @param isSelf whether the color is taken by the player
 | 
			
		||||
     * @param name the name of the player who took the color
 | 
			
		||||
     */
 | 
			
		||||
    public void setTaken(Color color, boolean isTaken, boolean isSelf, String name) {
 | 
			
		||||
        LobbyButton.Taken taken;
 | 
			
		||||
 | 
			
		||||
@@ -182,6 +209,12 @@ public void setTaken(Color color, boolean isTaken, boolean isSelf, String name)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the ready status of a color.
 | 
			
		||||
     *
 | 
			
		||||
     * @param color the color
 | 
			
		||||
     * @param isReady whether the color is ready
 | 
			
		||||
     */
 | 
			
		||||
    public void setReady(Color color, boolean isReady) {
 | 
			
		||||
        LobbyButton button = switch (color) {
 | 
			
		||||
            case CYBER -> cyberButton;
 | 
			
		||||
@@ -206,6 +239,11 @@ public void setReady(Color color, boolean isReady) {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Toggles the task selection for a color.
 | 
			
		||||
     *
 | 
			
		||||
     * @param color the color
 | 
			
		||||
     */
 | 
			
		||||
    private void toggleTsk(Color color) {
 | 
			
		||||
        LobbyButton.Taken taken = LobbyButton.Taken.NOT;
 | 
			
		||||
 | 
			
		||||
@@ -241,6 +279,9 @@ private void toggleTsk(Color color) {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the player as ready.
 | 
			
		||||
     */
 | 
			
		||||
    public void ready() {
 | 
			
		||||
        if (own == null) {
 | 
			
		||||
            app.getAcousticHandler().playSound(MdgaSound.WRONG_INPUT);
 | 
			
		||||
@@ -254,6 +295,9 @@ public void ready() {
 | 
			
		||||
        app.getModelSynchronize().setReady(!isReady);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Leaves the lobby.
 | 
			
		||||
     */
 | 
			
		||||
    private void leaveLobby() {
 | 
			
		||||
        app.getModelSynchronize().leave();
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,13 @@
 | 
			
		||||
import pp.mdga.client.dialog.JoinDialog;
 | 
			
		||||
import pp.mdga.client.dialog.StartDialog;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * MainView class that extends MdgaView and manages the main view of the application.
 | 
			
		||||
 */
 | 
			
		||||
public class MainView extends MdgaView {
 | 
			
		||||
    /**
 | 
			
		||||
     * Enum representing the different sub-states of the MainView.
 | 
			
		||||
     */
 | 
			
		||||
    private enum SubState {
 | 
			
		||||
        HOST,
 | 
			
		||||
        JOIN,
 | 
			
		||||
@@ -22,6 +28,11 @@ private enum SubState {
 | 
			
		||||
    private JoinDialog joinDialog;
 | 
			
		||||
    private HostDialog hostDialog;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Constructor for MainView.
 | 
			
		||||
     *
 | 
			
		||||
     * @param app the MdgaApp instance
 | 
			
		||||
     */
 | 
			
		||||
    public MainView(MdgaApp app) {
 | 
			
		||||
        super(app);
 | 
			
		||||
 | 
			
		||||
@@ -32,6 +43,9 @@ public MainView(MdgaApp app) {
 | 
			
		||||
        background = createBackground("Images/startmenu.png");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Called when the view is entered.
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onEnter() {
 | 
			
		||||
        app.setup();
 | 
			
		||||
@@ -41,6 +55,9 @@ public void onEnter() {
 | 
			
		||||
        enterSub(SubState.MAIN);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Called when the view is left.
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onLeave() {
 | 
			
		||||
        startDialog.hide();
 | 
			
		||||
@@ -50,6 +67,11 @@ public void onLeave() {
 | 
			
		||||
        guiNode.detachChild(background);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Called to update the view.
 | 
			
		||||
     *
 | 
			
		||||
     * @param tpf time per frame
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onUpdate(float tpf) {
 | 
			
		||||
        startDialog.update();
 | 
			
		||||
@@ -57,18 +79,31 @@ public void onUpdate(float tpf) {
 | 
			
		||||
        hostDialog.update();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Called when an overlay is entered.
 | 
			
		||||
     *
 | 
			
		||||
     * @param overlay the overlay being entered
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void onEnterOverlay(Overlay overlay) {
 | 
			
		||||
        guiNode.detachChild(background);
 | 
			
		||||
        settingsNode.attachChild(background);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Called when an overlay is left.
 | 
			
		||||
     *
 | 
			
		||||
     * @param overlay the overlay being left
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void onLeaveOverlay(Overlay overlay) {
 | 
			
		||||
        settingsNode.detachChild(background);
 | 
			
		||||
        guiNode.attachChild(background);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Shows the join menu.
 | 
			
		||||
     */
 | 
			
		||||
    private void joinMenu() {
 | 
			
		||||
        startDialog.hide();
 | 
			
		||||
        hostDialog.hide();
 | 
			
		||||
@@ -76,6 +111,9 @@ private void joinMenu() {
 | 
			
		||||
        joinDialog.show();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Shows the host menu.
 | 
			
		||||
     */
 | 
			
		||||
    private void hostMenu() {
 | 
			
		||||
        startDialog.hide();
 | 
			
		||||
        joinDialog.hide();
 | 
			
		||||
@@ -83,6 +121,9 @@ private void hostMenu() {
 | 
			
		||||
        hostDialog.show();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Shows the main menu.
 | 
			
		||||
     */
 | 
			
		||||
    private void mainMenu() {
 | 
			
		||||
        joinDialog.hide();
 | 
			
		||||
        hostDialog.hide();
 | 
			
		||||
@@ -90,6 +131,9 @@ private void mainMenu() {
 | 
			
		||||
        startDialog.show();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Attempts to host a game.
 | 
			
		||||
     */
 | 
			
		||||
    private void tryHost() {
 | 
			
		||||
        int port = 0;
 | 
			
		||||
        String text = hostDialog.getPort();
 | 
			
		||||
@@ -117,6 +161,9 @@ private void tryHost() {
 | 
			
		||||
        app.getAcousticHandler().playSound(MdgaSound.WRONG_INPUT);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Attempts to join a game.
 | 
			
		||||
     */
 | 
			
		||||
    private void tryJoin() {
 | 
			
		||||
        int port = 0;
 | 
			
		||||
        String ip = joinDialog.getIpt();
 | 
			
		||||
@@ -146,6 +193,12 @@ private void tryJoin() {
 | 
			
		||||
        app.getAcousticHandler().playSound(MdgaSound.WRONG_INPUT);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Validates an IP address.
 | 
			
		||||
     *
 | 
			
		||||
     * @param ip the IP address to validate
 | 
			
		||||
     * @return true if the IP address is valid, false otherwise
 | 
			
		||||
     */
 | 
			
		||||
    private boolean isValidIpAddress(String ip) {
 | 
			
		||||
        String ipRegex =
 | 
			
		||||
                "^(25[0-5]|2[0-4][0-9]|[0-1]?[0-9][0-9]?)\\." +
 | 
			
		||||
@@ -156,6 +209,11 @@ private boolean isValidIpAddress(String ip) {
 | 
			
		||||
        return ip != null && ip.matches(ipRegex);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Enters a sub-state.
 | 
			
		||||
     *
 | 
			
		||||
     * @param state the sub-state to enter
 | 
			
		||||
     */
 | 
			
		||||
    private void enterSub(SubState state) {
 | 
			
		||||
        this.state = state;
 | 
			
		||||
 | 
			
		||||
@@ -176,6 +234,9 @@ private void enterSub(SubState state) {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Forwards the state based on the current sub-state.
 | 
			
		||||
     */
 | 
			
		||||
    public void forward() {
 | 
			
		||||
        switch (state) {
 | 
			
		||||
            case HOST:
 | 
			
		||||
@@ -189,6 +250,11 @@ public void forward() {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Forwards the state based on the current sub-state and a boolean flag.
 | 
			
		||||
     *
 | 
			
		||||
     * @param host a boolean flag indicating whether to host or join
 | 
			
		||||
     */
 | 
			
		||||
    public void forward(boolean host) {
 | 
			
		||||
        switch (state) {
 | 
			
		||||
            case HOST:
 | 
			
		||||
@@ -209,6 +275,9 @@ public void forward(boolean host) {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Goes back to the main menu from the current sub-state.
 | 
			
		||||
     */
 | 
			
		||||
    public void back() {
 | 
			
		||||
        switch (state) {
 | 
			
		||||
            case HOST:
 | 
			
		||||
@@ -225,12 +294,21 @@ public void back() {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the JoinDialog instance.
 | 
			
		||||
     *
 | 
			
		||||
     * @return the JoinDialog instance
 | 
			
		||||
     */
 | 
			
		||||
    public JoinDialog getJoinDialog() {
 | 
			
		||||
        return joinDialog;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the HostDialog instance.
 | 
			
		||||
     *
 | 
			
		||||
     * @return the HostDialog instance
 | 
			
		||||
     */
 | 
			
		||||
    public HostDialog getHostDialog() {
 | 
			
		||||
        return hostDialog;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -18,7 +18,13 @@
 | 
			
		||||
import pp.mdga.client.dialog.SettingsDialog;
 | 
			
		||||
import pp.mdga.client.dialog.VideoSettingsDialog;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Abstract class representing a view in the MDGA application.
 | 
			
		||||
 */
 | 
			
		||||
public abstract class MdgaView {
 | 
			
		||||
    /**
 | 
			
		||||
     * Enum representing different types of overlays.
 | 
			
		||||
     */
 | 
			
		||||
    public enum Overlay {
 | 
			
		||||
        INTERRUPT,
 | 
			
		||||
        SETTINGS,
 | 
			
		||||
@@ -40,6 +46,11 @@ public enum Overlay {
 | 
			
		||||
 | 
			
		||||
    private int settingsDepth = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Constructor for MdgaView.
 | 
			
		||||
     *
 | 
			
		||||
     * @param app the application instance
 | 
			
		||||
     */
 | 
			
		||||
    public MdgaView(MdgaApp app) {
 | 
			
		||||
        this.app = app;
 | 
			
		||||
        settingsButton = new SettingsButton(app, guiNode, this::enterSettings);
 | 
			
		||||
@@ -49,6 +60,9 @@ public MdgaView(MdgaApp app) {
 | 
			
		||||
        audioSettingsDialog = new AudioSettingsDialog(app, settingsNode, this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Method to enter the view.
 | 
			
		||||
     */
 | 
			
		||||
    public void enter() {
 | 
			
		||||
        app.getRootNode().attachChild(rootNode);
 | 
			
		||||
        app.getGuiNode().attachChild(guiNode);
 | 
			
		||||
@@ -58,6 +72,9 @@ public void enter() {
 | 
			
		||||
        onEnter();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Method to leave the view.
 | 
			
		||||
     */
 | 
			
		||||
    public void leave() {
 | 
			
		||||
        onLeave();
 | 
			
		||||
 | 
			
		||||
@@ -71,18 +88,33 @@ public void leave() {
 | 
			
		||||
        app.getGuiNode().detachChild(guiNode);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Method to enter an overlay.
 | 
			
		||||
     *
 | 
			
		||||
     * @param overlay the overlay to enter
 | 
			
		||||
     */
 | 
			
		||||
    public void enterOverlay(Overlay overlay) {
 | 
			
		||||
        app.getGuiNode().detachChild(guiNode);
 | 
			
		||||
 | 
			
		||||
        onEnterOverlay(overlay);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Method to leave an overlay.
 | 
			
		||||
     *
 | 
			
		||||
     * @param overlay the overlay to leave
 | 
			
		||||
     */
 | 
			
		||||
    public void leaveOverlay(Overlay overlay) {
 | 
			
		||||
        app.getGuiNode().attachChild(guiNode);
 | 
			
		||||
 | 
			
		||||
        onLeaveOverlay(overlay);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Method to update the view.
 | 
			
		||||
     *
 | 
			
		||||
     * @param tpf time per frame
 | 
			
		||||
     */
 | 
			
		||||
    public void update(float tpf) {
 | 
			
		||||
        videoSettingsDialog.update();
 | 
			
		||||
        audioSettingsDialog.update();
 | 
			
		||||
@@ -95,17 +127,44 @@ public void update(float tpf) {
 | 
			
		||||
        onUpdate(tpf);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Abstract method to handle entering the view.
 | 
			
		||||
     */
 | 
			
		||||
    protected abstract void onEnter();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Abstract method to handle leaving the view.
 | 
			
		||||
     */
 | 
			
		||||
    protected abstract void onLeave();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Method to handle updating the view.
 | 
			
		||||
     *
 | 
			
		||||
     * @param tpf time per frame
 | 
			
		||||
     */
 | 
			
		||||
    protected void onUpdate(float tpf) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Abstract method to handle entering an overlay.
 | 
			
		||||
     *
 | 
			
		||||
     * @param overlay the overlay to enter
 | 
			
		||||
     */
 | 
			
		||||
    protected abstract void onEnterOverlay(Overlay overlay);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Abstract method to handle leaving an overlay.
 | 
			
		||||
     *
 | 
			
		||||
     * @param overlay the overlay to leave
 | 
			
		||||
     */
 | 
			
		||||
    protected abstract void onLeaveOverlay(Overlay overlay);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Method to create a background geometry with a texture.
 | 
			
		||||
     *
 | 
			
		||||
     * @param texturePath the path to the texture
 | 
			
		||||
     * @return the created background geometry
 | 
			
		||||
     */
 | 
			
		||||
    protected Geometry createBackground(String texturePath) {
 | 
			
		||||
        TextureKey key = new TextureKey(texturePath, true);
 | 
			
		||||
        Texture backgroundTexture = app.getAssetManager().loadTexture(key);
 | 
			
		||||
@@ -122,6 +181,9 @@ protected Geometry createBackground(String texturePath) {
 | 
			
		||||
        return background;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Method to enter the settings view.
 | 
			
		||||
     */
 | 
			
		||||
    public void enterSettings() {
 | 
			
		||||
        enterOverlay(Overlay.SETTINGS);
 | 
			
		||||
 | 
			
		||||
@@ -132,6 +194,9 @@ public void enterSettings() {
 | 
			
		||||
        settingsDepth++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Method to leave the settings view.
 | 
			
		||||
     */
 | 
			
		||||
    public void leaveSettings() {
 | 
			
		||||
        leaveOverlay(Overlay.SETTINGS);
 | 
			
		||||
 | 
			
		||||
@@ -142,6 +207,9 @@ public void leaveSettings() {
 | 
			
		||||
        settingsDepth--;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Method to enter the video settings view.
 | 
			
		||||
     */
 | 
			
		||||
    public void enterVideoSettings() {
 | 
			
		||||
        settingsDialog.hide();
 | 
			
		||||
        videoSettingsDialog.show();
 | 
			
		||||
@@ -149,6 +217,9 @@ public void enterVideoSettings() {
 | 
			
		||||
        settingsDepth++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Method to leave the video settings view.
 | 
			
		||||
     */
 | 
			
		||||
    public void leaveVideoSettings() {
 | 
			
		||||
        settingsDialog.show();
 | 
			
		||||
        videoSettingsDialog.hide();
 | 
			
		||||
@@ -156,6 +227,9 @@ public void leaveVideoSettings() {
 | 
			
		||||
        settingsDepth--;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Method to enter the audio settings view.
 | 
			
		||||
     */
 | 
			
		||||
    public void enterAudioSettings() {
 | 
			
		||||
        settingsDialog.hide();
 | 
			
		||||
        audioSettingsDialog.show();
 | 
			
		||||
@@ -163,6 +237,9 @@ public void enterAudioSettings() {
 | 
			
		||||
        settingsDepth++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Method to leave the audio settings view.
 | 
			
		||||
     */
 | 
			
		||||
    public void leaveAudioSettings() {
 | 
			
		||||
        settingsDialog.show();
 | 
			
		||||
        audioSettingsDialog.hide();
 | 
			
		||||
@@ -170,6 +247,9 @@ public void leaveAudioSettings() {
 | 
			
		||||
        settingsDepth--;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Method to leave advanced settings.
 | 
			
		||||
     */
 | 
			
		||||
    private void leaveAdvanced() {
 | 
			
		||||
        settingsDialog.show();
 | 
			
		||||
        audioSettingsDialog.hide();
 | 
			
		||||
@@ -177,6 +257,9 @@ private void leaveAdvanced() {
 | 
			
		||||
        settingsDepth--;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Method to handle pressing the escape key.
 | 
			
		||||
     */
 | 
			
		||||
    public void pressEscape() {
 | 
			
		||||
        if (settingsDepth == 0) {
 | 
			
		||||
            enterSettings();
 | 
			
		||||
@@ -187,6 +270,9 @@ public void pressEscape() {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Method to handle pressing the forward key.
 | 
			
		||||
     */
 | 
			
		||||
    public void pressForward() {
 | 
			
		||||
        if (this instanceof MainView mainView) {
 | 
			
		||||
            mainView.forward(false);
 | 
			
		||||
@@ -212,6 +298,12 @@ public void pressForward() {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Method to show information on the view.
 | 
			
		||||
     *
 | 
			
		||||
     * @param error the error message
 | 
			
		||||
     * @param isError flag indicating if it is an error
 | 
			
		||||
     */
 | 
			
		||||
    public void showInfo(String error, boolean isError) {
 | 
			
		||||
        infoTimer.reset();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user