From 44ef21e6af546c66f4e7f0a2d10a99b04bafc528 Mon Sep 17 00:00:00 2001 From: Cedric Beck Date: Wed, 4 Dec 2024 11:38:35 +0100 Subject: [PATCH] added handCard Num to playerName display + added remove card in guiHandler --- .../src/main/java/pp/mdga/client/Asset.java | 6 +-- .../pp/mdga/client/InputSynchronizer.java | 13 ++++- .../src/main/java/pp/mdga/client/MdgaApp.java | 2 +- .../mdga/client/NotificationSynchronizer.java | 10 ++-- .../java/pp/mdga/client/gui/CardControl.java | 2 +- .../java/pp/mdga/client/gui/CardLayer.java | 6 ++- .../pp/mdga/client/gui/CardLayerHandler.java | 13 +++++ .../java/pp/mdga/client/gui/GuiHandler.java | 33 ++++++++++-- .../pp/mdga/client/gui/PlayerNameHandler.java | 49 ++++++++++++++++-- .../java/pp/mdga/client/view/GameView.java | 9 ++-- .../src/main/resources/Images/handcard.png | Bin 0 -> 12257 bytes 11 files changed, 118 insertions(+), 25 deletions(-) create mode 100644 Projekte/mdga/client/src/main/resources/Images/handcard.png diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/Asset.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/Asset.java index 60dfebcb..a24d9d1c 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/Asset.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/Asset.java @@ -33,11 +33,11 @@ public enum Asset { treeSmall(1.2f), treeBig(1.2f), turboCard, - turboSymbol("Models/turboCard/turboSymbol.j3o", "Models/turboCard/turboCard_diff.j3o"), + turboSymbol("Models/turboCard/turboSymbol.j3o", "Models/turboCard/turboCard_diff.png"), swapCard, - swapSymbol("Models/swapCard/swapSymbol.j3o", "Models/swapCard/swapCard_diff.j3o"), + swapSymbol("Models/swapCard/swapSymbol.j3o", "Models/swapCard/swapCard_diff.png"), shieldCard, - shieldSymbol("Models/shieldCard/shieldSymbol.j3o", "Models/shieldCard/shieldCard_diff.j3o"), + shieldSymbol("Models/shieldCard/shieldSymbol.j3o", "Models/shieldCard/shieldCard_diff.png"), dice ; diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/InputSynchronizer.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/InputSynchronizer.java index 807a37c4..e0f657da 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/InputSynchronizer.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/InputSynchronizer.java @@ -27,6 +27,7 @@ import pp.mdga.notification.SelectableCardsNotification; import java.util.List; +import java.util.UUID; public class InputSynchronizer { @@ -127,7 +128,17 @@ else if(boardSelect != null) { // gameView.getGuiHandler().rollRankingResult(Color.ARMY, 2); // gameView.getGuiHandler().rollRankingResult(Color.NAVY, 3); // gameView.getGuiHandler().rollRankingResult(Color.CYBER, 4); - gameView.getGuiHandler().showDice(); +// gameView.getGuiHandler().showDice(); +// UUID p1 = UUID.randomUUID(); + +// gameView.getBoardHandler().addPlayer(Color.AIRFORCE,List.of(p1,UUID.randomUUID(),UUID.randomUUID(),UUID.randomUUID())); +// gameView.getBoardHandler().movePieceStartAnim(p1,0); + gameView.getGuiHandler().drawCard(Color.ARMY); + gameView.getGuiHandler().addCardOwn(BonusCard.SHIELD); + gameView.getGuiHandler().playCardOwn(BonusCard.SHIELD); + + + } } } diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaApp.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaApp.java index b0120dfb..fbe68143 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaApp.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaApp.java @@ -115,7 +115,7 @@ public void simpleInitApp() { gameView = new GameView(this); ceremonyView = new CeremonyView(this); - enter(MdgaState.MAIN); + enter(MdgaState.GAME); } /** diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/NotificationSynchronizer.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/NotificationSynchronizer.java index 0ffe9d44..3e648f28 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/NotificationSynchronizer.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/NotificationSynchronizer.java @@ -91,7 +91,7 @@ private void handleGame(Notification notification) { ModelSynchronizer modelSynchronizer = app.getModelSynchronize(); if (notification instanceof AcquireCardNotification n) { - guiHandler.addCard(n.getBonusCard()); + guiHandler.addCardOwn(n.getBonusCard()); } else if (notification instanceof ActivePlayerNotification n) { gameView.getGuiHandler().setActivePlayer(n.getColor()); boardHandler.showDice(n.getColor()); @@ -146,12 +146,8 @@ private void handleGame(Notification notification) { } else if (notification instanceof NoShieldNotification n) { boardHandler.unshieldPiece(n.getPieceId()); } else if (notification instanceof PlayCardNotification n) { - switch(n.getCard()){ - case SWAP -> guiHandler.swap(); - case TURBO -> guiHandler.turbo(); - case SHIELD -> guiHandler.shield(); - default -> throw new RuntimeException("invalid card"); - } + if(n.getColor() == gameView.getOwnColor()) guiHandler.playCardOwn(n.getCard()); + else guiHandler.playCardEnemy(n.getColor(), n.getCard()); } else if (notification instanceof PlayerInGameNotification n) { boardHandler.addPlayer(n.getColor(),n.getPiecesList()); guiHandler.addPlayer(n.getColor(),n.getName()); diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/CardControl.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/CardControl.java index f07e7e69..46e47ee6 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/CardControl.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/CardControl.java @@ -60,7 +60,7 @@ private Node createNum(){ Material mat = new Material(getApp().getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md"); mat.setColor("Color", ColorRGBA.Black); circle.setMaterial(mat); - root.attachChild(circle); +// root.attachChild(circle); BitmapFont guiFont = getApp().getAssetManager().loadFont("Fonts/Gunplay.fnt"); num = new BitmapText(guiFont); num.setSize(0.3f); diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/CardLayer.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/CardLayer.java index 860e5324..ebf21b6a 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/CardLayer.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/CardLayer.java @@ -86,7 +86,7 @@ public void render(RenderManager rm) { public void update(float tpf) { if (init && !cardBuffer.isEmpty()) { for (Spatial spatial : cardBuffer) { - root.attachChild(spatial); +// root.attachChild(spatial); } cardBuffer.clear(); } @@ -94,7 +94,9 @@ public void update(float tpf) { } public void addSpatial(Spatial card) { - cardBuffer.add(card); +// cardBuffer.add(card); + root.attachChild(card); + root = root; } public void deleteSpatial(Spatial spatial) { diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/CardLayerHandler.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/CardLayerHandler.java index 116e0987..2d5c4d2d 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/CardLayerHandler.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/CardLayerHandler.java @@ -85,6 +85,19 @@ public void addCard(BonusCard card) { bonusCardControlMap.get(card).setNumCard(newNum); } + public void removeCard(BonusCard card){ + if(bonusCardControlMap.containsKey(card)){ + bonusCardIntegerMap.put(card, bonusCardIntegerMap.get(card) - 1); + + if(bonusCardIntegerMap.get(card) <= 0){ + cardLayer.deleteSpatial(bonusCardControlMap.get(card).getRoot()); + bonusCardIntegerMap.remove(card); + bonusCardControlMap.remove(card); + } + + } + } + public void clearSelectableCards() { for (CardControl control : selectableCards) { control.setSelectable(false); diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/GuiHandler.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/GuiHandler.java index d4128081..c4024fbe 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/GuiHandler.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/GuiHandler.java @@ -74,8 +74,31 @@ public void hideDice() { cardLayerHandler.hideDice(); } - public void addCard(BonusCard card) { + //add own handCard + public void addCardOwn(BonusCard card) { cardLayerHandler.addCard(card); + playerNameHandler.addCard(ownColor); + actionTextHandler.drawCardOwn(ownColor); + } + + public void playCardOwn(BonusCard card){ + getEffectByCard(card); + cardLayerHandler.removeCard(card); + playerNameHandler.removeCard(ownColor); + } + + public void playCardEnemy(Color color, BonusCard card) { + getEffectByCard(card); + playerNameHandler.removeCard(color); + } + + private void getEffectByCard(BonusCard bonus){ + switch(bonus){ + case SWAP -> swap(); + case TURBO -> turbo(); + case SHIELD -> shield(); + default -> throw new RuntimeException("invalid card"); + } } public void clearSelectableCards() { @@ -125,9 +148,11 @@ public void hideText(){ actionTextHandler.hide(); } + //addCard Enemy (DrawCardNotification) public void drawCard(Color color) { - if (ownColor == color) actionTextHandler.drawCardOwn(color); - else actionTextHandler.drawCard(playerNameHandler.getName(color), color); + //Color != ownColor + actionTextHandler.drawCard(playerNameHandler.getName(color), color); + playerNameHandler.addCard(color); } public void finish(Color color){ @@ -141,4 +166,6 @@ public void rollRankingResult(Color color, int eye){ } + + } diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/PlayerNameHandler.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/PlayerNameHandler.java index 2d4bdbf7..e5069eae 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/PlayerNameHandler.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/PlayerNameHandler.java @@ -4,23 +4,27 @@ import com.jme3.font.BitmapFont; import com.jme3.font.BitmapText; import com.jme3.math.ColorRGBA; +import com.jme3.math.Vector3f; import com.jme3.scene.Node; import com.jme3.scene.Spatial; import com.jme3.system.AppSettings; import com.jme3.ui.Picture; +import pp.mdga.game.BonusCard; import pp.mdga.game.Color; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; - +import java.util.Vector; public class PlayerNameHandler { private final BitmapFont playerFont; private final Node playerNameNode; private final List playerOrder; private final Map colorNameMap; + private final Map colorCardMap; + private final AppSettings appSettings; private final AssetManager assetManager; private Color ownColor; @@ -43,6 +47,7 @@ public PlayerNameHandler(Node guiNode, AssetManager assetManager, AppSettings ap playerNameNode = new Node("player name node"); playerOrder = new ArrayList<>(); colorNameMap = new HashMap<>(); + colorCardMap = new HashMap<>(); this.appSettings = appSettings; this.assetManager = assetManager; } @@ -64,13 +69,38 @@ private void drawPlayers(){ if(!colorNameMap.containsKey(color)) throw new RuntimeException(color + " isn't mapped to a name"); Node nameParent = new Node("nameParent"); - nameParent.attachChild(createName(colorNameMap.get(color), i == 0, color == ownColor)); nameParent.attachChild(createColor(color)); + BitmapText name = createName(colorNameMap.get(color), i == 0, color == ownColor); + nameParent.attachChild(name); + if(colorCardMap.getOrDefault(color, 0) > 0){ + Picture pic = createHandCard(name.getLineWidth()); + nameParent.attachChild(pic); + nameParent.attachChild(createCardNum(colorCardMap.get(color), pic.getWidth(), pic.getLocalTranslation().getX())); + } nameParent.setLocalTranslation(50,appSettings.getWindowHeight()-PADDING_TOP- MARGIN_NAMES *i,0); playerNameNode.attachChild(nameParent); } } + private Spatial createCardNum(int num, float lastWidth, float lastX ) { + BitmapText hudText = new BitmapText(playerFont); + //renderedSize = 45 + hudText.setSize(TEXT_SIZE); + hudText.setColor(NORMAL_COLOR); + hudText.setText(String.valueOf(num)); + hudText.setLocalTranslation(lastX + lastWidth + 20,hudText.getHeight()/2, 0); + return hudText; + } + + private Picture createHandCard(float width) { + Picture pic = new Picture("HUD Picture"); + pic.setImage(assetManager, "./Images/handcard.png", true); + pic.setWidth(IMAGE_SIZE); + pic.setHeight(IMAGE_SIZE); + pic.setPosition(-pic.getWidth()/2 + width + PADDING_LEFT * 2 ,-pic.getHeight()/2); + return pic; + } + private String imagePath(Color color){ String root = "./Images/name_pictures/"; return switch(color){ @@ -93,7 +123,7 @@ private Spatial createColor(Color color) { - private Spatial createName(String name, boolean first, boolean own){ + private BitmapText createName(String name, boolean first, boolean own){ BitmapText hudText = new BitmapText(playerFont); //renderedSize = 45 hudText.setSize(TEXT_SIZE); @@ -124,5 +154,18 @@ public String getName(Color color){ return colorNameMap.get(color); } + public void addCard(Color color){ + colorCardMap.put(color, colorCardMap.getOrDefault(color, 0) + 1); + drawPlayers(); + } + + public void removeCard(Color color){ + if(colorCardMap.containsKey(color)){ + colorCardMap.put(color, colorCardMap.getOrDefault(color, 0) - 1); + if(colorCardMap.get(color) <= 0) colorCardMap.remove(color); + } + drawPlayers(); + } + } diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/view/GameView.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/view/GameView.java index f28719ac..60a2be45 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/view/GameView.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/view/GameView.java @@ -65,10 +65,11 @@ public void onEnter() { app.getAcousticHandler().playSound(MdgaSound.START); -// guiHandler.addPlayer(Color.AIRFORCE, "Cedric"); -// guiHandler.addPlayer(Color.ARMY, "Ben"); -// guiHandler.addPlayer(Color.CYBER, "Felix"); -// guiHandler.addPlayer(Color.NAVY, "Daniel"); + guiHandler.addPlayer(Color.AIRFORCE, "Cedric"); + guiHandler.addPlayer(Color.ARMY, "Ben"); + guiHandler.addPlayer(Color.CYBER, "Felix"); + guiHandler.addPlayer(Color.NAVY, "Daniel"); + } diff --git a/Projekte/mdga/client/src/main/resources/Images/handcard.png b/Projekte/mdga/client/src/main/resources/Images/handcard.png new file mode 100644 index 0000000000000000000000000000000000000000..6a30c799ee29d7d9bc10844b013d4dbbc7a56939 GIT binary patch literal 12257 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