package net.demilich.metastone.gui.playmode; import java.io.IOException; import java.util.HashMap; import java.util.List; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.image.ImageView; import javafx.scene.input.MouseEvent; import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; import net.demilich.metastone.game.GameContext; import net.demilich.metastone.game.Player; import net.demilich.metastone.game.actions.ActionType; import net.demilich.metastone.game.actions.GameAction; import net.demilich.metastone.game.behaviour.human.HumanTargetOptions; import net.demilich.metastone.game.cards.CardCollection; import net.demilich.metastone.game.entities.Actor; import net.demilich.metastone.game.entities.Entity; import net.demilich.metastone.game.entities.minions.Summon; import net.demilich.metastone.game.logic.GameLogic; import net.demilich.metastone.gui.IconFactory; import net.demilich.metastone.gui.cards.HandCard; import net.demilich.metastone.gui.playmode.animation.EventVisualizerDispatcher; public class GameBoardView extends BorderPane { @FXML private HBox p1CardPane; @FXML private HBox p2CardPane; @FXML private HBox p1MinionPane; @FXML private HBox p2MinionPane; @FXML private VBox p1HeroAnchor; @FXML private VBox p2HeroAnchor; @FXML private HBox centerMessageArea; private HeroToken p1Hero; private HeroToken p2Hero; private HandCard[] p1Cards = new HandCard[GameLogic.MAX_HAND_CARDS]; private HandCard[] p2Cards = new HandCard[GameLogic.MAX_HAND_CARDS]; private SummonToken[] p1Minions = new SummonToken[GameLogic.MAX_MINIONS]; private SummonToken[] p2Minions = new SummonToken[GameLogic.MAX_MINIONS]; private final HashMap<GameToken, Button> summonHelperMap1 = new HashMap<GameToken, Button>(); private final HashMap<GameToken, Button> summonHelperMap2 = new HashMap<GameToken, Button>(); private final HashMap<Actor, GameToken> entityTokenMap = new HashMap<Actor, GameToken>(); private final EventVisualizerDispatcher gameEventVisualizer = new EventVisualizerDispatcher(); @FXML private Label centerMessageLabel; public GameBoardView() { FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/GameBoardView.fxml")); fxmlLoader.setRoot(this); fxmlLoader.setController(this); try { fxmlLoader.load(); } catch (IOException exception) { throw new RuntimeException(exception); } // initialize card ui elements for (int i = 0; i < p1Cards.length; i++) { p1Cards[i] = new HandCard(); p1Cards[i].setVisible(false); p2Cards[i] = new HandCard(); p2Cards[i].setVisible(false); } p1CardPane.getChildren().addAll(p1Cards); p2CardPane.getChildren().addAll(p2Cards); // initialize minion tokens elements for (int i = 0; i < p1Minions.length; i++) { Button summonHelper = createSummonHelper(); p1MinionPane.getChildren().add(summonHelper); p1Minions[i] = new SummonToken(); p1MinionPane.getChildren().add(p1Minions[i]); summonHelperMap1.put(p1Minions[i], summonHelper); summonHelper = createSummonHelper(); p2MinionPane.getChildren().add(summonHelper); p2Minions[i] = new SummonToken(); p2MinionPane.getChildren().add(p2Minions[i]); summonHelperMap2.put(p2Minions[i], summonHelper); } // create one additional summon helper (for each player) Button summonHelper = createSummonHelper(); p1MinionPane.getChildren().add(summonHelper); summonHelperMap1.put(null, summonHelper); summonHelper = createSummonHelper(); p2MinionPane.getChildren().add(summonHelper); summonHelperMap2.put(null, summonHelper); p1Hero = new HeroToken(); p2Hero = new HeroToken(); p1HeroAnchor.getChildren().add(p1Hero); p2HeroAnchor.getChildren().add(p2Hero); } private void checkForWinner(GameContext context) { if (context.gameDecided()) { if (context.getWinningPlayerId() == -1) { centerMessageLabel.setStyle("-fx-text-fill: red;"); setCenterMessage("Game has ended in a draw."); } else { centerMessageLabel.setStyle("-fx-text-fill: green;"); Player winner = context.getPlayer(context.getWinningPlayerId()); setCenterMessage("Player " + winner.getName() + " has won the game."); } } } private Button createSummonHelper() { ImageView icon = new ImageView(IconFactory.getSummonHelper()); icon.setFitWidth(32); icon.setFitHeight(32); Button helper = new Button("", icon); helper.setStyle("-fx-padding: 2 2 2 2;"); helper.setVisible(false); helper.setManaged(false); return helper; } public void disableTargetSelection() { for (GameToken token : entityTokenMap.values()) { token.hideTargetMarker(); } for (Button summonHelper : summonHelperMap1.values()) { summonHelper.setVisible(false); summonHelper.setManaged(false); } for (Button summonHelper : summonHelperMap2.values()) { summonHelper.setVisible(false); summonHelper.setManaged(false); } hideCenterMessage(); } private void enableSpellTargets(final HumanTargetOptions targetOptions) { GameContext context = targetOptions.getContext(); for (final GameAction action : targetOptions.getActionGroup().getActionsInGroup()) { Entity target = context.resolveSingleTarget(action.getTargetKey()); GameToken token = getToken(target); EventHandler<MouseEvent> clickedHander = new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent event) { disableTargetSelection(); targetOptions.getActionSelectionListener().onActionSelected(action); } }; token.showTargetMarker(clickedHander); } } private void enableSummonTargets(final HumanTargetOptions targetOptions) { int playerId = targetOptions.getPlayerId(); GameContext context = targetOptions.getContext(); for (final GameAction action : targetOptions.getActionGroup().getActionsInGroup()) { Entity target = context.resolveSingleTarget(action.getTargetKey()); GameToken token = getToken(target); Button summonHelper = playerId == 0 ? summonHelperMap1.get(token) : summonHelperMap2.get(token); summonHelper.setVisible(true); summonHelper.setManaged(true); EventHandler<ActionEvent> clickedHander = new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { disableTargetSelection(); targetOptions.getActionSelectionListener().onActionSelected(action); } }; summonHelper.setOnAction(clickedHander); } } public void enableTargetSelection(final HumanTargetOptions targetOptions) { GameAction action = targetOptions.getActionGroup().getPrototype(); if (action.getActionType() == ActionType.SUMMON) { enableSummonTargets(targetOptions); } else { enableSpellTargets(targetOptions); } setCenterMessage("Select target for " + action.getPromptText() + " - ESC to cancel"); } public GameToken getToken(Entity entity) { return entityTokenMap.get(entity); } private void hideCenterMessage() { centerMessageLabel.setVisible(false); } private void setCenterMessage(String message) { centerMessageLabel.setText(message); centerMessageLabel.setVisible(true); } public void showAnimations(GameContext context) { gameEventVisualizer.visualize((GameContextVisualizable) context, this); } public void updateGameState(GameContext context) { entityTokenMap.clear(); p1Hero.setHero(context.getPlayer1()); p1Hero.updateHeroPowerCost(context, context.getPlayer1()); p1Hero.highlight(context.getActivePlayer() == context.getPlayer1()); entityTokenMap.put(context.getPlayer1().getHero(), p1Hero); p2Hero.setHero(context.getPlayer2()); p2Hero.updateHeroPowerCost(context, context.getPlayer2()); p2Hero.highlight(context.getActivePlayer() == context.getPlayer2()); entityTokenMap.put(context.getPlayer2().getHero(), p2Hero); updateHandCards(context, context.getPlayer1(), p1Cards); updateHandCards(context, context.getPlayer2(), p2Cards); updateSummonTokens(context.getPlayer1(), p1Minions); updateSummonTokens(context.getPlayer2(), p2Minions); checkForWinner(context); } private void updateHandCards(GameContext context, Player player, HandCard[] handCards) { CardCollection hand = player.getHand(); for (int i = 0; i < handCards.length; i++) { if (i < hand.getCount()) { handCards[i].setManaged(true); handCards[i].setVisible(true); handCards[i].setCard(context, hand.get(i), player); } else { handCards[i].setManaged(false); handCards[i].setVisible(false); } } } private void updateSummonTokens(Player player, SummonToken[] summonTokens) { List<Summon> summons = player.getSummons(); for (int i = 0; i < summonTokens.length; i++) { if (i < summons.size()) { Summon summon = summons.get(i); summonTokens[i].setSummon(summon); summonTokens[i].setManaged(true); summonTokens[i].setVisible(true); entityTokenMap.put(summon, summonTokens[i]); } else { summonTokens[i].setManaged(false); summonTokens[i].setVisible(false); } } } }