686 lines
26 KiB
Java
686 lines
26 KiB
Java
package client;
|
|
|
|
import server.*;
|
|
import server.*;
|
|
import server.automaton.ActionResult;
|
|
import server.automaton.Game;
|
|
import server.cards.*;
|
|
import javafx.animation.*;
|
|
import javafx.application.Application;
|
|
import javafx.application.Platform;
|
|
import javafx.embed.swing.SwingFXUtils;
|
|
import javafx.geometry.Insets;
|
|
import javafx.geometry.Pos;
|
|
import javafx.scene.Scene;
|
|
import javafx.scene.control.Alert;
|
|
import javafx.scene.control.Button;
|
|
import javafx.scene.control.Label;
|
|
import javafx.scene.control.ScrollPane;
|
|
import javafx.scene.effect.DropShadow;
|
|
import javafx.scene.image.Image;
|
|
import javafx.scene.image.ImageView;
|
|
import javafx.scene.layout.*;
|
|
import javafx.scene.paint.Color;
|
|
import javafx.scene.shape.Rectangle;
|
|
import javafx.scene.text.Font;
|
|
import javafx.scene.text.FontWeight;
|
|
import javafx.stage.Stage;
|
|
import javafx.util.Duration;
|
|
import org.apache.logging.log4j.LogManager;
|
|
import org.apache.logging.log4j.Logger;
|
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
|
import org.apache.pdfbox.rendering.PDFRenderer;
|
|
import server.cards.BuildingCard;
|
|
import server.cards.Card;
|
|
import server.cards.CharacterCard;
|
|
import server.cards.CharacterType;
|
|
|
|
import java.awt.image.BufferedImage;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.util.*;
|
|
import java.util.stream.Collectors;
|
|
|
|
public class DeckGridAppFX extends Application {
|
|
|
|
private static final Logger logger = LogManager.getLogger(DeckGridAppFX.class);
|
|
private static final int IMG_HEIGHT=200;
|
|
private PDDocument documentFront;
|
|
private PDDocument documentBack;
|
|
private PDFRenderer pdfRendererFront;
|
|
private PDFRenderer pdfRendererBack;
|
|
private int totalCards = 0;
|
|
|
|
// Contenitori Layout
|
|
private HBox topMenu;
|
|
private HBox topRow;
|
|
private HBox centerRow;
|
|
private HBox bottomRow;
|
|
private HBox playersArea; // NUOVO: Area per i giocatori
|
|
private Button btnRefresh;
|
|
private Button btnTop;
|
|
private Button btnBottom;
|
|
private Button btnChooseOffering;
|
|
|
|
private Button btnMsg;
|
|
// --------------------------------
|
|
|
|
@Override
|
|
public void start(Stage primaryStage) {
|
|
|
|
List<Player> players = new ArrayList<>();
|
|
//players.add(new Player("Yellow", TotemColor.YELLOW));
|
|
players.add(new Player("Blue", TotemColor.BLUE));
|
|
//players.add(new Player("Purple", TotemColor.PURPLE));
|
|
players.add(new Player("Red", TotemColor.RED));
|
|
//players.add(new Player("Green", TotemColor.GREEN));
|
|
|
|
Game game = new Game(players);
|
|
|
|
InputStream frontStream = getClass().getResourceAsStream("/files/Cards_total_front_PROMO.pdf");
|
|
InputStream backStream = getClass().getResourceAsStream("/files/Cards_total_back_PROMO.pdf");
|
|
InputStream csvStream = getClass().getResourceAsStream("/files/cards.csv");
|
|
|
|
try {
|
|
documentFront = PDDocument.load(frontStream);
|
|
pdfRendererFront = new PDFRenderer(documentFront);
|
|
|
|
documentBack = PDDocument.load(backStream);
|
|
pdfRendererBack = new PDFRenderer(documentBack);
|
|
|
|
} catch ( IOException e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
//File fileCsv = new File(getClass().getResource("/files/cards.csv").toURI());
|
|
game.newGame(csvStream);
|
|
|
|
game.setEventListener(notification -> {
|
|
Platform.runLater(() -> {
|
|
drawGameState(game);
|
|
switch (notification.event()) {
|
|
case TOTEM_PLACEMENT-> showPopup("TOTEM PLACEMENT\n" + (notification.message()!=null?notification.message():""));
|
|
case SETUP -> showPopup("SETUP \n" + (notification.message()!=null?notification.message():""));
|
|
case ACTION_RESOLUTION -> showPopup("ACTION_RESOLUTION \n" + (notification.message()!=null?notification.message():"" ));
|
|
case END_ACTION -> showPopup("END_ACTION \n" + (notification.message()!=null?notification.message():"" ));
|
|
case EVENT_RESOLUTION -> showPopup("EVENT_RESOLUTION \n" + (notification.message()!=null?notification.message():"" ));
|
|
case EXTRA_DRAW -> showPopup("EXTRA_DRAW \n" + (notification.message()!=null?notification.message():"" ));
|
|
case GAME_OVER -> showPopup("GAME OVER");
|
|
|
|
}
|
|
});
|
|
});
|
|
|
|
|
|
primaryStage.setTitle("Tavolo da Gioco - Board & Players");
|
|
|
|
btnTop = new Button("Pick Top");
|
|
btnBottom = new Button("Pick Bottom");
|
|
btnMsg = new Button("Game State");
|
|
btnRefresh= new Button("Refresh");
|
|
btnChooseOffering= new Button("Choose Offering");
|
|
//btnNext.setDisable(true);
|
|
topMenu = new HBox(15, btnRefresh, btnMsg);
|
|
topMenu.setAlignment(Pos.CENTER);
|
|
topMenu.setPadding(new Insets(10));
|
|
|
|
Label stateLabel = new Label("Game State = " + game.getState() );
|
|
stateLabel.setFont(Font.font("System", FontWeight.BOLD, 16));
|
|
stateLabel.setTextFill(Color.DARKBLUE);
|
|
|
|
//showPopup(topMenu, "STARTING GAME");
|
|
|
|
btnMsg.setOnAction(e -> {
|
|
new Alert(Alert.AlertType.INFORMATION,
|
|
game.toString()
|
|
).showAndWait();
|
|
});
|
|
btnRefresh.setOnAction(e -> {
|
|
drawGameState(game);
|
|
});
|
|
|
|
topRow = createRowContainer();
|
|
centerRow = createRowContainer();
|
|
bottomRow = createRowContainer();
|
|
|
|
// NUOVO: Inizializza l'area giocatori
|
|
playersArea = new HBox(30);
|
|
playersArea.setAlignment(Pos.CENTER);
|
|
playersArea.setPadding(new Insets(20));
|
|
|
|
|
|
|
|
|
|
VBox tableArea = new VBox(20,
|
|
new Label(" "), topRow,
|
|
new Label(" "), centerRow,
|
|
new Label(" "), bottomRow,
|
|
new Label("--- ASSET PLAYERS ---"), playersArea
|
|
);
|
|
tableArea.setAlignment(Pos.CENTER);
|
|
tableArea.setPadding(new Insets(20));
|
|
|
|
ScrollPane scrollPane = new ScrollPane(tableArea);
|
|
scrollPane.setFitToWidth(true);
|
|
|
|
BorderPane root = new BorderPane();
|
|
root.setTop(topMenu);
|
|
root.setCenter(scrollPane);
|
|
|
|
Scene scene = new Scene(root, 1300, 900);
|
|
primaryStage.setScene(scene);
|
|
primaryStage.show();
|
|
|
|
drawGameState(game);
|
|
}
|
|
|
|
private HBox createRowContainer() {
|
|
HBox row = new HBox(10);
|
|
row.setAlignment(Pos.CENTER);
|
|
return row;
|
|
}
|
|
|
|
|
|
private void drawGameState(Game game) {
|
|
if (documentFront == null) return;
|
|
|
|
|
|
topMenu.getChildren().clear();
|
|
topRow.getChildren().clear();
|
|
centerRow.getChildren().clear();
|
|
bottomRow.getChildren().clear();
|
|
playersArea.getChildren().clear();
|
|
|
|
drawTopMenu(topMenu, game);
|
|
drawTopRow(topRow, game);
|
|
drawTurnTileAndOffering(centerRow, game.getPlayers().size(), game);
|
|
drawBottomRow(bottomRow, game );
|
|
|
|
|
|
List<Player> players =game.getPlayers();
|
|
renderPlayers(players, game);
|
|
logger.info(game.getCurrentPlayer());
|
|
|
|
}
|
|
|
|
private void pickTopCardAction(Player player, GameBoard board, int cardid){
|
|
Card card = board.getTopRow().stream()
|
|
.filter(CharacterCard.class::isInstance)
|
|
.map(CharacterCard.class::cast)
|
|
.filter(c -> c.getCardId() == cardid)
|
|
.findFirst()
|
|
.orElse(null);
|
|
|
|
if (card != null) {
|
|
board.getTopRow().remove(card);
|
|
CharacterCard charCard = (CharacterCard)card;
|
|
player.addCharacterToTribe((CharacterCard) card);
|
|
}
|
|
}
|
|
|
|
private void pickBottomCardAction(Player player, GameBoard board, int cardid){
|
|
Card card = board.getBottomRow().stream()
|
|
.filter(CharacterCard.class::isInstance)
|
|
.map(CharacterCard.class::cast)
|
|
.filter(c -> c.getCardId() == cardid)
|
|
.findFirst()
|
|
.orElse(null);
|
|
if (card != null) {
|
|
board.getBottomRow().remove(card);
|
|
player.addCharacterToTribe((CharacterCard) card);
|
|
}
|
|
}
|
|
|
|
|
|
private void drawBottomRow(HBox row, Game game) {
|
|
for (Card c : game.getGameBoard().getBottomRow()) {
|
|
ImageView cardImage = createCardImageFromPdf(c.getCardId(), IMG_HEIGHT, true);
|
|
|
|
if (cardImage != null) {
|
|
// 1. Create a Label for your debugging text
|
|
Label debugLabel = new Label("ID: " + c.getCardId());
|
|
|
|
// 2. Style the label so it's readable over any card background
|
|
// (White text with a semi-transparent black background)
|
|
debugLabel.setStyle("-fx-background-color: rgba(0, 0, 0, 0.7); " +
|
|
"-fx-text-fill: white; " +
|
|
"-fx-padding: 3px; " +
|
|
"-fx-font-weight: bold;");
|
|
|
|
// 3. Create a StackPane and add both the image and the text
|
|
StackPane cardContainer = new StackPane();
|
|
cardContainer.getChildren().addAll(cardImage, debugLabel);
|
|
|
|
// 4. Align the text wherever you want (e.g., Top-Left corner of the card)
|
|
StackPane.setAlignment(debugLabel, Pos.TOP_LEFT);
|
|
// You can also use Pos.CENTER, Pos.BOTTOM_RIGHT, etc.
|
|
cardImage.setOnMouseClicked(event -> {
|
|
logger.info("Bottom Card clicked");
|
|
Player p = game.getCurrentPlayer();
|
|
//pickBottomCardAction(p, game.getGameBoard(), c.getCardId());
|
|
ActionResult result = game.resolveCardAction(p, false, c.getCardId());
|
|
if (!result.isSuccess()) {
|
|
new Alert(Alert.AlertType.ERROR,
|
|
result.getErrorMessage()
|
|
).showAndWait();
|
|
}
|
|
drawGameState(game);
|
|
});
|
|
// 5. Add the StackPane (which now holds both) to the row
|
|
row.getChildren().add(cardContainer);
|
|
}
|
|
}
|
|
}
|
|
private void drawTopMenu(HBox row, Game game) {
|
|
//topMenu = new HBox(15, btnChooseOffering, btnAction, btnTop, btnBottom, btnMsg);
|
|
//topMenu.setAlignment(Pos.CENTER);
|
|
//topMenu.setPadding(new Insets(10));
|
|
|
|
Label stateLabel = new Label("Game State = " + game.getState() );
|
|
stateLabel.setFont(Font.font("System", FontWeight.BOLD, 16));
|
|
stateLabel.setTextFill(Color.DARKBLUE);
|
|
row.getChildren().add(stateLabel);
|
|
row.getChildren().add(btnRefresh);
|
|
row.getChildren().add(btnMsg);
|
|
|
|
|
|
|
|
}
|
|
private void drawTopRow(HBox row, Game game) {
|
|
for (Card c : game.getGameBoard().getTopRow()) {
|
|
ImageView cardImage = createCardImageFromPdf(c.getCardId(), IMG_HEIGHT, true);
|
|
|
|
if (cardImage != null) {
|
|
// 1. Create a Label for your debugging text
|
|
Label debugLabel = new Label("ID: " + c.getCardId());
|
|
|
|
// 2. Style the label so it's readable over any card background
|
|
// (White text with a semi-transparent black background)
|
|
debugLabel.setStyle("-fx-background-color: rgba(0, 0, 0, 0.7); " +
|
|
"-fx-text-fill: white; " +
|
|
"-fx-padding: 3px; " +
|
|
"-fx-font-weight: bold;");
|
|
|
|
// 3. Create a StackPane and add both the image and the text
|
|
StackPane cardContainer = new StackPane();
|
|
cardContainer.getChildren().addAll(cardImage, debugLabel);
|
|
|
|
// 4. Align the text wherever you want (e.g., Top-Left corner of the card)
|
|
StackPane.setAlignment(debugLabel, Pos.TOP_LEFT);
|
|
// You can also use Pos.CENTER, Pos.BOTTOM_RIGHT, etc.
|
|
cardImage.setOnMouseClicked(event -> {
|
|
logger.info("Card clicked");
|
|
Player p = game.getCurrentPlayer();
|
|
//pickTopCardAction(p, game.getGameBoard(), c.getCardId());
|
|
//game.resolveCardAction(p, true, c.getCardId());
|
|
|
|
ActionResult result = game.resolveCardAction(p, true, c.getCardId());
|
|
if (!result.isSuccess()) {
|
|
new Alert(Alert.AlertType.ERROR,
|
|
result.getErrorMessage()
|
|
).showAndWait();
|
|
}
|
|
|
|
drawGameState(game);
|
|
});
|
|
// 5. Add the StackPane (which now holds both) to the row
|
|
row.getChildren().add(cardContainer);
|
|
}
|
|
}
|
|
}
|
|
|
|
private StackPane drawTurnTileCardImageWithPlayers(InputStream imgStream, int height, Player[] players) {
|
|
try {
|
|
Image fxImage = new Image(imgStream);
|
|
|
|
ImageView imageView = new ImageView(fxImage);
|
|
imageView.setFitHeight(height);
|
|
imageView.setPreserveRatio(true);
|
|
imageView.setStyle("-fx-effect: dropshadow(three-pass-box, rgba(0,0,0,0.4), 4, 0, 0, 0);");
|
|
|
|
StackPane stack = new StackPane(imageView);
|
|
|
|
VBox playerBox = new VBox(5);
|
|
playerBox.setPadding(new Insets(5));
|
|
playerBox.setAlignment(Pos.CENTER_RIGHT);
|
|
|
|
// 🔥 DEBUG background (to SEE the box)
|
|
playerBox.setStyle("-fx-background-color: rgba(255,0,0,0.3);");
|
|
|
|
for (Player p : players) {
|
|
if (p==null) continue;
|
|
Rectangle rect = new Rectangle(15,15);
|
|
rect.setFill(p.getTotemColor().getFxColor());
|
|
rect.setStroke(Color.WHITE);
|
|
rect.setStrokeWidth(1);
|
|
|
|
playerBox.getChildren().add(rect);
|
|
}
|
|
playerBox.setPadding(new Insets(22));
|
|
// 🔥 IMPORTANT: bring to front
|
|
playerBox.toFront();
|
|
|
|
// position it clearly
|
|
StackPane.setAlignment(playerBox, Pos.CENTER);
|
|
|
|
stack.getChildren().add(playerBox);
|
|
|
|
return stack;
|
|
|
|
} catch (Exception e) {
|
|
logger.error("Errore caricamento immagine {}", imgStream, e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
|
|
private void drawTurnTileAndOffering(HBox row, int n, Game game) {
|
|
|
|
// Clear row if needed (optional but recommended)
|
|
row.getChildren().clear();
|
|
|
|
// --- LEFT BLOCK (Turn + initial card) ---
|
|
VBox turnBox = new VBox(5);
|
|
turnBox.setAlignment(Pos.CENTER);
|
|
|
|
// Turn label
|
|
int round = game.getRound(); // adjust if different
|
|
Label turnLabel = new Label("Round = " + round);
|
|
turnLabel.setFont(Font.font("System", FontWeight.BOLD, 16));
|
|
turnLabel.setTextFill(Color.DARKBLUE);
|
|
|
|
Card first = game.getGameBoard().getCardDeck().getFirstCardForCover();
|
|
if (first!=null){
|
|
ImageView imgCover = createCardImageFromPdf(first.getCardId(), 120, false);
|
|
turnBox.getChildren().addAll(turnLabel, imgCover);
|
|
} else turnBox.getChildren().addAll(turnLabel);
|
|
|
|
// Add FIRST
|
|
row.getChildren().add(turnBox);
|
|
|
|
// --- TURN TILE ---
|
|
|
|
StackPane pane = drawTurnTileCardImageWithPlayers(
|
|
getClass().getResourceAsStream("/files/Start_" + n + "P.png"),
|
|
IMG_HEIGHT,
|
|
game.getGameBoard().getTurnTile().getPositions()
|
|
);
|
|
|
|
row.getChildren().add(pane);
|
|
|
|
// --- OFFERINGS ---
|
|
for (OfferingTile offering : game.getGameBoard().getOfferingTiles()) {
|
|
Player occupant = offering.getOccupant();
|
|
StackPane offPane =drawOfferingCardImageWithTotem(
|
|
getClass().getResourceAsStream("/files/offering" + offering.getLetter() + ".png"),
|
|
IMG_HEIGHT,
|
|
occupant, game, offering);
|
|
if (offPane != null) {
|
|
row.getChildren().add(offPane);
|
|
}
|
|
}
|
|
}
|
|
|
|
// --- NUOVO: RENDERIZZAZIONE GIOCATORI E RAGGRUPPAMENTO (JAVA 8) ---
|
|
private void renderPlayers(List<Player> players, Game game) {
|
|
playersArea.getChildren().clear();
|
|
for (Player player : players) {
|
|
boolean active = player.equals(game.getCurrentPlayer());
|
|
|
|
VBox playerBox = new VBox(10);
|
|
playerBox.setPadding(new Insets(15));
|
|
playerBox.setStyle("-fx-border-color: #555; -fx-border-width: 2; -fx-border-radius: 10; -fx-background-color: #f9f9f9; -fx-background-radius: 10;");
|
|
|
|
if (active) {
|
|
// Strong highlight (gold border + soft background)
|
|
playerBox.setStyle(
|
|
"-fx-border-color: gold;" +
|
|
"-fx-border-width: 3;" +
|
|
"-fx-border-radius: 10;" +
|
|
"-fx-background-color: linear-gradient(to bottom, #fffbe6, #f9f9f9);" +
|
|
"-fx-background-radius: 10;"
|
|
);
|
|
|
|
// Slight scale-up
|
|
playerBox.setScaleX(1.05);
|
|
playerBox.setScaleY(1.05);
|
|
|
|
// Glow effect
|
|
DropShadow glow = new DropShadow();
|
|
glow.setColor(Color.GOLD);
|
|
glow.setRadius(20);
|
|
playerBox.setEffect(glow);
|
|
|
|
// Smooth pulse animation (NOT blinking)
|
|
Timeline pulse = new Timeline(
|
|
new KeyFrame(Duration.ZERO,
|
|
new KeyValue(glow.radiusProperty(), 10)
|
|
),
|
|
new KeyFrame(Duration.seconds(1.2),
|
|
new KeyValue(glow.radiusProperty(), 25)
|
|
)
|
|
);
|
|
pulse.setAutoReverse(true);
|
|
pulse.setCycleCount(Animation.INDEFINITE);
|
|
pulse.play();
|
|
}
|
|
|
|
HBox nameRow = new HBox(8);
|
|
nameRow.setAlignment(Pos.CENTER_LEFT);
|
|
|
|
Rectangle rect = new Rectangle(12, 12);
|
|
|
|
TotemColor color = player.getTotemColor();
|
|
rect.setFill(color.getFxColor());
|
|
|
|
|
|
rect.setStroke(Color.BLACK);
|
|
rect.setStrokeWidth(1);
|
|
|
|
Label nameLbl = new Label(player.getNickname());
|
|
nameLbl.setFont(Font.font("System", FontWeight.BOLD, 16));
|
|
|
|
if (active) {
|
|
Label turnLbl = new Label(" ▶ Your Turn");
|
|
turnLbl.setTextFill(Color.GOLDENROD);
|
|
turnLbl.setFont(Font.font("System", FontWeight.BOLD, 14));
|
|
nameRow.getChildren().addAll(rect, nameLbl, turnLbl);
|
|
} else {
|
|
nameRow.getChildren().addAll(rect, nameLbl);
|
|
}
|
|
|
|
// Risorse Cibo e Soldi
|
|
Label statsLbl = new Label("🍖 Food: " + player.getFoodTokens() + " | 💰 Points: " + player.getPrestigePoints());
|
|
statsLbl.setTextFill(Color.DARKRED);
|
|
statsLbl.setFont(Font.font("System", FontWeight.BOLD, 14));
|
|
|
|
playerBox.getChildren().addAll(nameRow, statsLbl);
|
|
|
|
Map<CharacterType, List<CharacterCard>> groupedCards = player.getPlayerTribe().getCharacters().stream()
|
|
.collect(Collectors.groupingBy(CharacterCard::getCharacterType));
|
|
|
|
// Itera sui gruppi creati e genera la grafica
|
|
groupedCards.forEach((type, cardsOfType) -> {
|
|
Label typeLbl = new Label("Tipo: " + type.name() + " (" + cardsOfType.size() + ")");
|
|
typeLbl.setFont(Font.font("System", FontWeight.NORMAL, 12));
|
|
|
|
HBox cardImagesRow = new HBox(5);
|
|
for (Card c : cardsOfType) {
|
|
// Carte più piccole (90px) per l'area giocatore
|
|
ImageView img = createCardImageFromPdf(c.getCardId(), 90, true);
|
|
if (img != null) cardImagesRow.getChildren().add(img);
|
|
}
|
|
|
|
playerBox.getChildren().addAll(typeLbl, cardImagesRow);
|
|
});
|
|
|
|
Map<Era, List<BuildingCard>> groupedBuildCards = player.getPlayerTribe().getBuildingCard().stream()
|
|
.collect(Collectors.groupingBy(BuildingCard::getEra));
|
|
|
|
groupedBuildCards.forEach((type, cardsOfType) -> {
|
|
Label typeLbl = new Label("Build Tipo: " + type.name() + " (" + cardsOfType.size() + ")");
|
|
typeLbl.setFont(Font.font("System", FontWeight.NORMAL, 12));
|
|
|
|
HBox cardImagesRow = new HBox(5);
|
|
for (Card c : cardsOfType) {
|
|
// Carte più piccole (90px) per l'area giocatore
|
|
ImageView img = createCardImageFromPdf(c.getCardId(), 90, true);
|
|
if (img != null) cardImagesRow.getChildren().add(img);
|
|
}
|
|
|
|
playerBox.getChildren().addAll(typeLbl, cardImagesRow);
|
|
//playerBox.getChildren().addAll(nameRow, statsLbl);
|
|
});
|
|
playersArea.getChildren().add(playerBox);
|
|
}
|
|
}
|
|
|
|
private ImageView createCardImageFromPdf(int pageIndex, int height, boolean front) {
|
|
try {
|
|
BufferedImage bim =null;
|
|
if (front) bim = pdfRendererFront.renderImageWithDPI(pageIndex-1, 100);
|
|
else bim = pdfRendererBack.renderImageWithDPI(pageIndex-1, 100);
|
|
|
|
Image fxImage = SwingFXUtils.toFXImage(bim, null);
|
|
ImageView imageView = new ImageView(fxImage);
|
|
imageView.setFitHeight(height);
|
|
imageView.setPreserveRatio(true);
|
|
imageView.setStyle("-fx-effect: dropshadow(three-pass-box, rgba(0,0,0,0.4), 4, 0, 0, 0);");
|
|
return imageView;
|
|
} catch (IOException e) {
|
|
logger.error("Errore rendering pagina {}", pageIndex, e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private StackPane drawOfferingCardImageWithTotem(InputStream imagePath, int height, Player occupant, Game game, OfferingTile offering) {
|
|
try {
|
|
Image fxImage = new Image(imagePath);
|
|
|
|
ImageView imageView = new ImageView(fxImage);
|
|
imageView.setFitHeight(height);
|
|
imageView.setPreserveRatio(true);
|
|
imageView.setStyle("-fx-effect: dropshadow(three-pass-box, rgba(0,0,0,0.4), 4, 0, 0, 0);");
|
|
|
|
imageView.setOnMouseClicked(event -> {
|
|
int idx = game.getGameBoard().getOfferingTiles().indexOf(offering);
|
|
game.placeTotem(game.getCurrentPlayer(), idx);
|
|
logger.info(" PLAYER {} choose {} ", game.getCurrentPlayer().getNickname() , offering );
|
|
drawGameState(game);
|
|
});
|
|
|
|
StackPane stack = new StackPane(imageView);
|
|
if(occupant!=null){
|
|
Rectangle rect = new Rectangle(25, 25);
|
|
rect.setFill(occupant.getTotemColor().getFxColor());
|
|
rect.setStroke(Color.WHITE);
|
|
rect.setStrokeWidth(1);
|
|
|
|
StackPane.setAlignment(rect, Pos.TOP_CENTER);
|
|
rect.setTranslateY(20);
|
|
StackPane.setMargin(rect, new Insets(5));
|
|
|
|
stack.getChildren().add(rect);
|
|
}
|
|
|
|
return stack;
|
|
} catch (Exception e) {
|
|
logger.error("Errore caricamento immagine {}", imagePath, e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
|
|
private ImageView createCardImage(InputStream imagePath, int height) {
|
|
try {
|
|
Image fxImage = new Image(imagePath);
|
|
|
|
ImageView imageView = new ImageView(fxImage);
|
|
imageView.setFitHeight(height);
|
|
imageView.setPreserveRatio(true);
|
|
imageView.setStyle("-fx-effect: dropshadow(three-pass-box, rgba(0,0,0,0.4), 4, 0, 0, 0);");
|
|
|
|
return imageView;
|
|
} catch (Exception e) {
|
|
logger.error("Errore caricamento immagine {}", imagePath, e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private void showPopup(String message) {
|
|
Platform.runLater(() -> {
|
|
|
|
Label label = new Label("⚡ " + message); // icon improves readability
|
|
label.setWrapText(true);
|
|
label.setMaxWidth(400);
|
|
|
|
label.setStyle(
|
|
"-fx-background-color: rgba(20,20,20,0.9);" +
|
|
"-fx-text-fill: white;" +
|
|
"-fx-font-size: 20px;" +
|
|
"-fx-font-weight: bold;" +
|
|
"-fx-padding: 15 25 15 25;" +
|
|
"-fx-background-radius: 12;" +
|
|
"-fx-border-radius: 12;" +
|
|
"-fx-border-color: #00c3ff;"
|
|
);
|
|
|
|
label.setOpacity(0); // start invisible
|
|
|
|
topMenu.getChildren().add(label);
|
|
|
|
// Fade IN
|
|
FadeTransition fadeIn = new FadeTransition(Duration.millis(250), label);
|
|
fadeIn.setFromValue(0);
|
|
fadeIn.setToValue(1);
|
|
|
|
// Stay visible
|
|
PauseTransition pause = new PauseTransition(Duration.seconds(4));
|
|
|
|
// Fade OUT
|
|
FadeTransition fadeOut = new FadeTransition(Duration.millis(400), label);
|
|
fadeOut.setFromValue(1.0);
|
|
fadeOut.setToValue(0.0);
|
|
|
|
fadeOut.setOnFinished(f -> topMenu.getChildren().remove(label));
|
|
|
|
fadeIn.play();
|
|
fadeIn.setOnFinished(e -> pause.play());
|
|
pause.setOnFinished(e -> fadeOut.play());
|
|
});
|
|
}
|
|
private void showPopupNo(String message) {
|
|
Platform.runLater(() -> {
|
|
Label label = new Label(message);
|
|
label.setStyle(
|
|
"-fx-background-color: rgba(0,0,0,0.75);" +
|
|
"-fx-text-fill: white;" +
|
|
"-fx-font-size: 28px;" +
|
|
"-fx-font-weight: bold;" +
|
|
"-fx-padding: 20 40 20 40;" +
|
|
"-fx-background-radius: 12;"
|
|
);
|
|
label.setMouseTransparent(true);
|
|
|
|
topMenu.getChildren().add(label);
|
|
|
|
PauseTransition pause = new PauseTransition(Duration.seconds(5));
|
|
pause.setOnFinished(e -> {
|
|
FadeTransition fade = new FadeTransition(Duration.millis(400), label);
|
|
fade.setFromValue(1.0);
|
|
fade.setToValue(0.0);
|
|
fade.setOnFinished(f -> topMenu.getChildren().remove(label));
|
|
fade.play();
|
|
});
|
|
pause.play();
|
|
});
|
|
}
|
|
@Override
|
|
public void stop() throws Exception {
|
|
if (documentFront != null) documentFront.close();
|
|
super.stop();
|
|
}
|
|
|
|
public static void main(String[] args) {
|
|
launch(args);
|
|
}
|
|
} |