merge dev into test #33
@@ -1,4 +1,4 @@
|
|||||||
package pp.mdga.client.animation;
|
package pp.mdga.client;
|
||||||
|
|
||||||
import com.jme3.renderer.RenderManager;
|
import com.jme3.renderer.RenderManager;
|
||||||
import com.jme3.renderer.ViewPort;
|
import com.jme3.renderer.ViewPort;
|
||||||
@@ -106,7 +106,7 @@ public void simpleInitApp() {
|
|||||||
gameView = new GameView(this);
|
gameView = new GameView(this);
|
||||||
ceremonyView = new CeremonyView(this);
|
ceremonyView = new CeremonyView(this);
|
||||||
|
|
||||||
enter(MdgaState.MAIN);
|
enter(MdgaState.GAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -67,8 +67,9 @@ private void handleLobby(Notification notification) {
|
|||||||
lobbyView.setTaken(n.getColor(), false, false, null);
|
lobbyView.setTaken(n.getColor(), false, false, null);
|
||||||
} else if(notification instanceof LobbyReadyNotification lobbyReadyNotification) {
|
} else if(notification instanceof LobbyReadyNotification lobbyReadyNotification) {
|
||||||
lobbyView.setReady(lobbyReadyNotification.getColor(), lobbyReadyNotification.isReady());
|
lobbyView.setReady(lobbyReadyNotification.getColor(), lobbyReadyNotification.isReady());
|
||||||
} else if (notification instanceof GameNotification) {
|
} else if (notification instanceof GameNotification n) {
|
||||||
app.enter(MdgaState.GAME);
|
app.enter(MdgaState.GAME);
|
||||||
|
((GameView) app.getView()).setOwnColor(n.getOwnColor());
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("notification not expected: " + notification.toString());
|
throw new RuntimeException("notification not expected: " + notification.toString());
|
||||||
}
|
}
|
||||||
@@ -84,6 +85,7 @@ private void handleGame(Notification notification) {
|
|||||||
guiHandler.addCard(n.getBonusCard());
|
guiHandler.addCard(n.getBonusCard());
|
||||||
} else if (notification instanceof ActivePlayerNotification n) {
|
} else if (notification instanceof ActivePlayerNotification n) {
|
||||||
gameView.getGuiHandler().setActivePlayer(n.getColor());
|
gameView.getGuiHandler().setActivePlayer(n.getColor());
|
||||||
|
boardHandler.showDice(n.getColor());
|
||||||
} else if (notification instanceof CeremonyNotification ceremonyNotification) {
|
} else if (notification instanceof CeremonyNotification ceremonyNotification) {
|
||||||
app.enter(MdgaState.CEREMONY);
|
app.enter(MdgaState.CEREMONY);
|
||||||
CeremonyView ceremonyView = (CeremonyView) app.getView();
|
CeremonyView ceremonyView = (CeremonyView) app.getView();
|
||||||
@@ -116,23 +118,22 @@ private void handleGame(Notification notification) {
|
|||||||
} else if (notification instanceof DrawCardNotification n) {
|
} else if (notification instanceof DrawCardNotification n) {
|
||||||
guiHandler.drawCard(n.getColor());
|
guiHandler.drawCard(n.getColor());
|
||||||
} else if (notification instanceof HomeMoveNotification home) {
|
} else if (notification instanceof HomeMoveNotification home) {
|
||||||
boardHandler.moveHomePiece(home.getPieceId(), home.getHomeIndex());
|
boardHandler.movePieceHomeAnim(home.getPieceId(), home.getHomeIndex());
|
||||||
guiHandler.hideText();
|
guiHandler.hideText();
|
||||||
} else if (notification instanceof InterruptNotification) {
|
} else if (notification instanceof InterruptNotification) {
|
||||||
app.enter(MdgaState.LOBBY);
|
app.enter(MdgaState.LOBBY);
|
||||||
} else if (notification instanceof MovePieceNotification n) {
|
} else if (notification instanceof MovePieceNotification n) {
|
||||||
if(n.isMoveStart()) {
|
if(n.isMoveStart()) {
|
||||||
//StartMove
|
//StartMove
|
||||||
boardHandler.movePieceStart(n.getPiece(), n.getMoveIndex());
|
boardHandler.movePieceStartAnim(n.getPiece(), n.getMoveIndex());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//InfieldMove
|
//InfieldMove
|
||||||
boardHandler.movePiece(n.getPiece(), n.getStartIndex(), n.getMoveIndex());
|
boardHandler.movePieceAnim(n.getPiece(), n.getStartIndex(), n.getMoveIndex());
|
||||||
// boardHandler.test(n.getPiece(), n.getStartIndex(), n.getMoveIndex());
|
|
||||||
}
|
}
|
||||||
guiHandler.hideText();
|
guiHandler.hideText();
|
||||||
} else if (notification instanceof ThrowPieceNotification n) {
|
} else if (notification instanceof ThrowPieceNotification n) {
|
||||||
boardHandler.throwPiece(n.getPieceId());
|
boardHandler.throwPieceAnim(n.getPieceId());
|
||||||
} else if (notification instanceof NoShieldNotification n) {
|
} else if (notification instanceof NoShieldNotification n) {
|
||||||
boardHandler.unshieldPiece(n.getPieceId());
|
boardHandler.unshieldPiece(n.getPieceId());
|
||||||
} else if (notification instanceof PlayCardNotification n) {
|
} else if (notification instanceof PlayCardNotification n) {
|
||||||
@@ -152,6 +153,7 @@ private void handleGame(Notification notification) {
|
|||||||
guiHandler.rollDice(n.getEyes(), n.isTurbo() ? n.getMultiplier() : -1);
|
guiHandler.rollDice(n.getEyes(), n.isTurbo() ? n.getMultiplier() : -1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
boardHandler.hideDice();
|
||||||
if (n.isTurbo()) guiHandler.showRolledDiceMult(n.getEyes(), n.getMultiplier(), n.getColor());
|
if (n.isTurbo()) guiHandler.showRolledDiceMult(n.getEyes(), n.getMultiplier(), n.getColor());
|
||||||
else guiHandler.showRolledDice(n.getEyes(), n.getColor());
|
else guiHandler.showRolledDice(n.getEyes(), n.getColor());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
package pp.mdga.client.animation;
|
package pp.mdga.client.animation;
|
||||||
|
|
||||||
import com.jme3.math.Vector3f;
|
import com.jme3.math.Vector3f;
|
||||||
import com.jme3.renderer.RenderManager;
|
import pp.mdga.client.InitControl;
|
||||||
import com.jme3.renderer.ViewPort;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A control that smoothly moves a spatial from an initial position to an end position
|
* A control that smoothly moves a spatial from an initial position to an end position
|
||||||
|
|||||||
@@ -2,9 +2,7 @@
|
|||||||
|
|
||||||
import com.jme3.math.Quaternion;
|
import com.jme3.math.Quaternion;
|
||||||
import com.jme3.math.Vector3f;
|
import com.jme3.math.Vector3f;
|
||||||
import com.jme3.renderer.RenderManager;
|
import pp.mdga.client.InitControl;
|
||||||
import com.jme3.renderer.ViewPort;
|
|
||||||
import com.jme3.scene.control.AbstractControl;
|
|
||||||
import pp.mdga.game.BonusCard;
|
import pp.mdga.game.BonusCard;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
package pp.mdga.client.animation;
|
package pp.mdga.client.animation;
|
||||||
|
|
||||||
import com.jme3.renderer.RenderManager;
|
import pp.mdga.client.InitControl;
|
||||||
import com.jme3.renderer.ViewPort;
|
|
||||||
import com.jme3.scene.Spatial;
|
|
||||||
import com.jme3.scene.control.AbstractControl;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A control that applies a zoom effect to a spatial, smoothly scaling it in and out.
|
* A control that applies a zoom effect to a spatial, smoothly scaling it in and out.
|
||||||
|
|||||||
@@ -2,4 +2,7 @@
|
|||||||
|
|
||||||
import pp.mdga.client.Asset;
|
import pp.mdga.client.Asset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Record for holding Asset information
|
||||||
|
*/
|
||||||
record AssetOnMap(Asset asset, int x, int y, float rot) {}
|
record AssetOnMap(Asset asset, int x, int y, float rot) {}
|
||||||
|
|||||||
@@ -16,16 +16,24 @@
|
|||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BoardHandler is responsible for managing the game board in the MDGA client, including handling
|
||||||
|
* the initialization, movement, and management of game pieces and assets.
|
||||||
|
* It works closely with the MdgaApp to create and manipulate 3D models of assets, track player pieces,
|
||||||
|
* and manage movement across the game board.
|
||||||
|
*/
|
||||||
public class BoardHandler {
|
public class BoardHandler {
|
||||||
|
// Constants defining the grid size and elevation of the board
|
||||||
private static final float GRID_SIZE = 1.72f;
|
private static final float GRID_SIZE = 1.72f;
|
||||||
private static final float GRID_ELEVATION = 0.0f;
|
private static final float GRID_ELEVATION = 0.0f;
|
||||||
private static final String MAP_NAME = "Maps/map.mdga";
|
private static final String MAP_NAME = "Maps/map.mdga";
|
||||||
|
|
||||||
|
// The main application instance for accessing game assets and logic
|
||||||
private final MdgaApp app;
|
private final MdgaApp app;
|
||||||
|
|
||||||
|
// Collection of in-game assets and board elements
|
||||||
private ArrayList<NodeControl> infield;
|
private ArrayList<NodeControl> infield;
|
||||||
private Map<UUID, PieceControl> pieces;
|
private Map<UUID, PieceControl> pieces;
|
||||||
|
|
||||||
private Map<Color, List<AssetOnMap>> colorAssetsMap;
|
private Map<Color, List<AssetOnMap>> colorAssetsMap;
|
||||||
private Map<Color, List<NodeControl>> homeNodesMap;
|
private Map<Color, List<NodeControl>> homeNodesMap;
|
||||||
private Map<Color, List<NodeControl>> waitingNodesMap;
|
private Map<Color, List<NodeControl>> waitingNodesMap;
|
||||||
@@ -35,11 +43,11 @@ public class BoardHandler {
|
|||||||
|
|
||||||
private final Node rootNodeBoard;
|
private final Node rootNodeBoard;
|
||||||
private final Node rootNode;
|
private final Node rootNode;
|
||||||
|
|
||||||
private final FilterPostProcessor fpp;
|
private final FilterPostProcessor fpp;
|
||||||
|
|
||||||
private boolean isInitialised;
|
private boolean isInitialised;
|
||||||
|
|
||||||
|
// Flags and lists for handling piece selection and movement
|
||||||
private List<PieceControl> selectableOwnPieces;
|
private List<PieceControl> selectableOwnPieces;
|
||||||
private List<PieceControl> selectableEnemyPieces;
|
private List<PieceControl> selectableEnemyPieces;
|
||||||
private List<NodeControl> outlineNodes;
|
private List<NodeControl> outlineNodes;
|
||||||
@@ -47,6 +55,14 @@ public class BoardHandler {
|
|||||||
private PieceControl selectedEnemyPiece;
|
private PieceControl selectedEnemyPiece;
|
||||||
private DiceControl diceControl;
|
private DiceControl diceControl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new BoardHandler.
|
||||||
|
*
|
||||||
|
* @param app The main application instance
|
||||||
|
* @param rootNode The root node where the board will be attached
|
||||||
|
* @param fpp The post-processor for effects like shadows or filters
|
||||||
|
* @throws RuntimeException if the app is null
|
||||||
|
*/
|
||||||
public BoardHandler(MdgaApp app, Node rootNode, FilterPostProcessor fpp) {
|
public BoardHandler(MdgaApp app, Node rootNode, FilterPostProcessor fpp) {
|
||||||
if(app == null) throw new RuntimeException("app is null");
|
if(app == null) throw new RuntimeException("app is null");
|
||||||
|
|
||||||
@@ -57,6 +73,9 @@ public BoardHandler(MdgaApp app, Node rootNode, FilterPostProcessor fpp) {
|
|||||||
isInitialised = false;
|
isInitialised = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the game board by setting up the pieces and nodes.
|
||||||
|
*/
|
||||||
public void init() {
|
public void init() {
|
||||||
isInitialised = true;
|
isInitialised = true;
|
||||||
selectableOwnPieces = new ArrayList<>();
|
selectableOwnPieces = new ArrayList<>();
|
||||||
@@ -68,17 +87,30 @@ public void init() {
|
|||||||
rootNode.attachChild(rootNodeBoard);
|
rootNode.attachChild(rootNodeBoard);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shuts down the board handler by detaching all board-related nodes and clearing selected pieces.
|
||||||
|
*/
|
||||||
public void shutdown(){
|
public void shutdown(){
|
||||||
clearSelectable();
|
clearSelectable();
|
||||||
isInitialised = false;
|
isInitialised = false;
|
||||||
rootNode.detachChild(rootNodeBoard);
|
rootNode.detachChild(rootNodeBoard);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an asset to the map of player assets, ensuring that the player does not have too many assets.
|
||||||
|
*
|
||||||
|
* @param col The color of the player
|
||||||
|
* @param assetOnMap The asset to be added
|
||||||
|
* @throws RuntimeException if there are too many assets for the player
|
||||||
|
*/
|
||||||
private void addFigureToPlayerMap(Color col, AssetOnMap assetOnMap) {
|
private void addFigureToPlayerMap(Color col, AssetOnMap assetOnMap) {
|
||||||
List<AssetOnMap> inMap = addItemToMapList(colorAssetsMap, col, assetOnMap);
|
List<AssetOnMap> inMap = addItemToMapList(colorAssetsMap, col, assetOnMap);
|
||||||
if (inMap.size() > 4) throw new RuntimeException("to many assets for " + col);
|
if (inMap.size() > 4) throw new RuntimeException("to many assets for " + col);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the map with the assets loaded from the map file and corresponding nodes.
|
||||||
|
*/
|
||||||
private void initMap() {
|
private void initMap() {
|
||||||
pieces = new HashMap<>();
|
pieces = new HashMap<>();
|
||||||
colorAssetsMap = new HashMap<>();
|
colorAssetsMap = new HashMap<>();
|
||||||
@@ -120,6 +152,13 @@ private void initMap() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an asset to its corresponding color.
|
||||||
|
*
|
||||||
|
* @param asset The asset to be converted
|
||||||
|
* @return The color associated with the asset
|
||||||
|
* @throws RuntimeException if the asset is invalid
|
||||||
|
*/
|
||||||
private Color assetToColor(Asset asset) {
|
private Color assetToColor(Asset asset) {
|
||||||
return switch (asset) {
|
return switch (asset) {
|
||||||
case lw -> Color.AIRFORCE;
|
case lw -> Color.AIRFORCE;
|
||||||
@@ -130,6 +169,14 @@ private Color assetToColor(Asset asset) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a 3D model of an asset and adds it to the board.
|
||||||
|
*
|
||||||
|
* @param asset The asset to be displayed
|
||||||
|
* @param pos The position of the asset on the board
|
||||||
|
* @param rot The rotation of the asset
|
||||||
|
* @return The Spatial representation of the asset
|
||||||
|
*/
|
||||||
private Spatial createModel(Asset asset, Vector3f pos, float rot) {
|
private Spatial createModel(Asset asset, Vector3f pos, float rot) {
|
||||||
String modelName = asset.getModelPath();
|
String modelName = asset.getModelPath();
|
||||||
String texName = asset.getDiffPath();
|
String texName = asset.getDiffPath();
|
||||||
@@ -146,10 +193,23 @@ private Spatial createModel(Asset asset, Vector3f pos, float rot) {
|
|||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts grid coordinates to world space.
|
||||||
|
*
|
||||||
|
* @param x The x-coordinate on the grid
|
||||||
|
* @param y The y-coordinate on the grid
|
||||||
|
* @return The corresponding world position
|
||||||
|
*/
|
||||||
private static Vector3f gridToWorld(int x, int y) {
|
private static Vector3f gridToWorld(int x, int y) {
|
||||||
return new Vector3f(GRID_SIZE * x, GRID_SIZE * y, GRID_ELEVATION);
|
return new Vector3f(GRID_SIZE * x, GRID_SIZE * y, GRID_ELEVATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays an asset on the map at the given position with the specified rotation.
|
||||||
|
*
|
||||||
|
* @param assetOnMap The asset to be displayed.
|
||||||
|
* @return A spatial representation of the asset at the specified location and rotation.
|
||||||
|
*/
|
||||||
private Spatial displayAsset(AssetOnMap assetOnMap) {
|
private Spatial displayAsset(AssetOnMap assetOnMap) {
|
||||||
int x = assetOnMap.x();
|
int x = assetOnMap.x();
|
||||||
int y = assetOnMap.y();
|
int y = assetOnMap.y();
|
||||||
@@ -171,6 +231,13 @@ private void addHomeNode(Map<Color, List<NodeControl>> map, Color color, AssetOn
|
|||||||
if (homeNodes.size() > 4) throw new RuntimeException("too many homeNodes for " + color);
|
if (homeNodes.size() > 4) throw new RuntimeException("too many homeNodes for " + color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the rotation angle required to move a piece from one position to another.
|
||||||
|
*
|
||||||
|
* @param prev The previous position.
|
||||||
|
* @param next The target position.
|
||||||
|
* @return The rotation angle in degrees.
|
||||||
|
*/
|
||||||
private float getRotationMove(Vector3f prev, Vector3f next) {
|
private float getRotationMove(Vector3f prev, Vector3f next) {
|
||||||
Vector3f direction = next.subtract(prev).normalizeLocal();
|
Vector3f direction = next.subtract(prev).normalizeLocal();
|
||||||
//I had to reverse dir.y, because then it worked.
|
//I had to reverse dir.y, because then it worked.
|
||||||
@@ -179,6 +246,14 @@ private float getRotationMove(Vector3f prev, Vector3f next) {
|
|||||||
return newRot;
|
return newRot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively moves a piece from its current index to the destination index,
|
||||||
|
* to keep track of the piece rotation.
|
||||||
|
*
|
||||||
|
* @param uuid The UUID of the piece to move.
|
||||||
|
* @param curIndex The current index of the piece.
|
||||||
|
* @param moveIndex The target index to move the piece to.
|
||||||
|
*/
|
||||||
private void movePieceRek(UUID uuid, int curIndex, int moveIndex){
|
private void movePieceRek(UUID uuid, int curIndex, int moveIndex){
|
||||||
if (curIndex == moveIndex) return;
|
if (curIndex == moveIndex) return;
|
||||||
|
|
||||||
@@ -211,6 +286,12 @@ private Vector3f getWaitingPos(Color color){
|
|||||||
return getMeanPosition(waitingNodesMap.get(color).stream().map(NodeControl::getLocation).toList());
|
return getMeanPosition(waitingNodesMap.get(color).stream().map(NodeControl::getLocation).toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the mean position of a list of vectors.
|
||||||
|
*
|
||||||
|
* @param vectors The list of vectors.
|
||||||
|
* @return The mean position as a Vector3f.
|
||||||
|
*/
|
||||||
public static Vector3f getMeanPosition(List<Vector3f> vectors) {
|
public static Vector3f getMeanPosition(List<Vector3f> vectors) {
|
||||||
if (vectors.isEmpty()) return new Vector3f(0, 0, 0);
|
if (vectors.isEmpty()) return new Vector3f(0, 0, 0);
|
||||||
|
|
||||||
@@ -221,7 +302,13 @@ public static Vector3f getMeanPosition(List<Vector3f> vectors) {
|
|||||||
return sum.divide(vectors.size());
|
return sum.divide(vectors.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
//public methods****************************************************************************************************
|
/**
|
||||||
|
* Adds a player to the game by associating a color and a list of UUIDs to corresponding assets and waiting nodes.
|
||||||
|
*
|
||||||
|
* @param color the color of the player
|
||||||
|
* @param uuid the list of UUIDs representing the player's assets
|
||||||
|
* @throws RuntimeException if the number of assets or waiting nodes does not match the provided UUIDs
|
||||||
|
*/
|
||||||
public void addPlayer(Color color, List<UUID> uuid) {
|
public void addPlayer(Color color, List<UUID> uuid) {
|
||||||
|
|
||||||
List<AssetOnMap> playerAssets = colorAssetsMap.get(color);
|
List<AssetOnMap> playerAssets = colorAssetsMap.get(color);
|
||||||
@@ -254,7 +341,14 @@ public void addPlayer(Color color, List<UUID> uuid) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void moveHomePiece(UUID uuid, int index){
|
/**
|
||||||
|
* Moves a piece to its corresponding home node based on the given index.
|
||||||
|
*
|
||||||
|
* @param uuid the UUID of the piece to move
|
||||||
|
* @param index the index of the home node to move the piece to
|
||||||
|
* @throws RuntimeException if the UUID is not mapped to a color or if the home nodes are not properly defined
|
||||||
|
*/
|
||||||
|
private void moveHomePiece(UUID uuid, int index){
|
||||||
|
|
||||||
Color color = pieceColor.get(uuid);
|
Color color = pieceColor.get(uuid);
|
||||||
if(color == null) throw new RuntimeException("uuid is not mapped to a color");
|
if(color == null) throw new RuntimeException("uuid is not mapped to a color");
|
||||||
@@ -275,7 +369,15 @@ public void moveHomePiece(UUID uuid, int index){
|
|||||||
app.getModelSynchronize().animationEnd();
|
app.getModelSynchronize().animationEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void movePieceStart(UUID uuid, int nodeIndex){
|
/**
|
||||||
|
* Starts the movement of a piece to a target node based on the given index.
|
||||||
|
*
|
||||||
|
* @param uuid the UUID of the piece to move
|
||||||
|
* @param nodeIndex the index of the target node to move the piece to
|
||||||
|
* @throws RuntimeException if the UUID is not mapped to a color or the piece control is not found
|
||||||
|
* @throws IllegalArgumentException if the node index is invalid
|
||||||
|
*/
|
||||||
|
private void movePieceStart(UUID uuid, int nodeIndex){
|
||||||
|
|
||||||
// Farbe des Pieces abrufen
|
// Farbe des Pieces abrufen
|
||||||
Color color = pieceColor.get(uuid);
|
Color color = pieceColor.get(uuid);
|
||||||
@@ -298,13 +400,26 @@ public void movePieceStart(UUID uuid, int nodeIndex){
|
|||||||
app.getModelSynchronize().animationEnd();
|
app.getModelSynchronize().animationEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void movePiece(UUID uuid, int curIndex, int moveIndex){
|
/**
|
||||||
|
* Moves a piece from its current position to the target position based on the given indexes.
|
||||||
|
*
|
||||||
|
* @param uuid the UUID of the piece to move
|
||||||
|
* @param curIndex the current index of the piece
|
||||||
|
* @param moveIndex the target index of the move
|
||||||
|
*/
|
||||||
|
private void movePiece(UUID uuid, int curIndex, int moveIndex){
|
||||||
|
|
||||||
movePieceRek(uuid, curIndex, moveIndex);
|
movePieceRek(uuid, curIndex, moveIndex);
|
||||||
app.getModelSynchronize().animationEnd();
|
app.getModelSynchronize().animationEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void throwPiece(UUID uuid){
|
/**
|
||||||
|
* Throws a piece to the next available waiting node and updates the waiting node mapping.
|
||||||
|
*
|
||||||
|
* @param uuid the UUID of the piece to throw
|
||||||
|
* @throws RuntimeException if the UUID is not mapped to a color or if no available waiting nodes are found
|
||||||
|
*/
|
||||||
|
private void throwPiece(UUID uuid){
|
||||||
|
|
||||||
// Farbe des Pieces abrufen
|
// Farbe des Pieces abrufen
|
||||||
Color color = pieceColor.get(uuid);
|
Color color = pieceColor.get(uuid);
|
||||||
@@ -331,59 +446,65 @@ public void throwPiece(UUID uuid){
|
|||||||
app.getModelSynchronize().animationEnd();
|
app.getModelSynchronize().animationEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Activates the shield for the specified piece.
|
||||||
|
*
|
||||||
|
* @param uuid the UUID of the piece to shield
|
||||||
|
*/
|
||||||
public void shieldPiece(UUID uuid){
|
public void shieldPiece(UUID uuid){
|
||||||
|
|
||||||
pieces.get(uuid).activateShield();
|
pieces.get(uuid).activateShield();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deactivates the shield for the specified piece.
|
||||||
|
*
|
||||||
|
* @param uuid the UUID of the piece to unshield
|
||||||
|
*/
|
||||||
public void unshieldPiece(UUID uuid){
|
public void unshieldPiece(UUID uuid){
|
||||||
|
|
||||||
pieces.get(uuid).deactivateShield();
|
pieces.get(uuid).deactivateShield();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Suppresses the shield for the specified piece.
|
||||||
|
*
|
||||||
|
* @param uuid the UUID of the piece to suppress the shield
|
||||||
|
*/
|
||||||
public void suppressShield(UUID uuid){
|
public void suppressShield(UUID uuid){
|
||||||
|
|
||||||
pieces.get(uuid).suppressShield();
|
pieces.get(uuid).suppressShield();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void swapPieces(PieceControl p1, PieceControl p2, Vector3f loc1, float rot1, Vector3f loc2, float rot2){
|
/**
|
||||||
|
* Swaps the positions and rotations of two pieces.
|
||||||
// PieceControl piece1Control = pieces.get(piece1);
|
*
|
||||||
// PieceControl piece2Control = pieces.get(piece2);
|
* @param p1 the first piece to swap
|
||||||
|
* @param p2 the second piece to swap
|
||||||
// if(piece1Control == null) throw new RuntimeException("piece1 UUID is not valid");
|
* @param loc1 the original location of the first piece
|
||||||
// if(piece2Control == null) throw new RuntimeException("piece2 UUID is not valid");
|
* @param rot1 the original rotation of the first piece
|
||||||
|
* @param loc2 the original location of the second piece
|
||||||
// float rot1 = piece1Control.getRotation();
|
* @param rot2 the original rotation of the second piece
|
||||||
// float rot2 = piece2Control.getRotation();
|
*/
|
||||||
|
private void swapPieces(PieceControl p1, PieceControl p2, Vector3f loc1, float rot1, Vector3f loc2, float rot2){
|
||||||
// piece1Control.setRotation(rot2);
|
|
||||||
// piece2Control.setRotation(rot1);
|
|
||||||
|
|
||||||
// Vector3f pos1 = piece1Control.getLocation().clone();
|
|
||||||
// Vector3f pos2 = piece2Control.getLocation().clone();
|
|
||||||
|
|
||||||
// piece1Control.setLocation(pos2);
|
|
||||||
// piece2Control.setLocation(pos1);
|
|
||||||
|
|
||||||
p1.setLocation(loc2);
|
p1.setLocation(loc2);
|
||||||
p2.setLocation(loc1);
|
p2.setLocation(loc1);
|
||||||
|
|
||||||
p1.setRotation(rot2);
|
p1.setRotation(rot2);
|
||||||
p2.setRotation(rot1);
|
p2.setRotation(rot1);
|
||||||
|
|
||||||
|
|
||||||
app.getModelSynchronize().animationEnd();
|
app.getModelSynchronize().animationEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void highlight(UUID uuid, boolean bool){
|
/**
|
||||||
|
* Outlines the possible move nodes for a list of pieces based on the move indices and whether it's a home move.
|
||||||
pieces.get(uuid).highlight(bool);
|
*
|
||||||
pieces.get(uuid).setSelectable(bool);
|
* @param pieces the list of UUIDs representing the pieces to outline
|
||||||
|
* @param moveIndexe the list of indices for the target move nodes
|
||||||
}
|
* @param homeMoves the list indicating whether the move is a home move
|
||||||
|
* @throws RuntimeException if the sizes of the input lists do not match
|
||||||
//called when (dice) moveNum is received from server to display the movable pieces and corresponding moveNodes
|
*/
|
||||||
public void outlineMove(List<UUID> pieces, List<Integer> moveIndexe, List<Boolean> homeMoves) {
|
public void outlineMove(List<UUID> pieces, List<Integer> moveIndexe, List<Boolean> homeMoves) {
|
||||||
if(pieces.size() != moveIndexe.size() || pieces.size() != homeMoves.size()) throw new RuntimeException("arrays are not the same size");
|
if(pieces.size() != moveIndexe.size() || pieces.size() != homeMoves.size()) throw new RuntimeException("arrays are not the same size");
|
||||||
|
|
||||||
@@ -413,7 +534,12 @@ public void outlineMove(List<UUID> pieces, List<Integer> moveIndexe, List<Boolea
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//called when swap notification is received to highlight and select own/enemy pieces
|
/**
|
||||||
|
* Outlines the pieces that can be swapped based on the provided own and enemy pieces.
|
||||||
|
*
|
||||||
|
* @param ownPieces the list of UUIDs representing the player's pieces
|
||||||
|
* @param enemyPieces the list of UUIDs representing the enemy's pieces
|
||||||
|
*/
|
||||||
public void outlineSwap(List<UUID> ownPieces, List<UUID> enemyPieces){
|
public void outlineSwap(List<UUID> ownPieces, List<UUID> enemyPieces){
|
||||||
|
|
||||||
selectableEnemyPieces.clear();
|
selectableEnemyPieces.clear();
|
||||||
@@ -437,6 +563,11 @@ public void outlineSwap(List<UUID> ownPieces, List<UUID> enemyPieces){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Outlines the pieces that can be shielded based on the provided list of pieces.
|
||||||
|
*
|
||||||
|
* @param pieces the list of UUIDs representing the pieces to be shielded
|
||||||
|
*/
|
||||||
public void outlineShield(List<UUID> pieces){
|
public void outlineShield(List<UUID> pieces){
|
||||||
selectableOwnPieces.clear();
|
selectableOwnPieces.clear();
|
||||||
selectableEnemyPieces.clear();
|
selectableEnemyPieces.clear();
|
||||||
@@ -452,7 +583,11 @@ public void outlineShield(List<UUID> pieces){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//called from inputSynchronizer when a piece is selectable
|
/**
|
||||||
|
* Selects a piece from either the own or enemy pieces based on the input and deselects others if needed.
|
||||||
|
*
|
||||||
|
* @param pieceSelected the PieceControl instance representing the piece selected by the user
|
||||||
|
*/
|
||||||
public void pieceSelect(PieceControl pieceSelected) {
|
public void pieceSelect(PieceControl pieceSelected) {
|
||||||
boolean isSelected = pieceSelected.isSelected();
|
boolean isSelected = pieceSelected.isSelected();
|
||||||
if(selectableOwnPieces.contains(pieceSelected)){
|
if(selectableOwnPieces.contains(pieceSelected)){
|
||||||
@@ -486,7 +621,9 @@ else if(selectableEnemyPieces.contains(pieceSelected)) {
|
|||||||
app.getModelSynchronize().select(getKeyByValue(pieces, selectedOwnPiece), getKeyByValue(pieces, selectedEnemyPiece));
|
app.getModelSynchronize().select(getKeyByValue(pieces, selectedOwnPiece), getKeyByValue(pieces, selectedEnemyPiece));
|
||||||
}
|
}
|
||||||
|
|
||||||
//called when view is no longer needed to select pieces
|
/**
|
||||||
|
* Clears all highlighted, selectable, and selected pieces and nodes.
|
||||||
|
*/
|
||||||
public void clearSelectable(){
|
public void clearSelectable(){
|
||||||
for(PieceControl p : selectableEnemyPieces) {
|
for(PieceControl p : selectableEnemyPieces) {
|
||||||
p.unSelect();
|
p.unSelect();
|
||||||
@@ -508,16 +645,20 @@ public void clearSelectable(){
|
|||||||
selectedOwnPiece = null;
|
selectedOwnPiece = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void enableHover(UUID uuid){
|
/**
|
||||||
pieces.get(uuid).setHoverable(true);
|
* Displays the dice for the specified color at the appropriate position.
|
||||||
}
|
*
|
||||||
|
* @param color the color of the player whose dice should be displayed
|
||||||
|
*/
|
||||||
public void showDice(Color color){
|
public void showDice(Color color){
|
||||||
rootNodeBoard.attachChild(diceControl.getSpatial());
|
rootNodeBoard.attachChild(diceControl.getSpatial());
|
||||||
diceControl.setPos(getWaitingPos(color).add(new Vector3f(0,0,4)));
|
diceControl.setPos(getWaitingPos(color).add(new Vector3f(0,0,4)));
|
||||||
diceControl.spin();
|
diceControl.spin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hides the dice from the view.
|
||||||
|
*/
|
||||||
public void hideDice(){
|
public void hideDice(){
|
||||||
diceControl.hide();
|
diceControl.hide();
|
||||||
}
|
}
|
||||||
@@ -531,6 +672,13 @@ private <K, V> K getKeyByValue(Map<K, V> map, V value) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Animates the movement of a piece from its current index to a target index.
|
||||||
|
*
|
||||||
|
* @param uuid the UUID of the piece to animate
|
||||||
|
* @param curIndex the current index of the piece
|
||||||
|
* @param moveIndex the target index to animate the piece to
|
||||||
|
*/
|
||||||
public void movePieceAnim(UUID uuid, int curIndex, int moveIndex){
|
public void movePieceAnim(UUID uuid, int curIndex, int moveIndex){
|
||||||
pieces.get(uuid).getSpatial().addControl(new MoveControl(
|
pieces.get(uuid).getSpatial().addControl(new MoveControl(
|
||||||
infield.get(curIndex).getLocation(),
|
infield.get(curIndex).getLocation(),
|
||||||
@@ -538,6 +686,12 @@ public void movePieceAnim(UUID uuid, int curIndex, int moveIndex){
|
|||||||
()->movePiece(uuid,curIndex,moveIndex)));
|
()->movePiece(uuid,curIndex,moveIndex)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Animates the movement of a piece to its home position based on the given home index.
|
||||||
|
*
|
||||||
|
* @param uuid the UUID of the piece to animate
|
||||||
|
* @param homeIndex the index of the home node to move the piece to
|
||||||
|
*/
|
||||||
public void movePieceHomeAnim(UUID uuid, int homeIndex){
|
public void movePieceHomeAnim(UUID uuid, int homeIndex){
|
||||||
pieces.get(uuid).getSpatial().addControl(new MoveControl(
|
pieces.get(uuid).getSpatial().addControl(new MoveControl(
|
||||||
pieces.get(uuid).getLocation(),
|
pieces.get(uuid).getLocation(),
|
||||||
@@ -545,6 +699,12 @@ public void movePieceHomeAnim(UUID uuid, int homeIndex){
|
|||||||
()->moveHomePiece(uuid,homeIndex)));
|
()->moveHomePiece(uuid,homeIndex)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Animates the start of the movement of a piece to a target index.
|
||||||
|
*
|
||||||
|
* @param uuid the UUID of the piece to animate
|
||||||
|
* @param moveIndex the target index to animate the piece to
|
||||||
|
*/
|
||||||
public void movePieceStartAnim(UUID uuid, int moveIndex){
|
public void movePieceStartAnim(UUID uuid, int moveIndex){
|
||||||
pieces.get(uuid).getSpatial().addControl(new MoveControl(
|
pieces.get(uuid).getSpatial().addControl(new MoveControl(
|
||||||
pieces.get(uuid).getLocation(),
|
pieces.get(uuid).getLocation(),
|
||||||
@@ -553,6 +713,11 @@ public void movePieceStartAnim(UUID uuid, int moveIndex){
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Animates the throwing of a piece to the next available waiting node.
|
||||||
|
*
|
||||||
|
* @param uuid the UUID of the piece to animate
|
||||||
|
*/
|
||||||
public void throwPieceAnim(UUID uuid){
|
public void throwPieceAnim(UUID uuid){
|
||||||
pieces.get(uuid).getSpatial().addControl(new MoveControl(
|
pieces.get(uuid).getSpatial().addControl(new MoveControl(
|
||||||
pieces.get(uuid).getLocation(),
|
pieces.get(uuid).getLocation(),
|
||||||
@@ -561,6 +726,12 @@ public void throwPieceAnim(UUID uuid){
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Animates the swapping of two pieces by swapping their positions and rotations.
|
||||||
|
*
|
||||||
|
* @param piece1 the UUID of the first piece
|
||||||
|
* @param piece2 the UUID of the second piece
|
||||||
|
*/
|
||||||
public void swapPieceAnim(UUID piece1, UUID piece2){
|
public void swapPieceAnim(UUID piece1, UUID piece2){
|
||||||
PieceControl piece1Control = pieces.get(piece1);
|
PieceControl piece1Control = pieces.get(piece1);
|
||||||
PieceControl piece2Control = pieces.get(piece2);
|
PieceControl piece2Control = pieces.get(piece2);
|
||||||
@@ -582,6 +753,13 @@ public void swapPieceAnim(UUID piece1, UUID piece2){
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the next available waiting node for the specified color.
|
||||||
|
*
|
||||||
|
* @param color the color of the player to get the next waiting node for
|
||||||
|
* @return the next available NodeControl for the specified color
|
||||||
|
* @throws IllegalStateException if no available waiting nodes are found for the color
|
||||||
|
*/
|
||||||
private NodeControl getNextWaitingNode(Color color) {
|
private NodeControl getNextWaitingNode(Color color) {
|
||||||
List<NodeControl> nodes = waitingNodesMap.get(color);
|
List<NodeControl> nodes = waitingNodesMap.get(color);
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,10 @@
|
|||||||
import pp.mdga.client.MdgaApp;
|
import pp.mdga.client.MdgaApp;
|
||||||
import pp.mdga.game.Color;
|
import pp.mdga.game.Color;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the camera position, rotation, and lighting effects for the game.
|
||||||
|
* Provides methods for camera initialization, updates based on user input, and shutdown operations.
|
||||||
|
*/
|
||||||
public class CameraHandler {
|
public class CameraHandler {
|
||||||
MdgaApp app;
|
MdgaApp app;
|
||||||
|
|
||||||
@@ -34,6 +38,12 @@ public class CameraHandler {
|
|||||||
private boolean init;
|
private boolean init;
|
||||||
private boolean initRot;
|
private boolean initRot;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for the CameraHandler. Initializes the camera settings and lighting.
|
||||||
|
*
|
||||||
|
* @param app The main application instance that provides the camera and root node.
|
||||||
|
* @param fpp The FilterPostProcessor used for post-processing effects.
|
||||||
|
*/
|
||||||
public CameraHandler(MdgaApp app, FilterPostProcessor fpp) {
|
public CameraHandler(MdgaApp app, FilterPostProcessor fpp) {
|
||||||
init = false;
|
init = false;
|
||||||
initRot = false;
|
initRot = false;
|
||||||
@@ -61,6 +71,12 @@ public CameraHandler(MdgaApp app, FilterPostProcessor fpp) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the camera with a specific color orientation.
|
||||||
|
* Adds lights, sky, and shadow filters to the scene.
|
||||||
|
*
|
||||||
|
* @param ownColor The color that defines the initial camera view angle.
|
||||||
|
*/
|
||||||
public void init(Color ownColor) {
|
public void init(Color ownColor) {
|
||||||
app.getRootNode().addLight(sun);
|
app.getRootNode().addLight(sun);
|
||||||
app.getRootNode().addLight(ambient);
|
app.getRootNode().addLight(ambient);
|
||||||
@@ -72,6 +88,10 @@ public void init(Color ownColor) {
|
|||||||
app.getInputSynchronize().setRotation(getInitAngleByColor(ownColor)*2);
|
app.getInputSynchronize().setRotation(getInitAngleByColor(ownColor)*2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shuts down the camera handler by removing all lights, sky, and filters,
|
||||||
|
* and resets the camera position and rotation to its default state.
|
||||||
|
*/
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
app.getRootNode().removeLight(sun);
|
app.getRootNode().removeLight(sun);
|
||||||
app.getRootNode().removeLight(ambient);
|
app.getRootNode().removeLight(ambient);
|
||||||
@@ -84,6 +104,13 @@ public void shutdown() {
|
|||||||
fpp.removeFilter(dlsf);
|
fpp.removeFilter(dlsf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the camera position and rotation based on user input (scroll and rotation).
|
||||||
|
* Adjusts the vertical angle and radius based on zoom and rotation values.
|
||||||
|
*
|
||||||
|
* @param scroll The scroll input, determining zoom level.
|
||||||
|
* @param rotation The rotation input, determining camera orientation.
|
||||||
|
*/
|
||||||
public void update(float scroll, float rotation) {
|
public void update(float scroll, float rotation) {
|
||||||
if(!init) return;
|
if(!init) return;
|
||||||
float scrollValue = Math.max(0, Math.min(scroll, 100));
|
float scrollValue = Math.max(0, Math.min(scroll, 100));
|
||||||
@@ -117,6 +144,12 @@ public void update(float scroll, float rotation) {
|
|||||||
app.getCamera().lookAt(Vector3f.ZERO, Vector3f.UNIT_Z);
|
app.getCamera().lookAt(Vector3f.ZERO, Vector3f.UNIT_Z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the camera angle based on the specified color.
|
||||||
|
*
|
||||||
|
* @param color The color used to determine the camera angle.
|
||||||
|
* @return The camera angle in degrees.
|
||||||
|
*/
|
||||||
private float getAngleByColor(Color color){
|
private float getAngleByColor(Color color){
|
||||||
return switch (color){
|
return switch (color){
|
||||||
case ARMY -> 0;
|
case ARMY -> 0;
|
||||||
@@ -127,6 +160,12 @@ private float getAngleByColor(Color color){
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the initial camera angle based on the specified color.
|
||||||
|
*
|
||||||
|
* @param color The color used to determine the camera angle.
|
||||||
|
* @return The initial camera angle in degrees.
|
||||||
|
*/
|
||||||
private float getInitAngleByColor(Color color){
|
private float getInitAngleByColor(Color color){
|
||||||
return (getAngleByColor(color) + 180) % 360;
|
return (getAngleByColor(color) + 180) % 360;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,11 +10,27 @@
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A utility class for loading and parsing map data from a file.
|
||||||
|
* The map contains asset names and coordinates for objects placed on the map.
|
||||||
|
*/
|
||||||
class MapLoader {
|
class MapLoader {
|
||||||
|
/**
|
||||||
|
* Private constructor to prevent instantiation.
|
||||||
|
*/
|
||||||
private MapLoader() {
|
private MapLoader() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads a map file and parses its contents into a list of assets and their positions.
|
||||||
|
* Each line in the map file defines an asset, its coordinates, and its rotation.
|
||||||
|
*
|
||||||
|
* @param mapName The name of the map file to load. The file is expected to be located in the resources directory.
|
||||||
|
* @return A list of {@link AssetOnMap} objects representing the assets placed on the map.
|
||||||
|
* @throws IOException If an error occurs while reading the map file.
|
||||||
|
* @throws IllegalArgumentException If the map file contains invalid data.
|
||||||
|
*/
|
||||||
public static List<AssetOnMap> loadMap(String mapName) {
|
public static List<AssetOnMap> loadMap(String mapName) {
|
||||||
List<AssetOnMap> assetsOnMap = new ArrayList<>();
|
List<AssetOnMap> assetsOnMap = new ArrayList<>();
|
||||||
|
|
||||||
@@ -60,6 +76,13 @@ public static List<AssetOnMap> loadMap(String mapName) {
|
|||||||
return assetsOnMap;
|
return assetsOnMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the corresponding {@link Asset} for a given asset name.
|
||||||
|
*
|
||||||
|
* @param assetName The name of the asset to load.
|
||||||
|
* @return The {@link Asset} associated with the given name.
|
||||||
|
* @throws IllegalStateException If the asset name is unrecognized.
|
||||||
|
*/
|
||||||
private static Asset getLoadedAsset(String assetName) {
|
private static Asset getLoadedAsset(String assetName) {
|
||||||
return switch (assetName) {
|
return switch (assetName) {
|
||||||
case "lw" -> Asset.lw;
|
case "lw" -> Asset.lw;
|
||||||
|
|||||||
@@ -8,19 +8,40 @@
|
|||||||
import com.jme3.scene.control.AbstractControl;
|
import com.jme3.scene.control.AbstractControl;
|
||||||
import pp.mdga.client.MdgaApp;
|
import pp.mdga.client.MdgaApp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A control that adds highlighting functionality to a node in the game.
|
||||||
|
* This class extends {@link OutlineControl} to add an outline effect when the node is highlighted.
|
||||||
|
*/
|
||||||
public class NodeControl extends OutlineControl {
|
public class NodeControl extends OutlineControl {
|
||||||
|
|
||||||
private static final ColorRGBA OUTLINE_HIGHLIGHT_COLOR = ColorRGBA.White;
|
private static final ColorRGBA OUTLINE_HIGHLIGHT_COLOR = ColorRGBA.White;
|
||||||
private static final int OUTLINE_HIGHLIGHT_WIDTH = 6;
|
private static final int OUTLINE_HIGHLIGHT_WIDTH = 6;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a {@link NodeControl} with the specified application and post processor.
|
||||||
|
* This constructor sets up the necessary elements for highlighting functionality.
|
||||||
|
*
|
||||||
|
* @param app The {@link MdgaApp} instance to use for the application context.
|
||||||
|
* @param fpp The {@link FilterPostProcessor} to apply post-processing effects.
|
||||||
|
*/
|
||||||
public NodeControl(MdgaApp app, FilterPostProcessor fpp) {
|
public NodeControl(MdgaApp app, FilterPostProcessor fpp) {
|
||||||
super(app, fpp);
|
super(app, fpp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the location of the node in 3D space.
|
||||||
|
* This is the node's local translation in the scene.
|
||||||
|
*
|
||||||
|
* @return The {@link Vector3f} representing the node's location.
|
||||||
|
*/
|
||||||
public Vector3f getLocation(){
|
public Vector3f getLocation(){
|
||||||
return this.getSpatial().getLocalTranslation();
|
return this.getSpatial().getLocalTranslation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Highlights the node by applying an outline effect.
|
||||||
|
* The outline color and width are predefined as white and 6, respectively.
|
||||||
|
*/
|
||||||
public void highlight() {
|
public void highlight() {
|
||||||
super.outline(OUTLINE_HIGHLIGHT_COLOR, OUTLINE_HIGHLIGHT_WIDTH);
|
super.outline(OUTLINE_HIGHLIGHT_COLOR, OUTLINE_HIGHLIGHT_WIDTH);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,16 +3,19 @@
|
|||||||
import com.jme3.math.ColorRGBA;
|
import com.jme3.math.ColorRGBA;
|
||||||
import com.jme3.post.FilterPostProcessor;
|
import com.jme3.post.FilterPostProcessor;
|
||||||
import com.jme3.renderer.Camera;
|
import com.jme3.renderer.Camera;
|
||||||
import com.jme3.renderer.RenderManager;
|
|
||||||
import com.jme3.renderer.ViewPort;
|
|
||||||
import com.jme3.scene.Spatial;
|
|
||||||
import com.jme3.scene.control.AbstractControl;
|
|
||||||
import pp.mdga.client.MdgaApp;
|
import pp.mdga.client.MdgaApp;
|
||||||
|
import pp.mdga.client.InitControl;
|
||||||
import pp.mdga.client.outline.SelectObjectOutliner;
|
import pp.mdga.client.outline.SelectObjectOutliner;
|
||||||
|
|
||||||
public class OutlineControl extends AbstractControl {
|
/**
|
||||||
private static final int THICKNESS_DEFAULT = 6;
|
* A control that provides outline functionality to a spatial object.
|
||||||
|
* This class is responsible for adding an outline effect to a spatial
|
||||||
|
* object, allowing it to be highlighted or deselected.
|
||||||
|
*/
|
||||||
|
public class OutlineControl extends InitControl {
|
||||||
|
/** The {@link SelectObjectOutliner} responsible for managing the outline effect. */
|
||||||
private final SelectObjectOutliner outlineOwn;
|
private final SelectObjectOutliner outlineOwn;
|
||||||
|
private static final int THICKNESS_DEFAULT = 6;
|
||||||
private MdgaApp app;
|
private MdgaApp app;
|
||||||
|
|
||||||
|
|
||||||
@@ -31,44 +34,33 @@ public OutlineControl(MdgaApp app, FilterPostProcessor fpp, Camera cam, int thic
|
|||||||
outlineOwn = new SelectObjectOutliner(thickness, fpp, app.getRenderManager(), app.getAssetManager(), cam, app);
|
outlineOwn = new SelectObjectOutliner(thickness, fpp, app.getRenderManager(), app.getAssetManager(), cam, app);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies an outline to the spatial object with the given color.
|
||||||
|
*
|
||||||
|
* @param color The {@link ColorRGBA} representing the color of the outline.
|
||||||
|
*/
|
||||||
public void outline(ColorRGBA color){
|
public void outline(ColorRGBA color){
|
||||||
outlineOwn.select(spatial, color);
|
outlineOwn.select(spatial, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies an outline to the spatial object with the given color and width.
|
||||||
|
*
|
||||||
|
* @param color The {@link ColorRGBA} representing the color of the outline.
|
||||||
|
* @param width The width of the outline.
|
||||||
|
*/
|
||||||
public void outline(ColorRGBA color, int width){
|
public void outline(ColorRGBA color, int width){
|
||||||
deOutline();
|
deOutline();
|
||||||
outlineOwn.select(spatial, color, width);
|
outlineOwn.select(spatial, color, width);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the outline effect from the spatial object.
|
||||||
|
*/
|
||||||
public void deOutline(){
|
public void deOutline(){
|
||||||
outlineOwn.deselect(spatial);
|
outlineOwn.deselect(spatial);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void controlUpdate(float tpf) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void controlRender(RenderManager rm, ViewPort vp) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void initSpatial(){
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setSpatial(Spatial spatial){
|
|
||||||
if(this.spatial == null && spatial != null){
|
|
||||||
super.setSpatial(spatial);
|
|
||||||
initSpatial();
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
super.setSpatial(spatial);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public MdgaApp getApp() {
|
public MdgaApp getApp() {
|
||||||
return app;
|
return app;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,12 @@
|
|||||||
import pp.mdga.client.Asset;
|
import pp.mdga.client.Asset;
|
||||||
import pp.mdga.client.MdgaApp;
|
import pp.mdga.client.MdgaApp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A control that manages the behavior and properties of a game piece, such as its rotation,
|
||||||
|
* position, shield activation, and highlighting. This class extends {@link OutlineControl}
|
||||||
|
* to provide outline functionality and includes additional features like shield effects,
|
||||||
|
* hover states, and selection states.
|
||||||
|
*/
|
||||||
public class PieceControl extends OutlineControl {
|
public class PieceControl extends OutlineControl {
|
||||||
private final float initRotation;
|
private final float initRotation;
|
||||||
private final AssetManager assetManager;
|
private final AssetManager assetManager;
|
||||||
@@ -43,7 +49,15 @@ public class PieceControl extends OutlineControl {
|
|||||||
private boolean selectable;
|
private boolean selectable;
|
||||||
private boolean select;
|
private boolean select;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a {@link PieceControl} with the specified initial rotation, asset manager,
|
||||||
|
* application, and post-processor.
|
||||||
|
*
|
||||||
|
* @param initRotation The initial rotation of the piece in degrees.
|
||||||
|
* @param assetManager The {@link AssetManager} used for loading models and materials.
|
||||||
|
* @param app The {@link MdgaApp} instance to use for the application context.
|
||||||
|
* @param fpp The {@link FilterPostProcessor} to apply post-processing effects.
|
||||||
|
*/
|
||||||
public PieceControl(float initRotation, AssetManager assetManager, MdgaApp app, FilterPostProcessor fpp){
|
public PieceControl(float initRotation, AssetManager assetManager, MdgaApp app, FilterPostProcessor fpp){
|
||||||
super(app, fpp);
|
super(app, fpp);
|
||||||
this.parentNode = new Node();
|
this.parentNode = new Node();
|
||||||
@@ -59,10 +73,20 @@ public PieceControl(float initRotation, AssetManager assetManager, MdgaApp app,
|
|||||||
select = false;
|
select = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current rotation of the piece in degrees.
|
||||||
|
*
|
||||||
|
* @return The rotation of the piece in degrees.
|
||||||
|
*/
|
||||||
public float getRotation() {
|
public float getRotation() {
|
||||||
return (float) Math.toDegrees(spatial.getLocalRotation().toAngleAxis(new Vector3f(0,0,1)));
|
return (float) Math.toDegrees(spatial.getLocalRotation().toAngleAxis(new Vector3f(0,0,1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the rotation of the piece to the specified value in degrees.
|
||||||
|
*
|
||||||
|
* @param rot The rotation in degrees to set.
|
||||||
|
*/
|
||||||
public void setRotation(float rot){
|
public void setRotation(float rot){
|
||||||
if(rot < 0) rot =- 360;
|
if(rot < 0) rot =- 360;
|
||||||
|
|
||||||
@@ -71,10 +95,20 @@ public void setRotation(float rot){
|
|||||||
spatial.setLocalRotation(quaternion);
|
spatial.setLocalRotation(quaternion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current location (position) of the piece.
|
||||||
|
*
|
||||||
|
* @return The location of the piece as a {@link Vector3f}.
|
||||||
|
*/
|
||||||
public Vector3f getLocation(){
|
public Vector3f getLocation(){
|
||||||
return spatial.getLocalTranslation();
|
return spatial.getLocalTranslation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the piece control every frame. If the shield is active, it will rotate.
|
||||||
|
*
|
||||||
|
* @param delta The time difference between frames (time per frame).
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void controlUpdate(float delta) {
|
protected void controlUpdate(float delta) {
|
||||||
if(shieldRing != null){
|
if(shieldRing != null){
|
||||||
@@ -82,10 +116,19 @@ protected void controlUpdate(float delta) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the location (position) of the piece.
|
||||||
|
*
|
||||||
|
* @param loc The location to set as a {@link Vector3f}.
|
||||||
|
*/
|
||||||
public void setLocation(Vector3f loc){
|
public void setLocation(Vector3f loc){
|
||||||
this.spatial.setLocalTranslation(loc);
|
this.spatial.setLocalTranslation(loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the spatial object and sets its rotation.
|
||||||
|
* This also moves the spatial to a new parent node for organizational purposes.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void initSpatial(){
|
public void initSpatial(){
|
||||||
setRotation(this.initRotation);
|
setRotation(this.initRotation);
|
||||||
@@ -101,6 +144,10 @@ public void rotateInit() {
|
|||||||
// rotate(rotation - initRotation);
|
// rotate(rotation - initRotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Activates the shield around the piece.
|
||||||
|
* This adds a visual shield effect in the form of a rotating ring.
|
||||||
|
*/
|
||||||
public void activateShield(){
|
public void activateShield(){
|
||||||
shieldRing = assetManager.loadModel(Asset.shieldRing.getModelPath());
|
shieldRing = assetManager.loadModel(Asset.shieldRing.getModelPath());
|
||||||
shieldRing.scale(1f);
|
shieldRing.scale(1f);
|
||||||
@@ -115,11 +162,18 @@ public void activateShield(){
|
|||||||
parentNode.attachChild(shieldRing);
|
parentNode.attachChild(shieldRing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deactivates the shield by removing the shield ring from the scene.
|
||||||
|
*/
|
||||||
|
|
||||||
public void deactivateShield(){
|
public void deactivateShield(){
|
||||||
parentNode.detachChild(shieldRing);
|
parentNode.detachChild(shieldRing);
|
||||||
shieldRing = null;
|
shieldRing = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Suppresses the shield, changing its color to a suppressed state.
|
||||||
|
*/
|
||||||
public void suppressShield(){
|
public void suppressShield(){
|
||||||
assert(shieldRing != null) : "PieceControl: shieldRing is not set";
|
assert(shieldRing != null) : "PieceControl: shieldRing is not set";
|
||||||
shieldMat.setColor("Color", SHIELD_SUPPRESSED_COLOR);
|
shieldMat.setColor("Color", SHIELD_SUPPRESSED_COLOR);
|
||||||
@@ -133,22 +187,36 @@ public Material getMaterial(){
|
|||||||
return ((Geometry) getSpatial()).getMaterial();
|
return ((Geometry) getSpatial()).getMaterial();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Highlights the piece with the appropriate outline color based on whether it is an enemy or not.
|
||||||
|
*
|
||||||
|
* @param enemy True if the piece is an enemy, false if it is owned by the player.
|
||||||
|
*/
|
||||||
public void highlight(boolean enemy) {
|
public void highlight(boolean enemy) {
|
||||||
this.enemy = enemy;
|
this.enemy = enemy;
|
||||||
highlight = true;
|
highlight = true;
|
||||||
super.outline(enemy ? OUTLINE_ENEMY_COLOR : OUTLINE_OWN_COLOR, OUTLINE_HIGHLIGHT_WIDTH);
|
super.outline(enemy ? OUTLINE_ENEMY_COLOR : OUTLINE_OWN_COLOR, OUTLINE_HIGHLIGHT_WIDTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the highlight effect from the piece.
|
||||||
|
*/
|
||||||
public void unHighlight(){
|
public void unHighlight(){
|
||||||
highlight = false;
|
highlight = false;
|
||||||
deOutline();
|
deOutline();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies a hover effect on the piece if it is hoverable.
|
||||||
|
*/
|
||||||
public void hover(){
|
public void hover(){
|
||||||
if(!hoverable) return;
|
if(!hoverable) return;
|
||||||
super.outline(enemy ? OUTLINE_ENEMY_HOVER_COLOR : OUTLINE_OWN_HOVER_COLOR, OUTLINE_HOVER_WIDTH);
|
super.outline(enemy ? OUTLINE_ENEMY_HOVER_COLOR : OUTLINE_OWN_HOVER_COLOR, OUTLINE_HOVER_WIDTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the hover effect from the piece.
|
||||||
|
*/
|
||||||
public void hoverOff(){
|
public void hoverOff(){
|
||||||
if(!hoverable) return;
|
if(!hoverable) return;
|
||||||
|
|
||||||
@@ -157,28 +225,56 @@ public void hoverOff(){
|
|||||||
else deOutline();
|
else deOutline();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deselects the piece and removes the selection outline. If the piece was highlighted,
|
||||||
|
* it will be re-highlighted. Otherwise, the outline is removed.
|
||||||
|
*/
|
||||||
public void unSelect(){
|
public void unSelect(){
|
||||||
select = false;
|
select = false;
|
||||||
if(highlight) highlight(enemy);
|
if(highlight) highlight(enemy);
|
||||||
else deOutline();
|
else deOutline();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Selects the piece and applies the selection outline. If the piece is an enemy, it will
|
||||||
|
* be outlined with the enemy selection color; otherwise, the own selection color will be used.
|
||||||
|
*/
|
||||||
public void select(){
|
public void select(){
|
||||||
if(!selectable) return;
|
if(!selectable) return;
|
||||||
select = true;
|
select = true;
|
||||||
super.outline(enemy ? OUTLINE_ENEMY_SELECT_COLOR : OUTLINE_OWN_SELECT_COLOR, OUTLINE_SELECT_WIDTH);
|
super.outline(enemy ? OUTLINE_ENEMY_SELECT_COLOR : OUTLINE_OWN_SELECT_COLOR, OUTLINE_SELECT_WIDTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the piece is selectable.
|
||||||
|
*
|
||||||
|
* @param selectable True if the piece can be selected, false otherwise.
|
||||||
|
*/
|
||||||
public void setSelectable(boolean selectable){
|
public void setSelectable(boolean selectable){
|
||||||
this.selectable = selectable;
|
this.selectable = selectable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the piece is selected.
|
||||||
|
*
|
||||||
|
* @return True if the piece is selected, false otherwise.
|
||||||
|
*/
|
||||||
public boolean isSelected() { return select; }
|
public boolean isSelected() { return select; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the piece is selectable.
|
||||||
|
*
|
||||||
|
* @return True if the piece is selectable, false otherwise.
|
||||||
|
*/
|
||||||
public boolean isSelectable() {
|
public boolean isSelectable() {
|
||||||
return selectable;
|
return selectable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the piece is hoverable.
|
||||||
|
*
|
||||||
|
* @param hoverable True if the piece can be hovered over, false otherwise.
|
||||||
|
*/
|
||||||
public void setHoverable(boolean hoverable) {
|
public void setHoverable(boolean hoverable) {
|
||||||
this.hoverable = hoverable;
|
this.hoverable = hoverable;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
package pp.mdga.client.board;
|
|
||||||
|
|
||||||
class PileControl {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
package pp.mdga.client.board;
|
|
||||||
|
|
||||||
public enum Rotation {
|
|
||||||
UP,
|
|
||||||
RIGHT,
|
|
||||||
DOWN,
|
|
||||||
LEFT,
|
|
||||||
UP_LEFT,
|
|
||||||
UP_RIGHT,
|
|
||||||
DOWN_RIGHT,
|
|
||||||
DOWN_LEFT
|
|
||||||
}
|
|
||||||
@@ -64,6 +64,9 @@ public void onEnter() {
|
|||||||
app.getViewPort().addProcessor(fpp);
|
app.getViewPort().addProcessor(fpp);
|
||||||
|
|
||||||
app.getAcousticHandler().playSound(MdgaSound.START);
|
app.getAcousticHandler().playSound(MdgaSound.START);
|
||||||
|
|
||||||
|
app.getNotificationSynchronizer().addTestNotification(new AcquireCardNotification(BonusCard.SHIELD));
|
||||||
|
app.getNotificationSynchronizer().addTestNotification(new SelectableCardsNotification(List.of(BonusCard.SHIELD)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Reference in New Issue
Block a user